mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
- feat: Highlight inactive accounts in data-table.
- feat: Separate accounts list and table order.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -20,9 +20,9 @@ export default compose(
|
||||
AccountFormDialogConnect,
|
||||
withAccountsActions,
|
||||
withAccountDetail,
|
||||
withAccounts(({ accountsTypes, accounts }) => ({
|
||||
withAccounts(({ accountsTypes, accountsList }) => ({
|
||||
accountsTypes,
|
||||
accounts,
|
||||
accounts: accountsList,
|
||||
})),
|
||||
withDialogActions,
|
||||
);
|
||||
|
||||
@@ -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 }) => ({
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user