mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
feat: cashflow service.
This commit is contained in:
@@ -141,14 +141,14 @@ function BankAccountBalance({ amount, loading }) {
|
|||||||
|
|
||||||
const ACCOUNT_TYPE = {
|
const ACCOUNT_TYPE = {
|
||||||
CASH: 'cash',
|
CASH: 'cash',
|
||||||
|
BANK: 'bank',
|
||||||
CREDIT_CARD: 'credit-card',
|
CREDIT_CARD: 'credit-card',
|
||||||
BANK_ACCOUNT: 'bank-account',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ACCOUNT_TYPE_PAIR_ICON = {
|
const ACCOUNT_TYPE_PAIR_ICON = {
|
||||||
[ACCOUNT_TYPE.CASH]: 'payments',
|
[ACCOUNT_TYPE.CASH]: 'payments',
|
||||||
[ACCOUNT_TYPE.CREDIT_CARD]: 'credit-card',
|
[ACCOUNT_TYPE.CREDIT_CARD]: 'credit-card',
|
||||||
[ACCOUNT_TYPE.BANK_ACCOUNT]: 'account-balance',
|
[ACCOUNT_TYPE.BANK]: 'account-balance',
|
||||||
};
|
};
|
||||||
|
|
||||||
function BankAccountTypeIcon({ type }) {
|
function BankAccountTypeIcon({ type }) {
|
||||||
@@ -159,7 +159,7 @@ function BankAccountTypeIcon({ type }) {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<AccountIconWrap>
|
<AccountIconWrap>
|
||||||
<Icon icon={'credit-card'} iconSize={18} />
|
<Icon icon={icon} iconSize={18} />
|
||||||
</AccountIconWrap>
|
</AccountIconWrap>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ export function IntersectionObserver({ onIntersect }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={loadMoreButtonRef} style={{ opacity: 0 }}>
|
<div
|
||||||
|
ref={loadMoreButtonRef}
|
||||||
|
style={{ opacity: 0, height: 0, width: 0, padding: 0, margin: 0 }}
|
||||||
|
>
|
||||||
Load Newer
|
Load Newer
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Intent, Tag } from '@blueprintjs/core';
|
import { Intent, Tag } from '@blueprintjs/core';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import clsx from 'classnames';
|
|
||||||
|
|
||||||
import { CLASSES } from '../../common/classes';
|
|
||||||
import { If, AppToaster } from 'components';
|
import { If, AppToaster } from 'components';
|
||||||
import { NormalCell, BalanceCell } from './components';
|
import { NormalCell, BalanceCell } from './components';
|
||||||
import { transformTableStateToQuery, isBlank } from 'utils';
|
import { transformTableStateToQuery, isBlank } from 'utils';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { DataTable, TableFastCell } from 'components';
|
import { DataTable, TableFastCell } from 'components';
|
||||||
import { TABLES } from 'common/tables';
|
import { TABLES } from 'common/tables';
|
||||||
@@ -36,14 +37,13 @@ function AccountTransactionsDataTable({
|
|||||||
useMemorizedColumnsWidths(TABLES.CASHFLOW_Transactions);
|
useMemorizedColumnsWidths(TABLES.CASHFLOW_Transactions);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataTable
|
<CashflowTransactionsTable
|
||||||
noInitialFetch={true}
|
noInitialFetch={true}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={cashflowTransactions}
|
data={cashflowTransactions}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
loading={isCashFlowTransactionsLoading}
|
loading={isCashFlowTransactionsLoading}
|
||||||
headerLoading={isCashFlowTransactionsLoading}
|
headerLoading={isCashFlowTransactionsLoading}
|
||||||
progressBarLoading={isCashFlowTransactionsFetching}
|
|
||||||
expandColumnSpace={1}
|
expandColumnSpace={1}
|
||||||
expandToggleColumn={2}
|
expandToggleColumn={2}
|
||||||
selectionColumnWidth={45}
|
selectionColumnWidth={45}
|
||||||
@@ -54,11 +54,11 @@ function AccountTransactionsDataTable({
|
|||||||
// #TableVirtualizedListRows props.
|
// #TableVirtualizedListRows props.
|
||||||
vListrowHeight={cashflowTansactionsTableSize == 'small' ? 32 : 40}
|
vListrowHeight={cashflowTansactionsTableSize == 'small' ? 32 : 40}
|
||||||
vListOverscanRowCount={0}
|
vListOverscanRowCount={0}
|
||||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
size={cashflowTansactionsTableSize}
|
noResults={
|
||||||
noResults={'There is deposit/withdrawal transactions on the current account.'}
|
'There is deposit/withdrawal transactions on the current account.'
|
||||||
|
}
|
||||||
className="table-constrant"
|
className="table-constrant"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -69,3 +69,30 @@ export default compose(
|
|||||||
cashflowTansactionsTableSize: cashflowTransactionsSettings?.tableSize,
|
cashflowTansactionsTableSize: cashflowTransactionsSettings?.tableSize,
|
||||||
})),
|
})),
|
||||||
)(AccountTransactionsDataTable);
|
)(AccountTransactionsDataTable);
|
||||||
|
|
||||||
|
const DashboardConstrantTable = styled(DataTable)`
|
||||||
|
.table .thead {
|
||||||
|
.th {
|
||||||
|
border-bottom-color: #666;
|
||||||
|
border-top-color: #666;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CashflowTransactionsTable = styled(DashboardConstrantTable)`
|
||||||
|
.table .tbody {
|
||||||
|
|
||||||
|
.tbody-inner .tr.no-results {
|
||||||
|
.td {
|
||||||
|
padding: 3rem 0;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #888;
|
||||||
|
font-weight: 400;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DashboardRegularTable = styled(DataTable)``;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function useAccountTransactionsColumns() {
|
|||||||
width: 110,
|
width: 110,
|
||||||
className: 'deposit',
|
className: 'deposit',
|
||||||
textOverview: true,
|
textOverview: true,
|
||||||
align: 'right'
|
align: 'right',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'withdrawal',
|
id: 'withdrawal',
|
||||||
@@ -65,7 +65,7 @@ export function useAccountTransactionsColumns() {
|
|||||||
className: 'running_balance',
|
className: 'running_balance',
|
||||||
width: 150,
|
width: 150,
|
||||||
textOverview: true,
|
textOverview: true,
|
||||||
align: 'right'
|
align: 'right',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
@@ -76,7 +76,7 @@ export function useAccountTransactionsColumns() {
|
|||||||
* Account transactions progress bar.
|
* Account transactions progress bar.
|
||||||
*/
|
*/
|
||||||
export function AccountTransactionsProgressBar() {
|
export function AccountTransactionsProgressBar() {
|
||||||
const { isCashFlowTransactionsLoading } = useAccountTransactionsContext();
|
const { isCashFlowTransactionsFetching } = useAccountTransactionsContext();
|
||||||
|
|
||||||
return isCashFlowTransactionsLoading ? <MaterialProgressBar /> : null;
|
return isCashFlowTransactionsFetching ? <MaterialProgressBar /> : null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { getCashflowAccountsTableStateFactory } from 'store/CashflowAccounts/CashflowAccounts.selectors';
|
||||||
|
|
||||||
|
export default (mapState) => {
|
||||||
|
const getCashflowAccountsTableState = getCashflowAccountsTableStateFactory();
|
||||||
|
|
||||||
|
const mapStateToProps = (state, props) => {
|
||||||
|
const mapped = {
|
||||||
|
cashflowAccountsTableState: getCashflowAccountsTableState(state, props),
|
||||||
|
};
|
||||||
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
return connect(mapStateToProps);
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import {
|
||||||
|
setCashflowAccountsTableState,
|
||||||
|
resetCashflowAccountsTableState,
|
||||||
|
} from 'store/CashflowAccounts/CashflowAccounts.actions';
|
||||||
|
|
||||||
|
const mapActionsToProps = (dispatch) => ({
|
||||||
|
setCashflowAccountsTableState: (queries) =>
|
||||||
|
dispatch(setCashflowAccountsTableState(queries)),
|
||||||
|
|
||||||
|
resetCashflowAccountsTableState: () =>
|
||||||
|
dispatch(resetCashflowAccountsTableState()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, mapActionsToProps);
|
||||||
@@ -1,26 +1,22 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import { isEmpty } from 'lodash';
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
NavbarGroup,
|
NavbarGroup,
|
||||||
Classes,
|
Classes,
|
||||||
NavbarDivider,
|
NavbarDivider,
|
||||||
Alignment,
|
Alignment,
|
||||||
|
Switch,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Icon,
|
Icon,
|
||||||
DashboardRowsHeightButton,
|
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
} from 'components';
|
} from 'components';
|
||||||
|
|
||||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||||
import { useCashFlowAccountsContext } from './CashFlowAccountsProvider';
|
|
||||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||||
import withSettings from '../../Settings/withSettings';
|
import withSettings from '../../Settings/withSettings';
|
||||||
import withSettingsActions from '../../Settings/withSettingsActions';
|
import withSettingsActions from '../../Settings/withSettingsActions';
|
||||||
|
import withCashflowAccountsTableActions from '../AccountTransactions/withCashflowAccountsTableActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -36,12 +32,14 @@ function CashFlowAccountsActionsBar({
|
|||||||
|
|
||||||
// #withSettingsActions
|
// #withSettingsActions
|
||||||
addSetting,
|
addSetting,
|
||||||
|
|
||||||
|
// #
|
||||||
|
setCashflowAccountsTableState
|
||||||
}) {
|
}) {
|
||||||
// Handle table row size change.
|
// Handle table row size change.
|
||||||
const handleTableRowSizeChange = (size) => {
|
const handleTableRowSizeChange = (size) => {
|
||||||
addSetting('cashflowAccounts', 'tableSize', size);
|
addSetting('cashflowAccounts', 'tableSize', size);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle click a refresh
|
// Handle click a refresh
|
||||||
const handleRefreshBtnClick = () => {};
|
const handleRefreshBtnClick = () => {};
|
||||||
|
|
||||||
@@ -49,18 +47,21 @@ function CashFlowAccountsActionsBar({
|
|||||||
const handleAddBankAccount = () => {
|
const handleAddBankAccount = () => {
|
||||||
openDialog('account-form', {});
|
openDialog('account-form', {});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle add cash account.
|
// Handle add cash account.
|
||||||
const handleAddCashAccount = () => {
|
const handleAddCashAccount = () => {
|
||||||
openDialog('account-form', {});
|
openDialog('account-form', {});
|
||||||
};
|
};
|
||||||
|
// Handle inactive switch changing.
|
||||||
|
const handleInactiveSwitchChange = (event) => {
|
||||||
|
const checked = event.target.checked;
|
||||||
|
setCashflowAccountsTableState({ inactiveMode: checked });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
// className={classNames(Classes.MINIMAL, 'button--table-views')}
|
|
||||||
icon={<Icon icon={'plus-24'} iconSize={20} />}
|
icon={<Icon icon={'plus-24'} iconSize={20} />}
|
||||||
text={<T id={'cash_flow.label.add_cash_account'} />}
|
text={<T id={'cash_flow.label.add_cash_account'} />}
|
||||||
onClick={handleAddBankAccount}
|
onClick={handleAddBankAccount}
|
||||||
@@ -88,11 +89,12 @@ function CashFlowAccountsActionsBar({
|
|||||||
text={<T id={'import'} />}
|
text={<T id={'import'} />}
|
||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
<DashboardRowsHeightButton
|
|
||||||
initialValue={cashflowTableSize}
|
<Switch
|
||||||
onChange={handleTableRowSizeChange}
|
labelElement={<T id={'inactive'} />}
|
||||||
|
defaultChecked={false}
|
||||||
|
onChange={handleInactiveSwitchChange}
|
||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
|
||||||
</NavbarGroup>
|
</NavbarGroup>
|
||||||
<NavbarGroup align={Alignment.RIGHT}>
|
<NavbarGroup align={Alignment.RIGHT}>
|
||||||
<Button
|
<Button
|
||||||
@@ -110,4 +112,5 @@ export default compose(
|
|||||||
withSettings(({ cashflowSettings }) => ({
|
withSettings(({ cashflowSettings }) => ({
|
||||||
cashflowTableSize: cashflowSettings?.tableSize,
|
cashflowTableSize: cashflowSettings?.tableSize,
|
||||||
})),
|
})),
|
||||||
|
withCashflowAccountsTableActions,
|
||||||
)(CashFlowAccountsActionsBar);
|
)(CashFlowAccountsActionsBar);
|
||||||
|
|||||||
@@ -1,20 +1,37 @@
|
|||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
import { compose } from 'lodash/fp';
|
||||||
|
|
||||||
import 'style/pages/CashFlow/CashFlowAccounts/List.scss';
|
import 'style/pages/CashFlow/CashFlowAccounts/List.scss';
|
||||||
|
|
||||||
import { DashboardPageContent } from 'components';
|
import { DashboardPageContent } from 'components';
|
||||||
|
|
||||||
import { CashFlowAccountsProvider } from './CashFlowAccountsProvider';
|
import { CashFlowAccountsProvider } from './CashFlowAccountsProvider';
|
||||||
|
|
||||||
import CashFlowAccountsActionsBar from './CashFlowAccountsActionsBar';
|
import CashFlowAccountsActionsBar from './CashFlowAccountsActionsBar';
|
||||||
import CashflowAccountsGrid from './CashflowAccountsGrid';
|
import CashflowAccountsGrid from './CashflowAccountsGrid';
|
||||||
|
|
||||||
|
import withCashflowAccounts from '../AccountTransactions/withCashflowAccounts';
|
||||||
|
import withCashflowAccountsTableActions from '../AccountTransactions/withCashflowAccountsTableActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cash flow accounts list.
|
* Cashflow accounts list.
|
||||||
*/
|
*/
|
||||||
function CashFlowAccountsList({}) {
|
function CashFlowAccountsList({
|
||||||
|
// #withCashflowAccounts
|
||||||
|
cashflowAccountsTableState,
|
||||||
|
|
||||||
|
// #withCashflowAccountsTableActions
|
||||||
|
resetCashflowAccountsTableState,
|
||||||
|
}) {
|
||||||
|
// Resets the cashflow accounts table state.
|
||||||
|
useEffect(
|
||||||
|
() => () => {
|
||||||
|
resetCashflowAccountsTableState();
|
||||||
|
},
|
||||||
|
[resetCashflowAccountsTableState],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CashFlowAccountsProvider>
|
<CashFlowAccountsProvider tableState={cashflowAccountsTableState}>
|
||||||
<CashFlowAccountsActionsBar />
|
<CashFlowAccountsActionsBar />
|
||||||
|
|
||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
@@ -24,4 +41,9 @@ function CashFlowAccountsList({}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CashFlowAccountsList;
|
export default compose(
|
||||||
|
withCashflowAccounts(({ cashflowAccountsTableState }) => ({
|
||||||
|
cashflowAccountsTableState,
|
||||||
|
})),
|
||||||
|
withCashflowAccountsTableActions,
|
||||||
|
)(CashFlowAccountsList);
|
||||||
|
|||||||
@@ -3,12 +3,16 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
|||||||
|
|
||||||
import { useCashflowAccounts } from 'hooks/query';
|
import { useCashflowAccounts } from 'hooks/query';
|
||||||
|
|
||||||
|
import { transformAccountsStateToQuery } from './utils';
|
||||||
|
|
||||||
const CashFlowAccountsContext = React.createContext();
|
const CashFlowAccountsContext = React.createContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cash Flow data provider.
|
* Cash Flow data provider.
|
||||||
*/
|
*/
|
||||||
function CashFlowAccountsProvider({ query, tableStateChanged, ...props }) {
|
function CashFlowAccountsProvider({ tableState, ...props }) {
|
||||||
|
const query = transformAccountsStateToQuery(tableState);
|
||||||
|
|
||||||
// Fetch cash flow list .
|
// Fetch cash flow list .
|
||||||
const {
|
const {
|
||||||
data: cashflowAccounts,
|
data: cashflowAccounts,
|
||||||
@@ -32,4 +36,5 @@ function CashFlowAccountsProvider({ query, tableStateChanged, ...props }) {
|
|||||||
|
|
||||||
const useCashFlowAccountsContext = () =>
|
const useCashFlowAccountsContext = () =>
|
||||||
React.useContext(CashFlowAccountsContext);
|
React.useContext(CashFlowAccountsContext);
|
||||||
|
|
||||||
export { CashFlowAccountsProvider, useCashFlowAccountsContext };
|
export { CashFlowAccountsProvider, useCashFlowAccountsContext };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { isNull } from 'lodash';
|
import { isNull, isEmpty } from 'lodash';
|
||||||
import { compose } from 'lodash/fp';
|
import { compose, curry } from 'lodash/fp';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Menu, MenuItem, MenuDivider, Intent } from '@blueprintjs/core';
|
import { Menu, MenuItem, MenuDivider, Intent } from '@blueprintjs/core';
|
||||||
@@ -23,6 +23,7 @@ import withAlertsActions from '../../Alert/withAlertActions';
|
|||||||
import withDialogActions from '../../Dialog/withDialogActions';
|
import withDialogActions from '../../Dialog/withDialogActions';
|
||||||
|
|
||||||
import { safeCallback } from 'utils';
|
import { safeCallback } from 'utils';
|
||||||
|
import { addMoneyIn, addMoneyOut } from 'common/cashflowOptions';
|
||||||
|
|
||||||
const CASHFLOW_SKELETON_N = 4;
|
const CASHFLOW_SKELETON_N = 4;
|
||||||
|
|
||||||
@@ -91,6 +92,20 @@ function CashflowBankAccount({
|
|||||||
const handleEditAccount = () => {
|
const handleEditAccount = () => {
|
||||||
openDialog('account-form', { action: 'edit', id: account.id });
|
openDialog('account-form', { action: 'edit', id: account.id });
|
||||||
};
|
};
|
||||||
|
// Handle money in menu item actions.
|
||||||
|
const handleMoneyInClick = (transactionType) => {
|
||||||
|
openDialog('money-in', {
|
||||||
|
account_type: transactionType,
|
||||||
|
account_id: account.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// Handle money out menu item actions.
|
||||||
|
const handleMoneyOutClick = (transactionType) => {
|
||||||
|
openDialog('money-out', {
|
||||||
|
account_type: transactionType,
|
||||||
|
account_id: account.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CashflowBankAccountWrap>
|
<CashflowBankAccountWrap>
|
||||||
@@ -102,7 +117,7 @@ function CashflowBankAccount({
|
|||||||
title={account.name}
|
title={account.name}
|
||||||
code={account.code}
|
code={account.code}
|
||||||
balance={!isNull(account.amount) ? account.formatted_amount : '-'}
|
balance={!isNull(account.amount) ? account.formatted_amount : '-'}
|
||||||
type={'cash'}
|
type={account.account_type}
|
||||||
updatedBeforeText={getUpdatedBeforeText(account.createdAt)}
|
updatedBeforeText={getUpdatedBeforeText(account.createdAt)}
|
||||||
/>
|
/>
|
||||||
</CashflowAccountAnchor>
|
</CashflowAccountAnchor>
|
||||||
@@ -119,6 +134,8 @@ function CashflowBankAccount({
|
|||||||
onActivateClick={handleActivateClick}
|
onActivateClick={handleActivateClick}
|
||||||
onInactivateClick={handleInactivateClick}
|
onInactivateClick={handleInactivateClick}
|
||||||
onEditClick={handleEditAccount}
|
onEditClick={handleEditAccount}
|
||||||
|
onMoneyInClick={handleMoneyInClick}
|
||||||
|
onMoneyOutClick={handleMoneyOutClick}
|
||||||
/>
|
/>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</CashflowBankAccountWrap>
|
</CashflowBankAccountWrap>
|
||||||
@@ -144,6 +161,19 @@ function CashflowAccountsGridItems({ accounts }) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cashflow accounts empty state.
|
||||||
|
*/
|
||||||
|
function CashflowAccountsEmptyState() {
|
||||||
|
return (
|
||||||
|
<AccountsEmptyStateBase>
|
||||||
|
<AccountsEmptyStateTitle>
|
||||||
|
There is no cashflow accounts with current filter criteria.
|
||||||
|
</AccountsEmptyStateTitle>
|
||||||
|
</AccountsEmptyStateBase>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cashflow accounts grid.
|
* Cashflow accounts grid.
|
||||||
*/
|
*/
|
||||||
@@ -157,6 +187,8 @@ export default function CashflowAccountsGrid() {
|
|||||||
<BankAccountsList>
|
<BankAccountsList>
|
||||||
{isCashFlowAccountsLoading ? (
|
{isCashFlowAccountsLoading ? (
|
||||||
<CashflowAccountsSkeleton />
|
<CashflowAccountsSkeleton />
|
||||||
|
) : isEmpty(cashflowAccounts) ? (
|
||||||
|
<CashflowAccountsEmptyState />
|
||||||
) : (
|
) : (
|
||||||
<CashflowAccountsGridItems accounts={cashflowAccounts} />
|
<CashflowAccountsGridItems accounts={cashflowAccounts} />
|
||||||
)}
|
)}
|
||||||
@@ -167,6 +199,32 @@ export default function CashflowAccountsGrid() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cashflow account money out context menu.
|
||||||
|
*/
|
||||||
|
function CashflowAccountMoneyInContextMenu({ onClick }) {
|
||||||
|
const handleItemClick = curry((transactionType, event) => {
|
||||||
|
onClick && onClick(transactionType, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
return addMoneyIn.map((option) => (
|
||||||
|
<MenuItem text={option.name} onClick={handleItemClick(option.value)} />
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cashflow account money in context menu.
|
||||||
|
*/
|
||||||
|
function CashflowAccountMoneyOutContextMenu({ onClick }) {
|
||||||
|
const handleItemClick = curry((transactionType, event) => {
|
||||||
|
onClick && onClick(transactionType, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
return addMoneyOut.map((option) => (
|
||||||
|
<MenuItem text={option.name} onClick={handleItemClick(option.value)} />
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cashflow account context menu.
|
* Cashflow account context menu.
|
||||||
*/
|
*/
|
||||||
@@ -176,6 +234,8 @@ function CashflowAccountContextMenu({
|
|||||||
onInactivateClick,
|
onInactivateClick,
|
||||||
onActivateClick,
|
onActivateClick,
|
||||||
onDeleteClick,
|
onDeleteClick,
|
||||||
|
onMoneyInClick,
|
||||||
|
onMoneyOutClick,
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Menu>
|
<Menu>
|
||||||
@@ -185,6 +245,21 @@ function CashflowAccountContextMenu({
|
|||||||
onClick={safeCallback(onViewClick)}
|
onClick={safeCallback(onViewClick)}
|
||||||
/>
|
/>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
|
<MenuItem
|
||||||
|
text={'Money In'}
|
||||||
|
icon={<Icon icon={'arrow-downward'} iconSize={16} />}
|
||||||
|
>
|
||||||
|
<CashflowAccountMoneyInContextMenu onClick={onMoneyInClick} />
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
text={'Money Out'}
|
||||||
|
icon={<Icon icon={'arrow-upward'} iconSize={16} />}
|
||||||
|
>
|
||||||
|
<CashflowAccountMoneyOutContextMenu onClick={onMoneyOutClick} />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuDivider />
|
||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<Icon icon="pen-18" />}
|
icon={<Icon icon="pen-18" />}
|
||||||
text={intl.get('edit_account')}
|
text={intl.get('edit_account')}
|
||||||
@@ -230,3 +305,16 @@ const CashflowAccountsGridWrap = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const CashflowBankAccountWrap = styled.div``;
|
const CashflowBankAccountWrap = styled.div``;
|
||||||
|
|
||||||
|
const AccountsEmptyStateBase = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
margin: 2rem 0;
|
||||||
|
`;
|
||||||
|
const AccountsEmptyStateTitle = styled.h1`
|
||||||
|
font-size: 16px;
|
||||||
|
color: #626b76;
|
||||||
|
opacity: 0.8;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-weight: 500;
|
||||||
|
`;
|
||||||
|
|||||||
11
src/containers/CashFlow/CashFlowAccounts/utils.js
Normal file
11
src/containers/CashFlow/CashFlowAccounts/utils.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { transformTableStateToQuery } from 'utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes the table state to list query.
|
||||||
|
*/
|
||||||
|
export const transformAccountsStateToQuery = (tableState) => {
|
||||||
|
return {
|
||||||
|
...transformTableStateToQuery(tableState),
|
||||||
|
inactive_mode: tableState.inactiveMode,
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/store/CashflowAccounts/CashflowAccounts.actions.js
Normal file
21
src/store/CashflowAccounts/CashflowAccounts.actions.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cashflow accounts table state.
|
||||||
|
*/
|
||||||
|
export const setCashflowAccountsTableState = (queries) => {
|
||||||
|
return {
|
||||||
|
type: t.CASHFLOW_ACCOUNTS_TABLE_STATE_SET,
|
||||||
|
payload: { queries },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the cashflow accounts table state.
|
||||||
|
*/
|
||||||
|
export const resetCashflowAccountsTableState = () => {
|
||||||
|
return {
|
||||||
|
type: t.CASHFLOW_ACCOUNTS_TABLE_STATE_RESET,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
31
src/store/CashflowAccounts/CashflowAccounts.reducer.js
Normal file
31
src/store/CashflowAccounts/CashflowAccounts.reducer.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
|
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||||
|
import storage from 'redux-persist/lib/storage';
|
||||||
|
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
|
export const defaultTableQuery = {
|
||||||
|
filterRoles: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
tableState: defaultTableQuery,
|
||||||
|
};
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'bigcapital:cashflow_accounts';
|
||||||
|
|
||||||
|
const CONFIG = {
|
||||||
|
key: STORAGE_KEY,
|
||||||
|
whitelist: [],
|
||||||
|
storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducerInstance = createReducer(initialState, {
|
||||||
|
...createTableStateReducers('CASHFLOW_ACCOUNTS', defaultTableQuery),
|
||||||
|
|
||||||
|
[t.RESET]: () => {
|
||||||
|
purgeStoredState(CONFIG);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default persistReducer(CONFIG, reducerInstance);
|
||||||
19
src/store/CashflowAccounts/CashflowAccounts.selectors.js
Normal file
19
src/store/CashflowAccounts/CashflowAccounts.selectors.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { paginationLocationQuery } from 'store/selectors';
|
||||||
|
import { createDeepEqualSelector } from 'utils';
|
||||||
|
|
||||||
|
// Accounts table state selector
|
||||||
|
const cashflowAccountsTableStateSelector = (state, props) =>
|
||||||
|
state.cashflowAccounts.tableState;
|
||||||
|
|
||||||
|
// Get accounts table state marged with location query.
|
||||||
|
export const getCashflowAccountsTableStateFactory = () =>
|
||||||
|
createDeepEqualSelector(
|
||||||
|
paginationLocationQuery,
|
||||||
|
cashflowAccountsTableStateSelector,
|
||||||
|
(locationQuery, tableState) => {
|
||||||
|
return {
|
||||||
|
...locationQuery,
|
||||||
|
...tableState,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
5
src/store/CashflowAccounts/CashflowAccounts.types.js
Normal file
5
src/store/CashflowAccounts/CashflowAccounts.types.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
export default {
|
||||||
|
CASHFLOW_ACCOUNTS_TABLE_STATE_SET: 'CASHFLOW_ACCOUNTS/TABLE_STATE_SET',
|
||||||
|
CASHFLOW_ACCOUNTS_TABLE_STATE_RESET: 'CASHFLOW_ACCOUNTS/TABLE_STATE_RESET',
|
||||||
|
};
|
||||||
@@ -6,6 +6,7 @@ import authentication from './authentication/authentication.reducer';
|
|||||||
import dashboard from './dashboard/dashboard.reducer';
|
import dashboard from './dashboard/dashboard.reducer';
|
||||||
import users from './users/users.reducer';
|
import users from './users/users.reducer';
|
||||||
import accounts from './accounts/accounts.reducer';
|
import accounts from './accounts/accounts.reducer';
|
||||||
|
import cashflowAccounts from './CashflowAccounts/CashflowAccounts.reducer';
|
||||||
import fields from './customFields/customFields.reducer';
|
import fields from './customFields/customFields.reducer';
|
||||||
import items from './items/items.reducer';
|
import items from './items/items.reducer';
|
||||||
import views from './customViews/customViews.reducer';
|
import views from './customViews/customViews.reducer';
|
||||||
@@ -39,6 +40,7 @@ const appReducer = combineReducers({
|
|||||||
dashboard,
|
dashboard,
|
||||||
users,
|
users,
|
||||||
accounts,
|
accounts,
|
||||||
|
cashflowAccounts,
|
||||||
manualJournals,
|
manualJournals,
|
||||||
fields,
|
fields,
|
||||||
views,
|
views,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import authentication from './authentication/authentication.types';
|
import authentication from './authentication/authentication.types';
|
||||||
import accounts from './accounts/accounts.types';
|
import accounts from './accounts/accounts.types';
|
||||||
|
import cashflowAccounts from './CashflowAccounts/CashflowAccounts.types';
|
||||||
import accounting from './manualJournals/manualJournals.types';
|
import accounting from './manualJournals/manualJournals.types';
|
||||||
import currencies from './currencies/currencies.types';
|
import currencies from './currencies/currencies.types';
|
||||||
import customFields from './customFields/customFields.types';
|
import customFields from './customFields/customFields.types';
|
||||||
@@ -32,6 +33,7 @@ import plans from './plans/plans.types';
|
|||||||
export default {
|
export default {
|
||||||
...authentication,
|
...authentication,
|
||||||
...accounts,
|
...accounts,
|
||||||
|
...cashflowAccounts,
|
||||||
...currencies,
|
...currencies,
|
||||||
...customFields,
|
...customFields,
|
||||||
...customViews,
|
...customViews,
|
||||||
|
|||||||
@@ -3,14 +3,6 @@
|
|||||||
.bigcapital-datatable {
|
.bigcapital-datatable {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
.dashboard__page-content & {
|
|
||||||
.table .thead {
|
|
||||||
.th {
|
|
||||||
border-bottom-color: #d2dde2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
@@ -19,8 +11,6 @@
|
|||||||
|
|
||||||
.thead {
|
.thead {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
// overflow-y: auto;
|
|
||||||
// overflow-x: hidden;
|
|
||||||
|
|
||||||
.th {
|
.th {
|
||||||
padding: 0.7rem 0.5rem;
|
padding: 0.7rem 0.5rem;
|
||||||
@@ -28,7 +18,7 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #3b495d;
|
color: #3b495d;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-bottom: 1px solid rgb(224, 224, 224);
|
border-bottom: 1px solid #d2dde2;
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
Reference in New Issue
Block a user