mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 23:00:34 +00:00
refactoring: migrating to react-query to manage service-side state.
This commit is contained in:
@@ -7,7 +7,6 @@ import { orderingLinesIndexes, repeatValue } from 'utils';
|
||||
|
||||
export default function MakeJournalEntriesField({
|
||||
defaultRow,
|
||||
|
||||
linesNumber = 4,
|
||||
}) {
|
||||
return (
|
||||
|
||||
@@ -18,23 +18,20 @@ import MakeJournalEntriesField from './MakeJournalEntriesField';
|
||||
import MakeJournalNumberWatcher from './MakeJournalNumberWatcher';
|
||||
import MakeJournalFormFooter from './MakeJournalFormFooter';
|
||||
|
||||
import withJournalsActions from 'containers/Accounting/withJournalsActions';
|
||||
import withManualJournalDetail from 'containers/Accounting/withManualJournalDetail';
|
||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withSettings from 'containers/Settings/withSettings';
|
||||
|
||||
import AppToaster from 'components/AppToaster';
|
||||
import Dragzone from 'components/Dragzone';
|
||||
import withMediaActions from 'containers/Media/withMediaActions';
|
||||
import {
|
||||
compose,
|
||||
repeatValue,
|
||||
orderingLinesIndexes,
|
||||
defaultToTransform,
|
||||
transactionNumber,
|
||||
} from 'utils';
|
||||
import { transformErrors } from './utils';
|
||||
import withManualJournalsActions from './withManualJournalsActions';
|
||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
||||
|
||||
const defaultEntry = {
|
||||
index: 0,
|
||||
@@ -59,18 +56,6 @@ const defaultInitialValues = {
|
||||
* Journal entries form.
|
||||
*/
|
||||
function MakeJournalEntriesForm({
|
||||
// #withMedia
|
||||
requestSubmitMedia,
|
||||
requestDeleteMedia,
|
||||
|
||||
// #withJournalsActions
|
||||
requestMakeJournalEntries,
|
||||
requestEditManualJournal,
|
||||
setJournalNumberChanged,
|
||||
|
||||
// #withManualJournals
|
||||
journalNumberChanged,
|
||||
|
||||
// #withDashboard
|
||||
changePageTitle,
|
||||
changePageSubtitle,
|
||||
@@ -79,30 +64,33 @@ function MakeJournalEntriesForm({
|
||||
journalNextNumber,
|
||||
journalNumberPrefix,
|
||||
baseCurrency,
|
||||
// #ownProps
|
||||
manualJournalId,
|
||||
manualJournal,
|
||||
onFormSubmit,
|
||||
onCancelForm,
|
||||
}) {
|
||||
const isNewMode = !manualJournalId;
|
||||
const [submitPayload, setSubmitPayload] = useState({});
|
||||
const {
|
||||
createJournalMutate,
|
||||
editJournalMutate,
|
||||
isNewMode,
|
||||
manualJournal,
|
||||
submitPayload,
|
||||
} = useMakeJournalFormContext();
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
const history = useHistory();
|
||||
|
||||
const journalNumber = isNewMode
|
||||
? `${journalNumberPrefix}-${journalNextNumber}`
|
||||
: journalNextNumber;
|
||||
|
||||
// New journal number.
|
||||
const journalNumber = transactionNumber(
|
||||
journalNumberPrefix,
|
||||
journalNextNumber,
|
||||
);
|
||||
// Changes the page title based on the form in new and edit mode.
|
||||
useEffect(() => {
|
||||
const transactionNumber = manualJournal
|
||||
? manualJournal.journal_number
|
||||
: journalNumber;
|
||||
|
||||
if (manualJournal && manualJournal.id) {
|
||||
changePageTitle(formatMessage({ id: 'edit_journal' }));
|
||||
} else {
|
||||
if (isNewMode) {
|
||||
changePageTitle(formatMessage({ id: 'new_journal' }));
|
||||
} else {
|
||||
changePageTitle(formatMessage({ id: 'edit_journal' }));
|
||||
}
|
||||
changePageSubtitle(
|
||||
defaultToTransform(transactionNumber, `No. ${transactionNumber}`, ''),
|
||||
@@ -113,6 +101,7 @@ function MakeJournalEntriesForm({
|
||||
journalNumber,
|
||||
manualJournal,
|
||||
formatMessage,
|
||||
isNewMode,
|
||||
]);
|
||||
|
||||
const initialValues = useMemo(
|
||||
@@ -131,7 +120,7 @@ function MakeJournalEntriesForm({
|
||||
entries: orderingLinesIndexes(defaultInitialValues.entries),
|
||||
}),
|
||||
}),
|
||||
[manualJournal, journalNumber],
|
||||
[manualJournal, baseCurrency, journalNumber],
|
||||
);
|
||||
|
||||
// Handle journal number field change.
|
||||
@@ -144,6 +133,7 @@ function MakeJournalEntriesForm({
|
||||
[changePageSubtitle],
|
||||
);
|
||||
|
||||
// Handle the form submiting.
|
||||
const handleSubmit = (values, { setErrors, setSubmitting, resetForm }) => {
|
||||
setSubmitting(true);
|
||||
const entries = values.entries.filter(
|
||||
@@ -179,11 +169,13 @@ function MakeJournalEntriesForm({
|
||||
}
|
||||
const form = { ...values, publish: submitPayload.publish, entries };
|
||||
|
||||
// Handle the request error.
|
||||
const handleError = (error) => {
|
||||
transformErrors(error, { setErrors });
|
||||
setSubmitting(false);
|
||||
};
|
||||
|
||||
// Handle the request success.
|
||||
const handleSuccess = (errors) => {
|
||||
AppToaster.show({
|
||||
message: formatMessage(
|
||||
@@ -196,7 +188,6 @@ function MakeJournalEntriesForm({
|
||||
),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
|
||||
setSubmitting(false);
|
||||
|
||||
if (submitPayload.redirect) {
|
||||
@@ -208,25 +199,14 @@ function MakeJournalEntriesForm({
|
||||
};
|
||||
|
||||
if (isNewMode) {
|
||||
requestMakeJournalEntries(form).then(handleSuccess).catch(handleError);
|
||||
createJournalMutate(form).then(handleSuccess).catch(handleError);
|
||||
} else {
|
||||
requestEditManualJournal(manualJournal.id, form)
|
||||
editJournalMutate(manualJournal.id, form)
|
||||
.then(handleSuccess)
|
||||
.catch(handleError);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancelClick = useCallback(() => {
|
||||
history.goBack();
|
||||
}, [history]);
|
||||
|
||||
const handleSubmitClick = useCallback(
|
||||
(event, payload) => {
|
||||
setSubmitPayload({ ...payload });
|
||||
},
|
||||
[setSubmitPayload],
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
@@ -240,39 +220,21 @@ function MakeJournalEntriesForm({
|
||||
validationSchema={isNewMode ? CreateJournalSchema : EditJournalSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{({ isSubmitting }) => (
|
||||
<Form>
|
||||
<MakeJournalEntriesHeader
|
||||
manualJournal={manualJournalId}
|
||||
onJournalNumberChanged={handleJournalNumberChanged}
|
||||
/>
|
||||
<MakeJournalNumberWatcher journalNumber={journalNumber} />
|
||||
<MakeJournalEntriesField defaultRow={defaultEntry} />
|
||||
<MakeJournalFormFooter />
|
||||
<MakeJournalFormFloatingActions
|
||||
isSubmitting={isSubmitting}
|
||||
manualJournal={manualJournal}
|
||||
// manualJournalPublished={values.status}
|
||||
onCancelClick={handleCancelClick}
|
||||
onSubmitClick={handleSubmitClick}
|
||||
/>
|
||||
</Form>
|
||||
)}
|
||||
<Form>
|
||||
<MakeJournalEntriesHeader
|
||||
onJournalNumberChanged={handleJournalNumberChanged}
|
||||
/>
|
||||
<MakeJournalNumberWatcher journalNumber={journalNumber} />
|
||||
<MakeJournalEntriesField defaultRow={defaultEntry} />
|
||||
<MakeJournalFormFooter />
|
||||
<MakeJournalFormFloatingActions />
|
||||
</Form>
|
||||
</Formik>
|
||||
{/* <Dragzone
|
||||
initialFiles={initialAttachmentFiles}
|
||||
onDrop={handleDropFiles}
|
||||
onDeleteFile={handleDeleteFile}
|
||||
hint={'Attachments: Maxiumum size: 20MB'}
|
||||
/> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withJournalsActions,
|
||||
withManualJournalDetail(),
|
||||
withAccountsActions,
|
||||
withDashboardActions,
|
||||
withMediaActions,
|
||||
withSettings(({ manualJournalsSettings, organizationSettings }) => ({
|
||||
@@ -280,5 +242,4 @@ export default compose(
|
||||
journalNumberPrefix: manualJournalsSettings?.numberPrefix,
|
||||
baseCurrency: organizationSettings?.baseCurrency,
|
||||
})),
|
||||
withManualJournalsActions,
|
||||
)(MakeJournalEntriesForm);
|
||||
|
||||
@@ -21,25 +21,24 @@ import {
|
||||
CurrencySelectList,
|
||||
} from 'components';
|
||||
|
||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withCurrencies from 'containers/Currencies/withCurrencies';
|
||||
|
||||
import { compose, inputIntent, handleDateChange } from 'utils';
|
||||
|
||||
function MakeJournalEntriesHeader({
|
||||
// #ownProps
|
||||
manualJournal,
|
||||
onJournalNumberChanged,
|
||||
|
||||
// #withCurrencies
|
||||
currenciesList,
|
||||
|
||||
// #withDialog
|
||||
openDialog,
|
||||
}) {
|
||||
const handleJournalNumberChange = useCallback(() => {
|
||||
const { currencies } = useMakeJournalFormContext();
|
||||
|
||||
// Handle journal number change.
|
||||
const handleJournalNumberChange = () => {
|
||||
openDialog('journal-number-form', {});
|
||||
}, [openDialog]);
|
||||
};
|
||||
|
||||
// Handle journal number field blur event.
|
||||
const handleJournalNumberChanged = (event) => {
|
||||
@@ -165,7 +164,7 @@ function MakeJournalEntriesHeader({
|
||||
inline={true}
|
||||
>
|
||||
<CurrencySelectList
|
||||
currenciesList={currenciesList}
|
||||
currenciesList={currencies}
|
||||
selectedCurrencyCode={value}
|
||||
onCurrencySelected={(currencyItem) => {
|
||||
form.setFieldValue('currency_code', currencyItem.currency_code);
|
||||
@@ -181,7 +180,4 @@ function MakeJournalEntriesHeader({
|
||||
|
||||
export default compose(
|
||||
withDialogActions,
|
||||
withCurrencies(({ currenciesList }) => ({
|
||||
currenciesList,
|
||||
})),
|
||||
)(MakeJournalEntriesHeader);
|
||||
|
||||
@@ -1,44 +1,26 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
import MakeJournalEntriesForm from './MakeJournalEntriesForm';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { MakeJournalProvider } from './MakeJournalProvider';
|
||||
|
||||
import withCustomersActions from 'containers/Customers/withCustomersActions';
|
||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||
import withCurrenciesActions from 'containers/Currencies/withCurrenciesActions';
|
||||
import withSettingsActions from 'containers/Settings/withSettingsActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
import 'style/pages/ManualJournal/MakeJournal.scss'
|
||||
import 'style/pages/ManualJournal/MakeJournal.scss';
|
||||
|
||||
/**
|
||||
* Make journal entries page.
|
||||
*/
|
||||
function MakeJournalEntriesPage({
|
||||
// #withCustomersActions
|
||||
requestFetchCustomers,
|
||||
|
||||
// #withAccountsActions
|
||||
requestFetchAccounts,
|
||||
|
||||
// #withManualJournalActions
|
||||
requestFetchManualJournal,
|
||||
|
||||
// #wihtCurrenciesActions
|
||||
requestFetchCurrencies,
|
||||
|
||||
// #withSettingsActions
|
||||
requestFetchOptions,
|
||||
|
||||
// #withDashboardActions
|
||||
setSidebarShrink,
|
||||
resetSidebarPreviousExpand,
|
||||
setDashboardBackLink
|
||||
setDashboardBackLink,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const { id } = useParams();
|
||||
const { id: journalId } = useParams();
|
||||
|
||||
useEffect(() => {
|
||||
// Shrink the sidebar by foce.
|
||||
@@ -52,27 +34,7 @@ function MakeJournalEntriesPage({
|
||||
// Hide the back link on dashboard topbar.
|
||||
setDashboardBackLink(false);
|
||||
};
|
||||
}, [resetSidebarPreviousExpand, setSidebarShrink]);
|
||||
|
||||
const fetchAccounts = useQuery('accounts-list', (key) =>
|
||||
requestFetchAccounts(),
|
||||
);
|
||||
|
||||
const fetchCustomers = useQuery('customers-list', (key) =>
|
||||
requestFetchCustomers(),
|
||||
);
|
||||
|
||||
const fetchCurrencies = useQuery('currencies', () =>
|
||||
requestFetchCurrencies(),
|
||||
);
|
||||
|
||||
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
|
||||
|
||||
const fetchJournal = useQuery(
|
||||
['manual-journal', id],
|
||||
(key, journalId) => requestFetchManualJournal(journalId),
|
||||
{ enabled: id && id },
|
||||
);
|
||||
}, [resetSidebarPreviousExpand, setDashboardBackLink, setSidebarShrink]);
|
||||
|
||||
const handleFormSubmit = useCallback(
|
||||
(payload) => {
|
||||
@@ -86,29 +48,15 @@ function MakeJournalEntriesPage({
|
||||
}, [history]);
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={
|
||||
fetchJournal.isFetching ||
|
||||
fetchAccounts.isFetching ||
|
||||
fetchCurrencies.isFetching ||
|
||||
fetchCustomers.isFetching
|
||||
}
|
||||
name={'make-journal-page'}
|
||||
>
|
||||
<MakeJournalProvider journalId={journalId}>
|
||||
<MakeJournalEntriesForm
|
||||
onFormSubmit={handleFormSubmit}
|
||||
manualJournalId={id}
|
||||
onCancelForm={handleCancel}
|
||||
/>
|
||||
</DashboardInsider>
|
||||
</MakeJournalProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAccountsActions,
|
||||
withCustomersActions,
|
||||
withManualJournalsActions,
|
||||
withCurrenciesActions,
|
||||
withSettingsActions,
|
||||
withDashboardActions,
|
||||
)(MakeJournalEntriesPage);
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
||||
import { Button } from '@blueprintjs/core';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import { omit } from 'lodash';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { saveInvoke } from 'utils';
|
||||
import {
|
||||
AccountsListFieldCell,
|
||||
MoneyFieldCell,
|
||||
@@ -18,21 +18,13 @@ import {
|
||||
} from './components';
|
||||
import { DataTableEditable } from 'components';
|
||||
|
||||
import withAccounts from 'containers/Accounts/withAccounts';
|
||||
import withCustomers from 'containers/Customers/withCustomers';
|
||||
|
||||
import { updateDataReducer } from './utils';
|
||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
||||
|
||||
/**
|
||||
* Make journal entries table component.
|
||||
*/
|
||||
function MakeJournalEntriesTable({
|
||||
// #withCustomers
|
||||
customers,
|
||||
|
||||
// #withAccounts
|
||||
accountsList,
|
||||
|
||||
export default function MakeJournalEntriesTable({
|
||||
// #ownPorps
|
||||
onClickRemoveRow,
|
||||
onClickAddNewRow,
|
||||
@@ -44,6 +36,8 @@ function MakeJournalEntriesTable({
|
||||
const [rows, setRows] = useState([]);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const { accounts, customers } = useMakeJournalFormContext();
|
||||
|
||||
useEffect(() => {
|
||||
setRows([...entries.map((e) => ({ ...e, rowType: 'editor' }))]);
|
||||
}, [entries, setRows]);
|
||||
@@ -175,7 +169,7 @@ function MakeJournalEntriesTable({
|
||||
sticky={true}
|
||||
totalRow={true}
|
||||
payload={{
|
||||
accounts: accountsList,
|
||||
accounts,
|
||||
errors: error,
|
||||
updateData: handleUpdateData,
|
||||
removeRow: handleRemoveRow,
|
||||
@@ -209,12 +203,3 @@ function MakeJournalEntriesTable({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAccounts(({ accountsList }) => ({
|
||||
accountsList,
|
||||
})),
|
||||
withCustomers(({ customers }) => ({
|
||||
customers,
|
||||
})),
|
||||
)(MakeJournalEntriesTable);
|
||||
|
||||
@@ -12,73 +12,64 @@ import {
|
||||
import { useFormikContext } from 'formik';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import { saveInvoke } from 'utils';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { Icon, If } from 'components';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
||||
|
||||
/**
|
||||
* Make Journal floating actions bar.
|
||||
*/
|
||||
export default function MakeJournalFloatingAction({
|
||||
isSubmitting,
|
||||
onSubmitClick,
|
||||
onCancelClick,
|
||||
manualJournal,
|
||||
}) {
|
||||
const { submitForm, resetForm } = useFormikContext();
|
||||
export default function MakeJournalFloatingAction() {
|
||||
const history = useHistory();
|
||||
|
||||
// Formik context.
|
||||
const { submitForm, resetForm, isSubmitting } = useFormikContext();
|
||||
|
||||
// Make journal form context.
|
||||
const { setSubmitPayload, manualJournal } = useMakeJournalFormContext();
|
||||
|
||||
// Handle submit & publish button click.
|
||||
const handleSubmitPublishBtnClick = (event) => {
|
||||
saveInvoke(onSubmitClick, event, {
|
||||
redirect: true,
|
||||
publish: true,
|
||||
});
|
||||
submitForm();
|
||||
setSubmitPayload({ redirect: true, publish: true });
|
||||
};
|
||||
|
||||
// Handle submit, publish & new button click.
|
||||
const handleSubmitPublishAndNewBtnClick = (event) => {
|
||||
submitForm();
|
||||
saveInvoke(onSubmitClick, event, {
|
||||
redirect: false,
|
||||
publish: true,
|
||||
resetForm: true,
|
||||
});
|
||||
setSubmitPayload({ redirect: false, publish: true, resetForm: true });
|
||||
};
|
||||
|
||||
// Handle submit, publish & edit button click.
|
||||
const handleSubmitPublishContinueEditingBtnClick = (event) => {
|
||||
submitForm();
|
||||
saveInvoke(onSubmitClick, event, {
|
||||
redirect: false,
|
||||
publish: true,
|
||||
});
|
||||
setSubmitPayload({ redirect: false, publish: true });
|
||||
};
|
||||
|
||||
// Handle submit as draft button click.
|
||||
const handleSubmitDraftBtnClick = (event) => {
|
||||
saveInvoke(onSubmitClick, event, {
|
||||
redirect: true,
|
||||
publish: false,
|
||||
});
|
||||
setSubmitPayload({ redirect: true, publish: false });
|
||||
};
|
||||
|
||||
// Handle submit as draft & new button click.
|
||||
const handleSubmitDraftAndNewBtnClick = (event) => {
|
||||
submitForm();
|
||||
saveInvoke(onSubmitClick, event, {
|
||||
redirect: false,
|
||||
publish: false,
|
||||
resetForm: true,
|
||||
});
|
||||
setSubmitPayload({ redirect: false, publish: false, resetForm: true });
|
||||
};
|
||||
|
||||
// Handle submit as draft & continue editing button click.
|
||||
const handleSubmitDraftContinueEditingBtnClick = (event) => {
|
||||
submitForm();
|
||||
saveInvoke(onSubmitClick, event, {
|
||||
redirect: false,
|
||||
publish: false,
|
||||
});
|
||||
setSubmitPayload({ redirect: false, publish: false });
|
||||
};
|
||||
|
||||
// Handle cancel button click.
|
||||
const handleCancelBtnClick = (event) => {
|
||||
saveInvoke(onCancelClick, event);
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
// Handle clear button click.
|
||||
const handleClearBtnClick = (event) => {
|
||||
resetForm();
|
||||
};
|
||||
@@ -90,6 +81,7 @@ export default function MakeJournalFloatingAction({
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitPublishBtnClick}
|
||||
text={<T id={'save_publish'} />}
|
||||
@@ -114,6 +106,7 @@ export default function MakeJournalFloatingAction({
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
@@ -144,6 +137,7 @@ export default function MakeJournalFloatingAction({
|
||||
>
|
||||
<Button
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
@@ -173,6 +167,7 @@ export default function MakeJournalFloatingAction({
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
|
||||
@@ -9,14 +9,20 @@ import withManualJournals from './withManualJournals';
|
||||
import { defaultToTransform } from 'utils';
|
||||
|
||||
/**
|
||||
*
|
||||
* Journal number chaلing watcher.
|
||||
*/
|
||||
function MakeJournalNumberChangingWatcher({
|
||||
journalNumber,
|
||||
// #withDashboardActions
|
||||
changePageSubtitle,
|
||||
|
||||
// #withManualJournals
|
||||
journalNumberChanged,
|
||||
|
||||
// #withManualJournalsActions
|
||||
setJournalNumberChanged,
|
||||
changePageSubtitle
|
||||
|
||||
// #ownProps
|
||||
journalNumber,
|
||||
}) {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
||||
|
||||
87
client/src/containers/Accounting/MakeJournalProvider.js
Normal file
87
client/src/containers/Accounting/MakeJournalProvider.js
Normal file
@@ -0,0 +1,87 @@
|
||||
import React, { createContext, useState } from 'react';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import {
|
||||
useAccounts,
|
||||
useCustomers,
|
||||
useCurrencies,
|
||||
useJournal,
|
||||
useCreateJournal,
|
||||
useEditJournal,
|
||||
useSettings
|
||||
} from 'hooks/query';
|
||||
|
||||
const MakeJournalFormContext = createContext();
|
||||
|
||||
/**
|
||||
* Make journal form provider.
|
||||
*/
|
||||
function MakeJournalProvider({ journalId, ...props }) {
|
||||
// Load the accounts list.
|
||||
const { data: accounts, isFetching: isAccountsLoading } = useAccounts();
|
||||
|
||||
// Load the customers list.
|
||||
const {
|
||||
data: { customers },
|
||||
isFetching: isCustomersLoading,
|
||||
} = useCustomers();
|
||||
|
||||
// Load the currencies list.
|
||||
const { data: currencies, isFetching: isCurrenciesLoading } = useCurrencies();
|
||||
|
||||
// Load the details of the given manual journal.
|
||||
const { data: manualJournal, isFetching: isJournalLoading } = useJournal(
|
||||
journalId,
|
||||
{
|
||||
enabled: !!journalId,
|
||||
},
|
||||
);
|
||||
// Create and edit journal mutations.
|
||||
const { mutateAsync: createJournalMutate } = useCreateJournal();
|
||||
const { mutateAsync: editJournalMutate } = useEditJournal();
|
||||
|
||||
// Loading the journal settings.
|
||||
const { isFetching: isSettingsLoading } = useSettings();
|
||||
|
||||
const [submitPayload, setSubmitPayload] = useState({});
|
||||
|
||||
const provider = {
|
||||
accounts,
|
||||
customers,
|
||||
currencies,
|
||||
manualJournal,
|
||||
|
||||
createJournalMutate,
|
||||
editJournalMutate,
|
||||
|
||||
isAccountsLoading,
|
||||
isCustomersLoading,
|
||||
isCurrenciesLoading,
|
||||
isJournalLoading,
|
||||
isSettingsLoading,
|
||||
|
||||
isNewMode: !journalId,
|
||||
|
||||
submitPayload,
|
||||
setSubmitPayload
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={
|
||||
isJournalLoading ||
|
||||
isAccountsLoading ||
|
||||
isCurrenciesLoading ||
|
||||
isCustomersLoading ||
|
||||
isSettingsLoading
|
||||
}
|
||||
name={'make-journal-page'}
|
||||
>
|
||||
<MakeJournalFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
const useMakeJournalFormContext = () =>
|
||||
React.useContext(MakeJournalFormContext);
|
||||
|
||||
export { MakeJournalProvider, useMakeJournalFormContext };
|
||||
@@ -1,23 +1,21 @@
|
||||
import React, { useMemo, useState, useCallback } from 'react';
|
||||
import React from 'react';
|
||||
import Icon from 'components/Icon';
|
||||
import {
|
||||
Button,
|
||||
NavbarGroup,
|
||||
Classes,
|
||||
NavbarDivider,
|
||||
MenuItem,
|
||||
Menu,
|
||||
Popover,
|
||||
PopoverInteractionKind,
|
||||
Position,
|
||||
Intent,
|
||||
} from '@blueprintjs/core';
|
||||
import classNames from 'classnames';
|
||||
import { useRouteMatch, useHistory } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import FilterDropdown from 'components/FilterDropdown';
|
||||
import { useManualJournalsContext } from 'containers/Accounting/ManualJournalsListProvider';
|
||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
|
||||
@@ -33,53 +31,24 @@ import { compose } from 'utils';
|
||||
* Manual journal actions bar.
|
||||
*/
|
||||
function ManualJournalActionsBar({
|
||||
// #withResourceDetail
|
||||
resourceFields,
|
||||
|
||||
// #withManualJournals
|
||||
manualJournalsViews,
|
||||
|
||||
// #withManualJournalsActions
|
||||
addManualJournalsTableQueries,
|
||||
changeManualJournalCurrentView,
|
||||
|
||||
onFilterChanged,
|
||||
selectedRows = [],
|
||||
onBulkDelete,
|
||||
}) {
|
||||
const [filterCount, setFilterCount] = useState(0);
|
||||
const history = useHistory();
|
||||
const { journalsViews } = useManualJournalsContext();
|
||||
|
||||
const onClickNewManualJournal = useCallback(() => {
|
||||
// Handle click a new manual journal.
|
||||
const onClickNewManualJournal = () => {
|
||||
history.push('/make-journal-entry');
|
||||
}, [history]);
|
||||
|
||||
// const filterDropdown = FilterDropdown({
|
||||
// fields: resourceFields,
|
||||
// initialCondition: {
|
||||
// fieldKey: 'journal_number',
|
||||
// compatator: 'contains',
|
||||
// value: '',
|
||||
// },
|
||||
// onFilterChange: (filterConditions) => {
|
||||
// setFilterCount(filterConditions.length || 0);
|
||||
// addManualJournalsTableQueries({
|
||||
// filter_roles: filterConditions || '',
|
||||
// });
|
||||
// onFilterChanged && onFilterChanged(filterConditions);
|
||||
// },
|
||||
// });
|
||||
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [
|
||||
selectedRows,
|
||||
]);
|
||||
};
|
||||
|
||||
// Handle delete button click.
|
||||
const handleBulkDelete = useCallback(() => {
|
||||
onBulkDelete && onBulkDelete(selectedRows.map((r) => r.id));
|
||||
}, [onBulkDelete, selectedRows]);
|
||||
const handleBulkDelete = () => {
|
||||
|
||||
};
|
||||
|
||||
// Handle tab change.
|
||||
const handleTabChange = (viewId) => {
|
||||
changeManualJournalCurrentView(viewId.id || -1);
|
||||
addManualJournalsTableQueries({
|
||||
custom_view_id: viewId.id || null,
|
||||
});
|
||||
@@ -90,7 +59,7 @@ function ManualJournalActionsBar({
|
||||
<NavbarGroup>
|
||||
<DashboardActionViewsList
|
||||
resourceName={'manual-journals'}
|
||||
views={manualJournalsViews}
|
||||
views={journalsViews}
|
||||
onChange={handleTabChange}
|
||||
/>
|
||||
<NavbarDivider />
|
||||
@@ -109,14 +78,14 @@ function ManualJournalActionsBar({
|
||||
>
|
||||
<Button
|
||||
className={classNames(Classes.MINIMAL, 'button--filter', {
|
||||
'has-active-filters': filterCount > 0,
|
||||
'has-active-filters': false,
|
||||
})}
|
||||
text="Filter"
|
||||
icon={<Icon icon="filter-16" iconSize={16} />}
|
||||
/>
|
||||
</Popover>
|
||||
|
||||
<If condition={hasSelectedRows}>
|
||||
<If condition={false}>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="trash-16" iconSize={16} />}
|
||||
|
||||
15
client/src/containers/Accounting/ManualJournalsAlerts.js
Normal file
15
client/src/containers/Accounting/ManualJournalsAlerts.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import JournalDeleteAlert from 'containers/Alerts/ManualJournals/JournalDeleteAlert';
|
||||
import JournalPublishAlert from 'containers/Alerts/ManualJournals/JournalPublishAlert';
|
||||
|
||||
/**
|
||||
* Manual journals alerts.
|
||||
*/
|
||||
export default function ManualJournalsAlerts() {
|
||||
return (
|
||||
<div>
|
||||
<JournalDeleteAlert name={'journal-delete'} />
|
||||
<JournalPublishAlert name={'journal-publish'} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -3,13 +3,11 @@ import {
|
||||
Intent,
|
||||
Button,
|
||||
Popover,
|
||||
Tooltip,
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuDivider,
|
||||
Position,
|
||||
} from '@blueprintjs/core';
|
||||
import { withRouter, useParams } from 'react-router-dom';
|
||||
import { useIntl } from 'react-intl';
|
||||
import moment from 'moment';
|
||||
import classNames from 'classnames';
|
||||
@@ -17,68 +15,59 @@ import classNames from 'classnames';
|
||||
import {
|
||||
DataTable,
|
||||
If,
|
||||
Money,
|
||||
Choose,
|
||||
Icon,
|
||||
LoadingIndicator,
|
||||
} from 'components';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import ManualJournalsEmptyStatus from './ManualJournalsEmptyStatus';
|
||||
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
|
||||
import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
|
||||
import {
|
||||
AmountPopoverContent,
|
||||
NoteAccessor,
|
||||
StatusAccessor,
|
||||
DateAccessor,
|
||||
AmountAccessor
|
||||
} from './components';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withManualJournals from 'containers/Accounting/withManualJournals';
|
||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useManualJournalsContext } from './ManualJournalsListProvider';
|
||||
|
||||
|
||||
/**
|
||||
* Manual journals data-table.
|
||||
*/
|
||||
function ManualJournalsDataTable({
|
||||
// #withManualJournals
|
||||
manualJournalsCurrentPage,
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
manualJournalsCurrentViewId,
|
||||
|
||||
// #withManualJournalsActions
|
||||
addManualJournalsTableQueries,
|
||||
|
||||
// #ownProps
|
||||
onEditJournal,
|
||||
onDeleteJournal,
|
||||
onPublishJournal,
|
||||
onSelectedRowsChange,
|
||||
manualJournalViewLoading,
|
||||
}) {
|
||||
const { custom_view_id: customViewId } = useParams();
|
||||
const { formatMessage } = useIntl();
|
||||
const isLoadedBefore = useIsValuePassed(manualJournalsLoading, false);
|
||||
|
||||
const { manualJournals, isManualJournalsLoading } = useManualJournalsContext();
|
||||
|
||||
const handlePublishJournal = useCallback(
|
||||
(journal) => () => {
|
||||
saveInvoke(onPublishJournal, journal);
|
||||
|
||||
},
|
||||
[onPublishJournal],
|
||||
[],
|
||||
);
|
||||
|
||||
const handleEditJournal = useCallback(
|
||||
(journal) => () => {
|
||||
saveInvoke(onEditJournal, journal);
|
||||
|
||||
},
|
||||
[onEditJournal],
|
||||
[],
|
||||
);
|
||||
|
||||
const handleDeleteJournal = useCallback(
|
||||
(journal) => () => {
|
||||
saveInvoke(onDeleteJournal, journal);
|
||||
|
||||
},
|
||||
[onDeleteJournal],
|
||||
[],
|
||||
);
|
||||
|
||||
const actionMenuList = useCallback(
|
||||
@@ -127,22 +116,14 @@ function ManualJournalsDataTable({
|
||||
{
|
||||
id: 'date',
|
||||
Header: formatMessage({ id: 'date' }),
|
||||
accessor: (r) => moment(r.date).format('YYYY MMM DD'),
|
||||
accessor: DateAccessor,
|
||||
width: 115,
|
||||
className: 'date',
|
||||
},
|
||||
{
|
||||
id: 'amount',
|
||||
Header: formatMessage({ id: 'amount' }),
|
||||
accessor: (r) => (
|
||||
<Tooltip
|
||||
content={<AmountPopoverContent journalEntries={r.entries} />}
|
||||
position={Position.RIGHT_TOP}
|
||||
boundary={'viewport'}
|
||||
>
|
||||
<Money amount={r.amount} currency={'USD'} />
|
||||
</Tooltip>
|
||||
),
|
||||
accessor: AmountAccessor,
|
||||
className: 'amount',
|
||||
width: 115,
|
||||
},
|
||||
@@ -227,66 +208,42 @@ function ManualJournalsDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
manualJournalsCurrentViewId === -1,
|
||||
manualJournalsCurrentPage.length === 0,
|
||||
].every((condition) => condition === true);
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
||||
<LoadingIndicator
|
||||
loading={
|
||||
(manualJournalsLoading && !isLoadedBefore) || manualJournalViewLoading
|
||||
}
|
||||
>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<ManualJournalsEmptyStatus />
|
||||
</Choose.When>
|
||||
<Choose>
|
||||
<Choose.When condition={false}>
|
||||
<ManualJournalsEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={manualJournalsCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
expandable={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagesCount={manualJournalsPagination.pagesCount}
|
||||
pagination={true}
|
||||
initialPageSize={manualJournalsTableQuery.page_size}
|
||||
initialPageIndex={manualJournalsTableQuery.page - 1}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={manualJournals}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
expandable={true}
|
||||
sticky={true}
|
||||
loading={isManualJournalsLoading}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
// pagesCount={manualJournalsPagination.pagesCount}
|
||||
pagination={true}
|
||||
// initialPageSize={manualJournalsTableQuery.page_size}
|
||||
// initialPageIndex={manualJournalsTableQuery.page - 1}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
|
||||
TableLoadingRenderer={TableSkeletonRows}
|
||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withRouter,
|
||||
withDialogActions,
|
||||
withManualJournalsActions,
|
||||
withManualJournals(
|
||||
({
|
||||
manualJournalsCurrentPage,
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
manualJournalsCurrentViewId,
|
||||
}) => ({
|
||||
manualJournalsCurrentPage,
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
manualJournalsCurrentViewId,
|
||||
}),
|
||||
),
|
||||
)(ManualJournalsDataTable);
|
||||
|
||||
@@ -1,31 +1,26 @@
|
||||
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
import { Route, Switch, useHistory, withRouter } from 'react-router-dom';
|
||||
import { queryCache, useQuery } from 'react-query';
|
||||
import { Alert, Intent } from '@blueprintjs/core';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { Route, Switch, useHistory } from 'react-router-dom';
|
||||
import {
|
||||
FormattedMessage as T,
|
||||
useIntl,
|
||||
} from 'react-intl';
|
||||
|
||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
|
||||
import ManualJournalsViewTabs from 'containers/Accounting/ManualJournalsViewTabs';
|
||||
import ManualJournalsDataTable from 'containers/Accounting/ManualJournalsDataTable';
|
||||
import ManualJournalsActionsBar from 'containers/Accounting/ManualJournalActionsBar';
|
||||
import { ManualJournalsListProvider } from './ManualJournalsListProvider';
|
||||
import ManualJournalsAlerts from './ManualJournalsAlerts';
|
||||
import ManualJournalsViewTabs from './ManualJournalsViewTabs';
|
||||
import ManualJournalsDataTable from './ManualJournalsDataTable';
|
||||
import ManualJournalsActionsBar from './ManualJournalActionsBar';
|
||||
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withManualJournals from 'containers/Accounting/withManualJournals';
|
||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||
import withViewsActions from 'containers/Views/withViewsActions';
|
||||
import withRouteActions from 'containers/Router/withRouteActions';
|
||||
import withResourceActions from 'containers/Resources/withResourcesActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
import 'style/pages/ManualJournal/List.scss';
|
||||
|
||||
|
||||
/**
|
||||
* Manual journals table.
|
||||
*/
|
||||
@@ -33,117 +28,17 @@ function ManualJournalsTable({
|
||||
// #withDashboardActions
|
||||
changePageTitle,
|
||||
|
||||
// #withViewsActions
|
||||
requestFetchResourceViews,
|
||||
|
||||
// #withResourceActions
|
||||
requestFetchResourceFields,
|
||||
|
||||
// #withManualJournals
|
||||
manualJournalsTableQuery,
|
||||
|
||||
// #withManualJournalsActions
|
||||
requestFetchManualJournalsTable,
|
||||
requestDeleteManualJournal,
|
||||
requestPublishManualJournal,
|
||||
requestDeleteBulkManualJournals,
|
||||
addManualJournalsTableQueries,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
|
||||
const [deleteManualJournal, setDeleteManualJournal] = useState(false);
|
||||
const [selectedRows, setSelectedRows] = useState([]);
|
||||
const [bulkDelete, setBulkDelete] = useState(false);
|
||||
const [publishManualJournal, setPublishManualJournal] = useState(false);
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const fetchResourceViews = useQuery(
|
||||
['resource-views', 'manual-journals'],
|
||||
() => requestFetchResourceViews('manual_journals'),
|
||||
);
|
||||
|
||||
// const fetchResourceFields = useQuery(
|
||||
// ['resource-fields', 'manual-journals'],
|
||||
// () => requestFetchResourceFields('manual_journals'),
|
||||
// );
|
||||
|
||||
const fetchManualJournals = useQuery(
|
||||
['manual-journals-table', manualJournalsTableQuery],
|
||||
(key, q) => requestFetchManualJournalsTable(),
|
||||
);
|
||||
|
||||
// Handle update the page title.
|
||||
useEffect(() => {
|
||||
changePageTitle(formatMessage({ id: 'manual_journals' }));
|
||||
}, [changePageTitle, formatMessage]);
|
||||
|
||||
// Handle delete manual journal click.
|
||||
const handleDeleteJournal = useCallback(
|
||||
(journal) => {
|
||||
setDeleteManualJournal(journal);
|
||||
},
|
||||
[setDeleteManualJournal],
|
||||
);
|
||||
|
||||
// Handle cancel delete manual journal.
|
||||
const handleCancelManualJournalDelete = useCallback(() => {
|
||||
setDeleteManualJournal(false);
|
||||
}, [setDeleteManualJournal]);
|
||||
|
||||
// Handle confirm delete manual journal.
|
||||
const handleConfirmManualJournalDelete = useCallback(() => {
|
||||
requestDeleteManualJournal(deleteManualJournal.id).then(() => {
|
||||
AppToaster.show({
|
||||
message: formatMessage(
|
||||
{ id: 'the_journal_has_been_deleted_successfully' },
|
||||
{ number: deleteManualJournal.journal_number },
|
||||
),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setDeleteManualJournal(false);
|
||||
});
|
||||
}, [deleteManualJournal, requestDeleteManualJournal, formatMessage]);
|
||||
|
||||
// Calculates the selected rows count.
|
||||
const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [
|
||||
selectedRows,
|
||||
]);
|
||||
|
||||
const handleBulkDelete = useCallback(
|
||||
(accountsIds) => {
|
||||
setBulkDelete(accountsIds);
|
||||
},
|
||||
[setBulkDelete],
|
||||
);
|
||||
|
||||
// Handle confirm journals bulk delete.
|
||||
const handleConfirmBulkDelete = useCallback(() => {
|
||||
requestDeleteBulkManualJournals(bulkDelete)
|
||||
.then(() => {
|
||||
setBulkDelete(false);
|
||||
AppToaster.show({
|
||||
message: formatMessage(
|
||||
{ id: 'the_journals_has_been_deleted_successfully' },
|
||||
{ count: selectedRowsCount },
|
||||
),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
setBulkDelete(false);
|
||||
});
|
||||
}, [
|
||||
requestDeleteBulkManualJournals,
|
||||
bulkDelete,
|
||||
formatMessage,
|
||||
selectedRowsCount,
|
||||
]);
|
||||
|
||||
// Handle cancel bulk delete alert.
|
||||
const handleCancelBulkDelete = useCallback(() => {
|
||||
setBulkDelete(false);
|
||||
}, []);
|
||||
|
||||
const handleEditJournal = useCallback(
|
||||
(journal) => {
|
||||
history.push(`/manual-journals/${journal.id}/edit`);
|
||||
@@ -154,79 +49,9 @@ function ManualJournalsTable({
|
||||
// Handle filter change to re-fetch data-table.
|
||||
const handleFilterChanged = useCallback(() => {}, []);
|
||||
|
||||
// Handle view change to re-fetch data table.
|
||||
// const handleViewChanged = useCallback(() => {
|
||||
|
||||
// }, [fetchManualJournals]);
|
||||
|
||||
// Handle fetch data of manual jouranls datatable.
|
||||
const handleFetchData = useCallback(
|
||||
({ pageIndex, pageSize, sortBy }) => {
|
||||
const page = pageIndex + 1;
|
||||
|
||||
addManualJournalsTableQueries({
|
||||
...(sortBy.length > 0
|
||||
? {
|
||||
column_sort_by: sortBy[0].id,
|
||||
sort_order: sortBy[0].desc ? 'desc' : 'asc',
|
||||
}
|
||||
: {}),
|
||||
page_size: pageSize,
|
||||
page,
|
||||
});
|
||||
},
|
||||
[addManualJournalsTableQueries],
|
||||
);
|
||||
|
||||
// Handle publish manual Journal click.
|
||||
const handlePublishMaunalJournal = useCallback(
|
||||
(jouranl) => {
|
||||
setPublishManualJournal(jouranl);
|
||||
},
|
||||
[setPublishManualJournal],
|
||||
);
|
||||
|
||||
// Handle cancel manual journal alert.
|
||||
const handleCancelPublishMaunalJournal = useCallback(() => {
|
||||
setPublishManualJournal(false);
|
||||
}, [setPublishManualJournal]);
|
||||
|
||||
// Handle publish manual journal confirm.
|
||||
const handleConfirmPublishManualJournal = useCallback(() => {
|
||||
requestPublishManualJournal(publishManualJournal.id)
|
||||
.then(() => {
|
||||
setPublishManualJournal(false);
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'the_manual_journal_has_been_published',
|
||||
}),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
queryCache.invalidateQueries('manual-journals-table');
|
||||
})
|
||||
.catch((error) => {
|
||||
setPublishManualJournal(false);
|
||||
});
|
||||
}, [publishManualJournal, requestPublishManualJournal, formatMessage]);
|
||||
|
||||
// Handle selected rows change.
|
||||
const handleSelectedRowsChange = useCallback(
|
||||
(accounts) => {
|
||||
setSelectedRows(accounts);
|
||||
},
|
||||
[setSelectedRows],
|
||||
);
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={fetchResourceViews.isFetching}
|
||||
name={'manual-journals'}
|
||||
>
|
||||
<ManualJournalsActionsBar
|
||||
onBulkDelete={handleBulkDelete}
|
||||
selectedRows={selectedRows}
|
||||
onFilterChanged={handleFilterChanged}
|
||||
/>
|
||||
<ManualJournalsListProvider query={manualJournalsTableQuery}>
|
||||
<ManualJournalsActionsBar />
|
||||
|
||||
<DashboardPageContent>
|
||||
<Switch>
|
||||
@@ -238,72 +63,17 @@ function ManualJournalsTable({
|
||||
]}
|
||||
>
|
||||
<ManualJournalsViewTabs />
|
||||
|
||||
<ManualJournalsDataTable
|
||||
onDeleteJournal={handleDeleteJournal}
|
||||
onEditJournal={handleEditJournal}
|
||||
onPublishJournal={handlePublishMaunalJournal}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
manualJournalViewLoading={fetchManualJournals.isFetching}
|
||||
/>
|
||||
<ManualJournalsDataTable />
|
||||
<ManualJournalsAlerts />
|
||||
</Route>
|
||||
</Switch>
|
||||
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'delete'} />}
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={deleteManualJournal}
|
||||
onCancel={handleCancelManualJournalDelete}
|
||||
onConfirm={handleConfirmManualJournalDelete}
|
||||
>
|
||||
<p>
|
||||
<T id={'once_delete_this_journal_you_will_able_to_restore_it'} />
|
||||
</p>
|
||||
</Alert>
|
||||
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={
|
||||
<T id={'delete_count'} values={{ count: selectedRowsCount }} />
|
||||
}
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={bulkDelete}
|
||||
onCancel={handleCancelBulkDelete}
|
||||
onConfirm={handleConfirmBulkDelete}
|
||||
>
|
||||
<p>
|
||||
<T
|
||||
id={'once_delete_these_journals_you_will_not_able_restore_them'}
|
||||
/>
|
||||
</p>
|
||||
</Alert>
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'publish'} />}
|
||||
intent={Intent.WARNING}
|
||||
isOpen={publishManualJournal}
|
||||
onCancel={handleCancelPublishMaunalJournal}
|
||||
onConfirm={handleConfirmPublishManualJournal}
|
||||
>
|
||||
<p>
|
||||
<T id={'are_sure_to_publish_this_manual_journal'} />
|
||||
</p>
|
||||
</Alert>
|
||||
</DashboardPageContent>
|
||||
</DashboardInsider>
|
||||
</ManualJournalsListProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withRouter,
|
||||
withRouteActions,
|
||||
withDashboardActions,
|
||||
withManualJournalsActions,
|
||||
withViewsActions,
|
||||
withResourceActions,
|
||||
withManualJournals(({ manualJournalsTableQuery }) => ({
|
||||
manualJournalsTableQuery,
|
||||
})),
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import React, { createContext } from 'react';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { useResourceViews, useJournals } from 'hooks/query';
|
||||
|
||||
const ManualJournalsContext = createContext();
|
||||
|
||||
function ManualJournalsListProvider({ query, ...props }) {
|
||||
// Fetches accounts resource views and fields.
|
||||
const { data: journalsViews, isFetching: isViewsLoading } = useResourceViews(
|
||||
'manual_journals',
|
||||
);
|
||||
|
||||
// Fetches the manual journals transactions with pagination meta.
|
||||
const {
|
||||
data: { manualJournals },
|
||||
isFetching: isManualJournalsLoading,
|
||||
} = useJournals(query);
|
||||
|
||||
// Global state.
|
||||
const state = {
|
||||
manualJournals,
|
||||
journalsViews,
|
||||
|
||||
isManualJournalsLoading,
|
||||
isViewsLoading,
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={isViewsLoading} name={'manual-journals'}>
|
||||
<ManualJournalsContext.Provider value={state} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
const useManualJournalsContext = () => React.useContext(ManualJournalsContext);
|
||||
|
||||
export { ManualJournalsListProvider, useManualJournalsContext };
|
||||
@@ -1,61 +1,38 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import React from 'react';
|
||||
import { Alignment, Navbar, NavbarGroup } from '@blueprintjs/core';
|
||||
import { useParams, withRouter } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { pick } from 'lodash';
|
||||
|
||||
import { DashboardViewsTabs, Icon } from 'components';
|
||||
import { DashboardViewsTabs } from 'components';
|
||||
|
||||
import withManualJournals from './withManualJournals';
|
||||
import { useManualJournalsContext } from './ManualJournalsListProvider';
|
||||
import withManualJournalsActions from './withManualJournalsActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withViewDetail from 'containers/Views/withViewDetails';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
|
||||
/**
|
||||
* Manual journal views tabs.
|
||||
*/
|
||||
function ManualJournalsViewTabs({
|
||||
// #withViewDetail
|
||||
viewId,
|
||||
viewItem,
|
||||
|
||||
// #withManualJournals
|
||||
manualJournalsViews,
|
||||
|
||||
// #withManualJournalsActions
|
||||
addManualJournalsTableQueries,
|
||||
changeManualJournalCurrentView,
|
||||
|
||||
// #withDashboardActions
|
||||
setTopbarEditView,
|
||||
changePageSubtitle,
|
||||
|
||||
// #ownProps
|
||||
onViewChanged,
|
||||
}) {
|
||||
const { custom_view_id: customViewId } = useParams();
|
||||
const { journalsViews } = useManualJournalsContext();
|
||||
|
||||
useEffect(() => {
|
||||
setTopbarEditView(customViewId);
|
||||
changePageSubtitle(customViewId && viewItem ? viewItem.name : '');
|
||||
}, [customViewId]);
|
||||
|
||||
const tabs = manualJournalsViews.map((view) => ({
|
||||
const tabs = journalsViews.map((view) => ({
|
||||
...pick(view, ['name', 'id']),
|
||||
}));
|
||||
|
||||
const handleClickNewView = () => {};
|
||||
|
||||
const handleTabChange = (viewId) => {
|
||||
changeManualJournalCurrentView(viewId || -1);
|
||||
addManualJournalsTableQueries({
|
||||
custom_view_id: viewId || null,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Navbar className="navbar--dashboard-views">
|
||||
<NavbarGroup align={Alignment.LEFT}>
|
||||
@@ -71,19 +48,7 @@ function ManualJournalsViewTabs({
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
viewId: parseInt(ownProps.match.params.custom_view_id, 10),
|
||||
});
|
||||
|
||||
const withManualJournalsViewTabs = connect(mapStateToProps);
|
||||
|
||||
export default compose(
|
||||
withRouter,
|
||||
withManualJournalsViewTabs,
|
||||
withManualJournals(({ manualJournalsViews }) => ({
|
||||
manualJournalsViews,
|
||||
})),
|
||||
withManualJournalsActions,
|
||||
withDashboardActions,
|
||||
withViewDetail(),
|
||||
)(ManualJournalsViewTabs);
|
||||
|
||||
@@ -1,10 +1,31 @@
|
||||
import React from 'react';
|
||||
import { Intent, Classes, Tooltip, Position, Tag, Button } from '@blueprintjs/core';
|
||||
import {
|
||||
Intent,
|
||||
Classes,
|
||||
Tooltip,
|
||||
Position,
|
||||
Tag,
|
||||
Button,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import moment from 'moment';
|
||||
import { Choose, Money, If, Icon, Hint } from 'components';
|
||||
|
||||
import withAccountDetails from 'containers/Accounts/withAccountDetail';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
// Amount accessor.
|
||||
export const AmountAccessor = (r) => (
|
||||
<Tooltip
|
||||
content={<AmountPopoverContent journalEntries={r.entries} />}
|
||||
position={Position.RIGHT_TOP}
|
||||
boundary={'viewport'}
|
||||
>
|
||||
<Money amount={r.amount} currency={'USD'} />
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const AmountPopoverContentLineRender = ({
|
||||
journalEntry,
|
||||
accountId,
|
||||
@@ -77,6 +98,13 @@ export const StatusAccessor = (row) => {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Date accessor.
|
||||
*/
|
||||
export const DateAccessor = (row) => {
|
||||
return moment(row.date).format('YYYY MMM DD');
|
||||
};
|
||||
|
||||
/**
|
||||
* Note column accessor.
|
||||
*/
|
||||
@@ -156,7 +184,11 @@ export const TotalCreditDebitCellRenderer = (chainedComponent, type) => (
|
||||
return computed;
|
||||
}, 0);
|
||||
|
||||
return <span><Money amount={total} currency={'USD'} /></span>;
|
||||
return (
|
||||
<span>
|
||||
<Money amount={total} currency={'USD'} />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return chainedComponent(props);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user