- {row.cells.map((cell, index) => (
-
- ))}
+
+ {children}
setVisible(false)}
+ onClosed={handleClose}
>
);
}
+
+/**
+ * Table row.
+ */
+export default function TableRow({ row, className, style }) {
+ const {
+ props: {
+ TableCellRenderer,
+ rowClassNames,
+ ContextMenu: ContextMenuContent,
+ },
+ } = useContext(TableContext);
+
+ return (
+
+
+ {row.cells.map((cell, index) => (
+
+ ))}
+
+
+ );
+}
diff --git a/client/src/components/Datatable/TableRows.js b/client/src/components/Datatable/TableRows.js
index cd27400f0..976ccbe42 100644
--- a/client/src/components/Datatable/TableRows.js
+++ b/client/src/components/Datatable/TableRows.js
@@ -10,8 +10,8 @@ export default function TableRows() {
props: { TableRowRenderer, TableCellRenderer },
} = useContext(TableContext);
- return page.map((row) => {
+ return page.map((row, index) => {
prepareRow(row);
- return
;
+ return
;
});
}
\ No newline at end of file
diff --git a/client/src/components/Datatable/TableVirtualizedRows.js b/client/src/components/Datatable/TableVirtualizedRows.js
index 10c8e751e..e3689bb67 100644
--- a/client/src/components/Datatable/TableVirtualizedRows.js
+++ b/client/src/components/Datatable/TableVirtualizedRows.js
@@ -3,11 +3,13 @@ import { WindowScroller, AutoSizer, List } from 'react-virtualized';
import { CLASSES } from 'common/classes';
import TableContext from './TableContext';
+/**
+ * Table virtualized list row.
+ */
function TableVirtualizedListRow({
index,
isScrolling,
isVisible,
- key,
style,
}) {
const {
@@ -18,7 +20,7 @@ function TableVirtualizedListRow({
const row = page[index];
prepareRow(row);
- return
;
+ return (
);
}
/**
@@ -27,39 +29,38 @@ function TableVirtualizedListRow({
export default function TableVirtualizedListRows() {
const {
table: { page },
- props: { vListrowHeight, vListOverscanRowCount }
+ props: { vListrowHeight, vListOverscanRowCount },
} = useContext(TableContext);
// Dashboard content pane.
- const dashboardContentPane = document.querySelector(
+ const dashboardContentPane = React.useMemo(()=> document.querySelector(
`.${CLASSES.DASHBOARD_CONTENT_PANE}`,
- );
+ ), []);
+
+ const rowRenderer = React.useCallback(({ key, ...args }) => (
+
+ ), []);
+
return (
- {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (
-
-
- {({ width }) => (
-
-
{
- return ;
- }}
- scrollTop={scrollTop}
- width={width}
- />
-
- )}
-
-
+ {({ height, isScrolling, onChildScroll, scrollTop }) => (
+
+ {({ width }) => (
+
+ )}
+
)}
);
diff --git a/client/src/components/FinancialSheet.js b/client/src/components/FinancialSheet.js
index 181747f35..0f2373090 100644
--- a/client/src/components/FinancialSheet.js
+++ b/client/src/components/FinancialSheet.js
@@ -7,7 +7,6 @@ import 'style/pages/FinancialStatements/FinancialSheet.scss';
import { If, LoadingIndicator, MODIFIER } from 'components';
-
export default function FinancialSheet({
companyName,
sheetType,
@@ -57,49 +56,47 @@ export default function FinancialSheet({
'is-full-width': fullWidth,
})}
>
-
-
-
-
- {companyName}
-
-
-
- {sheetType}
-
-
-
-
- {formattedAsDate}
+ {loading ? (
+
+ ) : (
+
+
+ {companyName}
-
- {formattedFromDate} | {' '}
- {formattedToDate}
+
+ {sheetType}
+
+
+
+ {formattedAsDate}
+
+
+
+ {formattedFromDate} | {' '}
+ {formattedToDate}
+
+
+
+ {children}
+ {accountingBasis}
+
+
-
- {children}
- {accountingBasis}
-
-
-
+ )}
);
}
diff --git a/client/src/components/Guards/EnsureOrganizationIsNotReady.js b/client/src/components/Guards/EnsureOrganizationIsNotReady.js
index 33bfa6b53..cdbfee0cc 100644
--- a/client/src/components/Guards/EnsureOrganizationIsNotReady.js
+++ b/client/src/components/Guards/EnsureOrganizationIsNotReady.js
@@ -5,6 +5,9 @@ import { compose } from 'utils';
import withAuthentication from 'containers/Authentication/withAuthentication';
import withOrganization from 'containers/Organization/withOrganization';
+/**
+ * Ensures organization is not ready.
+ */
function EnsureOrganizationIsNotReady({
children,
diff --git a/client/src/components/Guards/PrivateRoute.js b/client/src/components/Guards/PrivateRoute.js
index e50904cd0..9fa112a1e 100644
--- a/client/src/components/Guards/PrivateRoute.js
+++ b/client/src/components/Guards/PrivateRoute.js
@@ -11,11 +11,7 @@ export default function PrivateRoute({ component: Component, ...rest }) {
{isAuthenticated ? (
) : (
-
+
)}
);
diff --git a/client/src/components/Utils/If.js b/client/src/components/Utils/If.js
index f6ae2c418..7ed0a6750 100644
--- a/client/src/components/Utils/If.js
+++ b/client/src/components/Utils/If.js
@@ -5,7 +5,7 @@ const If = props => props.condition
? (props.render ? props.render() : props.children) : null;
If.propTypes = {
- condition: PropTypes.bool.isRequired,
+ // condition: PropTypes.bool.isRequired,
children: PropTypes.node,
render: PropTypes.func
};
diff --git a/client/src/components/index.js b/client/src/components/index.js
index 4be74d6b4..25d53d033 100644
--- a/client/src/components/index.js
+++ b/client/src/components/index.js
@@ -53,6 +53,7 @@ import Drawer from './Drawer/Drawer';
import DrawerSuspense from './Drawer/DrawerSuspense';
import Postbox from './Postbox';
import AccountsSuggestField from './AccountsSuggestField';
+import MaterialProgressBar from './MaterialProgressBar';
const Hint = FieldHint;
@@ -112,5 +113,6 @@ export {
Drawer,
DrawerSuspense,
Postbox,
- AccountsSuggestField
+ AccountsSuggestField,
+ MaterialProgressBar
};
diff --git a/client/src/containers/Accounts/AccountsDataTable.js b/client/src/containers/Accounts/AccountsDataTable.js
index 876c605bb..c89eba307 100644
--- a/client/src/containers/Accounts/AccountsDataTable.js
+++ b/client/src/containers/Accounts/AccountsDataTable.js
@@ -99,7 +99,7 @@ function AccountsDataTable({
// #TableVirtualizedListRows props.
vListrowHeight={42}
- vListOverscanRowCount={10}
+ vListOverscanRowCount={0}
payload={{
onEdit: handleEditAccount,
diff --git a/client/src/containers/Accounts/components.js b/client/src/containers/Accounts/components.js
index 5c0721fab..1453e4fe6 100644
--- a/client/src/containers/Accounts/components.js
+++ b/client/src/containers/Accounts/components.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { memo } from 'react';
import {
Position,
Classes,
@@ -75,7 +75,7 @@ export function ActionsMenu({
/**
* Actions cell.
*/
-export const ActionsCell = (props) => {
+export function ActionsCell(props) {
return (
{
} />
);
-};
+}
/**
* Normal cell.
diff --git a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js
index 45698070f..20b2dba0c 100644
--- a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js
+++ b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummary.js
@@ -10,6 +10,7 @@ import APAgingSummaryActionsBar from './APAgingSummaryActionsBar';
import APAgingSummaryTable from './APAgingSummaryTable';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import { APAgingSummaryProvider } from './APAgingSummaryProvider';
+import { APAgingSummarySheetLoadingBar } from './components';
import withSettings from 'containers/Settings/withSettings';
import withAPAgingSummaryActions from './withAPAgingSummaryActions'
@@ -59,6 +60,8 @@ function APAgingSummary({
numberFormat={filter.numberFormat}
onNumberFormatSubmit={handleNumberFormatSubmit}
/>
+
+
+
-
+
);
}
-
const useAPAgingSummaryContext = () => useContext(APAgingSummaryContext);
-
export { APAgingSummaryProvider, useAPAgingSummaryContext };
diff --git a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js
index bd433e254..7ef048ae4 100644
--- a/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js
+++ b/client/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.js
@@ -18,7 +18,7 @@ export default function APAgingSummaryTable({
// AP aging summary report content.
const {
APAgingSummary: { tableRows },
- isAPAgingFetching,
+ isAPAgingLoading,
} = useAPAgingSummaryContext();
// AP aging summary columns.
@@ -32,7 +32,7 @@ export default function APAgingSummaryTable({
name={'payable-aging-summary'}
sheetType={formatMessage({ id: 'payable_aging_summary' })}
asDate={new Date()}
- loading={isAPAgingFetching}
+ loading={isAPAgingLoading}
>
{
[tableRows, agingColumns],
);
};
+
+/**
+ * A/P aging summary sheet loading bar.
+ */
+ export function APAgingSummarySheetLoadingBar() {
+ const {
+ isAPAgingFetching
+ } = useAPAgingSummaryContext();
+
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js
index 69c880264..3f069c2e8 100644
--- a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js
@@ -10,6 +10,7 @@ import ARAgingSummaryActionsBar from './ARAgingSummaryActionsBar';
import ARAgingSummaryTable from './ARAgingSummaryTable';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import { ARAgingSummaryProvider } from './ARAgingSummaryProvider';
+import { ARAgingSummarySheetLoadingBar } from './components';
import withARAgingSummaryActions from './withARAgingSummaryActions'
import withSettings from 'containers/Settings/withSettings';
@@ -57,6 +58,8 @@ function ReceivableAgingSummarySheet({
numberFormat={filter.numberFormat}
onNumberFormatSubmit={handleNumberFormatSubmit}
/>
+
+
transformFilterFormToQuery(filter), [filter]);
+ // A/R aging summary sheet context.
const {
data: ARAgingSummary,
isLoading: isARAgingLoading,
isFetching: isARAgingFetching,
refetch,
- } = useARAgingSummaryReport(query);
+ } = useARAgingSummaryReport(query, { keepPreviousData: true });
// Retrieve the customers list.
const {
@@ -36,9 +37,9 @@ function ARAgingSummaryProvider({ filter, ...props }) {
};
return (
-
+
-
+
);
}
diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.js
index 09300f2b1..5f24d6f78 100644
--- a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.js
+++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.js
@@ -16,7 +16,7 @@ export default function ReceivableAgingSummaryTable({
const { formatMessage } = useIntl();
// AR aging summary report context.
- const { ARAgingSummary, isARAgingFetching } = useARAgingSummaryContext();
+ const { ARAgingSummary, isARAgingLoading } = useARAgingSummaryContext();
// AR aging summary columns.
const columns = useARAgingSummaryColumns();
@@ -33,7 +33,7 @@ export default function ReceivableAgingSummaryTable({
name={'receivable-aging-summary'}
sheetType={formatMessage({ id: 'receivable_aging_summary' })}
asDate={new Date()}
- loading={isARAgingFetching}
+ loading={isARAgingLoading}
>
{
[tableRows, agingColumns],
);
};
+
+/**
+ * A/R aging summary sheet loading bar.
+ */
+ export function ARAgingSummarySheetLoadingBar() {
+ const {
+ isARAgingFetching,
+ } = useARAgingSummaryContext();
+
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js
index 07defa0f9..e21a53dee 100644
--- a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js
+++ b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheet.js
@@ -1,13 +1,12 @@
import React, { useEffect, useState } from 'react';
import moment from 'moment';
-
import 'style/pages/FinancialStatements/BalanceSheet.scss';
import BalanceSheetHeader from './BalanceSheetHeader';
import BalanceSheetTable from './BalanceSheetTable';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import BalanceSheetActionsBar from './BalanceSheetActionsBar';
-import { BalanceSheetAlerts } from './components';
+import { BalanceSheetAlerts, BalanceSheetLoadingBar } from './components';
import { FinancialStatement } from 'components';
import withBalanceSheetActions from './withBalanceSheetActions';
@@ -63,6 +62,7 @@ function BalanceSheet({
numberFormat={filter.numberFormat}
onNumberFormatSubmit={handleNumberFormatSubmit}
/>
+
diff --git a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetProvider.js b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetProvider.js
index 65153cb9c..087728cd1 100644
--- a/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetProvider.js
+++ b/client/src/containers/FinancialStatements/BalanceSheet/BalanceSheetProvider.js
@@ -12,20 +12,24 @@ function BalanceSheetProvider({ filter, ...props }) {
]);
// Fetches the balance sheet report.
- const { data: balanceSheet, isFetching, refetch } = useBalanceSheet(query);
+ const {
+ data: balanceSheet,
+ isFetching,
+ isLoading,
+ refetch,
+ } = useBalanceSheet(query, { keepPreviousData: true });
const provider = {
balanceSheet,
- isLoading: isFetching,
+ isFetching,
+ isLoading,
refetchBalanceSheet: refetch,
query,
filter,
};
return (
-
+
);
diff --git a/client/src/containers/FinancialStatements/BalanceSheet/components.js b/client/src/containers/FinancialStatements/BalanceSheet/components.js
index b5da25ec7..ad0992fb9 100644
--- a/client/src/containers/FinancialStatements/BalanceSheet/components.js
+++ b/client/src/containers/FinancialStatements/BalanceSheet/components.js
@@ -2,6 +2,7 @@ import React from 'react';
import { Button } from '@blueprintjs/core';
import { Icon, If } from 'components';
import { useBalanceSheetContext } from './BalanceSheetProvider';
+import FinancialLoadingBar from '../FinancialLoadingBar';
/**
* Balance sheet alerts.
@@ -13,7 +14,7 @@ export function BalanceSheetAlerts() {
balanceSheet,
} = useBalanceSheetContext();
- // Handle recalculate the report button.
+ // Handle refetch the report sheet.
const handleRecalcReport = () => {
refetchBalanceSheet();
};
@@ -34,3 +35,18 @@ export function BalanceSheetAlerts() {
);
}
+
+/**
+ * Balance sheet loading bar.
+ */
+export function BalanceSheetLoadingBar() {
+ const {
+ isFetching
+ } = useBalanceSheetContext();
+
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/FinancialLoadingBar.js b/client/src/containers/FinancialStatements/FinancialLoadingBar.js
new file mode 100644
index 000000000..9a087d954
--- /dev/null
+++ b/client/src/containers/FinancialStatements/FinancialLoadingBar.js
@@ -0,0 +1,13 @@
+import React from 'react';
+import { MaterialProgressBar } from 'components';
+
+/**
+ * Financnail progress bar.
+ */
+export default function FinancialLoadingBar() {
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/FinancialReports.js b/client/src/containers/FinancialStatements/FinancialReports.js
index cc478561e..1b4c1822c 100644
--- a/client/src/containers/FinancialStatements/FinancialReports.js
+++ b/client/src/containers/FinancialStatements/FinancialReports.js
@@ -1,13 +1,9 @@
-import React, { useEffect } from 'react';
-import { useIntl } from 'react-intl';
+import React from 'react';
import { Link } from 'react-router-dom';
import { For } from 'components';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import financialReportMenus from 'config/financialReportsMenu';
-import withDashboardActions from 'containers/Dashboard/withDashboardActions';
-
-import { compose } from 'utils';
import 'style/pages/FinancialStatements/FinancialSheets.scss';
@@ -34,6 +30,9 @@ function FinancialReportsSection({ sectionTitle, reports }) {
);
}
+/**
+ * Financial reports.
+ */
export default function FinancialReports() {
return (
diff --git a/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.js b/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.js
index 2d5649d16..8e52874d8 100644
--- a/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.js
+++ b/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.js
@@ -9,6 +9,10 @@ import GeneralLedgerHeader from './GeneralLedgerHeader';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import GeneralLedgerActionsBar from './GeneralLedgerActionsBar';
import { GeneralLedgerProvider } from './GeneralLedgerProvider';
+import {
+ GeneralLedgerSheetAlerts,
+ GeneralLedgerSheetLoadingBar,
+} from './components';
import withGeneralLedgerActions from './withGeneralLedgerActions';
import withSettings from 'containers/Settings/withSettings';
@@ -64,6 +68,8 @@ function GeneralLedger({
pageFilter={filter}
onSubmitFilter={handleFilterSubmit}
/>
+
+
+
-
+
);
}
diff --git a/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerTable.js b/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerTable.js
index b21a12f99..8684c024d 100644
--- a/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerTable.js
+++ b/client/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerTable.js
@@ -5,6 +5,8 @@ import { useIntl } from 'react-intl';
import FinancialSheet from 'components/FinancialSheet';
import DataTable from 'components/DataTable';
+import TableVirtualizedListRows from 'components/Datatable/TableVirtualizedRows';
+import TableFastCell from 'components/Datatable/TableFastCell';
import { useGeneralLedgerContext } from './GeneralLedgerProvider';
import { useGeneralLedgerTableColumns } from './components';
@@ -12,25 +14,22 @@ import { useGeneralLedgerTableColumns } from './components';
/**
* General ledger table.
*/
-export default function GeneralLedgerTable({
- companyName,
-}) {
+export default function GeneralLedgerTable({ companyName }) {
const { formatMessage } = useIntl();
// General ledger context.
const {
generalLedger: { tableRows, query },
- isSheetLoading
+ isLoading,
} = useGeneralLedgerContext();
// General ledger table columns.
const columns = useGeneralLedgerTableColumns();
// Default expanded rows of general ledger table.
- const expandedRows = useMemo(
- () => defaultExpanderReducer(tableRows, 1),
- [tableRows],
- );
+ const expandedRows = useMemo(() => defaultExpanderReducer(tableRows, 1), [
+ tableRows,
+ ]);
const rowClassNames = (row) => [`row-type--${row.original.rowType}`];
@@ -41,11 +40,11 @@ export default function GeneralLedgerTable({
fromDate={query.from_date}
toDate={query.to_date}
name="general-ledger"
- loading={isSheetLoading}
+ loading={isLoading}
fullWidth={true}
>
);
-}
\ No newline at end of file
+}
diff --git a/client/src/containers/FinancialStatements/GeneralLedger/components.js b/client/src/containers/FinancialStatements/GeneralLedger/components.js
index 3b29cc4ae..4c92c1571 100644
--- a/client/src/containers/FinancialStatements/GeneralLedger/components.js
+++ b/client/src/containers/FinancialStatements/GeneralLedger/components.js
@@ -1,7 +1,10 @@
import React from 'react';
import { useIntl } from 'react-intl';
+import { Button } from '@blueprintjs/core';
+import { Icon, If } from 'components';
import { getForceWidth, getColumnWidth } from 'utils';
import { useGeneralLedgerContext } from './GeneralLedgerProvider';
+import FinancialLoadingBar from '../FinancialLoadingBar';
/**
* Retrieve the general ledger table columns.
@@ -46,6 +49,7 @@ export function useGeneralLedgerTableColumns() {
accessor: 'reference_type_formatted',
className: 'transaction_type',
width: 125,
+ textOverview: true,
},
{
Header: formatMessage({ id: 'transaction_number' }),
@@ -99,3 +103,51 @@ export function useGeneralLedgerTableColumns() {
[formatMessage, tableRows],
);
}
+
+
+/**
+ * General ledger sheet alerts.
+ */
+ export function GeneralLedgerSheetAlerts() {
+ const {
+ generalLedger,
+ isLoading,
+ sheetRefresh
+ } = useGeneralLedgerContext();
+
+ // Handle refetch the report sheet.
+ const handleRecalcReport = () => {
+ sheetRefresh();
+ };
+ // Can't display any error if the report is loading.
+ if (isLoading) { return null; }
+
+ return (
+
+
+ Just a moment! We're
+ calculating your cost transactions and this doesn't take much time.
+ Please check after sometime.{' '}
+
+
+
+
+ );
+}
+
+/**
+ * General ledger sheet loading bar.
+ */
+export function GeneralLedgerSheetLoadingBar() {
+ const {
+ isFetching,
+ } = useGeneralLedgerContext();
+
+ return (
+
+
+
+ )
+}
diff --git a/client/src/containers/FinancialStatements/Journal/Journal.js b/client/src/containers/FinancialStatements/Journal/Journal.js
index d238cfc85..5eeca928d 100644
--- a/client/src/containers/FinancialStatements/Journal/Journal.js
+++ b/client/src/containers/FinancialStatements/Journal/Journal.js
@@ -1,20 +1,21 @@
import React, { useState, useCallback, useEffect } from 'react';
import moment from 'moment';
-import { useIntl } from 'react-intl';
-import { compose } from 'utils';
+import 'style/pages/FinancialStatements/Journal.scss';
+
+import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
+
import JournalTable from './JournalTable';
-
import JournalHeader from './JournalHeader';
import JournalActionsBar from './JournalActionsBar';
-import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
import { JournalSheetProvider } from './JournalProvider';
+import { JournalSheetLoadingBar, JournalSheetAlerts } from './components';
import withSettings from 'containers/Settings/withSettings';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withJournalActions from './withJournalActions';
-import 'style/pages/FinancialStatements/Journal.scss';
+import { compose } from 'utils';
/**
* Journal sheet.
@@ -60,6 +61,9 @@ function Journal({
onSubmitFilter={handleFilterSubmit}
pageFilter={filter}
/>
+
+
+
+
-
+
);
}
diff --git a/client/src/containers/FinancialStatements/Journal/JournalTable.js b/client/src/containers/FinancialStatements/Journal/JournalTable.js
index 1d8ced6ea..6b53b78c2 100644
--- a/client/src/containers/FinancialStatements/Journal/JournalTable.js
+++ b/client/src/containers/FinancialStatements/Journal/JournalTable.js
@@ -4,7 +4,8 @@ import { useIntl } from 'react-intl';
import FinancialSheet from 'components/FinancialSheet';
import DataTable from 'components/DataTable';
import { useJournalSheetContext } from './JournalProvider';
-
+import TableVirtualizedListRows from 'components/Datatable/TableVirtualizedRows';
+import TableFastCell from 'components/Datatable/TableFastCell';
import { defaultExpanderReducer } from 'utils';
import { useJournalTableColumns } from './components';
@@ -41,6 +42,8 @@ export default function JournalSheetTable({
};
}, []);
+
+
return (
);
diff --git a/client/src/containers/FinancialStatements/Journal/components.js b/client/src/containers/FinancialStatements/Journal/components.js
index 34d95feb3..c8667a724 100644
--- a/client/src/containers/FinancialStatements/Journal/components.js
+++ b/client/src/containers/FinancialStatements/Journal/components.js
@@ -1,6 +1,10 @@
import React from 'react';
import { useIntl } from 'react-intl';
import moment from 'moment';
+import { Button } from '@blueprintjs/core';
+import { Icon, If } from 'components';
+import { useJournalSheetContext } from './JournalProvider';
+import FinancialLoadingBar from '../FinancialLoadingBar';
/**
* Retrieve the journal table columns.
@@ -60,3 +64,50 @@ export const useJournalTableColumns = () => {
[formatMessage],
);
};
+
+/**
+ * Journal sheet loading bar.
+ */
+export function JournalSheetLoadingBar() {
+ const {
+ isFetching
+ } = useJournalSheetContext();
+
+ return (
+
+
+
+ )
+}
+
+/**
+ * Journal sheet alerts.
+ */
+ export function JournalSheetAlerts() {
+ const {
+ isLoading,
+ refetchSheet,
+ journalSheet,
+ } = useJournalSheetContext();
+
+ // Handle refetch the report sheet.
+ const handleRecalcReport = () => {
+ refetchSheet();
+ };
+ // Can't display any error if the report is loading.
+ if (isLoading) { return null; }
+
+ return (
+
+
+ Just a moment! We're
+ calculating your cost transactions and this doesn't take much time.
+ Please check after sometime.{' '}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.js b/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.js
index 71d0d8e87..81aa7a99c 100644
--- a/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.js
+++ b/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossProvider.js
@@ -1,25 +1,31 @@
import React, { createContext, useContext } from 'react';
-import DashboardInsider from 'components/Dashboard/DashboardInsider';
+import FinancialReportPage from '../FinancialReportPage';
import { useProfitLossSheet } from 'hooks/query';
import { transformFilterFormToQuery } from '../common';
const ProfitLossSheetContext = createContext();
function ProfitLossSheetProvider({ query, ...props }) {
- const { data: profitLossSheet, isFetching, refetch } = useProfitLossSheet({
+ const {
+ data: profitLossSheet,
+ isFetching,
+ isLoading,
+ refetch,
+ } = useProfitLossSheet({
...transformFilterFormToQuery(query),
});
const provider = {
profitLossSheet,
- isLoading: isFetching,
+ isLoading,
+ isFetching,
sheetRefetch: refetch,
};
return (
-
+
-
+
);
}
diff --git a/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheet.js b/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheet.js
index e2fb6c2af..e65eba735 100644
--- a/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheet.js
+++ b/client/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheet.js
@@ -14,6 +14,10 @@ import withSettings from 'containers/Settings/withSettings';
import 'style/pages/FinancialStatements/ProfitLossSheet.scss';
import { ProfitLossSheetProvider } from './ProfitLossProvider';
+import {
+ ProfitLossSheetLoadingBar,
+ ProfitLossSheetAlerts
+} from './components';
/**
* Profit/Loss financial statement sheet.
@@ -23,7 +27,7 @@ function ProfitLossSheet({
organizationName,
// #withProfitLossActions
- toggleProfitLossFilterDrawer: toggleDisplayFilterDrawer
+ toggleProfitLossFilterDrawer: toggleDisplayFilterDrawer,
}) {
const [filter, setFilter] = useState({
basis: 'cash',
@@ -32,7 +36,7 @@ function ProfitLossSheet({
displayColumnsType: 'total',
accountsFilter: 'all-accounts',
});
-
+
// Handle submit filter.
const handleSubmitFilter = (filter) => {
const _filter = {
@@ -52,9 +56,12 @@ function ProfitLossSheet({
};
// Hide the filter drawer once the page unmount.
- React.useEffect(() => () => {
- toggleDisplayFilterDrawer(false);
- }, [toggleDisplayFilterDrawer])
+ React.useEffect(
+ () => () => {
+ toggleDisplayFilterDrawer(false);
+ },
+ [toggleDisplayFilterDrawer],
+ );
return (
@@ -62,6 +69,8 @@ function ProfitLossSheet({
numberFormat={filter.numberFormat}
onNumberFormatSubmit={handleNumberFormatSubmit}
/>
+
+
@@ -71,9 +80,7 @@ function ProfitLossSheet({
/>
diff --git a/client/src/containers/FinancialStatements/ProfitLossSheet/components.js b/client/src/containers/FinancialStatements/ProfitLossSheet/components.js
new file mode 100644
index 000000000..6e69b4438
--- /dev/null
+++ b/client/src/containers/FinancialStatements/ProfitLossSheet/components.js
@@ -0,0 +1,51 @@
+import React from 'react';
+import { Button } from '@blueprintjs/core';
+import { Icon, If } from 'components';
+import { useProfitLossSheetContext } from './ProfitLossProvider';
+import FinancialLoadingBar from '../FinancialLoadingBar';
+
+/**
+ * Profit/loss sheet loading bar.
+ */
+export function ProfitLossSheetLoadingBar() {
+ const { isFetching } = useProfitLossSheetContext();
+
+ return (
+
+
+
+ );
+}
+
+/**
+ * Balance sheet alerts.
+ */
+export function ProfitLossSheetAlerts() {
+ const {
+ isLoading,
+ sheetRefetch,
+ profitLossSheet,
+ } = useProfitLossSheetContext();
+
+ // Handle refetch the report sheet.
+ const handleRecalcReport = () => {
+ sheetRefetch();
+ };
+ // Can't display any error if the report is loading.
+ if (isLoading) {
+ return null;
+ }
+
+ return (
+
+
+ Just a moment! We're
+ calculating your cost transactions and this doesn't take much time.
+ Please check after sometime.{' '}
+
+
+
+ );
+}
diff --git a/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceProvider.js b/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceProvider.js
index 4446dbb46..72996193d 100644
--- a/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceProvider.js
+++ b/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceProvider.js
@@ -1,27 +1,36 @@
import React, { createContext, useContext } from 'react';
-import DashboardInsider from 'components/Dashboard/DashboardInsider';
+import FinancialReportPage from '../FinancialReportPage';
import { useTrialBalanceSheet } from 'hooks/query';
import { transformFilterFormToQuery } from '../common';
const TrialBalanceSheetContext = createContext();
function TrialBalanceSheetProvider({ query, ...props }) {
- const { data: trialBalanceSheet, isFetching, refetch } = useTrialBalanceSheet(
+ const {
+ data: trialBalanceSheet,
+ isFetching,
+ isLoading,
+ refetch,
+ } = useTrialBalanceSheet(
{
...transformFilterFormToQuery(query),
},
+ {
+ keepPreviousData: true,
+ },
);
const provider = {
trialBalanceSheet,
- isLoading: isFetching,
+ isLoading,
+ isFetching,
refetchSheet: refetch,
};
return (
-
+
-
+
);
}
diff --git a/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheet.js b/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheet.js
index d2c149eb2..6bb6fce25 100644
--- a/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheet.js
+++ b/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheet.js
@@ -9,6 +9,11 @@ import TrialBalanceSheetHeader from './TrialBalanceSheetHeader';
import TrialBalanceSheetTable from './TrialBalanceSheetTable';
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
+import {
+ TrialBalanceSheetAlerts,
+ TrialBalanceSheetLoadingBar,
+} from './components';
+
import withTrialBalanceActions from './withTrialBalanceActions';
import withSettings from 'containers/Settings/withSettings';
@@ -22,7 +27,7 @@ function TrialBalanceSheet({
organizationName,
// #withTrialBalanceSheetActions
- toggleTrialBalanceFilterDrawer: toggleFilterDrawer
+ toggleTrialBalanceFilterDrawer: toggleFilterDrawer,
}) {
const [filter, setFilter] = useState({
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
@@ -53,9 +58,12 @@ function TrialBalanceSheet({
};
// Hide the filter drawer once the page unmount.
- useEffect(() => () => {
- toggleFilterDrawer(false)
- }, [toggleFilterDrawer]);
+ useEffect(
+ () => () => {
+ toggleFilterDrawer(false);
+ },
+ [toggleFilterDrawer],
+ );
return (
@@ -63,6 +71,9 @@ function TrialBalanceSheet({
numberFormat={filter.numberFormat}
onNumberFormatSubmit={handleNumberFormatSubmit}
/>
+
+
+
{
[tableRows, formatMessage],
);
};
+
+/**
+ * Trial balance sheet progress loading bar.
+ */
+export function TrialBalanceSheetLoadingBar() {
+ const {
+ isFetching
+ } = useTrialBalanceSheetContext();
+
+ return (
+
+
+
+ )
+}
+
+/**
+ * Trial balance sheet alerts.
+ */
+export function TrialBalanceSheetAlerts() {
+ const {
+ trialBalanceSheet: { meta },
+ isLoading,
+ refetchSheet
+ } = useTrialBalanceSheetContext();
+
+ // Handle refetch the sheet.
+ const handleRecalcReport = () => {
+ refetchSheet();
+ };
+ // Can't display any error if the report is loading.
+ if (isLoading) { return null; }
+
+ return (
+
+
+ Just a moment! We're
+ calculating your cost transactions and this doesn't take much time.
+ Please check after sometime.{' '}
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/client/src/containers/Items/ItemsListProvider.js b/client/src/containers/Items/ItemsListProvider.js
index d381264e4..a2b71ae64 100644
--- a/client/src/containers/Items/ItemsListProvider.js
+++ b/client/src/containers/Items/ItemsListProvider.js
@@ -17,12 +17,12 @@ function ItemsListProvider({
...props
}) {
// Fetch accounts resource views and fields.
- const { data: itemsViews, isFetching: isViewsLoading } = useResourceViews(
+ const { data: itemsViews, isLoading: isViewsLoading } = useResourceViews(
'items',
);
// Fetch the accounts resource fields.
- const { data: itemsFields, isFetching: isFieldsLoading } = useResourceFields(
+ const { data: itemsFields, isLoading: isFieldsLoading } = useResourceFields(
'items',
);
diff --git a/client/src/containers/Purchases/Bills/BillsLanding/BillsListProvider.js b/client/src/containers/Purchases/Bills/BillsLanding/BillsListProvider.js
index 931bc50e5..432dea87e 100644
--- a/client/src/containers/Purchases/Bills/BillsLanding/BillsListProvider.js
+++ b/client/src/containers/Purchases/Bills/BillsLanding/BillsListProvider.js
@@ -10,14 +10,14 @@ const BillsListContext = createContext();
*/
function BillsListProvider({ query, ...props }) {
// Fetch accounts resource views and fields.
- const { data: billsViews, isFetching: isViewsLoading } = useResourceViews(
+ const { data: billsViews, isLoading: isViewsLoading } = useResourceViews(
'bills',
);
// Fetch the accounts resource fields.
const {
data: billsFields,
- isFetching: isFieldsLoading,
+ isLoading: isFieldsLoading,
} = useResourceFields('bills');
// Fetch accounts list according to the given custom view id.
diff --git a/client/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormProvider.js b/client/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormProvider.js
index 3cc2eaec8..2ac1deaee 100644
--- a/client/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormProvider.js
+++ b/client/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeFormProvider.js
@@ -21,7 +21,7 @@ function PaymentMadeFormProvider({ paymentMadeId, ...props }) {
const [paymentVendorId, setPaymentVendorId] = React.useState(null);
// Handle fetch accounts data.
- const { data: accounts, isFetching: isAccountsFetching } = useAccounts();
+ const { data: accounts, isLoading: isAccountsLoading } = useAccounts();
// Handle fetch Items data table or list.
const {
@@ -33,7 +33,7 @@ function PaymentMadeFormProvider({ paymentMadeId, ...props }) {
// Handle fetch venders data table or list.
const {
data: { vendors },
- isFetching: isVendorsFetching,
+ isLoading: isVendorsLoading,
} = useVendors({ page_size: 10000 });
// Handle fetch specific payment made details.
@@ -66,10 +66,10 @@ function PaymentMadeFormProvider({ paymentMadeId, ...props }) {
paymentVendorId,
isNewMode,
- isAccountsFetching,
+ isAccountsLoading,
isItemsFetching,
isItemsLoading,
- isVendorsFetching,
+ isVendorsLoading,
isPaymentFetching,
isPaymentLoading,
@@ -83,9 +83,9 @@ function PaymentMadeFormProvider({ paymentMadeId, ...props }) {
return (
diff --git a/client/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptsListProvider.js b/client/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptsListProvider.js
index 5c0668b5a..edbccc319 100644
--- a/client/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptsListProvider.js
+++ b/client/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptsListProvider.js
@@ -1,6 +1,6 @@
import React, { createContext } from 'react';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
-import { useResourceViews, useResourceFields, useReceipts } from 'hooks/query';
+import { useResourceViews, useReceipts } from 'hooks/query';
import { isTableEmptyStatus } from 'utils';
const ReceiptsListContext = createContext();
@@ -8,7 +8,7 @@ const ReceiptsListContext = createContext();
// Receipts list provider.
function ReceiptsListProvider({ query, ...props }) {
// Fetch receipts resource views and fields.
- const { data: receiptsViews, isFetching: isViewsLoading } = useResourceViews(
+ const { data: receiptsViews, isLoading: isViewsLoading } = useResourceViews(
'sale_receipt',
);
diff --git a/client/src/hooks/query/items.js b/client/src/hooks/query/items.js
index 8013949d1..3e417a44a 100644
--- a/client/src/hooks/query/items.js
+++ b/client/src/hooks/query/items.js
@@ -1,4 +1,4 @@
-import { useMutation, useQuery, useQueryClient } from 'react-query';
+import { useMutation, useQueryClient } from 'react-query';
import { transformPagination, transformResponse } from 'utils';
import { useQueryTenant } from '../useQueryTenant';
import useApiRequest from '../useRequest';
diff --git a/client/src/hooks/query/organization.js b/client/src/hooks/query/organization.js
index 46bbfe988..8feeaf259 100644
--- a/client/src/hooks/query/organization.js
+++ b/client/src/hooks/query/organization.js
@@ -1,9 +1,13 @@
-import t from 'store/types';
+import { useMutation } from 'react-query';
+import t from './types';
import useApiRequest from '../useRequest';
import { useQueryTenant } from '../useQueryTenant';
+import { useEffect } from 'react';
+import { useSetOrganizations, useSetSubscriptions } from '../state';
+import { omit } from 'lodash';
/**
- * Retrieve the contact duplicate.
+ * Retrieve organizations of the authenticated user.
*/
export function useOrganizations(props) {
const apiRequest = useApiRequest();
@@ -23,3 +27,74 @@ export function useOrganizations(props) {
},
);
}
+
+/**
+ * Retrieve the current organization metadata.
+ */
+export function useCurrentOrganization(props) {
+ const apiRequest = useApiRequest();
+ const setOrganizations = useSetOrganizations();
+ const setSubscriptions = useSetSubscriptions();
+
+ const query = useQueryTenant(
+ [t.ORGANIZATION_CURRENT],
+ () => apiRequest.get(`organization/current`),
+ {
+ select: (res) => res.data.organization,
+ initialDataUpdatedAt: 0,
+ initialData: {
+ data: {
+ organization: {},
+ },
+ },
+ ...props,
+ },
+ );
+
+ useEffect(() => {
+ if (query.isSuccess) {
+ const organization = omit(query.data, ['subscriptions']);
+
+ // Sets organizations.
+ setOrganizations([organization]);
+
+ // Sets subscriptions.
+ setSubscriptions(query.data.subscriptions);
+ }
+ }, [query.data, query.isSuccess, setOrganizations, setSubscriptions]);
+
+ return query;
+}
+
+/**
+ * Builds the current tenant.
+ */
+export function useBuildTenant(props) {
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.post('organization/build'),
+ {
+ onSuccess: (res, values) => {
+
+ },
+ ...props,
+ },
+ );
+};
+
+/**
+ * Seeds the current tenant
+ */
+export function useSeedTenant() {
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.post('organization/seed'),
+ {
+ onSuccess: (res) => {
+
+ },
+ }
+ )
+};
\ No newline at end of file
diff --git a/client/src/hooks/query/settings.js b/client/src/hooks/query/settings.js
index b91463b92..559052565 100644
--- a/client/src/hooks/query/settings.js
+++ b/client/src/hooks/query/settings.js
@@ -1,9 +1,9 @@
import { useEffect } from 'react';
import { useMutation, useQueryClient } from 'react-query';
import { useQueryTenant } from '../useQueryTenant';
-import { useDispatch } from 'react-redux';
import useApiRequest from '../useRequest';
-import t from 'store/types';
+import { useSetSettings } from 'hooks/state';
+import t from './types';
/**
* Saves the settings.
@@ -21,8 +21,8 @@ export function useSaveSettings(props) {
}
function useSettingsQuery(key, query, props) {
- const dispatch = useDispatch();
const apiRequest = useApiRequest();
+ const setSettings = useSetSettings();
const state = useQueryTenant(
key,
@@ -40,10 +40,10 @@ function useSettingsQuery(key, query, props) {
);
useEffect(() => {
- if (typeof state.data !== 'undefined') {
- dispatch({ type: t.SETTING_SET, options: state.data });
+ if (state.isSuccess) {
+ setSettings(state.data);
}
- }, [state.data, dispatch]);
+ }, [state.data, state.isSuccess, setSettings]);
return state.data;
}
diff --git a/client/src/hooks/query/types.js b/client/src/hooks/query/types.js
index 766230392..716b0015f 100644
--- a/client/src/hooks/query/types.js
+++ b/client/src/hooks/query/types.js
@@ -90,7 +90,8 @@ const SETTING = {
};
const ORGANIZATIONS = {
- ORGANIZATIONS: 'ORGANIZATIONS'
+ ORGANIZATIONS: 'ORGANIZATIONS',
+ ORGANIZATION_CURRENT: 'ORGANIZATION_CURRENT'
};
export default {
diff --git a/client/src/hooks/state/authentication.js b/client/src/hooks/state/authentication.js
index bb74b8d94..5af99dfd5 100644
--- a/client/src/hooks/state/authentication.js
+++ b/client/src/hooks/state/authentication.js
@@ -2,13 +2,22 @@ import { useDispatch, useSelector } from 'react-redux';
import { useCallback } from 'react';
import { isAuthenticated } from 'store/authentication/authentication.reducer';
import { setLogin, setLogout } from 'store/authentication/authentication.actions';
+import { useQueryClient } from 'react-query';
export const useAuthActions = () => {
const dispatch = useDispatch();
+ const queryClient = useQueryClient();
return {
setLogin: useCallback((login) => dispatch(setLogin(login)), [dispatch]),
- setLogout: useCallback(() => dispatch(setLogout()), [dispatch]),
+ setLogout: useCallback(() => {
+
+ // Logout action.
+ dispatch(setLogout());
+
+ // Remove all cached queries.
+ queryClient.removeQueries();
+ }, [dispatch, queryClient]),
};
};
diff --git a/client/src/hooks/state/index.js b/client/src/hooks/state/index.js
index 4208d88aa..75580b504 100644
--- a/client/src/hooks/state/index.js
+++ b/client/src/hooks/state/index.js
@@ -1,3 +1,6 @@
export * from './dashboard';
export * from './authentication';
-export * from './globalErrors';
\ No newline at end of file
+export * from './globalErrors';
+export * from './subscriptions';
+export * from './organizations';
+export * from './settings';
\ No newline at end of file
diff --git a/client/src/hooks/state/organizations.js b/client/src/hooks/state/organizations.js
new file mode 100644
index 000000000..56647c500
--- /dev/null
+++ b/client/src/hooks/state/organizations.js
@@ -0,0 +1,11 @@
+import { useCallback } from "react";
+import { useDispatch } from "react-redux";
+import { setOrganizations } from 'store/organizations/organizations.actions';
+
+export const useSetOrganizations = () => {
+ const dispatch = useDispatch();
+
+ return useCallback((organizations) => {
+ dispatch(setOrganizations(organizations))
+ }, [dispatch]);
+};
\ No newline at end of file
diff --git a/client/src/hooks/state/settings.js b/client/src/hooks/state/settings.js
new file mode 100644
index 000000000..b26393c21
--- /dev/null
+++ b/client/src/hooks/state/settings.js
@@ -0,0 +1,12 @@
+import { useCallback } from "react";
+import { useDispatch } from "react-redux";
+import { setSettings } from 'store/settings/settings.actions';
+
+
+export const useSetSettings = () => {
+ const dispatch = useDispatch();
+
+ return useCallback((settings) => {
+ dispatch(setSettings(settings));
+ }, [dispatch]);
+};
\ No newline at end of file
diff --git a/client/src/hooks/state/subscriptions.js b/client/src/hooks/state/subscriptions.js
new file mode 100644
index 000000000..7da587908
--- /dev/null
+++ b/client/src/hooks/state/subscriptions.js
@@ -0,0 +1,14 @@
+import { useCallback } from "react"
+import { useDispatch } from "react-redux";
+import { setSubscriptions } from 'store/subscription/subscription.actions';
+
+/**
+ * Sets subscriptions.
+ */
+export const useSetSubscriptions = () => {
+ const dispatch = useDispatch();
+
+ return useCallback((subscriptions) => {
+ dispatch(setSubscriptions(subscriptions));
+ }, [dispatch]);
+}
\ No newline at end of file
diff --git a/client/src/hooks/useRequest.js b/client/src/hooks/useRequest.js
index f3cc834c6..be5909ed0 100644
--- a/client/src/hooks/useRequest.js
+++ b/client/src/hooks/useRequest.js
@@ -18,10 +18,11 @@ export default function useApiRequest() {
const organizationId = useAuthOrganizationId();
const http = React.useMemo(() => {
- axios.create();
+ // Axios instance.
+ const instance = axios.create();
// Request interceptors.
- axios.interceptors.request.use(
+ instance.interceptors.request.use(
(request) => {
const locale = 'en';
@@ -40,9 +41,8 @@ export default function useApiRequest() {
return Promise.reject(error);
},
);
-
// Response interceptors.
- axios.interceptors.response.use(
+ instance.interceptors.response.use(
(response) => response,
(error) => {
const { status } = error.response;
@@ -57,8 +57,7 @@ export default function useApiRequest() {
return Promise.reject(error);
},
);
-
- return axios;
+ return instance;
}, [token, organizationId, setGlobalErrors, setLogout]);
return {
diff --git a/client/src/store/authentication/authentication.reducer.js b/client/src/store/authentication/authentication.reducer.js
index 12db81283..eb7e66097 100644
--- a/client/src/store/authentication/authentication.reducer.js
+++ b/client/src/store/authentication/authentication.reducer.js
@@ -29,6 +29,8 @@ export default createReducer(initialState, {
state.token = '';
state.user = {};
state.organization = '';
+ state.organizationId = null;
+ state.tenant = {};
},
[t.LOGIN_CLEAR_ERRORS]: (state) => {
diff --git a/client/src/store/organizations/organizations.actions.js b/client/src/store/organizations/organizations.actions.js
index ec44a62d4..e49a23393 100644
--- a/client/src/store/organizations/organizations.actions.js
+++ b/client/src/store/organizations/organizations.actions.js
@@ -1,6 +1,15 @@
import ApiService from 'services/ApiService';
import t from 'store/types';
+export const setOrganizations = (organizations) => {
+ return {
+ type: t.ORGANIZATIONS_LIST_SET,
+ payload: {
+ organizations,
+ },
+ };
+}
+
export const fetchOrganizations = () => (dispatch) => new Promise((resolve, reject) => {
ApiService.get('organization/all').then((response) => {
dispatch({
diff --git a/client/src/store/settings/settings.actions.js b/client/src/store/settings/settings.actions.js
index f4560cd20..3eea4aefa 100644
--- a/client/src/store/settings/settings.actions.js
+++ b/client/src/store/settings/settings.actions.js
@@ -29,3 +29,11 @@ export const FetchOptions = ({ form }) => {
});
});
};
+
+
+export const setSettings = (settings) => {
+ return {
+ type: t.SETTING_SET,
+ options: settings,
+ };
+}
\ No newline at end of file
diff --git a/client/src/store/subscription/subscription.actions.js b/client/src/store/subscription/subscription.actions.js
index 28ef9d8f2..bd765a782 100644
--- a/client/src/store/subscription/subscription.actions.js
+++ b/client/src/store/subscription/subscription.actions.js
@@ -11,4 +11,14 @@ export const fetchSubscriptions = () => (dispatch) => new Promise((resolve, reje
});
resolve(response);
}).catch((error) => { reject(error); })
-});
\ No newline at end of file
+});
+
+
+export const setSubscriptions = (subscriptions) => {
+ return {
+ type: t.SET_PLAN_SUBSCRIPTIONS_LIST,
+ payload: {
+ subscriptions,
+ },
+ }
+};
\ No newline at end of file
diff --git a/client/src/style/App.scss b/client/src/style/App.scss
index 8cebb9fcc..32073e3d9 100644
--- a/client/src/style/App.scss
+++ b/client/src/style/App.scss
@@ -100,3 +100,80 @@ body.hide-scrollbar .Pane2{
background-color: rgba(0,10,30, .7);
}
+
+.ReactVirtualized__Collection {
+}
+
+.ReactVirtualized__Collection__innerScrollContainer {
+}
+
+/* Grid default theme */
+
+.ReactVirtualized__Grid {
+}
+
+.ReactVirtualized__Grid__innerScrollContainer {
+}
+
+/* Table default theme */
+
+.ReactVirtualized__Table {
+}
+
+.ReactVirtualized__Table__Grid {
+}
+
+.ReactVirtualized__Table__headerRow {
+ font-weight: 700;
+ text-transform: uppercase;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+.ReactVirtualized__Table__row {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+
+.ReactVirtualized__Table__headerTruncatedText {
+ display: inline-block;
+ max-width: 100%;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.ReactVirtualized__Table__headerColumn,
+.ReactVirtualized__Table__rowColumn {
+ margin-right: 10px;
+ min-width: 0px;
+}
+.ReactVirtualized__Table__rowColumn {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.ReactVirtualized__Table__headerColumn:first-of-type,
+.ReactVirtualized__Table__rowColumn:first-of-type {
+ margin-left: 10px;
+}
+.ReactVirtualized__Table__sortableHeaderColumn {
+ cursor: pointer;
+}
+
+.ReactVirtualized__Table__sortableHeaderIconContainer {
+ display: flex;
+ align-items: center;
+}
+.ReactVirtualized__Table__sortableHeaderIcon {
+ flex: 0 0 24px;
+ height: 1em;
+ width: 1em;
+ fill: currentColor;
+}
+
+/* List default theme */
+
+.ReactVirtualized__List {
+}
\ No newline at end of file
diff --git a/client/src/style/components/DataTable/DataTable.scss b/client/src/style/components/DataTable/DataTable.scss
index 92b1de9a8..64ec85bf8 100644
--- a/client/src/style/components/DataTable/DataTable.scss
+++ b/client/src/style/components/DataTable/DataTable.scss
@@ -68,6 +68,11 @@
.bp3-context-menu-popover-target{
z-index: 100;
}
+
+ .tr-context{
+ display: flex;
+ flex: 1 0 auto;
+ }
}
.th,
@@ -256,6 +261,11 @@
}
}
}
+
+ .tr-inner{
+ display: flex;
+ width: 100%;
+ }
}
.no-results {
@@ -314,4 +324,9 @@
overflow-x: hidden;
}
}
+
+
+ .ReactVirtualized__Grid{
+ will-change: auto !important;
+ }
}
diff --git a/client/src/style/pages/FinancialStatements/FinancialReportPage.scss b/client/src/style/pages/FinancialStatements/FinancialReportPage.scss
index 4172db4c0..213fcd485 100644
--- a/client/src/style/pages/FinancialStatements/FinancialReportPage.scss
+++ b/client/src/style/pages/FinancialStatements/FinancialReportPage.scss
@@ -9,7 +9,7 @@
border-radius: 2px;
background-color: #fdecda;
color: #342515;
- font-size: 12px;
+ font-size: 13px;
button{
font-size: 12px;
@@ -29,4 +29,10 @@
fill: #975f19;
}
}
-}
+
+ .financial-progressbar{
+ .progress-materializecss{
+ top: -2px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/src/style/pages/FinancialStatements/Journal.scss b/client/src/style/pages/FinancialStatements/Journal.scss
index f841d3a6c..d544ee1b7 100644
--- a/client/src/style/pages/FinancialStatements/Journal.scss
+++ b/client/src/style/pages/FinancialStatements/Journal.scss
@@ -36,6 +36,10 @@
font-weight: 600;
}
+ .tr{
+ height: 28px;
+ }
+
}
}
}
diff --git a/client/src/utils.js b/client/src/utils.js
index 75978d6d9..f6deeee19 100644
--- a/client/src/utils.js
+++ b/client/src/utils.js
@@ -178,8 +178,8 @@ export function formattedExchangeRate(amount, currency) {
return formatter.format(amount);
}
-export const ConditionalWrapper = ({ condition, wrapper, children }) =>
- condition ? wrapper(children) : children;
+export const ConditionalWrapper = ({ condition, wrapper, children, ...rest }) =>
+ condition ? wrapper({ children, ...rest }) : children;
export const checkRequiredProperties = (obj, properties) => {
return properties.some((prop) => {
diff --git a/server/src/api/controllers/Organization.ts b/server/src/api/controllers/Organization.ts
index 4153837a8..e89de8750 100644
--- a/server/src/api/controllers/Organization.ts
+++ b/server/src/api/controllers/Organization.ts
@@ -1,6 +1,6 @@
import { Inject, Service } from 'typedi';
import { Router, Request, Response, NextFunction } from 'express';
-import asyncMiddleware from "api/middleware/asyncMiddleware";
+import asyncMiddleware from 'api/middleware/asyncMiddleware';
import JWTAuth from 'api/middleware/jwtAuth';
import TenancyMiddleware from 'api/middleware/TenancyMiddleware';
import SubscriptionMiddleware from 'api/middleware/SubscriptionMiddleware';
@@ -12,7 +12,7 @@ import EnsureConfiguredMiddleware from 'api/middleware/EnsureConfiguredMiddlewar
import SettingsMiddleware from 'api/middleware/SettingsMiddleware';
@Service()
-export default class OrganizationController extends BaseController{
+export default class OrganizationController extends BaseController {
@Inject()
organizationService: OrganizationService;
@@ -22,12 +22,12 @@ export default class OrganizationController extends BaseController{
router() {
const router = Router();
- // Should before build tenant database the user be authorized and
+ // Should before build tenant database the user be authorized and
// most important than that, should be subscribed to any plan.
router.use(JWTAuth);
router.use(AttachCurrentTenantUser);
router.use(TenancyMiddleware);
-
+
// Should to seed organization tenant be configured.
router.use('/seed', SubscriptionMiddleware('main'));
router.use('/seed', SettingsMiddleware);
@@ -35,17 +35,12 @@ export default class OrganizationController extends BaseController{
router.use('/build', SubscriptionMiddleware('main'));
- router.post(
- '/build',
- asyncMiddleware(this.build.bind(this))
- );
- router.post(
- '/seed',
- asyncMiddleware(this.seed.bind(this)),
- );
+ router.post('/build', asyncMiddleware(this.build.bind(this)));
+ router.post('/seed', asyncMiddleware(this.seed.bind(this)));
+ router.get('/all', asyncMiddleware(this.allOrganizations.bind(this)));
router.get(
- '/all',
- asyncMiddleware(this.allOrganizations.bind(this)),
+ '/current',
+ asyncMiddleware(this.currentOrganization.bind(this))
);
return router;
}
@@ -54,19 +49,19 @@ export default class OrganizationController extends BaseController{
* Builds tenant database and migrate database schema.
* @param {Request} req - Express request.
* @param {Response} res - Express response.
- * @param {NextFunction} next
+ * @param {NextFunction} next
*/
async build(req: Request, res: Response, next: Function) {
const { organizationId } = req.tenant;
const { user } = req;
-
+
try {
await this.organizationService.build(organizationId, user);
return res.status(200).send({
type: 'success',
code: 'ORGANIZATION.DATABASE.INITIALIZED',
- message: 'The organization database has been initialized.'
+ message: 'The organization database has been initialized.',
});
} catch (error) {
if (error instanceof ServiceError) {
@@ -87,9 +82,9 @@ export default class OrganizationController extends BaseController{
/**
* Seeds initial data to tenant database.
- * @param {Request} req
- * @param {Response} res
- * @param {NextFunction} next
+ * @param {Request} req
+ * @param {Response} res
+ * @param {NextFunction} next
*/
async seed(req: Request, res: Response, next: Function) {
const { organizationId } = req.tenant;
@@ -100,7 +95,7 @@ export default class OrganizationController extends BaseController{
return res.status(200).send({
type: 'success',
code: 'ORGANIZATION.DATABASE.SEED',
- message: 'The organization database has been seeded.'
+ message: 'The organization database has been seeded.',
});
} catch (error) {
if (error instanceof ServiceError) {
@@ -126,18 +121,39 @@ export default class OrganizationController extends BaseController{
/**
* Listing all organizations that assocaited to the authorized user.
- * @param {Request} req
- * @param {Response} res
- * @param {NextFunction} next
+ * @param {Request} req
+ * @param {Response} res
+ * @param {NextFunction} next
*/
async allOrganizations(req: Request, res: Response, next: NextFunction) {
const { user } = req;
try {
- const organizations = await this.organizationService.listOrganizations(user);
+ const organizations = await this.organizationService.listOrganizations(
+ user
+ );
return res.status(200).send({ organizations });
} catch (error) {
next(error);
}
}
-}
\ No newline at end of file
+
+ /**
+ * Retrieve the current organization of the associated authenticated user.
+ * @param {Request} req
+ * @param {Response} res
+ * @param {NextFunction} next
+ */
+ async currentOrganization(req: Request, res: Response, next: NextFunction) {
+ const { tenantId } = req;
+
+ try {
+ const organization = await this.organizationService.currentOrganization(
+ tenantId
+ );
+ return res.status(200).send({ organization });
+ } catch (error) {
+ next(error);
+ }
+ }
+}
diff --git a/server/src/services/Organization/index.ts b/server/src/services/Organization/index.ts
index 45e5e9b75..e81ed40d8 100644
--- a/server/src/services/Organization/index.ts
+++ b/server/src/services/Organization/index.ts
@@ -19,6 +19,7 @@ const ERRORS = {
TENANT_ALREADY_SEEDED: 'tenant_already_seeded',
TENANT_DB_NOT_BUILT: 'tenant_db_not_built',
};
+
@Service()
export default class OrganizationService {
@EventDispatcher()
@@ -111,6 +112,20 @@ export default class OrganizationService {
return [tenant];
}
+ /**
+ * Retrieve the current organization metadata.
+ * @param {number} tenantId
+ * @returns {Promise}
+ */
+ public async currentOrganization(tenantId: number): Promise {
+ const { tenantRepository } = this.sysRepositories;
+ const tenant = await tenantRepository.findOneById(tenantId, ['subscriptions']);
+
+ this.throwIfTenantNotExists(tenant);
+
+ return tenant;
+ }
+
/**
* Throws error in case the given tenant is undefined.
* @param {ITenant} tenant