mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
Merge remote-tracking branch 'origin/task_expense_journal'
This commit is contained in:
@@ -34,6 +34,7 @@ const ERROR = {
|
|||||||
VENDORS_NOT_WITH_PAYABLE_ACCOUNT: 'VENDORS.NOT.WITH.PAYABLE.ACCOUNT',
|
VENDORS_NOT_WITH_PAYABLE_ACCOUNT: 'VENDORS.NOT.WITH.PAYABLE.ACCOUNT',
|
||||||
PAYABLE_ENTRIES_HAS_NO_VENDORS: 'PAYABLE.ENTRIES.HAS.NO.VENDORS',
|
PAYABLE_ENTRIES_HAS_NO_VENDORS: 'PAYABLE.ENTRIES.HAS.NO.VENDORS',
|
||||||
RECEIVABLE_ENTRIES_HAS_NO_CUSTOMERS: 'RECEIVABLE.ENTRIES.HAS.NO.CUSTOMERS',
|
RECEIVABLE_ENTRIES_HAS_NO_CUSTOMERS: 'RECEIVABLE.ENTRIES.HAS.NO.CUSTOMERS',
|
||||||
|
CREDIT_DEBIT_SUMATION_SHOULD_NOT_EQUAL_ZERO:'CREDIT.DEBIT.SUMATION.SHOULD.NOT.EQUAL.ZERO'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,6 +58,7 @@ function MakeJournalEntriesForm({
|
|||||||
onFormSubmit,
|
onFormSubmit,
|
||||||
onCancelForm,
|
onCancelForm,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const {
|
const {
|
||||||
setFiles,
|
setFiles,
|
||||||
@@ -68,10 +70,12 @@ function MakeJournalEntriesForm({
|
|||||||
saveCallback: requestSubmitMedia,
|
saveCallback: requestSubmitMedia,
|
||||||
deleteCallback: requestDeleteMedia,
|
deleteCallback: requestDeleteMedia,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDropFiles = useCallback((_files) => {
|
const handleDropFiles = useCallback((_files) => {
|
||||||
setFiles(_files.filter((file) => file.uploaded === false));
|
setFiles(_files.filter((file) => file.uploaded === false));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const savedMediaIds = useRef([]);
|
const savedMediaIds = useRef([]);
|
||||||
const clearSavedMediaIds = () => {
|
const clearSavedMediaIds = () => {
|
||||||
savedMediaIds.current = [];
|
savedMediaIds.current = [];
|
||||||
@@ -238,12 +242,15 @@ function MakeJournalEntriesForm({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
setErrors({ ...newErrors });
|
setErrors({ ...newErrors });
|
||||||
AppToaster.show({
|
|
||||||
message: toastMessages.map((message) => {
|
if (toastMessages.length > 0) {
|
||||||
return <div>- {message}</div>;
|
AppToaster.show({
|
||||||
}),
|
message: toastMessages.map((message) => {
|
||||||
intent: Intent.DANGER,
|
return <div>- {message}</div>;
|
||||||
});
|
}),
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ function MakeJournalEntriesPage({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleCancel = useCallback(() => {
|
const handleCancel = useCallback(() => {
|
||||||
history.push('/manual-journals');
|
history.goBack();
|
||||||
}, [history]);
|
}, [history]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ function ManualJournalActionsBar({
|
|||||||
addManualJournalsTableQueries,
|
addManualJournalsTableQueries,
|
||||||
|
|
||||||
onFilterChanged,
|
onFilterChanged,
|
||||||
selectedRows,
|
selectedRows = [],
|
||||||
onBulkDelete,
|
onBulkDelete,
|
||||||
}) {
|
}) {
|
||||||
const { path } = useRouteMatch();
|
const { path } = useRouteMatch();
|
||||||
@@ -73,9 +73,9 @@ function ManualJournalActionsBar({
|
|||||||
onFilterChanged && onFilterChanged(filterConditions);
|
onFilterChanged && onFilterChanged(filterConditions);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [
|
const hasSelectedRows = useMemo(
|
||||||
selectedRows,
|
() => selectedRows.length > 0,
|
||||||
]);
|
[selectedRows]);
|
||||||
|
|
||||||
// Handle delete button click.
|
// Handle delete button click.
|
||||||
const handleBulkDelete = useCallback(() => {
|
const handleBulkDelete = useCallback(() => {
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import withManualJournals from 'containers/Accounting/withManualJournals';
|
|||||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status column accessor.
|
* Status column accessor.
|
||||||
*/
|
*/
|
||||||
function StatusAccessor(row) {
|
const StatusAccessor = (row) => {
|
||||||
return (
|
return (
|
||||||
<Choose>
|
<Choose>
|
||||||
<Choose.When condition={!!row.status}>
|
<Choose.When condition={!!row.status}>
|
||||||
@@ -41,7 +41,7 @@ function StatusAccessor(row) {
|
|||||||
</Choose.Otherwise>
|
</Choose.Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note column accessor.
|
* Note column accessor.
|
||||||
@@ -115,12 +115,12 @@ function ManualJournalsDataTable({
|
|||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem text={formatMessage({ id: 'view_details' })} />
|
<MenuItem text={formatMessage({ id: 'view_details' })} />
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
{!journal.status && (
|
<If condition={!journal.status}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text={formatMessage({ id: 'publish_journal' })}
|
text={formatMessage({ id: 'publish_journal' })}
|
||||||
onClick={handlePublishJournal(journal)}
|
onClick={handlePublishJournal(journal)}
|
||||||
/>
|
/>
|
||||||
)}
|
</If>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text={formatMessage({ id: 'edit_journal' })}
|
text={formatMessage({ id: 'edit_journal' })}
|
||||||
onClick={handleEditJournal(journal)}
|
onClick={handleEditJournal(journal)}
|
||||||
@@ -230,20 +230,29 @@ function ManualJournalsDataTable({
|
|||||||
},
|
},
|
||||||
[onSelectedRowsChange],
|
[onSelectedRowsChange],
|
||||||
);
|
);
|
||||||
|
const selectionColumn = useMemo(
|
||||||
|
() => ({
|
||||||
|
minWidth: 40,
|
||||||
|
width: 40,
|
||||||
|
maxWidth: 40,
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataTable
|
<DataTable
|
||||||
|
noInitialFetch={true}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={manualJournalsCurrentPage}
|
data={manualJournalsCurrentPage}
|
||||||
onFetchData={handleDataTableFetchData}
|
onFetchData={handleDataTableFetchData}
|
||||||
manualSortBy={true}
|
manualSortBy={true}
|
||||||
selectionColumn={true}
|
selectionColumn={selectionColumn}
|
||||||
noInitialFetch={true}
|
expandable={true}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
loading={manualJournalsLoading && !isMounted}
|
|
||||||
onSelectedRowsChange={handleSelectedRowsChange}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
pagination={true}
|
loading={manualJournalsLoading && !isMounted}
|
||||||
rowContextMenu={onRowContextMenu}
|
rowContextMenu={onRowContextMenu}
|
||||||
|
pagination={true}
|
||||||
pagesCount={manualJournalsPagination.pagesCount}
|
pagesCount={manualJournalsPagination.pagesCount}
|
||||||
initialPageSize={manualJournalsTableQuery.page_size}
|
initialPageSize={manualJournalsTableQuery.page_size}
|
||||||
initialPageIndex={manualJournalsTableQuery.page - 1}
|
initialPageIndex={manualJournalsTableQuery.page - 1}
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ import { Route, Switch, useHistory, withRouter } from 'react-router-dom';
|
|||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { Alert, Intent } from '@blueprintjs/core';
|
import { Alert, Intent } from '@blueprintjs/core';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import {
|
||||||
|
FormattedMessage as T,
|
||||||
|
useIntl,
|
||||||
|
FormattedHTMLMessage,
|
||||||
|
} from 'react-intl';
|
||||||
|
|
||||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||||
@@ -114,6 +118,7 @@ function ManualJournalsTable({
|
|||||||
const handleConfirmBulkDelete = useCallback(() => {
|
const handleConfirmBulkDelete = useCallback(() => {
|
||||||
requestDeleteBulkManualJournals(bulkDelete)
|
requestDeleteBulkManualJournals(bulkDelete)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
setBulkDelete(false);
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: formatMessage(
|
message: formatMessage(
|
||||||
{ id: 'the_journals_has_been_successfully_deleted' },
|
{ id: 'the_journals_has_been_successfully_deleted' },
|
||||||
@@ -121,7 +126,6 @@ function ManualJournalsTable({
|
|||||||
),
|
),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
setBulkDelete(false);
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
setBulkDelete(false);
|
setBulkDelete(false);
|
||||||
@@ -181,6 +185,7 @@ function ManualJournalsTable({
|
|||||||
message: formatMessage({
|
message: formatMessage({
|
||||||
id: 'the_manual_journal_id_has_been_published',
|
id: 'the_manual_journal_id_has_been_published',
|
||||||
}),
|
}),
|
||||||
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -237,11 +242,7 @@ function ManualJournalsTable({
|
|||||||
onConfirm={handleConfirmManualJournalDelete}
|
onConfirm={handleConfirmManualJournalDelete}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
<T
|
<T id={'once_delete_this_journal_you_will_able_to_restore_it'} />
|
||||||
id={
|
|
||||||
'once_delete_this_journal_category_you_will_able_to_restore_it'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</p>
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
@@ -258,7 +259,7 @@ function ManualJournalsTable({
|
|||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
<T
|
<T
|
||||||
id={'once_delete_these_journalss_you_will_not_able_restore_them'}
|
id={'once_delete_these_journals_you_will_not_able_restore_them'}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import { Alignment, Navbar, NavbarGroup } from '@blueprintjs/core';
|
||||||
Alignment,
|
|
||||||
Navbar,
|
|
||||||
NavbarGroup,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import { useParams, withRouter } from 'react-router-dom';
|
import { useParams, withRouter } from 'react-router-dom';
|
||||||
import { pick, debounce } from 'lodash';
|
import { pick, debounce } from 'lodash';
|
||||||
|
|
||||||
@@ -38,13 +34,14 @@ function AccountsViewsTabs({
|
|||||||
customViewChanged,
|
customViewChanged,
|
||||||
onViewChanged,
|
onViewChanged,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { custom_view_id: customViewId = null } = useParams();
|
const { custom_view_id: customViewId = null } = useParams();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
changeAccountsCurrentView(customViewId || -1);
|
changeAccountsCurrentView(customViewId || -1);
|
||||||
setTopbarEditView(customViewId);
|
setTopbarEditView(customViewId);
|
||||||
changePageSubtitle((customViewId && viewItem) ? viewItem.name : '');
|
changePageSubtitle(customViewId && viewItem ? viewItem.name : '');
|
||||||
|
|
||||||
addAccountsTableQueries({
|
addAccountsTableQueries({
|
||||||
custom_view_id: customViewId,
|
custom_view_id: customViewId,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
Tag,
|
Tag,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { withRouter } from 'react-router';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
|||||||
import withViewDetails from 'containers/Views/withViewDetails';
|
import withViewDetails from 'containers/Views/withViewDetails';
|
||||||
import withExpenses from 'containers/Expenses/withExpenses';
|
import withExpenses from 'containers/Expenses/withExpenses';
|
||||||
import withExpensesActions from 'containers/Expenses/withExpensesActions';
|
import withExpensesActions from 'containers/Expenses/withExpensesActions';
|
||||||
|
import withCurrentView from 'containers/Views/withCurrentView';
|
||||||
|
|
||||||
function ExpensesDataTable({
|
function ExpensesDataTable({
|
||||||
//#withExpenes
|
//#withExpenes
|
||||||
@@ -55,6 +57,10 @@ function ExpensesDataTable({
|
|||||||
const [initialMount, setInitialMount] = useState(false);
|
const [initialMount, setInitialMount] = useState(false);
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
setInitialMount(false)
|
||||||
|
},[customViewId])
|
||||||
|
|
||||||
useUpdateEffect(() => {
|
useUpdateEffect(() => {
|
||||||
if (!expensesLoading) {
|
if (!expensesLoading) {
|
||||||
setInitialMount(true);
|
setInitialMount(true);
|
||||||
@@ -260,7 +266,7 @@ function ExpensesDataTable({
|
|||||||
selectionColumn={true}
|
selectionColumn={true}
|
||||||
noInitialFetch={true}
|
noInitialFetch={true}
|
||||||
sticky={true}
|
sticky={true}
|
||||||
loading={expensesLoading}
|
loading={expensesLoading && !initialMount}
|
||||||
onSelectedRowsChange={handleSelectedRowsChange}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
rowContextMenu={onRowContextMenu}
|
rowContextMenu={onRowContextMenu}
|
||||||
pagination={true}
|
pagination={true}
|
||||||
@@ -274,6 +280,8 @@ function ExpensesDataTable({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
|
withRouter,
|
||||||
|
withCurrentView,
|
||||||
withDialogActions,
|
withDialogActions,
|
||||||
withDashboardActions,
|
withDashboardActions,
|
||||||
withExpensesActions,
|
withExpensesActions,
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ import useMedia from 'hooks/useMedia';
|
|||||||
import { compose, repeatValue } from 'utils';
|
import { compose, repeatValue } from 'utils';
|
||||||
|
|
||||||
const MIN_LINES_NUMBER = 4;
|
const MIN_LINES_NUMBER = 4;
|
||||||
|
const ERROR = {
|
||||||
|
EXPENSE_ALREADY_PUBLISHED: 'EXPENSE.ALREADY.PUBLISHED',
|
||||||
|
};
|
||||||
|
|
||||||
function ExpenseForm({
|
function ExpenseForm({
|
||||||
// #withMedia
|
// #withMedia
|
||||||
@@ -187,6 +190,21 @@ function ExpenseForm({
|
|||||||
: [];
|
: [];
|
||||||
}, [expense]);
|
}, [expense]);
|
||||||
|
|
||||||
|
// Transform API errors in toasts messages.
|
||||||
|
const transformErrors = (errors, { setErrors }) => {
|
||||||
|
const hasError = (errorType) => errors.some((e) => e.type === errorType);
|
||||||
|
|
||||||
|
if (hasError(ERROR.EXPENSE_ALREADY_PUBLISHED)) {
|
||||||
|
setErrors(
|
||||||
|
AppToaster.show({
|
||||||
|
message: formatMessage({
|
||||||
|
id: 'the_expense_is_already_published',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
validationSchema,
|
validationSchema,
|
||||||
@@ -237,16 +255,7 @@ function ExpenseForm({
|
|||||||
resetForm();
|
resetForm();
|
||||||
})
|
})
|
||||||
.catch((errors) => {
|
.catch((errors) => {
|
||||||
if (errors.find((e) => e.type === 'TOTAL.AMOUNT.EQUALS.ZERO')) {
|
transformErrors(errors, { setErrors });
|
||||||
}
|
|
||||||
setErrors(
|
|
||||||
AppToaster.show({
|
|
||||||
message: formatMessage({
|
|
||||||
id: 'total_amount_equals_zero',
|
|
||||||
}),
|
|
||||||
intent: Intent.DANGER,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -265,6 +274,7 @@ function ExpenseForm({
|
|||||||
clearSavedMediaIds();
|
clearSavedMediaIds();
|
||||||
})
|
})
|
||||||
.catch((errors) => {
|
.catch((errors) => {
|
||||||
|
transformErrors(errors, { setErrors });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -335,7 +345,6 @@ function ExpenseForm({
|
|||||||
formik={formik}
|
formik={formik}
|
||||||
defaultRow={defaultCategory}
|
defaultRow={defaultCategory}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="expense-form-footer">
|
<div class="expense-form-footer">
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={<T id={'description'} />}
|
label={<T id={'description'} />}
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import {
|
import { Alignment, Navbar, NavbarGroup } from '@blueprintjs/core';
|
||||||
Alignment,
|
|
||||||
Navbar,
|
|
||||||
NavbarGroup,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import { useParams, withRouter } from 'react-router-dom';
|
import { useParams, withRouter } from 'react-router-dom';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { pick, debounce } from 'lodash';
|
import { pick, debounce } from 'lodash';
|
||||||
|
|
||||||
import { DashboardViewsTabs } from 'components';
|
import { DashboardViewsTabs } from 'components';
|
||||||
|
import { useUpdateEffect } from 'hooks';
|
||||||
|
|
||||||
import withExpenses from './withExpenses';
|
import withExpenses from './withExpenses';
|
||||||
import withExpensesActions from './withExpensesActions';
|
import withExpensesActions from './withExpensesActions';
|
||||||
@@ -32,9 +29,13 @@ function ExpenseViewTabs({
|
|||||||
// #withDashboardActions
|
// #withDashboardActions
|
||||||
setTopbarEditView,
|
setTopbarEditView,
|
||||||
changePageSubtitle,
|
changePageSubtitle,
|
||||||
|
|
||||||
|
// props
|
||||||
|
customViewChanged,
|
||||||
|
onViewChanged,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { custom_view_id: customViewId } = useParams();
|
const { custom_view_id: customViewId = null } = useParams();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
changeExpensesView(customViewId || -1);
|
changeExpensesView(customViewId || -1);
|
||||||
@@ -51,6 +52,10 @@ function ExpenseViewTabs({
|
|||||||
};
|
};
|
||||||
}, [customViewId, addExpensesTableQueries, changeExpensesView]);
|
}, [customViewId, addExpensesTableQueries, changeExpensesView]);
|
||||||
|
|
||||||
|
useUpdateEffect(() => {
|
||||||
|
onViewChanged && onViewChanged(customViewId);
|
||||||
|
}, [customViewId]);
|
||||||
|
|
||||||
const debounceChangeHistory = useRef(
|
const debounceChangeHistory = useRef(
|
||||||
debounce((toUrl) => {
|
debounce((toUrl) => {
|
||||||
history.push(toUrl);
|
history.push(toUrl);
|
||||||
@@ -59,7 +64,7 @@ function ExpenseViewTabs({
|
|||||||
|
|
||||||
const handleTabsChange = (viewId) => {
|
const handleTabsChange = (viewId) => {
|
||||||
const toPath = viewId ? `${viewId}/custom_view` : '';
|
const toPath = viewId ? `${viewId}/custom_view` : '';
|
||||||
debounceChangeHistory.current(`/expenses/${toPath}`);
|
debounceChangeHistory.current(`/expenses-list/${toPath}`);
|
||||||
setTopbarEditView(viewId);
|
setTopbarEditView(viewId);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -78,7 +83,7 @@ function ExpenseViewTabs({
|
|||||||
<NavbarGroup align={Alignment.LEFT}>
|
<NavbarGroup align={Alignment.LEFT}>
|
||||||
<DashboardViewsTabs
|
<DashboardViewsTabs
|
||||||
initialViewId={customViewId}
|
initialViewId={customViewId}
|
||||||
baseUrl={'/expenses'}
|
baseUrl={'/expenses-list'}
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
onNewViewTabClick={handleClickNewView}
|
onNewViewTabClick={handleClickNewView}
|
||||||
onChange={handleTabsChange}
|
onChange={handleTabsChange}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
||||||
import { Route, Switch, useHistory, useParams } from 'react-router-dom';
|
import { Route, Switch, useHistory, useParams } from 'react-router-dom';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery, queryCache } from 'react-query';
|
||||||
import { Alert, Intent } from '@blueprintjs/core';
|
import { Alert, Intent } from '@blueprintjs/core';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
@@ -45,6 +45,7 @@ function ExpensesList({
|
|||||||
const [deleteExpense, setDeleteExpense] = useState(false);
|
const [deleteExpense, setDeleteExpense] = useState(false);
|
||||||
const [selectedRows, setSelectedRows] = useState([]);
|
const [selectedRows, setSelectedRows] = useState([]);
|
||||||
const [bulkDelete, setBulkDelete] = useState(false);
|
const [bulkDelete, setBulkDelete] = useState(false);
|
||||||
|
const [publishExpense, setPublishExpense] = useState(false);
|
||||||
|
|
||||||
const fetchResourceViews = useQuery(
|
const fetchResourceViews = useQuery(
|
||||||
['resource-views', 'expenses'],
|
['resource-views', 'expenses'],
|
||||||
@@ -155,18 +156,35 @@ function ExpensesList({
|
|||||||
[addExpensesTableQueries],
|
[addExpensesTableQueries],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handlePublishExpense = useCallback(
|
// const fetchExpenses = useQuery(['expenses-table', expensesTableQuery], () =>
|
||||||
(expense) => {
|
// requestFetchExpensesTable(),
|
||||||
requestPublishExpense(expense.id).then(() => {
|
// );
|
||||||
|
|
||||||
|
const handlePublishExpense = useCallback((expense) => {
|
||||||
|
setPublishExpense(expense);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleCancelPublishExpense = useCallback(() => {
|
||||||
|
setPublishExpense(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle publish expense confirm.
|
||||||
|
const handleConfirmPublishExpense = useCallback(() => {
|
||||||
|
requestPublishExpense(publishExpense.id)
|
||||||
|
.then(() => {
|
||||||
|
setPublishExpense(false);
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: formatMessage({ id: 'the_expense_id_has_been_published' }),
|
message: formatMessage({
|
||||||
|
id: 'the_expense_has_been_published',
|
||||||
|
}),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
|
queryCache.invalidateQueries('expenses-table');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setPublishExpense(false);
|
||||||
});
|
});
|
||||||
fetchExpenses.refetch();
|
}, [publishExpense, requestPublishExpense, formatMessage]);
|
||||||
},
|
|
||||||
[requestPublishExpense, formatMessage],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handle selected rows change.
|
// Handle selected rows change.
|
||||||
const handleSelectedRowsChange = useCallback(
|
const handleSelectedRowsChange = useCallback(
|
||||||
@@ -190,11 +208,11 @@ function ExpensesList({
|
|||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route
|
<Route
|
||||||
// exact={true}
|
exact={true}
|
||||||
// path={[
|
// path={[
|
||||||
// '/expenses/:custom_view_id/custom_view',
|
// '/expenses/:custom_view_id/custom_view',
|
||||||
// '/expenses/new',
|
// 'expenses',
|
||||||
// ]}
|
// ]}
|
||||||
>
|
>
|
||||||
<ExpenseViewTabs />
|
<ExpenseViewTabs />
|
||||||
|
|
||||||
@@ -240,14 +258,26 @@ function ExpensesList({
|
|||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
<Alert
|
||||||
|
cancelButtonText={<T id={'cancel'} />}
|
||||||
|
confirmButtonText={<T id={'publish'} />}
|
||||||
|
intent={Intent.WARNING}
|
||||||
|
isOpen={publishExpense}
|
||||||
|
onCancel={handleCancelPublishExpense}
|
||||||
|
onConfirm={handleConfirmPublishExpense}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
<T id={'are_sure_to_publish_this_expense'} />
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
</DashboardPageContent>
|
</DashboardPageContent>
|
||||||
</DashboardInsider>
|
</DashboardInsider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboardActions,
|
|
||||||
withExpensesActions,
|
withExpensesActions,
|
||||||
|
withDashboardActions,
|
||||||
withViewsActions,
|
withViewsActions,
|
||||||
withResourceActions,
|
withResourceActions,
|
||||||
withExpenses(({ expensesTableQuery }) => ({ expensesTableQuery })),
|
withExpenses(({ expensesTableQuery }) => ({ expensesTableQuery })),
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ export default {
|
|||||||
'The expenses #{number} have been successfully deleted',
|
'The expenses #{number} have been successfully deleted',
|
||||||
once_delete_these_expenses_you_will_not_able_restore_them:
|
once_delete_these_expenses_you_will_not_able_restore_them:
|
||||||
"Once you delete these expenses, you won't be able to retrieve them later. Are you sure you want to delete them?",
|
"Once you delete these expenses, you won't be able to retrieve them later. Are you sure you want to delete them?",
|
||||||
the_expense_id_has_been_published: 'The expense id has been published',
|
the_expense_has_been_published: 'The expense has been published',
|
||||||
select_beneficiary_account: 'Select Beneficiary Account',
|
select_beneficiary_account: 'Select Beneficiary Account',
|
||||||
total_amount_equals_zero: 'Total amount equals zero',
|
total_amount_equals_zero: 'Total amount equals zero',
|
||||||
value: 'Value',
|
value: 'Value',
|
||||||
@@ -449,7 +449,7 @@ export default {
|
|||||||
as_date: 'As Date',
|
as_date: 'As Date',
|
||||||
aging_before_days: 'Aging before days',
|
aging_before_days: 'Aging before days',
|
||||||
aging_periods: 'Aging periods',
|
aging_periods: 'Aging periods',
|
||||||
name_:'name',
|
name_: 'name',
|
||||||
as: 'As',
|
as: 'As',
|
||||||
receivable_aging_summary: 'Receivable Aging Summary',
|
receivable_aging_summary: 'Receivable Aging Summary',
|
||||||
customers: 'Customers',
|
customers: 'Customers',
|
||||||
@@ -536,5 +536,11 @@ export default {
|
|||||||
should_total_of_credit_and_debit_be_equal: 'Should total of credit and debit be equal.',
|
should_total_of_credit_and_debit_be_equal: 'Should total of credit and debit be equal.',
|
||||||
no_accounts: 'No Accounts',
|
no_accounts: 'No Accounts',
|
||||||
the_accounts_have_been_successfully_inactivated: 'The accounts have been successfully inactivated.',
|
the_accounts_have_been_successfully_inactivated: 'The accounts have been successfully inactivated.',
|
||||||
account_code_is_not_unique: 'Account code is not unqiue.'
|
account_code_is_not_unique: 'Account code is not unqiue.',
|
||||||
|
are_sure_to_publish_this_expense:
|
||||||
|
'Are you sure you want to publish this expense?',
|
||||||
|
once_delete_these_journals_you_will_not_able_restore_them:
|
||||||
|
"Once you delete these journalss, you won't be able to retrieve them later. Are you sure you want to delete them?",
|
||||||
|
once_delete_this_journal_you_will_able_to_restore_it: `Once you delete this journal, you won\'t be able to restore it later. Are you sure you want to delete ?`,
|
||||||
|
the_expense_is_already_published: 'The expense is already published.',
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user