mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
WIP / Fix_ExchangeRate / localize
This commit is contained in:
@@ -21,14 +21,19 @@ import MediaConnect from 'connectors/Media.connect';
|
||||
import useMedia from 'hooks/useMedia';
|
||||
import {compose} from 'utils';
|
||||
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
|
||||
function MakeJournalEntriesForm({
|
||||
// #withMedia
|
||||
requestSubmitMedia,
|
||||
requestDeleteMedia,
|
||||
|
||||
// #withJournalsActions
|
||||
requestMakeJournalEntries,
|
||||
requestEditManualJournal,
|
||||
|
||||
// #withDashboard
|
||||
changePageTitle,
|
||||
changePageSubtitle,
|
||||
|
||||
@@ -47,13 +52,14 @@ function MakeJournalEntriesForm({
|
||||
|
||||
const savedMediaIds = useRef([]);
|
||||
const clearSavedMediaIds = () => { savedMediaIds.current = []; }
|
||||
const {formatMessage} =useIntl()
|
||||
|
||||
useEffect(() => {
|
||||
if (manualJournal && manualJournal.id) {
|
||||
changePageTitle('Edit Journal');
|
||||
changePageTitle(formatMessage({id:'edit_journal'}));
|
||||
changePageSubtitle(`No. ${manualJournal.journal_number}`);
|
||||
} else {
|
||||
changePageTitle('New Journal');
|
||||
changePageTitle(formatMessage({id:'new_journal'}));
|
||||
}
|
||||
}, [changePageTitle, changePageSubtitle, manualJournal]);
|
||||
|
||||
@@ -252,8 +258,6 @@ function MakeJournalEntriesForm({
|
||||
}
|
||||
|
||||
export default compose(
|
||||
// ManualJournalsConnect,
|
||||
// MakeJournalEntriesConnect,
|
||||
withJournalsActions,
|
||||
withManualJournalDetail,
|
||||
withAccountsActions,
|
||||
|
||||
@@ -22,22 +22,24 @@ import { compose } from 'utils';
|
||||
* Manual journals table.
|
||||
*/
|
||||
function ManualJournalsTable({
|
||||
// #withDashboardActions
|
||||
changePageTitle,
|
||||
|
||||
// #withViewsActions
|
||||
requestFetchResourceViews,
|
||||
|
||||
// #withManualJournalsActions
|
||||
requestFetchManualJournalsTable,
|
||||
requestDeleteManualJournal,
|
||||
requestPublishManualJournal,
|
||||
requestDeleteBulkManualJournals,
|
||||
|
||||
addManualJournalsTableQueries,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const [deleteManualJournal, setDeleteManualJournal] = useState(false);
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
const [bulkDelete, setBulkDelete] = useState(false);
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
const fetchViews = useQuery('journals-resource-views', () => {
|
||||
return requestFetchResourceViews('manual_journals');
|
||||
});
|
||||
@@ -47,7 +49,7 @@ function ManualJournalsTable({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle('Manual Journals');
|
||||
changePageTitle(formatMessage({id:'manual_journals'}));
|
||||
}, [changePageTitle]);
|
||||
|
||||
// Handle delete manual journal click.
|
||||
@@ -163,9 +165,7 @@ function ManualJournalsTable({
|
||||
'/dashboard/accounting/manual-journals/:custom_view_id/custom_view',
|
||||
'/dashboard/accounting/manual-journals',
|
||||
]}
|
||||
>
|
||||
<ManualJournalsViewTabs onViewChanged={handleViewChanged} />
|
||||
</Route>
|
||||
></Route>
|
||||
</Switch>
|
||||
|
||||
<ManualJournalsDataTable
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import {
|
||||
Route,
|
||||
Switch,
|
||||
} from 'react-router-dom';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import { Alert, Intent } from '@blueprintjs/core';
|
||||
import { useQuery } from 'react-query'
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
import AppToaster from 'components/AppToaster';
|
||||
|
||||
@@ -26,7 +23,6 @@ import { compose } from 'utils';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
function AccountsChart({
|
||||
|
||||
// #withDashboard
|
||||
changePageTitle,
|
||||
|
||||
@@ -54,7 +50,7 @@ function AccountsChart({
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
|
||||
const [tableLoading, setTableLoading] = useState(false);
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
// Fetch accounts resource views and fields.
|
||||
const fetchHook = useQuery('resource-accounts', () => {
|
||||
return Promise.all([
|
||||
@@ -64,38 +60,49 @@ function AccountsChart({
|
||||
});
|
||||
|
||||
// Fetch accounts list according to the given custom view id.
|
||||
const fetchAccountsHook = useQuery(['accounts-table', accountsTableQuery],
|
||||
() => requestFetchAccountsTable());
|
||||
const fetchAccountsHook = useQuery(
|
||||
['accounts-table', accountsTableQuery],
|
||||
() => requestFetchAccountsTable(),
|
||||
{ refetchInterval: 3000 }
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle('Chart of Accounts');
|
||||
changePageTitle(formatMessage({ id: 'chart_of_accounts' }));
|
||||
}, [changePageTitle]);
|
||||
|
||||
|
||||
// Handle click and cancel/confirm account delete
|
||||
const handleDeleteAccount = (account) => { setDeleteAccount(account); };
|
||||
|
||||
const handleDeleteAccount = (account) => {
|
||||
setDeleteAccount(account);
|
||||
};
|
||||
|
||||
// handle cancel delete account alert.
|
||||
const handleCancelAccountDelete = useCallback(() => { setDeleteAccount(false); }, []);
|
||||
|
||||
const handleCancelAccountDelete = useCallback(() => {
|
||||
setDeleteAccount(false);
|
||||
}, []);
|
||||
|
||||
// Handle confirm account delete
|
||||
const handleConfirmAccountDelete = useCallback(() => {
|
||||
requestDeleteAccount(deleteAccount.id).then(() => {
|
||||
setDeleteAccount(false);
|
||||
AppToaster.show({ message: 'the_account_has_been_deleted' });
|
||||
}).catch(errors => {
|
||||
setDeleteAccount(false);
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.PREDEFINED')) {
|
||||
AppToaster.show({
|
||||
message: 'cannot_delete_predefined_account',
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
}
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS')) {
|
||||
AppToaster.show({
|
||||
message: 'cannot_delete_account_has_associated_transactions'
|
||||
});
|
||||
}
|
||||
});
|
||||
requestDeleteAccount(deleteAccount.id)
|
||||
.then(() => {
|
||||
setDeleteAccount(false);
|
||||
AppToaster.show({ message: 'the_account_has_been_deleted' });
|
||||
})
|
||||
.catch((errors) => {
|
||||
setDeleteAccount(false);
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.PREDEFINED')) {
|
||||
AppToaster.show({
|
||||
message: 'cannot_delete_predefined_account',
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
}
|
||||
if (
|
||||
errors.find((e) => e.type === 'ACCOUNT.HAS.ASSOCIATED.TRANSACTIONS')
|
||||
) {
|
||||
AppToaster.show({
|
||||
message: 'cannot_delete_account_has_associated_transactions',
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [deleteAccount, requestDeleteAccount]);
|
||||
|
||||
// Handle cancel/confirm account inactive.
|
||||
@@ -117,43 +124,44 @@ function AccountsChart({
|
||||
});
|
||||
}, [inactiveAccount, requestFetchAccountsTable, requestInactiveAccount]);
|
||||
|
||||
const handleEditAccount = (account) => {};
|
||||
|
||||
const handleEditAccount = (account) => {
|
||||
const handleRestoreAccount = (account) => {};
|
||||
|
||||
};
|
||||
|
||||
const handleRestoreAccount = (account) => {
|
||||
|
||||
};
|
||||
|
||||
const handleBulkDelete = useCallback((accountsIds) => {
|
||||
setBulkDelete(accountsIds);
|
||||
}, [setBulkDelete]);
|
||||
const handleBulkDelete = useCallback(
|
||||
(accountsIds) => {
|
||||
setBulkDelete(accountsIds);
|
||||
},
|
||||
[setBulkDelete]
|
||||
);
|
||||
|
||||
const handleConfirmBulkDelete = useCallback(() => {
|
||||
requestDeleteBulkAccounts(bulkDelete).then(() => {
|
||||
setBulkDelete(false);
|
||||
AppToaster.show({ message: 'the_accounts_have_been_deleted' });
|
||||
}).catch((error) => {
|
||||
setBulkDelete(false);
|
||||
});
|
||||
requestDeleteBulkAccounts(bulkDelete)
|
||||
.then(() => {
|
||||
setBulkDelete(false);
|
||||
AppToaster.show({ message: 'the_accounts_have_been_deleted' });
|
||||
})
|
||||
.catch((error) => {
|
||||
setBulkDelete(false);
|
||||
});
|
||||
}, [requestDeleteBulkAccounts, bulkDelete]);
|
||||
|
||||
const handleCancelBulkDelete = useCallback(() => {
|
||||
setBulkDelete(false);
|
||||
}, []);
|
||||
|
||||
const handleBulkArchive = useCallback((accounts) => {
|
||||
|
||||
}, []);
|
||||
const handleBulkArchive = useCallback((accounts) => {}, []);
|
||||
|
||||
// Handle selected rows change.
|
||||
const handleSelectedRowsChange = useCallback((accounts) => {
|
||||
setSelectedRows(accounts);
|
||||
}, [setSelectedRows]);
|
||||
const handleSelectedRowsChange = useCallback(
|
||||
(accounts) => {
|
||||
setSelectedRows(accounts);
|
||||
},
|
||||
[setSelectedRows]
|
||||
);
|
||||
|
||||
// Refetches accounts data table when current custom view changed.
|
||||
const handleFilterChanged = useCallback(() => {
|
||||
const handleFilterChanged = useCallback(() => {
|
||||
fetchAccountsHook.refetch();
|
||||
}, [fetchAccountsHook]);
|
||||
|
||||
@@ -169,25 +177,29 @@ function AccountsChart({
|
||||
}, [tableLoading, fetchAccountsHook.isFetching]);
|
||||
|
||||
// Handle fetch data of accounts datatable.
|
||||
const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
|
||||
addAccountsTableQueries({
|
||||
...(sortBy.length > 0) ? {
|
||||
column_sort_by: sortBy[0].id,
|
||||
sort_order: sortBy[0].desc ? 'desc' : 'asc',
|
||||
} : {},
|
||||
});
|
||||
fetchAccountsHook.refetch();
|
||||
}, [fetchAccountsHook, addAccountsTableQueries]);
|
||||
const handleFetchData = useCallback(
|
||||
({ pageIndex, pageSize, sortBy }) => {
|
||||
addAccountsTableQueries({
|
||||
...(sortBy.length > 0
|
||||
? {
|
||||
column_sort_by: sortBy[0].id,
|
||||
sort_order: sortBy[0].desc ? 'desc' : 'asc',
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
fetchAccountsHook.refetch();
|
||||
},
|
||||
[fetchAccountsHook, addAccountsTableQueries]
|
||||
);
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={fetchHook.isFetching}
|
||||
name={'accounts-chart'}>
|
||||
<DashboardInsider loading={fetchHook.isFetching} name={'accounts-chart'}>
|
||||
<DashboardActionsBar
|
||||
selectedRows={selectedRows}
|
||||
onFilterChanged={handleFilterChanged}
|
||||
onBulkDelete={handleBulkDelete}
|
||||
onBulkArchive={handleBulkArchive} />
|
||||
onBulkArchive={handleBulkArchive}
|
||||
/>
|
||||
|
||||
<DashboardPageContent>
|
||||
<Switch>
|
||||
@@ -196,9 +208,9 @@ function AccountsChart({
|
||||
path={[
|
||||
'/dashboard/accounts/:custom_view_id/custom_view',
|
||||
'/dashboard/accounts',
|
||||
]}>
|
||||
<AccountsViewsTabs
|
||||
onViewChanged={handleViewChanged} />
|
||||
]}
|
||||
>
|
||||
<AccountsViewsTabs onViewChanged={handleViewChanged} />
|
||||
|
||||
<AccountsDataTable
|
||||
onDeleteAccount={handleDeleteAccount}
|
||||
@@ -207,49 +219,53 @@ function AccountsChart({
|
||||
onEditAccount={handleEditAccount}
|
||||
onFetchData={handleFetchData}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
loading={tableLoading} />
|
||||
loading={tableLoading}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
|
||||
<Alert
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText="Move to Trash"
|
||||
icon="trash"
|
||||
cancelButtonText='Cancel'
|
||||
confirmButtonText='Move to Trash'
|
||||
icon='trash'
|
||||
intent={Intent.DANGER}
|
||||
isOpen={deleteAccount}
|
||||
onCancel={handleCancelAccountDelete}
|
||||
onConfirm={handleConfirmAccountDelete}>
|
||||
onConfirm={handleConfirmAccountDelete}
|
||||
>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be
|
||||
able to restore it later, but it will become private to you.
|
||||
</p>
|
||||
</Alert>
|
||||
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'}/>}
|
||||
confirmButtonText={<T id={'inactivate'}/>}
|
||||
icon="trash"
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'inactivate'} />}
|
||||
icon='trash'
|
||||
intent={Intent.WARNING}
|
||||
isOpen={inactiveAccount}
|
||||
onCancel={handleCancelInactiveAccount}
|
||||
onConfirm={handleConfirmAccountActive}>
|
||||
onConfirm={handleConfirmAccountActive}
|
||||
>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be
|
||||
able to restore it later, but it will become private to you.
|
||||
</p>
|
||||
</Alert>
|
||||
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'}/>}
|
||||
confirmButtonText={<T id={'delete'}/>}
|
||||
icon="trash"
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'delete'} />}
|
||||
icon='trash'
|
||||
intent={Intent.DANGER}
|
||||
isOpen={bulkDelete}
|
||||
onCancel={handleCancelBulkDelete}
|
||||
onConfirm={handleConfirmBulkDelete}>
|
||||
onConfirm={handleConfirmBulkDelete}
|
||||
>
|
||||
<p>
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be able to restore it later,
|
||||
but it will become private to you.
|
||||
Are you sure you want to move <b>filename</b> to Trash? You will be
|
||||
able to restore it later, but it will become private to you.
|
||||
</p>
|
||||
</Alert>
|
||||
</DashboardPageContent>
|
||||
@@ -263,6 +279,7 @@ export default compose(
|
||||
withViewsActions,
|
||||
withResourceActions,
|
||||
withDashboardActions,
|
||||
|
||||
withAccounts,
|
||||
)(AccountsChart);
|
||||
withAccounts(({ accountsTableQuery }) => ({
|
||||
accountsTableQuery,
|
||||
}))
|
||||
)(AccountsChart);
|
||||
|
||||
@@ -21,16 +21,15 @@ import withDashboardActions from 'containers/Dashboard/withDashboard';
|
||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||
import withAccounts from 'containers/Accounts/withAccounts';
|
||||
|
||||
import {If} from 'components';
|
||||
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
function AccountsDataTable({
|
||||
// # withAccounts
|
||||
// #withAccounts
|
||||
accounts,
|
||||
accountsLoading,
|
||||
|
||||
// # withDialog.
|
||||
// #withDialog.
|
||||
openDialog,
|
||||
|
||||
// own properties
|
||||
@@ -58,7 +57,7 @@ function AccountsDataTable({
|
||||
|
||||
const actionMenuList = useCallback((account) => (
|
||||
<Menu>
|
||||
<MenuItem text='View Details' />
|
||||
<MenuItem text={<T id={'view_details'}/>} />
|
||||
<MenuDivider />
|
||||
<MenuItem
|
||||
text={<T id={'edit_account'}/>}
|
||||
@@ -166,9 +165,6 @@ function AccountsDataTable({
|
||||
|
||||
return (
|
||||
<LoadingIndicator loading={loading} mount={false}>
|
||||
<If condition={loading}>
|
||||
asdasdsadsa
|
||||
</If>
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
@@ -189,5 +185,8 @@ export default compose(
|
||||
DialogConnect,
|
||||
withDashboardActions,
|
||||
withAccountsActions,
|
||||
withAccounts,
|
||||
withAccounts(({ accountsLoading, accounts }) => ({
|
||||
accountsLoading,
|
||||
accounts,
|
||||
})),
|
||||
)(AccountsDataTable);
|
||||
|
||||
@@ -13,32 +13,36 @@ import * as Yup from 'yup';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import { useFormik } from 'formik';
|
||||
import Dialog from 'components/Dialog';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
|
||||
import { useQuery, queryCache } from 'react-query';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
import ErrorMessage from 'components/ErrorMessage';
|
||||
import classNames from 'classnames';
|
||||
import { Select } from '@blueprintjs/select';
|
||||
import moment from 'moment';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { momentFormatter } from 'utils';
|
||||
import ExchangeRatesDialogConnect from 'connectors/ExchangeRatesFromDialog.connect';
|
||||
|
||||
import CurrencyFromDialogConnect from 'connectors/CurrencyFromDialog.connect'
|
||||
import withExchangeRatesDialog from 'containers/FinancialStatements/ExchangeRates/withExchangeRateDialog';
|
||||
import withExchangeRate from 'containers/FinancialStatements/ExchangeRates/withExchangeRates'
|
||||
|
||||
function ExchangeRateDialog({
|
||||
name,
|
||||
payload,
|
||||
isOpen,
|
||||
|
||||
openDialog,
|
||||
// #withDialog
|
||||
|
||||
closeDialog,
|
||||
currencies,
|
||||
|
||||
// #withExchangeRatesActions
|
||||
requestSubmitExchangeRate,
|
||||
requestFetchExchangeRates,
|
||||
requestEditExchangeRate,
|
||||
requestFetchCurrencies,
|
||||
editExchangeRate,
|
||||
addExchangeRatesTableQueries,
|
||||
|
||||
}) {
|
||||
const {formatMessage} = useIntl();
|
||||
|
||||
@@ -107,9 +111,14 @@ function ExchangeRateDialog({
|
||||
closeDialog(name);
|
||||
}, [name, closeDialog]);
|
||||
|
||||
const fetchHook = useQuery('exchange-rates-dialog', () => {
|
||||
return Promise.all([requestFetchExchangeRates(), requestFetchCurrencies()]);
|
||||
});
|
||||
// const fetchHook = useQuery('exchange-rates-dialog', () => {
|
||||
// return Promise.all([requestFetchExchangeRates(), requestFetchCurrencies()]);
|
||||
// });
|
||||
|
||||
const fetchExchangeRatesDialog = useQuery('exchange-rates-dialog',
|
||||
() => requestFetchExchangeRates(),
|
||||
{ refetchInterval: 3000 });
|
||||
|
||||
|
||||
const onDialogClosed = useCallback(() => {
|
||||
formik.resetForm();
|
||||
@@ -117,8 +126,8 @@ function ExchangeRateDialog({
|
||||
}, [formik, closeDialog, name]);
|
||||
|
||||
const onDialogOpening = useCallback(() => {
|
||||
fetchHook.refetch();
|
||||
}, [fetchHook]);
|
||||
fetchExchangeRatesDialog.refetch();
|
||||
}, [fetchExchangeRatesDialog]);
|
||||
|
||||
const handleDateChange = useCallback(
|
||||
(date) => {
|
||||
@@ -185,14 +194,14 @@ function ExchangeRateDialog({
|
||||
}
|
||||
className={classNames(
|
||||
{
|
||||
'dialog--loading': fetchHook.pending,
|
||||
'dialog--loading': fetchExchangeRatesDialog.pending,
|
||||
},
|
||||
'dialog--exchangeRate-form'
|
||||
)}
|
||||
isOpen={isOpen}
|
||||
onClosed={onDialogClosed}
|
||||
onOpening={onDialogOpening}
|
||||
isLoading={fetchHook.pending}
|
||||
isLoading={fetchExchangeRatesDialog.pending}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
@@ -279,4 +288,4 @@ function ExchangeRateDialog({
|
||||
);
|
||||
}
|
||||
|
||||
export default ExchangeRatesDialogConnect(ExchangeRateDialog);
|
||||
export default withExchangeRatesDialog(ExchangeRateDialog);
|
||||
|
||||
@@ -4,6 +4,7 @@ import {useParams} from 'react-router-dom';
|
||||
import Connector from 'connectors/ExpenseForm.connector';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import ExpenseForm from 'components/Expenses/ExpenseForm';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
function ExpenseFormContainer({
|
||||
fetchAccounts,
|
||||
@@ -15,12 +16,12 @@ function ExpenseFormContainer({
|
||||
currencies,
|
||||
}) {
|
||||
const { id } = useParams();
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
changePageTitle('Edit Expense Details');
|
||||
changePageTitle(formatMessage({id:'edit_expense_details'}));
|
||||
} else {
|
||||
changePageTitle('New Expense');
|
||||
changePageTitle(formatMessage({id:'new_expense'}));
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@ function ExpensesList({
|
||||
getResourceViews,
|
||||
changePageTitle
|
||||
}) {
|
||||
const {formatMessage} =useIntl()
|
||||
useEffect(() => {
|
||||
changePageTitle('Expenses List');
|
||||
changePageTitle(formatMessage({id:'expenses_list'}));
|
||||
}, []);
|
||||
|
||||
const [deleteExpenseState, setDeleteExpense] = useState();
|
||||
|
||||
@@ -18,9 +18,12 @@ import { compose } from 'utils';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
function ExchangeRate({
|
||||
views,
|
||||
// #withDashboard
|
||||
changePageTitle,
|
||||
|
||||
//#withExchangeRatesActions
|
||||
requestFetchResourceFields,
|
||||
|
||||
requestFetchExchangeRates,
|
||||
requestDeleteExchangeRate,
|
||||
addExchangeRatesTableQueries,
|
||||
@@ -28,15 +31,21 @@ function ExchangeRate({
|
||||
const { id } = useParams();
|
||||
const [deleteExchangeRate, setDeleteExchangeRate] = useState(false);
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
// const fetchExchangeRates = useQuery('exchange-rates-table', () => {
|
||||
// return Promise.all([requestFetchExchangeRates()]);
|
||||
// });
|
||||
|
||||
const fetchExchangeRates = useQuery('exchange-rates-table',
|
||||
() => requestFetchExchangeRates(),
|
||||
{ refetchInterval: 3000 });
|
||||
|
||||
const fetchHook = useQuery('exchange-rates', () => {
|
||||
return Promise.all([requestFetchExchangeRates()]);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
id
|
||||
? changePageTitle('Exchange Rate Details')
|
||||
: changePageTitle('Exchange Rate List');
|
||||
? changePageTitle(formatMessage({id:'exchange_rate_details'}))
|
||||
: changePageTitle(formatMessage({id:'exchange_rate_list'}));
|
||||
}, [id, changePageTitle]);
|
||||
|
||||
const handelDeleteExchangeRate = useCallback(
|
||||
@@ -84,9 +93,8 @@ function ExchangeRate({
|
||||
);
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={fetchHook.pending}>
|
||||
<DashboardInsider>
|
||||
<ExchangeRateActionsBar
|
||||
views={views}
|
||||
onDeleteExchangeRate={handelDeleteExchangeRate}
|
||||
selectedRows={selectedRows}
|
||||
/>
|
||||
@@ -98,8 +106,8 @@ function ExchangeRate({
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
/>
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'}/>}
|
||||
confirmButtonText={<T id={'move_to_trash'}/>}
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'move_to_trash'} />}
|
||||
icon='trash'
|
||||
intent={Intent.DANGER}
|
||||
isOpen={deleteExchangeRate}
|
||||
@@ -118,5 +126,6 @@ function ExchangeRate({
|
||||
|
||||
export default compose(
|
||||
withExchangeRatesActions,
|
||||
withResourceActions,
|
||||
withDashboardActions
|
||||
)(ExchangeRate);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import React, { useCallback, useState, useMemo } from 'react';
|
||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
import { compose } from 'utils';
|
||||
import {
|
||||
NavbarGroup,
|
||||
Button,
|
||||
@@ -10,37 +8,39 @@ import {
|
||||
Position,
|
||||
PopoverInteractionKind,
|
||||
} from '@blueprintjs/core';
|
||||
import { connect } from 'react-redux';
|
||||
import classNames from 'classnames';
|
||||
import Icon from 'components/Icon';
|
||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
import DialogConnect from 'connectors/Dialog.connector';
|
||||
|
||||
import FilterDropdown from 'components/FilterDropdown';
|
||||
import ExchangeRatesDialogConnect from 'connectors/ExchangeRatesFromDialog.connect';
|
||||
|
||||
import withResourceDetail from 'containers/Resources/withResourceDetails';
|
||||
import withExchangeRates from 'containers/FinancialStatements/ExchangeRates/withExchangeRates';
|
||||
import withExchangeRatesActions from 'containers/FinancialStatements/ExchangeRates/withExchangeRatesActions';
|
||||
import withExchangeRateDialog from 'containers/FinancialStatements/ExchangeRates/withExchangeRateDialog';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
|
||||
function ExchangeRateActionsBar({
|
||||
// #withDialog.
|
||||
openDialog,
|
||||
|
||||
// #withResourceDetail
|
||||
resourceFields,
|
||||
|
||||
selectedRows = [],
|
||||
onDeleteExchangeRate,
|
||||
onFilterChanged,
|
||||
resourceFields,
|
||||
selectedRows = [],
|
||||
}) {
|
||||
const onClickNewExchangeRate = useCallback(() => {
|
||||
openDialog('exchangeRate-form', {});
|
||||
}, [openDialog]);
|
||||
|
||||
const handelDeleteExchangeRate = useCallback(
|
||||
(exchangeRate) => {
|
||||
onDeleteExchangeRate(exchangeRate);
|
||||
},
|
||||
[selectedRows, onDeleteExchangeRate]
|
||||
);
|
||||
const [filterCount, setFilterCount] = useState(0);
|
||||
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [
|
||||
selectedRows,
|
||||
]);
|
||||
|
||||
const onClickNewExchangeRate = () => {
|
||||
openDialog('exchangeRate-form', {});
|
||||
};
|
||||
|
||||
const filterDropdown = FilterDropdown({
|
||||
fields: resourceFields,
|
||||
@@ -51,13 +51,24 @@ function ExchangeRateActionsBar({
|
||||
},
|
||||
});
|
||||
|
||||
const handelDeleteExchangeRate = useCallback(
|
||||
(exchangeRate) => {
|
||||
onDeleteExchangeRate(exchangeRate);
|
||||
},
|
||||
[selectedRows, onDeleteExchangeRate]
|
||||
);
|
||||
|
||||
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [
|
||||
selectedRows,
|
||||
]);
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<NavbarGroup>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon='plus' />}
|
||||
text={<T id={'new_exchange_rate'}/>}
|
||||
text={<T id={'new_exchange_rate'} />}
|
||||
onClick={onClickNewExchangeRate}
|
||||
/>
|
||||
<Popover
|
||||
@@ -69,7 +80,11 @@ function ExchangeRateActionsBar({
|
||||
<Button
|
||||
className={classNames(Classes.MINIMAL, 'button--filter')}
|
||||
text={
|
||||
filterCount <= 0 ? <T id={'filter'}/> : `${filterCount} filters applied`
|
||||
filterCount <= 0 ? (
|
||||
<T id={'filter'} />
|
||||
) : (
|
||||
`${filterCount} filters applied`
|
||||
)
|
||||
}
|
||||
icon={<Icon icon='filter' />}
|
||||
/>
|
||||
@@ -78,7 +93,7 @@ function ExchangeRateActionsBar({
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon='trash' iconSize={15} />}
|
||||
text={<T id={'delete'}/>}
|
||||
text={<T id={'delete'} />}
|
||||
intent={Intent.DANGER}
|
||||
onClick={handelDeleteExchangeRate}
|
||||
/>
|
||||
@@ -86,12 +101,12 @@ function ExchangeRateActionsBar({
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon='file-import' />}
|
||||
text={<T id={'import'}/>}
|
||||
text={<T id={'import'} />}
|
||||
/>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon='file-export' />}
|
||||
text={<T id={'export'}/>}
|
||||
text={<T id={'export'} />}
|
||||
/>
|
||||
</NavbarGroup>
|
||||
</DashboardActionsBar>
|
||||
@@ -106,7 +121,8 @@ const withExchangeRateActionBar = connect(mapStateToProps);
|
||||
|
||||
export default compose(
|
||||
withExchangeRateActionBar,
|
||||
DashboardConnect,
|
||||
ExchangeRatesDialogConnect,
|
||||
withResourceDetail
|
||||
DialogConnect,
|
||||
withResourceDetail(({ resourceFields }) => ({
|
||||
resourceFields,
|
||||
}))
|
||||
)(ExchangeRateActionsBar);
|
||||
|
||||
@@ -1,41 +1,40 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo,useState } from 'react';
|
||||
import Icon from 'components/Icon';
|
||||
import DialogConnect from 'connectors/Dialog.connector';
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import DataTable from 'components/DataTable';
|
||||
import { Button, Popover, Menu, MenuItem, Position } from '@blueprintjs/core';
|
||||
|
||||
import withExchangeRates from 'containers/FinancialStatements/ExchangeRates/withExchangeRates';
|
||||
import withExchangeRatesActions from 'containers/FinancialStatements/ExchangeRates/withExchangeRatesActions';
|
||||
import withExchangeRates from 'containers/FinancialStatements/ExchangeRates/withExchangeRates';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
function ExchangeRateTable({
|
||||
// #withExchangeRates
|
||||
exchangeRatesList,
|
||||
onFetchData,
|
||||
exchangeRatesLoading,
|
||||
// #withDialog.
|
||||
openDialog,
|
||||
|
||||
// own properties
|
||||
loading,
|
||||
onFetchData,
|
||||
onDeleteExchangeRate,
|
||||
onEditExchangeRate,
|
||||
onSelectedRowsChange,
|
||||
}) {
|
||||
|
||||
const {formatMessage} = useIntl();
|
||||
|
||||
const [initialMount, setInitialMount] = useState(false);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const handelEditExchangeRate = (exchange_rate) => () => {
|
||||
openDialog('exchangeRate-form', { action: 'edit', id: exchange_rate.id });
|
||||
onEditExchangeRate(exchange_rate.id);
|
||||
};
|
||||
|
||||
// const handelEditExchangeRate = useCallback(
|
||||
// (exchange_rate) => () => {
|
||||
// openDialog('exchangeRate-form', { action: 'edit', id: exchange_rate.id });
|
||||
// onEditExchangeRate(exchange_rate.id);
|
||||
// },
|
||||
// [openDialog]
|
||||
// );
|
||||
|
||||
const handleDeleteExchangeRate = (exchange_rate) => () => {
|
||||
onDeleteExchangeRate(exchange_rate);
|
||||
@@ -45,36 +44,36 @@ function ExchangeRateTable({
|
||||
(ExchangeRate) => (
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'edit_exchange_rate'}/>}
|
||||
text={<T id={'edit_exchange_rate'} />}
|
||||
onClick={handelEditExchangeRate(ExchangeRate)}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'delete_exchange_rate'}/>}
|
||||
text={<T id={'delete_exchange_rate'} />}
|
||||
onClick={handleDeleteExchangeRate(ExchangeRate)}
|
||||
/>
|
||||
</Menu>
|
||||
),
|
||||
[]
|
||||
[handelEditExchangeRate, handleDeleteExchangeRate]
|
||||
);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'date',
|
||||
Header: formatMessage({id:'date'}),
|
||||
Header: formatMessage({ id: 'date' }),
|
||||
// accessor: 'date',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
id: 'currency_code',
|
||||
Header: formatMessage({id:'currency_code'}),
|
||||
Header: formatMessage({ id: 'currency_code' }),
|
||||
accessor: 'currency_code',
|
||||
className: 'currency_code',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
id: 'exchange_rate',
|
||||
Header: formatMessage({id:'exchange_rate'}),
|
||||
Header: formatMessage({ id: 'exchange_rate' }),
|
||||
accessor: 'exchange_rate',
|
||||
className: 'exchange_rate',
|
||||
width: 150,
|
||||
@@ -126,6 +125,7 @@ function ExchangeRateTable({
|
||||
columns={columns}
|
||||
data={exchangeRatesList}
|
||||
onFetchData={handelFetchData}
|
||||
loading={exchangeRatesLoading && !initialMount}
|
||||
manualSortBy={true}
|
||||
selectionColumn={selectionColumn}
|
||||
expandable={true}
|
||||
@@ -139,5 +139,8 @@ function ExchangeRateTable({
|
||||
export default compose(
|
||||
DialogConnect,
|
||||
withExchangeRatesActions,
|
||||
withExchangeRates
|
||||
withExchangeRates(({ exchangeRatesList ,exchangeRatesLoading }) => ({
|
||||
exchangeRatesList,
|
||||
exchangeRatesLoading
|
||||
}))
|
||||
)(ExchangeRateTable);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'utils';
|
||||
import DialogConnect from 'connectors/Dialog.connector';
|
||||
import DialogReduxConnect from 'components/DialogReduxConnect';
|
||||
import {getDialogPayload} from 'store/dashboard/dashboard.reducer';
|
||||
import withExchangeRatesActions from 'containers/FinancialStatements/ExchangeRates/withExchangeRatesActions';
|
||||
import withExchangeRates from 'containers/FinancialStatements/ExchangeRates/withExchangeRates';
|
||||
import CurrencyFromDialogConnect from 'connectors/CurrencyFromDialog.connect'
|
||||
|
||||
export const mapStateToProps = (state, props) => {
|
||||
const dialogPayload = getDialogPayload(state, 'exchangeRate-form');
|
||||
|
||||
return {
|
||||
name: 'exchangeRate-form',
|
||||
payload: { action: 'new', id: null, ...dialogPayload },
|
||||
editExchangeRate:
|
||||
dialogPayload && dialogPayload.action === 'edit'
|
||||
? state.exchangeRates.exchangeRates[dialogPayload.id]
|
||||
: {},
|
||||
};
|
||||
};
|
||||
const ExchangeRatesDialogConnect = connect(mapStateToProps);
|
||||
export default compose(
|
||||
CurrencyFromDialogConnect,
|
||||
ExchangeRatesDialogConnect,
|
||||
withExchangeRatesActions,
|
||||
withExchangeRates(({ exchangeRatesList }) => ({
|
||||
exchangeRatesList
|
||||
})),
|
||||
DialogReduxConnect,
|
||||
DialogConnect
|
||||
);
|
||||
@@ -1,8 +1,14 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { getResourceViews } from 'store/customViews/customViews.selectors';
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
exchangeRatesList: Object.values(state.exchangeRates.exchangeRates),
|
||||
});
|
||||
export default (mapState) => {
|
||||
const mapStateToProps = (state, props) => {
|
||||
const mapped = {
|
||||
exchangeRatesList: Object.values(state.exchangeRates.exchangeRates),
|
||||
exchangeRatesLoading: state.exchangeRates.loading,
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps);
|
||||
return connect(mapStateToProps);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import useAsync from 'hooks/async';
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import ItemCategoriesDataTable from 'containers/Items/ItemCategoriesTable';
|
||||
@@ -8,40 +8,46 @@ import ItemsCategoryActionsBar from 'containers/Items/ItemsCategoryActionsBar';
|
||||
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
||||
import withItemCategoriesActions from 'containers/Items/withItemCategoriesActions';
|
||||
import withItemCategories from 'containers/Items/withItemCategories';
|
||||
import { compose } from 'utils';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
|
||||
const ItemCategoryList = ({
|
||||
// #withDashboardActions
|
||||
changePageTitle,
|
||||
|
||||
// #withItemCategoriesActions
|
||||
requestFetchItemCategories,
|
||||
}) => {
|
||||
const { id } = useParams();
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
|
||||
const {formatMessage} =useIntl()
|
||||
useEffect(() => {
|
||||
id
|
||||
? changePageTitle('Edit Category Details')
|
||||
: changePageTitle('Category List');
|
||||
? changePageTitle(formatMessage({id:'edit_category_details'}))
|
||||
: changePageTitle(formatMessage({id:'category_list'}));
|
||||
}, []);
|
||||
|
||||
const fetchCategories = useAsync(() => {
|
||||
return Promise.all([
|
||||
requestFetchItemCategories(),
|
||||
]);
|
||||
});
|
||||
const fetchCategories = useQuery('items-categories-table',
|
||||
() => { requestFetchItemCategories(); });
|
||||
|
||||
const handleFilterChanged = useCallback(() => {
|
||||
|
||||
}, []);
|
||||
|
||||
// Handle selected rows change.
|
||||
const handleSelectedRowsChange = useCallback((itemCategories) => {
|
||||
setSelectedRows(itemCategories);
|
||||
}, [setSelectedRows]);
|
||||
|
||||
return (
|
||||
<DashboardInsider name={'item-category-list'}>
|
||||
<ItemsCategoryActionsBar
|
||||
onFilterChanged={handleFilterChanged}
|
||||
selectedRows={selectedRows} />
|
||||
|
||||
<ItemCategoriesDataTable />
|
||||
<ItemCategoriesDataTable
|
||||
onSelectedRowsChange={handleSelectedRowsChange} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
};
|
||||
@@ -49,5 +55,4 @@ const ItemCategoryList = ({
|
||||
export default compose(
|
||||
withDashboardActions,
|
||||
withItemCategoriesActions,
|
||||
withItemCategories,
|
||||
)(ItemCategoryList);
|
||||
|
||||
@@ -10,6 +10,7 @@ import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||
import withItemCategoriesActions from 'containers/Items/withItemCategoriesActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
|
||||
const ItemFormContainer = ({
|
||||
@@ -23,11 +24,11 @@ const ItemFormContainer = ({
|
||||
requestFetchItemCategories,
|
||||
}) => {
|
||||
const { id } = useParams();
|
||||
|
||||
const {formatMessage} =useIntl()
|
||||
useEffect(() => {
|
||||
id ?
|
||||
changePageTitle('Edit Item Details') :
|
||||
changePageTitle('New Item');
|
||||
changePageTitle(formatMessage({id:'edit_item_details'})) :
|
||||
changePageTitle(formatMessage({id:'new_item'}));
|
||||
}, [id, changePageTitle]);
|
||||
|
||||
const fetchAccounts = useQuery('accounts-list',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, {useState, useEffect, useCallback, useMemo} from 'react';
|
||||
import { useFormik } from "formik";
|
||||
import {useIntl} from 'react-intl';
|
||||
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { useFormik } from 'formik';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
import {
|
||||
InputGroup,
|
||||
@@ -13,26 +14,24 @@ import {
|
||||
Menu,
|
||||
H5,
|
||||
H6,
|
||||
} from "@blueprintjs/core";
|
||||
import {Row, Col} from 'react-grid-system';
|
||||
} from '@blueprintjs/core';
|
||||
import { Row, Col } from 'react-grid-system';
|
||||
import { ReactSortable } from 'react-sortablejs';
|
||||
import * as Yup from 'yup';
|
||||
import {pick, get} from 'lodash';
|
||||
import { pick, get } from 'lodash';
|
||||
import Icon from 'components/Icon';
|
||||
import ErrorMessage from 'components/ErrorMessage';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
import { If } from 'components';
|
||||
import ViewFormContainer from 'containers/Views/ViewForm.container.js';
|
||||
|
||||
|
||||
function ViewForm({
|
||||
function ViewForm({
|
||||
requestSubmitView,
|
||||
requestEditView,
|
||||
onDelete,
|
||||
|
||||
viewId,
|
||||
viewMeta,
|
||||
viewItem,
|
||||
|
||||
resourceName,
|
||||
resourceColumns,
|
||||
@@ -52,20 +51,30 @@ function ViewForm({
|
||||
}, []);
|
||||
|
||||
const [draggedColumns, setDraggedColumn] = useState([
|
||||
...(viewMeta && viewMeta.columns) ? viewMeta.columns : []
|
||||
...(viewMeta && viewMeta.columns ? viewMeta.columns : []),
|
||||
]);
|
||||
|
||||
const draggedColumnsIds = useMemo(() => draggedColumns.map((c) => c.id), [
|
||||
draggedColumns,
|
||||
]);
|
||||
|
||||
const draggedColumnsIds = useMemo(() => draggedColumns.map(c => c.id), [draggedColumns]);
|
||||
|
||||
const [availableColumns, setAvailableColumns] = useState([
|
||||
...(viewMeta && viewMeta.columns) ? resourceColumns.filter((column) =>
|
||||
draggedColumnsIds.indexOf(column.id) === -1
|
||||
) : resourceColumns,
|
||||
...(viewMeta && viewMeta.columns
|
||||
? resourceColumns.filter(
|
||||
(column) => draggedColumnsIds.indexOf(column.id) === -1
|
||||
)
|
||||
: resourceColumns),
|
||||
]);
|
||||
|
||||
const defaultViewRole = useMemo(() => ({
|
||||
field_key: '', comparator: '', value: '', index: 1,
|
||||
}), []);
|
||||
const defaultViewRole = useMemo(
|
||||
() => ({
|
||||
field_key: '',
|
||||
comparator: '',
|
||||
value: '',
|
||||
index: 1,
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
resource_name: Yup.string().required(),
|
||||
@@ -83,27 +92,33 @@ function ViewForm({
|
||||
Yup.object().shape({
|
||||
key: Yup.string().required(),
|
||||
index: Yup.string().required(),
|
||||
}),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
const initialEmptyForm = useMemo(() => ({
|
||||
resource_name: resourceName || '',
|
||||
name: '',
|
||||
logic_expression: '',
|
||||
roles: [
|
||||
defaultViewRole,
|
||||
],
|
||||
columns: [],
|
||||
}), [defaultViewRole, resourceName]);
|
||||
const initialEmptyForm = useMemo(
|
||||
() => ({
|
||||
resource_name: resourceName || '',
|
||||
name: '',
|
||||
logic_expression: '',
|
||||
roles: [defaultViewRole],
|
||||
columns: [],
|
||||
}),
|
||||
[defaultViewRole, resourceName]
|
||||
);
|
||||
|
||||
const initialForm = useMemo(() => ({
|
||||
...initialEmptyForm,
|
||||
...viewMeta ? {
|
||||
...viewMeta,
|
||||
resource_name: viewMeta.resource?.name || resourceName,
|
||||
} : {},
|
||||
}), [initialEmptyForm, viewMeta, resourceName]);
|
||||
const initialForm = useMemo(
|
||||
() => ({
|
||||
...initialEmptyForm,
|
||||
...(viewMeta
|
||||
? {
|
||||
...viewMeta,
|
||||
resource_name: viewMeta.resource?.name || resourceName,
|
||||
}
|
||||
: {}),
|
||||
}),
|
||||
[initialEmptyForm, viewMeta, resourceName]
|
||||
);
|
||||
|
||||
const {
|
||||
values,
|
||||
@@ -136,7 +151,9 @@ function ViewForm({
|
||||
message: 'the_view_has_been_edited',
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
history.push(`${resourceMetadata.baseRoute}/${viewMeta.id}/custom_view`);
|
||||
history.push(
|
||||
`${resourceMetadata.baseRoute}/${viewMeta.id}/custom_view`
|
||||
);
|
||||
setSubmitting(false);
|
||||
});
|
||||
} else {
|
||||
@@ -145,7 +162,9 @@ function ViewForm({
|
||||
message: 'the_view_has_been_submit',
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
history.push(`${resourceMetadata.baseRoute}/${viewMeta.id}/custom_view`);
|
||||
history.push(
|
||||
`${resourceMetadata.baseRoute}/${viewMeta.id}/custom_view`
|
||||
);
|
||||
setSubmitting(false);
|
||||
});
|
||||
}
|
||||
@@ -153,39 +172,55 @@ function ViewForm({
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setFieldValue('columns',
|
||||
setFieldValue(
|
||||
'columns',
|
||||
draggedColumns.map((column, index) => ({
|
||||
index, key: column.key,
|
||||
})));
|
||||
index,
|
||||
key: column.key,
|
||||
}))
|
||||
);
|
||||
}, [setFieldValue, draggedColumns]);
|
||||
|
||||
const conditionalsItems = useMemo(() => ([
|
||||
{ value: 'and', label: 'AND' },
|
||||
{ value: 'or', label: 'OR' },
|
||||
]), []);
|
||||
const conditionalsItems = useMemo(
|
||||
() => [
|
||||
{ value: 'and', label: 'AND' },
|
||||
{ value: 'or', label: 'OR' },
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const whenConditionalsItems = useMemo(() => ([
|
||||
{ value: '', label: 'When' },
|
||||
]), []);
|
||||
const whenConditionalsItems = useMemo(
|
||||
() => [{ value: '', label: 'When' }],
|
||||
[]
|
||||
);
|
||||
|
||||
// Compatotors items.
|
||||
const compatatorsItems = useMemo(() => ([
|
||||
{value: '', label: 'Compatator'},
|
||||
{value: 'equals', label: 'Equals'},
|
||||
{value: 'not_equal', label: 'Not Equal'},
|
||||
{value: 'contain', label: 'Contain'},
|
||||
{value: 'not_contain', label: 'Not Contain'},
|
||||
]), []);
|
||||
const compatatorsItems = useMemo(
|
||||
() => [
|
||||
{ value: '', label: 'Compatator' },
|
||||
{ value: 'equals', label: 'Equals' },
|
||||
{ value: 'not_equal', label: 'Not Equal' },
|
||||
{ value: 'contain', label: 'Contain' },
|
||||
{ value: 'not_contain', label: 'Not Contain' },
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
// Resource fields.
|
||||
const resourceFieldsOptions = useMemo(() => ([
|
||||
{value: '', label: 'Select a field'},
|
||||
...resourceFields.map((field) => ({ value: field.key, label: field.label_name, })),
|
||||
]), [resourceFields]);
|
||||
const resourceFieldsOptions = useMemo(
|
||||
() => [
|
||||
{ value: '', label: 'Select a field' },
|
||||
...resourceFields.map((field) => ({
|
||||
value: field.key,
|
||||
label: field.label_name,
|
||||
})),
|
||||
],
|
||||
[resourceFields]
|
||||
);
|
||||
|
||||
// Account item of select accounts field.
|
||||
const selectItem = (item, { handleClick, modifiers, query }) => {
|
||||
return (<MenuItem text={item.label} key={item.key} onClick={handleClick} />)
|
||||
return <MenuItem text={item.label} key={item.key} onClick={handleClick} />;
|
||||
};
|
||||
// Handle click new condition button.
|
||||
const onClickNewRole = useCallback(() => {
|
||||
@@ -194,219 +229,273 @@ function ViewForm({
|
||||
{
|
||||
...defaultViewRole,
|
||||
index: values.roles.length + 1,
|
||||
}
|
||||
},
|
||||
]);
|
||||
}, [defaultViewRole, setFieldValue, values]);
|
||||
|
||||
// Handle click remove view role button.
|
||||
const onClickRemoveRole = useCallback((viewRole, index) => {
|
||||
let viewRoles = [...values.roles];
|
||||
const onClickRemoveRole = useCallback(
|
||||
(viewRole, index) => {
|
||||
let viewRoles = [...values.roles];
|
||||
|
||||
// Can't continue if view roles equals or less than 1.
|
||||
if (viewRoles.length > 1) {
|
||||
viewRoles.splice(index, 1);
|
||||
// Can't continue if view roles equals or less than 1.
|
||||
if (viewRoles.length > 1) {
|
||||
viewRoles.splice(index, 1);
|
||||
|
||||
setFieldValue(
|
||||
'roles',
|
||||
viewRoles.map((role) => {
|
||||
return role;
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
[values, setFieldValue]
|
||||
);
|
||||
|
||||
setFieldValue('roles', viewRoles.map((role) => {
|
||||
return role;
|
||||
}));
|
||||
}
|
||||
}, [values, setFieldValue]);
|
||||
|
||||
const onClickDeleteView = useCallback(() => {
|
||||
onDelete && onDelete(viewMeta);
|
||||
}, [onDelete, viewMeta]);
|
||||
|
||||
const hasError = (path) => get(errors, path) && get(touched, path);
|
||||
const hasError = (path) => get(errors, path) && get(touched, path);
|
||||
|
||||
const handleClickCancelBtn = () => {
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
return (
|
||||
<div class="view-form">
|
||||
<div class='view-form'>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div class="view-form--name-section">
|
||||
<div class='view-form--name-section'>
|
||||
<Row>
|
||||
<Col sm={8}>
|
||||
<FormGroup
|
||||
label={intl.formatMessage({'id': 'View Name'})}
|
||||
label={<T id={'view_name'} />}
|
||||
className={'form-group--name'}
|
||||
intent={(errors.name && touched.name) && Intent.DANGER}
|
||||
helperText={<ErrorMessage {...{errors, touched}} name={'name'} />}
|
||||
intent={errors.name && touched.name && Intent.DANGER}
|
||||
helperText={
|
||||
<ErrorMessage {...{ errors, touched }} name={'name'} />
|
||||
}
|
||||
inline={true}
|
||||
fill={true}>
|
||||
|
||||
fill={true}
|
||||
>
|
||||
<InputGroup
|
||||
intent={(errors.name && touched.name) && Intent.DANGER}
|
||||
intent={errors.name && touched.name && Intent.DANGER}
|
||||
fill={true}
|
||||
{...getFieldProps('name')} />
|
||||
{...getFieldProps('name')}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<H5 className="mb2">Define the conditionals</H5>
|
||||
|
||||
<H5 className='mb2'>Define the conditionals</H5>
|
||||
|
||||
{values.roles.map((role, index) => (
|
||||
<Row class="view-form__role-conditional">
|
||||
<Col sm={2} class="flex">
|
||||
<div class="mr2 pt1 condition-number">{ index + 1 }</div>
|
||||
{(index === 0) ? (
|
||||
<HTMLSelect options={whenConditionalsItems} className={Classes.FILL} />
|
||||
<Row class='view-form__role-conditional'>
|
||||
<Col sm={2} class='flex'>
|
||||
<div class='mr2 pt1 condition-number'>{index + 1}</div>
|
||||
{index === 0 ? (
|
||||
<HTMLSelect
|
||||
options={whenConditionalsItems}
|
||||
className={Classes.FILL}
|
||||
/>
|
||||
) : (
|
||||
<HTMLSelect options={conditionalsItems} className={Classes.FILL} />
|
||||
<HTMLSelect
|
||||
options={conditionalsItems}
|
||||
className={Classes.FILL}
|
||||
/>
|
||||
)}
|
||||
</Col>
|
||||
|
||||
<Col sm={2}>
|
||||
<FormGroup
|
||||
intent={hasError(`roles[${index}].field_key`) && Intent.DANGER}>
|
||||
intent={hasError(`roles[${index}].field_key`) && Intent.DANGER}
|
||||
>
|
||||
<HTMLSelect
|
||||
options={resourceFieldsOptions}
|
||||
value={role.field_key}
|
||||
className={Classes.FILL}
|
||||
{...getFieldProps(`roles[${index}].field_key`)} />
|
||||
{...getFieldProps(`roles[${index}].field_key`)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
|
||||
<Col sm={2}>
|
||||
<FormGroup
|
||||
intent={hasError(`roles[${index}].comparator`) && Intent.DANGER}>
|
||||
intent={hasError(`roles[${index}].comparator`) && Intent.DANGER}
|
||||
>
|
||||
<HTMLSelect
|
||||
options={compatatorsItems}
|
||||
value={role.comparator}
|
||||
className={Classes.FILL}
|
||||
{...getFieldProps(`roles[${index}].comparator`)} />
|
||||
{...getFieldProps(`roles[${index}].comparator`)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
|
||||
<Col sm={5} class="flex">
|
||||
<Col sm={5} class='flex'>
|
||||
<FormGroup
|
||||
intent={hasError(`roles[${index}].value`) && Intent.DANGER}>
|
||||
intent={hasError(`roles[${index}].value`) && Intent.DANGER}
|
||||
>
|
||||
<InputGroup
|
||||
placeholder={intl.formatMessage({'id': 'value'})}
|
||||
{...getFieldProps(`roles[${index}].value`)} />
|
||||
placeholder={intl.formatMessage({ id: 'value' })}
|
||||
{...getFieldProps(`roles[${index}].value`)}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<Button
|
||||
icon={<Icon icon="times-circle" iconSize={14} />}
|
||||
|
||||
<Button
|
||||
icon={<Icon icon='times-circle' iconSize={14} />}
|
||||
iconSize={14}
|
||||
className="ml2"
|
||||
minimal={true}
|
||||
className='ml2'
|
||||
minimal={true}
|
||||
intent={Intent.DANGER}
|
||||
onClick={() => onClickRemoveRole(role, index)} />
|
||||
onClick={() => onClickRemoveRole(role, index)}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
))}
|
||||
|
||||
<div className={'view-form__role-conditions-actions'}>
|
||||
<Button
|
||||
minimal={true}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={onClickNewRole}>
|
||||
New Conditional
|
||||
</Button>
|
||||
</div>
|
||||
<div className={'view-form__role-conditions-actions'}>
|
||||
<Button
|
||||
minimal={true}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={onClickNewRole}
|
||||
>
|
||||
<T id={'new_conditional'} />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="view-form--logic-expression-section">
|
||||
<Row>
|
||||
<Col sm={8}>
|
||||
<FormGroup
|
||||
label={intl.formatMessage({'id': 'Logic Expression'})}
|
||||
className={'form-group--logic-expression'}
|
||||
intent={(errors.logic_expression && touched.logic_expression) && Intent.DANGER}
|
||||
helperText={<ErrorMessage {...{errors, touched}} name='logic_expression' />}
|
||||
inline={true}
|
||||
fill={true}>
|
||||
<div class='view-form--logic-expression-section'>
|
||||
<Row>
|
||||
<Col sm={8}>
|
||||
<FormGroup
|
||||
label={intl.formatMessage({ id: 'Logic Expression' })}
|
||||
className={'form-group--logic-expression'}
|
||||
intent={
|
||||
errors.logic_expression &&
|
||||
touched.logic_expression &&
|
||||
Intent.DANGER
|
||||
}
|
||||
helperText={
|
||||
<ErrorMessage
|
||||
{...{ errors, touched }}
|
||||
name='logic_expression'
|
||||
/>
|
||||
}
|
||||
inline={true}
|
||||
fill={true}
|
||||
>
|
||||
<InputGroup
|
||||
intent={
|
||||
errors.logic_expression &&
|
||||
touched.logic_expression &&
|
||||
Intent.DANGER
|
||||
}
|
||||
fill={true}
|
||||
{...getFieldProps('logic_expression')}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<H5 className={'mb2'}>Columns Preferences</H5>
|
||||
|
||||
<div class='dragable-columns'>
|
||||
<Row gutterWidth={14}>
|
||||
<Col sm={4} className='dragable-columns__column'>
|
||||
<H6 className='dragable-columns__title'>Available Columns</H6>
|
||||
|
||||
<InputGroup
|
||||
intent={(errors.logic_expression && touched.logic_expression) && Intent.DANGER}
|
||||
fill={true}
|
||||
{...getFieldProps('logic_expression')} />
|
||||
</FormGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
placeholder={intl.formatMessage({ id: 'search' })}
|
||||
leftIcon='search'
|
||||
/>
|
||||
|
||||
<H5 className={'mb2'}>Columns Preferences</H5>
|
||||
|
||||
<div class="dragable-columns">
|
||||
<Row gutterWidth={14}>
|
||||
<Col sm={4} className="dragable-columns__column">
|
||||
<H6 className="dragable-columns__title">Available Columns</H6>
|
||||
<div class='dragable-columns__items'>
|
||||
<Menu>
|
||||
<ReactSortable
|
||||
list={availableColumns}
|
||||
setList={setAvailableColumns}
|
||||
group='shared-group-name'
|
||||
>
|
||||
{availableColumns.map((field) => (
|
||||
<MenuItem key={field.id} text={field.label} />
|
||||
))}
|
||||
</ReactSortable>
|
||||
</Menu>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
<InputGroup
|
||||
placeholder={intl.formatMessage({id: 'search'})}
|
||||
leftIcon="search" />
|
||||
<Col sm={1}>
|
||||
<div class='dragable-columns__arrows'>
|
||||
<div>
|
||||
<Icon
|
||||
icon='arrow-circle-left'
|
||||
iconSize={30}
|
||||
color='#cecece'
|
||||
/>
|
||||
</div>
|
||||
<div class='mt2'>
|
||||
<Icon
|
||||
icon='arrow-circle-right'
|
||||
iconSize={30}
|
||||
color='#cecece'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
<div class="dragable-columns__items">
|
||||
<Menu>
|
||||
<ReactSortable
|
||||
list={availableColumns}
|
||||
setList={setAvailableColumns}
|
||||
group="shared-group-name">
|
||||
{availableColumns.map((field) => (
|
||||
<MenuItem key={field.id} text={field.label} />
|
||||
))}
|
||||
</ReactSortable>
|
||||
</Menu>
|
||||
</div>
|
||||
</Col>
|
||||
<Col sm={4} className='dragable-columns__column'>
|
||||
<H6 className='dragable-columns__title'>Selected Columns</H6>
|
||||
<InputGroup
|
||||
placeholder={intl.formatMessage({ id: 'search' })}
|
||||
leftIcon='search'
|
||||
/>
|
||||
|
||||
<Col sm={1}>
|
||||
<div class="dragable-columns__arrows">
|
||||
<div><Icon icon="arrow-circle-left" iconSize={30} color="#cecece" /></div>
|
||||
<div class="mt2"><Icon icon="arrow-circle-right" iconSize={30} color="#cecece" /></div>
|
||||
</div>
|
||||
</Col>
|
||||
<div class='dragable-columns__items'>
|
||||
<Menu>
|
||||
<ReactSortable
|
||||
list={draggedColumns}
|
||||
setList={setDraggedColumn}
|
||||
group='shared-group-name'
|
||||
>
|
||||
{draggedColumns.map((field) => (
|
||||
<MenuItem key={field.id} text={field.label} />
|
||||
))}
|
||||
</ReactSortable>
|
||||
</Menu>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<Col sm={4} className="dragable-columns__column">
|
||||
<H6 className="dragable-columns__title">Selected Columns</H6>
|
||||
<InputGroup placeholder={intl.formatMessage({id: 'search'})} leftIcon="search" />
|
||||
|
||||
<div class="dragable-columns__items">
|
||||
<Menu>
|
||||
<ReactSortable
|
||||
list={draggedColumns}
|
||||
setList={setDraggedColumn}
|
||||
group="shared-group-name">
|
||||
{draggedColumns.map((field) => (
|
||||
<MenuItem key={field.id} text={field.label} />
|
||||
))}
|
||||
</ReactSortable>
|
||||
</Menu>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div class="form__floating-footer">
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
type="submit"
|
||||
disabled={isSubmitting}>
|
||||
Submit
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
intent={Intent.NONE}
|
||||
className="ml1"
|
||||
onClick={handleClickCancelBtn}>
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<If condition={viewMeta && viewMeta.id}>
|
||||
<Button
|
||||
intent={Intent.DANGER}
|
||||
onClick={onClickDeleteView}
|
||||
className={"right mr2"}>
|
||||
Delete
|
||||
<div class='form__floating-footer'>
|
||||
<Button intent={Intent.PRIMARY} type='submit' disabled={isSubmitting}>
|
||||
<T id={'submit'} />
|
||||
</Button>
|
||||
</If>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
intent={Intent.NONE}
|
||||
className='ml1'
|
||||
onClick={handleClickCancelBtn}
|
||||
>
|
||||
<T id={'cancel'} />
|
||||
</Button>
|
||||
|
||||
<If condition={viewMeta && viewMeta.id}>
|
||||
<Button
|
||||
intent={Intent.DANGER}
|
||||
onClick={onClickDeleteView}
|
||||
className={'right mr2'}
|
||||
>
|
||||
<T id={'delete'} />
|
||||
</Button>
|
||||
</If>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ViewFormContainer(ViewForm);
|
||||
export default ViewFormContainer(ViewForm);
|
||||
|
||||
@@ -5,14 +5,17 @@ import { Intent, Alert } from '@blueprintjs/core';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||
import ViewForm from 'containers/Views/ViewForm';
|
||||
import withResourcesActions from 'containers/Resources/withResourcesActions';
|
||||
import withViewsActions from 'containers/Views/withViewsActions';
|
||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
||||
|
||||
import AppToaster from 'components/AppToaster';
|
||||
import {compose} from 'utils';
|
||||
import { If } from 'components';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
|
||||
import withResourcesActions from 'containers/Resources/withResourcesActions';
|
||||
import withViewsActions from 'containers/Views/withViewsActions';
|
||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
||||
|
||||
|
||||
// @flow
|
||||
function ViewFormPage({
|
||||
changePageTitle,
|
||||
@@ -27,6 +30,7 @@ function ViewFormPage({
|
||||
}) {
|
||||
const { resource_slug: resourceSlug, view_id: viewId } = useParams();
|
||||
const [stateDeleteView, setStateDeleteView] = useState(null);
|
||||
const {formatMessage} =useIntl()
|
||||
|
||||
const fetchHook = useAsync(async () => {
|
||||
return Promise.all([
|
||||
@@ -44,9 +48,9 @@ function ViewFormPage({
|
||||
|
||||
useEffect(() => {
|
||||
if (viewId) {
|
||||
changePageTitle('Edit Custom View');
|
||||
changePageTitle(formatMessage({id:'edit_custom_view'}));
|
||||
} else {
|
||||
changePageTitle('New Custom View');
|
||||
changePageTitle(formatMessage({id:'new_custom_view'}));
|
||||
}
|
||||
return () => {
|
||||
changePageTitle('');
|
||||
|
||||
@@ -149,7 +149,22 @@ bulk_update:'Bulk Update',
|
||||
all_accounts:'All accounts',
|
||||
go_to_bigcapital_com:'← Go to bigcapital.com',
|
||||
currency:'Currency',
|
||||
new_conditional:'+ New Conditional'
|
||||
new_conditional:'+ New Conditional',
|
||||
chart_of_accounts:'Chart of Accounts',
|
||||
exchange_rate_details:'Exchange Rate Details',
|
||||
exchange_rate_list:'Exchange Rate List',
|
||||
manual_journals:'Manual Journals',
|
||||
edit_expense_details:'Edit Expense Details',
|
||||
expenses_list:'Expenses List',
|
||||
edit_category_details:'Edit Category Details',
|
||||
category_list:'Category List',
|
||||
edit_item_details:'Edit Item Details',
|
||||
items_list:'Items List',
|
||||
edit_custom_view:'Edit Custom View',
|
||||
new_custom_view:'New Custom View',
|
||||
view_name:'View Name',
|
||||
new_conditional:'New Conditional'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ export const fetchExchangeRates = () => {
|
||||
dispatch({
|
||||
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||
});
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATE_TABLE_LOADING,
|
||||
loading: true,
|
||||
});
|
||||
ApiService.get('exchange_rates')
|
||||
.then((response) => {
|
||||
dispatch({
|
||||
@@ -16,6 +20,10 @@ export const fetchExchangeRates = () => {
|
||||
dispatch({
|
||||
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||
});
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATE_TABLE_LOADING,
|
||||
loading: false,
|
||||
});
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -17,4 +17,7 @@ export default createReducer(initialState, {
|
||||
..._exchangeRates,
|
||||
};
|
||||
},
|
||||
[t.EXCHANGE_RATE_TABLE_LOADING]: (state, action) => {
|
||||
state.loading = action.loading;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,4 +4,5 @@ export default {
|
||||
EXCHANGE_RATE_LIST_SET: 'EXCHANGE_RATE_LIST_SET',
|
||||
CLEAR_EXCHANGE_RATE_FORM_ERRORS: 'CLEAR_EXCHANGE_RATE_FORM_ERRORS',
|
||||
ExchangeRates_TABLE_QUERIES_ADD: 'ExchangeRates_TABLE_QUERIES_ADD',
|
||||
EXCHANGE_RATE_TABLE_LOADING:'EXCHANGE_RATE_TABLE_LOADING'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user