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