- feat: Update react-query package to V 2.1.1.

- feat: Favicon setup.
- feat: Fix accounts inactivate/activate 1 account.
- feat: Seed accounts, expenses and manual journals resource fields.
- feat: Validate make journal receivable/payable without contact.
- feat: Validate make journal contact without receivable or payable.
- feat: More components abstractions.
- feat: Use reselect.js to memorize components properties.
- fix: Journal type of manual journal.
- fix: Sidebar style optimization.
- fix: Data-table check-box style optimization.
- fix: Data-table spinner style dimensions.
- fix: Submit journal with contact_id and contact_type.
This commit is contained in:
Ahmed Bouhuolia
2020-07-01 12:51:12 +02:00
parent 111aa83908
commit 4718f63c94
94 changed files with 1706 additions and 1001 deletions

View File

@@ -59,20 +59,22 @@ function AccountsChart({
const [selectedRows, setSelectedRows] = useState([]);
const [bulkActivate, setBulkActivate] = useState(false);
const [bulkInactiveAccounts, setBulkInactiveAccounts] = useState(false);
const [tableLoading, setTableLoading] = useState(false);
// Fetch accounts resource views and fields.
const fetchHook = useQuery('resource-accounts', () => {
return Promise.all([
requestFetchResourceViews('accounts'),
requestFetchResourceFields('accounts'),
]);
});
const fetchResourceViews = useQuery(
['resource-views', 'accounts'],
(key, resourceName) => requestFetchResourceViews(resourceName),
);
const fetchResourceFields = useQuery(
['resource-fields', 'accounts'],
(key, resourceName) => requestFetchResourceFields(resourceName),
);
// Fetch accounts list according to the given custom view id.
const fetchAccountsHook = useQuery(
['accounts-table', accountsTableQuery],
() => requestFetchAccountsTable(),
(key, q) => requestFetchAccountsTable(),
);
useEffect(() => {
@@ -89,6 +91,7 @@ function AccountsChart({
setDeleteAccount(false);
}, []);
// Handle delete errors in bulk and singular.
const handleDeleteErrors = (errors) => {
if (errors.find((e) => e.type === 'ACCOUNT.PREDEFINED')) {
AppToaster.show({
@@ -221,17 +224,6 @@ function AccountsChart({
fetchAccountsHook.refetch();
}, [fetchAccountsHook]);
// Refetch accounts data table when current custom view changed.
const handleViewChanged = useCallback(async () => {
setTableLoading(true);
}, [fetchAccountsHook]);
useEffect(() => {
if (tableLoading && !fetchAccountsHook.isFetching) {
setTableLoading(false);
}
}, [tableLoading, fetchAccountsHook.isFetching]);
// Handle fetch data of accounts datatable.
const handleFetchData = useCallback(
({ pageIndex, pageSize, sortBy }) => {
@@ -243,7 +235,6 @@ function AccountsChart({
}
: {}),
});
fetchAccountsHook.refetch();
},
[fetchAccountsHook, addAccountsTableQueries],
);
@@ -314,7 +305,10 @@ function AccountsChart({
}, [requestBulkInactiveAccounts, bulkInactiveAccounts]);
return (
<DashboardInsider loading={fetchHook.isFetching} name={'accounts-chart'}>
<DashboardInsider
loading={fetchResourceFields.isFetching || fetchResourceViews.isFetching}
name={'accounts-chart'}
>
<DashboardActionsBar
selectedRows={selectedRows}
onFilterChanged={handleFilterChanged}
@@ -323,17 +317,15 @@ function AccountsChart({
onBulkActivate={handleBulkActivate}
onBulkInactive={handleBulkInactive}
/>
<DashboardPageContent>
<Switch>
<Route
exact={true}
path={['/accounts/:custom_view_id/custom_view', '/accounts']}
>
<AccountsViewsTabs onViewChanged={handleViewChanged} />
<AccountsViewsTabs />
<AccountsDataTable
loading={fetchAccountsHook.isFetching}
onDeleteAccount={handleDeleteAccount}
onInactiveAccount={handleInactiveAccount}
onActivateAccount={handleActivateAccount}
@@ -341,7 +333,6 @@ function AccountsChart({
onEditAccount={handleEditAccount}
onFetchData={handleFetchData}
onSelectedRowsChange={handleSelectedRowsChange}
/>
</Route>
</Switch>

View File

@@ -12,13 +12,13 @@ import {
} from '@blueprintjs/core';
import { withRouter } from 'react-router';
import { FormattedMessage as T, useIntl } from 'react-intl';
import Icon from 'components/Icon';
import {
Icon,
DataTable,
Money,
If,
} from 'components';
import { compose } from 'utils';
import LoadingIndicator from 'components/LoadingIndicator';
import DataTable from 'components/DataTable';
import Money from 'components/Money';
import { useUpdateEffect } from 'hooks';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
@@ -27,7 +27,53 @@ import withAccounts from 'containers/Accounts/withAccounts';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withCurrentView from 'containers/Views/withCurrentView';
import { If } from 'components';
function NormalCell({ cell }) {
const { formatMessage } = useIntl();
const account = cell.row.original;
const normal = account?.type?.normal || '';
const arrowDirection = normal === 'credit' ? 'down' : 'up';
return (
<Tooltip
className={Classes.TOOLTIP_INDICATOR}
content={formatMessage({ id: normal })}
position={Position.RIGHT}
hoverOpenDelay={100}
>
<Icon icon={`arrow-${arrowDirection}`} />
</Tooltip>
);
}
function BalanceCell({ cell }) {
const account = cell.row.original;
const { balance = null } = account;
return balance ? (
<span>
<Money amount={balance.amount} currency={balance.currency_code} />
</span>
) : (
<span class="placeholder">--</span>
);
}
function AccountNameAccessor(row) {
return row.description ? (
<Tooltip
className={Classes.TOOLTIP_INDICATOR}
content={row.description}
position={Position.RIGHT_TOP}
hoverOpenDelay={500}
>
{row.name}
</Tooltip>
) : (
row.name
);
}
function AccountsDataTable({
// #withDashboardActions
@@ -40,7 +86,6 @@ function AccountsDataTable({
currentViewId,
// own properties
loading,
onFetchData,
onSelectedRowsChange,
onDeleteAccount,
@@ -125,20 +170,7 @@ function AccountsDataTable({
{
id: 'name',
Header: formatMessage({ id: 'account_name' }),
accessor: (row) => {
return row.description ? (
<Tooltip
className={Classes.TOOLTIP_INDICATOR}
content={row.description}
position={Position.RIGHT_TOP}
hoverOpenDelay={500}
>
{row.name}
</Tooltip>
) : (
row.name
);
},
accessor: AccountNameAccessor,
className: 'account_name',
width: 220,
},
@@ -159,40 +191,22 @@ function AccountsDataTable({
{
id: 'normal',
Header: formatMessage({ id: 'normal' }),
Cell: ({ cell }) => {
const account = cell.row.original;
const normal = account.type ? account.type.normal : '';
const arrowDirection = normal === 'credit' ? 'down' : 'up';
return (
<Tooltip
className={Classes.TOOLTIP_INDICATOR}
content={formatMessage({ id: normal })}
position={Position.RIGHT}
hoverOpenDelay={500}
>
<Icon icon={`arrow-${arrowDirection}`} />
</Tooltip>
);
},
Cell: NormalCell,
accessor: 'type.normal',
className: 'normal',
width: 115,
},
{
id: 'currency',
Header: formatMessage({ id: 'currency' }),
accessor: (row) => 'USD',
width: 100,
},
{
id: 'balance',
Header: formatMessage({ id: 'balance' }),
Cell: ({ cell }) => {
const account = cell.row.original;
const { balance = null } = account;
return balance ? (
<span>
<Money amount={balance.amount} currency={balance.currency_code} />
</span>
) : (
<span class="placeholder">--</span>
);
},
accessor: 'balance',
Cell: BalanceCell,
width: 150,
},
{
@@ -235,23 +249,19 @@ function AccountsDataTable({
);
return (
<LoadingIndicator loading={loading && !isMounted} mount={false}>
<DataTable
noInitialFetch={true}
columns={columns}
data={accounts}
onFetchData={handleDatatableFetchData}
manualSortBy={true}
selectionColumn={selectionColumn}
expandable={true}
treeGraph={true}
sticky={true}
onSelectedRowsChange={handleSelectedRowsChange}
loading={accountsLoading && !isMounted}
spinnerProps={{ size: 30 }}
rowContextMenu={rowContextMenu}
/>
</LoadingIndicator>
<DataTable
noInitialFetch={true}
columns={columns}
data={accounts}
onFetchData={handleDatatableFetchData}
manualSortBy={true}
selectionColumn={selectionColumn}
expandable={true}
sticky={true}
onSelectedRowsChange={handleSelectedRowsChange}
loading={accountsLoading && !isMounted}
rowContextMenu={rowContextMenu}
/>
);
}

View File

@@ -5,17 +5,12 @@ import {
Alignment,
Navbar,
NavbarGroup,
Tabs,
Tab,
Button,
} from '@blueprintjs/core';
import { useParams, withRouter } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { pick, debounce } from 'lodash';
import Icon from 'components/Icon';
import { FormattedMessage as T } from 'react-intl';
import { useUpdateEffect } from 'hooks';
import { DashboardViewsTabs } from 'components';
import { DashboardViewsTabs, Icon } from 'components';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withAccounts from 'containers/Accounts/withAccounts';
import withAccountsTableActions from 'containers/Accounts/withAccountsTableActions';
@@ -49,7 +44,7 @@ function AccountsViewsTabs({
useEffect(() => {
changeAccountsCurrentView(customViewId || -1);
setTopbarEditView(customViewId);
changePageSubtitle(customViewId && viewItem ? viewItem.name : '');
changePageSubtitle((customViewId && viewItem) ? viewItem.name : '');
addAccountsTableQueries({
custom_view_id: customViewId,
@@ -92,6 +87,7 @@ function AccountsViewsTabs({
<Navbar className="navbar--dashboard-views">
<NavbarGroup align={Alignment.LEFT}>
<DashboardViewsTabs
initialViewId={customViewId}
baseUrl={'/accounts'}
tabs={tabs}
onNewViewTabClick={handleClickNewView}
@@ -116,5 +112,5 @@ export default compose(
accountsViews,
})),
withAccountsTableActions,
withViewDetail,
withViewDetail(),
)(AccountsViewsTabs);

View File

@@ -1,10 +1,8 @@
import { connect } from 'react-redux';
import {
getItemById
} from 'store/selectors';
import { getAccountById } from 'store/accounts/accounts.selectors';
const mapStateToProps = (state, props) => ({
account: getItemById(state.accounts.items, props.accountId),
account: getAccountById(state, props),
});
export default connect(mapStateToProps);