- feat: Highlight inactive accounts in data-table.

- feat: Separate accounts list and table order.
This commit is contained in:
Ahmed Bouhuolia
2020-07-04 15:30:24 +02:00
parent 273834b13e
commit 3fc390652d
13 changed files with 116 additions and 49 deletions

View File

@@ -95,7 +95,7 @@ function MakeJournalEntriesTable({
customers,
// #withAccounts
accounts,
accountsList,
// #ownPorps
onClickRemoveRow,
@@ -251,7 +251,7 @@ function MakeJournalEntriesTable({
rowClassNames={rowClassNames}
sticky={true}
payload={{
accounts,
accounts: accountsList,
errors: errors.entries || [],
updateData: handleUpdateData,
removeRow: handleRemoveRow,
@@ -286,8 +286,8 @@ function MakeJournalEntriesTable({
}
export default compose(
withAccounts(({ accounts }) => ({
accounts,
withAccounts(({ accountsList }) => ({
accountsList,
})),
withCustomers(({ customersItems }) => ({
customers: customersItems,

View File

@@ -12,11 +12,13 @@ import {
} from '@blueprintjs/core';
import { withRouter } from 'react-router';
import { FormattedMessage as T, useIntl } from 'react-intl';
import classnames from 'classnames';
import {
Icon,
DataTable,
Money,
If,
Choose,
} from 'components';
import { compose } from 'utils';
import { useUpdateEffect } from 'hooks';
@@ -60,24 +62,54 @@ function BalanceCell({ cell }) {
);
}
function AccountNameAccessor(row) {
return row.description ? (
function InactiveSemafro() {
return (
<Tooltip
className={Classes.TOOLTIP_INDICATOR}
content={row.description}
position={Position.RIGHT_TOP}
hoverOpenDelay={500}
>
{row.name}
content={<T id='inactive' />}
className={classnames(
Classes.TOOLTIP_INDICATOR,
'bp3-popover-wrapper--inactive-semafro'
)}
position={Position.TOP}
hoverOpenDelay={250}>
<div className="inactive-semafro"></div>
</Tooltip>
) : (
row.name
);
}
function AccountNameAccessor(row) {
return (
<>
<Choose>
<Choose.When condition={!!row.description}>
<Tooltip
className={classnames(
Classes.TOOLTIP_INDICATOR,
'bp3-popover-wrapper--account-desc',
)}
content={row.description}
position={Position.RIGHT_TOP}
hoverOpenDelay={500}
>
{row.name}
</Tooltip>
</Choose.When>
<Choose.Otherwise>
{ row.name }
</Choose.Otherwise>
</Choose>
<If condition={!row.active}>
<InactiveSemafro />
</If>
</>
);
}
function AccountsDataTable({
// #withDashboardActions
accounts,
accountsTable,
accountsLoading,
// #withDialog.
@@ -256,7 +288,7 @@ function AccountsDataTable({
<DataTable
noInitialFetch={true}
columns={columns}
data={accounts}
data={accountsTable}
onFetchData={handleDatatableFetchData}
manualSortBy={true}
selectionColumn={selectionColumn}
@@ -275,8 +307,8 @@ export default compose(
withDialogActions,
withDashboardActions,
withAccountsActions,
withAccounts(({ accountsLoading, accounts }) => ({
withAccounts(({ accountsLoading, accountsTable }) => ({
accountsLoading,
accounts,
accountsTable,
})),
)(AccountsDataTable);

View File

@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import {
getAccountsItems,
getAccountsItems, getAccountsListFactory,
} from 'store/accounts/accounts.selectors';
import {
getResourceViews,
@@ -8,10 +8,13 @@ import {
export default (mapState) => {
const getAccountsList = getAccountsListFactory();
const mapStateToProps = (state, props) => {
const mapped = {
accountsViews: getResourceViews(state, props, 'accounts'),
accounts: getAccountsItems(state, props),
accountsTable: getAccountsItems(state, props),
accountsList: getAccountsList(state, props),
accountsTypes: state.accounts.accountsTypes,
accountsTableQuery: state.accounts.tableQuery,

View File

@@ -20,9 +20,9 @@ export default compose(
AccountFormDialogConnect,
withAccountsActions,
withAccountDetail,
withAccounts(({ accountsTypes, accounts }) => ({
withAccounts(({ accountsTypes, accountsList }) => ({
accountsTypes,
accounts,
accounts: accountsList,
})),
withDialogActions,
);

View File

@@ -26,7 +26,7 @@ import withAccounts from 'containers/Accounts/withAccounts';
function ExpenseFormHeader({
formik: { errors, touched, setFieldValue, getFieldProps, values },
currenciesList,
accounts,
accountsList,
accountsTypes,
}) {
const [selectedItems, setSelectedItems] = useState({});
@@ -165,7 +165,7 @@ function ExpenseFormHeader({
}
>
<AccountsSelectList
accounts={accounts}
accounts={accountsList}
onAccountSelected={onChangeAccount}
defaultSelectText={<T id={'select_payment_account'} />}
selectedAccountId={values.payment_account_id}
@@ -252,8 +252,8 @@ function ExpenseFormHeader({
}
export default compose(
withAccounts(({ accounts, accountsTypes }) => ({
accounts,
withAccounts(({ accountsList, accountsTypes }) => ({
accountsList,
accountsTypes,
})),
withCurrencies(({ currenciesList }) => ({

View File

@@ -87,7 +87,7 @@ const TotalAmountCellRenderer = (chainedComponent, type) => (props) => {
function ExpenseTable({
// #withAccounts
accounts,
accountsList,
// #ownPorps
onClickRemoveRow,
@@ -228,7 +228,7 @@ function ExpenseTable({
rowClassNames={rowClassNames}
sticky={true}
payload={{
accounts,
accounts: accountsList,
errors: errors.categories || [],
updateData: handleUpdateData,
removeRow: handleRemoveRow,
@@ -256,7 +256,7 @@ function ExpenseTable({
}
export default compose(
withAccounts(({ accounts }) => ({
accounts,
withAccounts(({ accountsList }) => ({
accountsList,
})),
)(ExpenseTable);

View File

@@ -25,7 +25,7 @@ function GeneralLedgerHeader({
pageFilter,
// #withAccounts
accounts,
accountsList,
// #withGeneralLedgerActions
refreshGeneralLedgerSheet,
@@ -83,7 +83,7 @@ function GeneralLedgerHeader({
className={classNames('form-group--select-list', Classes.FILL)}
>
<AccountsMultiSelect
accounts={accounts}
accounts={accountsList}
onAccountSelected={onAccountSelected}
/>
</FormGroup>
@@ -102,8 +102,8 @@ function GeneralLedgerHeader({
}
export default compose(
withAccounts(({ accounts }) => ({
accounts,
withAccounts(({ accountsList }) => ({
accountsList,
})),
withGeneralLedger(({ generalLedgerSheetFilter, generalLedgerSheetRefresh }) => ({
generalLedgerSheetFilter,

View File

@@ -528,4 +528,5 @@ export default {
'A unique code/number for this account (limited to 10 characters)',
logic_expression: 'logic expression',
assign_to_customer: 'Assign to Customer',
inactive: 'Inactive',
};

View File

@@ -19,32 +19,29 @@ export const fetchAccountTypes = () => {
});
};
export const fetchAccountsList = ({ query } = {}) => {
export const fetchAccountsList = () => {
return (dispatch) =>
new Promise((resolve, reject) => {
dispatch({
type: t.SET_DASHBOARD_REQUEST_LOADING,
});
const query = { column_sort_by: 'name', sort_order: 'asc' };
ApiService.get('accounts', { params: query })
.then((response) => {
dispatch({
type: t.ACCOUNTS_PAGE_SET,
accounts: response.data.accounts,
customViewId: response.data.customViewId,
});
dispatch({
type: t.ACCOUNTS_ITEMS_SET,
accounts: response.data.accounts,
});
dispatch({
type: t.ACCOUNTS_LIST_SET,
payload: {
accounts: response.data.accounts,
}
})
dispatch({
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
});
resolve(response);
})
.catch((error) => {
dispatch({
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
});
reject(error);
});
});

View File

@@ -5,6 +5,7 @@ import { createTableQueryReducers } from 'store/queryReducers';
const initialState = {
items: {},
views: {},
list: [],
accountsTypes: [],
accountsById: {},
tableQuery: {
@@ -40,6 +41,11 @@ const accountsReducer = createReducer(initialState, {
};
},
[t.ACCOUNTS_LIST_SET]: (state, action) => {
const { accounts } = action.payload;
state.list = accounts.map(account => account.id);
},
[t.ACCOUNT_TYPES_LIST_SET]: (state, action) => {
state.accountsTypes = action.account_types;
},

View File

@@ -6,6 +6,9 @@ const accountsDataSelector = (state) => state.accounts.items;
const accountsCurrentViewSelector = (state) => state.accounts.currentViewId;
const accountIdPropSelector = (state, props) => props.accountId;
const accountsListSelector = state => state.accounts.list;
export const getAccountsItems = createSelector(
accountsViewsSelector,
accountsDataSelector,
@@ -19,6 +22,14 @@ export const getAccountsItems = createSelector(
},
);
export const getAccountsListFactory = () => createSelector(
accountsListSelector,
accountsDataSelector,
(accounts, accountsItems) => {
return pickItemsFromIds(accountsItems, accounts);
},
)
export const getAccountById = createSelector(
accountsDataSelector,
accountIdPropSelector,

View File

@@ -3,6 +3,7 @@
export default {
ACCOUNT_TYPES_LIST_SET: 'ACCOUNT_TYPES_LIST_SET',
ACCOUNTS_PAGE_SET: 'ACCOUNTS_PAGE_SET',
ACCOUNTS_LIST_SET: 'ACCOUNTS_LIST_SET',
ACCOUNTS_ITEMS_SET: 'ACCOUNTS_ITEMS_SET',
ACCOUNT_SET: 'ACCOUNT_SET',
ACCOUNT_DELETE: 'ACCOUNT_DELETE',

View File

@@ -16,10 +16,26 @@
padding-bottom: 0.36rem;
}
.account_name{
> div{
width: 100%;
}
.bp3-tooltip-indicator{
cursor: default;
border-bottom-color: #c6c6c6;
.bp3-popover-wrapper--inactive-semafro{
margin-left: 8px;
margin-right: 6px;
float: right;
border: 0;
}
.bp3-popover-wrapper--account-desc{
border-bottom-color: #BBB;
}
.inactive-semafro{
height: 7px;
width: 7px;
background: #BBB;
display: inline-block;
border-radius: 8px;
}
}
.normal{