mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
fix: dashboard sidebar expanding.
This commit is contained in:
@@ -22,7 +22,8 @@ export default function DashboardContentRoute() {
|
||||
pageTitle={route.pageTitle}
|
||||
backLink={route.backLink}
|
||||
hint={route.hint}
|
||||
sidebarShrink={route.sidebarShrink}
|
||||
sidebarExpand={route.sidebarExpand}
|
||||
pageType={route.pageType}
|
||||
/>
|
||||
</Route>
|
||||
))}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import React, { useEffect, Suspense } from 'react';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import { compose } from 'utils';
|
||||
import { Spinner } from '@blueprintjs/core';
|
||||
|
||||
/**
|
||||
* Dashboard pages wrapper.
|
||||
*/
|
||||
@@ -9,7 +12,7 @@ function DashboardPage({
|
||||
// #ownProps
|
||||
pageTitle,
|
||||
backLink,
|
||||
sidebarShrink,
|
||||
sidebarExpand = true,
|
||||
Component,
|
||||
name,
|
||||
hint,
|
||||
@@ -17,10 +20,10 @@ function DashboardPage({
|
||||
// #withDashboardActions
|
||||
changePageTitle,
|
||||
setDashboardBackLink,
|
||||
setSidebarShrink,
|
||||
resetSidebarPreviousExpand,
|
||||
changePageHint,
|
||||
toggleSidebarExpand
|
||||
}) {
|
||||
// Hydrate the given page title.
|
||||
useEffect(() => {
|
||||
pageTitle && changePageTitle(pageTitle);
|
||||
|
||||
@@ -29,6 +32,7 @@ function DashboardPage({
|
||||
};
|
||||
});
|
||||
|
||||
// Hydrate the given page hint.
|
||||
useEffect(() => {
|
||||
hint && changePageHint(hint);
|
||||
|
||||
@@ -37,6 +41,7 @@ function DashboardPage({
|
||||
}
|
||||
}, [hint, changePageHint]);
|
||||
|
||||
// Hydrate the dashboard back link status.
|
||||
useEffect(() => {
|
||||
backLink && setDashboardBackLink(backLink);
|
||||
|
||||
@@ -45,16 +50,6 @@ function DashboardPage({
|
||||
};
|
||||
}, [backLink, setDashboardBackLink]);
|
||||
|
||||
// Handle sidebar shrink in mount and reset to the pervious state
|
||||
// once the page unmount.
|
||||
useEffect(() => {
|
||||
sidebarShrink && setSidebarShrink();
|
||||
|
||||
return () => {
|
||||
sidebarShrink && resetSidebarPreviousExpand();
|
||||
};
|
||||
}, [resetSidebarPreviousExpand, sidebarShrink, setSidebarShrink]);
|
||||
|
||||
useEffect(() => {
|
||||
const className = `page-${name}`;
|
||||
name && document.body.classList.add(className);
|
||||
@@ -64,13 +59,23 @@ function DashboardPage({
|
||||
};
|
||||
}, [name]);
|
||||
|
||||
useEffect(() => {
|
||||
toggleSidebarExpand(sidebarExpand);
|
||||
}, [toggleSidebarExpand, sidebarExpand])
|
||||
|
||||
return (
|
||||
<div className={CLASSES.DASHBOARD_PAGE}>
|
||||
<Suspense fallback={''}>
|
||||
<Suspense fallback={
|
||||
<div class="dashboard__fallback-loading">
|
||||
<Spinner size={40} value={null} />
|
||||
</div>
|
||||
}>
|
||||
<Component />
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDashboardActions)(DashboardPage);
|
||||
export default compose(
|
||||
withDashboardActions,
|
||||
)(DashboardPage);
|
||||
|
||||
@@ -34,8 +34,7 @@ function DashboardTopbar({
|
||||
pageHint,
|
||||
|
||||
// #withDashboardActions
|
||||
toggleSidebarExpend,
|
||||
recordSidebarPreviousExpand,
|
||||
toggleSidebarExpand,
|
||||
|
||||
// #withDashboard
|
||||
sidebarExpended,
|
||||
@@ -53,8 +52,7 @@ function DashboardTopbar({
|
||||
};
|
||||
|
||||
const handleSidebarToggleBtn = () => {
|
||||
toggleSidebarExpend();
|
||||
recordSidebarPreviousExpand();
|
||||
toggleSidebarExpand();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useContext } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import TableContext from './TableContext';
|
||||
|
||||
/**
|
||||
@@ -20,10 +21,12 @@ export default function TableFooter() {
|
||||
{group.headers.map((column) => (
|
||||
<div
|
||||
{...column.getFooterProps({
|
||||
className: 'td',
|
||||
className: classNames(column.className || '', 'td'),
|
||||
})}
|
||||
>
|
||||
{column.render('Footer')}
|
||||
<div className={'cell-inner'}>
|
||||
{column.render('Footer')}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -72,20 +72,6 @@ export function ActionsMenu({
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions cell.
|
||||
*/
|
||||
export function ActionsCell(props) {
|
||||
return (
|
||||
<Popover
|
||||
position={Position.RIGHT_BOTTOM}
|
||||
content={<ActionsMenu {...props} />}
|
||||
>
|
||||
<Button icon={<Icon icon="more-h-16" iconSize={16} />} />
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal cell.
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { Intent, Tag } from '@blueprintjs/core';
|
||||
import { If, AppToaster } from 'components';
|
||||
import { formatMessage } from 'services/intl';
|
||||
import { NormalCell, BalanceCell, ActionsCell } from './components';
|
||||
import { NormalCell, BalanceCell } from './components';
|
||||
|
||||
/**
|
||||
* Account name accessor.
|
||||
@@ -40,6 +40,13 @@ export const handleDeleteErrors = (errors) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export const AccountCodeAccessor = (row) => (
|
||||
<Tag minimal={true} round={true} intent={Intent.NONE}>
|
||||
{ row.code }
|
||||
</Tag>
|
||||
);
|
||||
|
||||
/**
|
||||
* Accounts table columns.
|
||||
*/
|
||||
@@ -56,7 +63,7 @@ export const useAccountsTableColumns = () => {
|
||||
{
|
||||
id: 'code',
|
||||
Header: formatMessage({ id: 'code' }),
|
||||
accessor: 'code',
|
||||
accessor: AccountCodeAccessor,
|
||||
className: 'code',
|
||||
width: 80,
|
||||
},
|
||||
@@ -88,14 +95,6 @@ export const useAccountsTableColumns = () => {
|
||||
Cell: BalanceCell,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
Header: '',
|
||||
Cell: ActionsCell,
|
||||
className: 'actions',
|
||||
width: 50,
|
||||
skeletonWidthMin: 100,
|
||||
},
|
||||
],
|
||||
[],
|
||||
)
|
||||
|
||||
@@ -49,20 +49,6 @@ export function ActionsMenu({
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions cell.
|
||||
*/
|
||||
export function ActionsCell(props) {
|
||||
return (
|
||||
<Popover
|
||||
content={<ActionsMenu {...props} />}
|
||||
position={Position.RIGHT_BOTTOM}
|
||||
>
|
||||
<Button icon={<Icon icon="more-h-16" iconSize={16} />} />
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Avatar cell.
|
||||
*/
|
||||
@@ -129,14 +115,6 @@ export function useCustomersTableColumns() {
|
||||
className: 'receivable_balance',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
Cell: ActionsCell,
|
||||
className: 'actions',
|
||||
width: 70,
|
||||
disableResizing: true,
|
||||
disableSortBy: true,
|
||||
},
|
||||
],
|
||||
[formatMessage],
|
||||
);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { connect } from 'react-redux';
|
||||
import t from 'store/types';
|
||||
import {
|
||||
toggleExpendSidebar,
|
||||
} from 'store/dashboard/dashboard.actions';
|
||||
|
||||
const mapActionsToProps = (dispatch) => ({
|
||||
changePageTitle: (pageTitle) =>
|
||||
@@ -14,10 +17,10 @@ const mapActionsToProps = (dispatch) => ({
|
||||
pageSubtitle,
|
||||
}),
|
||||
|
||||
changePageHint: (pageHint) =>
|
||||
changePageHint: (pageHint) =>
|
||||
dispatch({
|
||||
type: t.CHANGE_DASHBOARD_PAGE_HINT,
|
||||
payload: { pageHint }
|
||||
payload: { pageHint },
|
||||
}),
|
||||
|
||||
setTopbarEditView: (id) =>
|
||||
@@ -36,32 +39,22 @@ const mapActionsToProps = (dispatch) => ({
|
||||
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||
}),
|
||||
|
||||
toggleSidebarExpend: () =>
|
||||
/**
|
||||
* Toggles the sidebar expend.
|
||||
*/
|
||||
toggleSidebarExpand: (toggle) => dispatch(toggleExpendSidebar(toggle)),
|
||||
|
||||
changePreferencesPageTitle: (pageTitle) =>
|
||||
dispatch({
|
||||
type: t.SIDEBAR_EXPEND_TOGGLE,
|
||||
type: 'CHANGE_PREFERENCES_PAGE_TITLE',
|
||||
pageTitle,
|
||||
}),
|
||||
|
||||
setDashboardBackLink: (backLink) =>
|
||||
dispatch({
|
||||
type: t.SET_DASHBOARD_BACK_LINK,
|
||||
payload: { backLink },
|
||||
}),
|
||||
|
||||
changePreferencesPageTitle: (pageTitle) => dispatch({
|
||||
type: 'CHANGE_PREFERENCES_PAGE_TITLE',
|
||||
pageTitle,
|
||||
}),
|
||||
setSidebarShrink: () => dispatch({
|
||||
type: t.SIDEBAR_SHRINK,
|
||||
}),
|
||||
setSidebarExpand: () => dispatch({
|
||||
type: t.SIDEBAR_SHRINK,
|
||||
}),
|
||||
resetSidebarPreviousExpand: () => dispatch({
|
||||
type: t.RESET_SIDEBAR_PREVIOUS_EXPAND,
|
||||
}),
|
||||
recordSidebarPreviousExpand: () => dispatch({
|
||||
type: t.RECORD_SIDEBAR_PREVIOUS_EXPAND,
|
||||
}),
|
||||
|
||||
setDashboardBackLink: (backLink) => dispatch({
|
||||
type: t.SET_DASHBOARD_BACK_LINK,
|
||||
payload: { backLink }
|
||||
})
|
||||
});
|
||||
|
||||
export default connect(null, mapActionsToProps);
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { useExpensesListContext } from './ExpensesListProvider';
|
||||
|
||||
import { Choose } from 'components';
|
||||
import { CLASSES } from 'common/classes';
|
||||
|
||||
import DataTable from 'components/DataTable';
|
||||
import ExpensesEmptyStatus from './ExpensesEmptyStatus';
|
||||
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
|
||||
|
||||
@@ -175,14 +175,6 @@ export function useExpensesTableColumns() {
|
||||
className: 'description',
|
||||
disableSortBy: true,
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
Header: '',
|
||||
Cell: ActionsCell,
|
||||
className: 'actions',
|
||||
width: 50,
|
||||
disableResizing: true,
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import 'style/pages/InventoryAdjustments/List.scss';
|
||||
|
||||
import { DashboardContentTable, DashboardPageContent } from 'components';
|
||||
import InventoryAdjustmentsAlerts from './InventoryAdjustmentsAlerts';
|
||||
|
||||
|
||||
@@ -179,14 +179,6 @@ export const useInventoryAdjustmentsColumns = () => {
|
||||
width: 125,
|
||||
className: 'created_at',
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
Header: '',
|
||||
Cell: ActionsCell,
|
||||
className: 'actions',
|
||||
width: 50,
|
||||
disableResizing: true,
|
||||
},
|
||||
],
|
||||
[formatMessage],
|
||||
);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import React, { useEffect, createContext } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import React, { createContext } from 'react';
|
||||
|
||||
import { transformTableQueryToParams, isTableEmptyStatus } from 'utils';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { useResourceViews, useResourceFields, useItems } from 'hooks/query';
|
||||
import { useDashboardPageTitle } from 'hooks/state';
|
||||
|
||||
const ItemsContext = createContext();
|
||||
|
||||
@@ -40,17 +38,6 @@ function ItemsListProvider({
|
||||
data: items, pagination, filterMeta,
|
||||
}) && !isItemsFetching;
|
||||
|
||||
// Format message intl.
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
// Change page title dispatcher.
|
||||
const changePageTitle = useDashboardPageTitle();
|
||||
|
||||
// Changeas the page title once the page mount.
|
||||
useEffect(() => {
|
||||
changePageTitle(formatMessage({ id: 'items_list' }));
|
||||
}, [changePageTitle, formatMessage]);
|
||||
|
||||
const state = {
|
||||
itemsViews,
|
||||
itemsFields,
|
||||
|
||||
@@ -181,7 +181,6 @@ export const useItemsTableColumns = () => {
|
||||
{
|
||||
id: 'sell_price',
|
||||
Header: formatMessage({ id: 'sell_price' }),
|
||||
// Cell: SellPriceCell,
|
||||
accessor: 'sell_price_formatted',
|
||||
className: 'sell-price',
|
||||
width: 150,
|
||||
@@ -189,7 +188,6 @@ export const useItemsTableColumns = () => {
|
||||
{
|
||||
id: 'cost_price',
|
||||
Header: formatMessage({ id: 'cost_price' }),
|
||||
// Cell: CostPriceCell,
|
||||
accessor: 'cost_price_formatted',
|
||||
className: 'cost-price',
|
||||
width: 150,
|
||||
@@ -201,12 +199,6 @@ export const useItemsTableColumns = () => {
|
||||
Cell: QuantityOnHandCell,
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
Cell: ItemsActionsTableCell,
|
||||
width: 60,
|
||||
skeletonWidthMin: 100,
|
||||
},
|
||||
],
|
||||
[formatMessage],
|
||||
);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React from 'react';
|
||||
import 'style/pages/ItemsCategories/List.scss';
|
||||
|
||||
import { DashboardContentTable, DashboardPageContent } from 'components';
|
||||
|
||||
import ItemsCategoriesAlerts from './ItemsCategoriesAlerts';
|
||||
@@ -11,7 +13,7 @@ import ItemCategoriesTable from './ItemCategoriesTable';
|
||||
*/
|
||||
export default function ItemCategoryList() {
|
||||
return (
|
||||
<ItemsCategoriesProvider query={{}}>
|
||||
<ItemsCategoriesProvider>
|
||||
<ItemsCategoryActionsBar />
|
||||
|
||||
<DashboardPageContent>
|
||||
|
||||
@@ -25,7 +25,7 @@ function ItemsCategoriesProvider({ query, ...props }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider name={'item-category-list'}>
|
||||
<DashboardInsider name={'items-categories-list'}>
|
||||
<ItemsCategoriesContext.Provider value={state} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
|
||||
@@ -81,14 +81,7 @@ export function useItemsCategoriesTableColumns() {
|
||||
accessor: 'description',
|
||||
className: 'description',
|
||||
width: 220,
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
Header: '',
|
||||
Cell: TableActionsCell,
|
||||
className: 'actions',
|
||||
width: 50,
|
||||
},
|
||||
}
|
||||
],
|
||||
[formatMessage],
|
||||
);
|
||||
|
||||
@@ -7,8 +7,29 @@ import { useQueryTenant } from '../useQueryRequest';
|
||||
export function useContact(id, props) {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useQueryTenant(['CONTACT', id], () => apiRequest.get(`contacts/${id}`), {
|
||||
select: (res) => res.data.customer,
|
||||
...props,
|
||||
});
|
||||
return useQueryTenant(
|
||||
['CONTACT', id],
|
||||
() => apiRequest.get(`contacts/${id}`),
|
||||
{
|
||||
select: (res) => res.data.customer,
|
||||
...props,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the auto-complete contacts.
|
||||
*/
|
||||
export function useAutoCompleteContacts(props) {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useQueryTenant(
|
||||
['CONTACTS', 'AUTO-COMPLETE'],
|
||||
() => apiRequest.get('contacts/auto-complete'),
|
||||
{
|
||||
select: (res) => res.data.contacts,
|
||||
defaultData: [],
|
||||
...props,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -96,8 +96,17 @@ const ORGANIZATIONS = {
|
||||
|
||||
const SUBSCRIPTIONS = {
|
||||
SUBSCRIPTIONS: 'SUBSCRIPTIONS',
|
||||
}
|
||||
};
|
||||
|
||||
const EXPENSES = {
|
||||
EXPENSES: 'EXPENSES',
|
||||
EXPENSE: 'EXPENSE',
|
||||
};
|
||||
|
||||
const MANUAL_JOURNALS = {
|
||||
MANUAL_JOURNALS: 'MANUAL_JOURNALS',
|
||||
MANUAL_JOURNAL: 'MANUAL_JOURNAL',
|
||||
};
|
||||
export default {
|
||||
...ACCOUNTS,
|
||||
...BILLS,
|
||||
@@ -115,5 +124,7 @@ export default {
|
||||
...USERS,
|
||||
...SETTING,
|
||||
...ORGANIZATIONS,
|
||||
...SUBSCRIPTIONS
|
||||
...SUBSCRIPTIONS,
|
||||
...EXPENSES,
|
||||
...MANUAL_JOURNALS
|
||||
};
|
||||
|
||||
@@ -858,7 +858,7 @@ export default {
|
||||
the_item_categories_has_been_deleted_successfully:
|
||||
'The item categories has been deleted successfully .',
|
||||
receivable_accounts_should_assign_with_customers:
|
||||
'receivable accounts should assign with customers',
|
||||
'Receivable accounts should assign with customers.',
|
||||
delivered: 'Delivered',
|
||||
save_and_deliver: 'Save & Deliver',
|
||||
deliver_and_new: 'Deliver and new',
|
||||
@@ -1049,4 +1049,5 @@ export default {
|
||||
asset_value: 'Asset value',
|
||||
average: 'Average',
|
||||
inventory_valuation: 'Inventory valuation',
|
||||
payable_accounts_should_assign_with_vendors: 'Payable accounts should assign with vendors.'
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ export default [
|
||||
breadcrumb: 'Make Journal Entry',
|
||||
hotkey: 'ctrl+shift+m',
|
||||
pageTitle: formatMessage({ id: 'new_journal' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -42,7 +42,7 @@ export default [
|
||||
),
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_journal' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -92,6 +92,7 @@ export default [
|
||||
component: lazy(() => import('containers/Items/ItemsList')),
|
||||
breadcrumb: 'Items',
|
||||
hotkey: 'shift+w',
|
||||
pageTitle: formatMessage({ id: 'items_list' }),
|
||||
},
|
||||
|
||||
// Inventory adjustments.
|
||||
@@ -115,7 +116,7 @@ export default [
|
||||
hotkey: 'shift+4',
|
||||
pageTitle: formatMessage({ id: 'general_ledger' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/financial-reports/balance-sheet`,
|
||||
@@ -127,7 +128,7 @@ export default [
|
||||
hotkey: 'shift+1',
|
||||
pageTitle: formatMessage({ id: 'balance_sheet' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/financial-reports/trial-balance-sheet`,
|
||||
@@ -141,7 +142,7 @@ export default [
|
||||
hotkey: 'shift+5',
|
||||
pageTitle: formatMessage({ id: 'trial_balance_sheet' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/financial-reports/profit-loss-sheet`,
|
||||
@@ -153,7 +154,7 @@ export default [
|
||||
hotkey: 'shift+2',
|
||||
pageTitle: formatMessage({ id: 'profit_loss_sheet' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: '/financial-reports/receivable-aging-summary',
|
||||
@@ -164,7 +165,7 @@ export default [
|
||||
hint: "Summarize total unpaid balances of customers invoices with number of days the unpaid invoice is overdue.",
|
||||
pageTitle: formatMessage({ id: 'receivable_aging_summary' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: '/financial-reports/payable-aging-summary',
|
||||
@@ -175,7 +176,7 @@ export default [
|
||||
hint: "Summarize total unpaid balances of vendors purchase invoices with the number of days the unpaid invoice is overdue.",
|
||||
pageTitle: formatMessage({ id: 'payable_aging_summary' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/financial-reports/journal-sheet`,
|
||||
@@ -186,7 +187,7 @@ export default [
|
||||
hint: "The debit and credit entries of system transactions, sorted by date.",
|
||||
hotkey: 'shift+3',
|
||||
pageTitle: formatMessage({ id: 'journal_sheet' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -200,7 +201,7 @@ export default [
|
||||
// hotkey: '',
|
||||
pageTitle: formatMessage({ id: 'purchases_by_items' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/financial-reports/sales-by-items`,
|
||||
@@ -211,7 +212,7 @@ export default [
|
||||
pageTitle: formatMessage({ id: 'sales_by_items' }),
|
||||
hint: 'Summarize the business’s sold items quantity, income and average income rate of each item during a specific point in time.',
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/financial-reports/inventory-valuation`,
|
||||
@@ -224,7 +225,7 @@ export default [
|
||||
hint: 'Summerize your transactions for each inventory item and how they affect quantity, valuation and weighted average.',
|
||||
pageTitle: formatMessage({ id: 'inventory_valuation' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: '/financial-reports',
|
||||
@@ -250,7 +251,7 @@ export default [
|
||||
breadcrumb: 'Expenses',
|
||||
hotkey: 'ctrl+shift+x',
|
||||
pageTitle: formatMessage({ id: 'new_expense' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -260,7 +261,7 @@ export default [
|
||||
),
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_expense' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -367,7 +368,7 @@ export default [
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_estimate' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/invoices/new?from_estimate_id=/:id`,
|
||||
@@ -378,7 +379,7 @@ export default [
|
||||
breadcrumb: 'New Estimate',
|
||||
pageTitle: formatMessage({ id: 'new_estimate' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/estimates/new`,
|
||||
@@ -390,7 +391,7 @@ export default [
|
||||
hotkey: 'ctrl+shift+e',
|
||||
pageTitle: formatMessage({ id: 'new_estimate' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/estimates`,
|
||||
@@ -412,7 +413,7 @@ export default [
|
||||
name: 'invoice-edit',
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_invoice' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -424,7 +425,7 @@ export default [
|
||||
breadcrumb: 'New Invoice',
|
||||
hotkey: 'ctrl+shift+i',
|
||||
pageTitle: formatMessage({ id: 'new_invoice' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -447,7 +448,7 @@ export default [
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_receipt' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/receipts/new`,
|
||||
@@ -459,7 +460,7 @@ export default [
|
||||
hotkey: 'ctrl+shift+r',
|
||||
pageTitle: formatMessage({ id: 'new_receipt' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/receipts`,
|
||||
@@ -483,7 +484,7 @@ export default [
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_payment_receive' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/payment-receives/new`,
|
||||
@@ -496,7 +497,7 @@ export default [
|
||||
breadcrumb: 'New Payment Receive',
|
||||
pageTitle: formatMessage({ id: 'new_payment_receive' }),
|
||||
backLink: true,
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
},
|
||||
{
|
||||
path: `/payment-receives`,
|
||||
@@ -518,7 +519,7 @@ export default [
|
||||
name: 'bill-edit',
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_bill' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -530,7 +531,7 @@ export default [
|
||||
breadcrumb: 'New Bill',
|
||||
hotkey: 'ctrl+shift+b',
|
||||
pageTitle: formatMessage({ id: 'new_bill' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -560,7 +561,7 @@ export default [
|
||||
name: 'payment-made-edit',
|
||||
breadcrumb: 'Edit',
|
||||
pageTitle: formatMessage({ id: 'edit_payment_made' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
@@ -573,7 +574,7 @@ export default [
|
||||
name: 'payment-made-new',
|
||||
breadcrumb: 'New Payment Made',
|
||||
pageTitle: formatMessage({ id: 'new_payment_made' }),
|
||||
sidebarShrink: true,
|
||||
sidebarExpand: false,
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -60,3 +60,13 @@ export function closeDrawer(name, payload) {
|
||||
payload,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the sidebar expend.
|
||||
*/
|
||||
export function toggleExpendSidebar(toggle) {
|
||||
return {
|
||||
type: t.SIDEBAR_EXPEND_TOGGLE,
|
||||
payload: { toggle }
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import t from 'store/types';
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
import { isUndefined } from 'lodash';
|
||||
import t from 'store/types';
|
||||
import { persistReducer, purgeStoredState } from 'redux-persist';
|
||||
import storage from 'redux-persist/lib/storage';
|
||||
|
||||
@@ -9,7 +10,6 @@ const initialState = {
|
||||
pageHint: '',
|
||||
preferencesPageTitle: '',
|
||||
sidebarExpended: true,
|
||||
previousSidebarExpended: null,
|
||||
dialogs: {},
|
||||
alerts: {},
|
||||
drawers: {},
|
||||
@@ -22,7 +22,7 @@ const STORAGE_KEY = 'bigcapital:dashboard';
|
||||
|
||||
const CONFIG = {
|
||||
key: STORAGE_KEY,
|
||||
whitelist: ['sidebarExpended', 'previousSidebarExpended'],
|
||||
whitelist: [],
|
||||
storage,
|
||||
};
|
||||
|
||||
@@ -88,33 +88,11 @@ const reducerInstance = createReducer(initialState, {
|
||||
state.topbarEditViewId = action.id;
|
||||
},
|
||||
|
||||
[t.SET_DASHBOARD_REQUEST_LOADING]: (state, action) => {
|
||||
state.requestsLoading = state.requestsLoading + 1;
|
||||
},
|
||||
|
||||
[t.SET_DASHBOARD_REQUEST_COMPLETED]: (state, action) => {
|
||||
const requestsLoading = state.requestsLoading - 1;
|
||||
state.requestsLoading = Math.max(requestsLoading, 0);
|
||||
},
|
||||
|
||||
[t.RECORD_SIDEBAR_PREVIOUS_EXPAND]: (state) => {
|
||||
state.previousSidebarExpended = state.sidebarExpended;
|
||||
},
|
||||
|
||||
[t.SIDEBAR_EXPEND_TOGGLE]: (state) => {
|
||||
state.sidebarExpended = !state.sidebarExpended;
|
||||
},
|
||||
|
||||
[t.SIDEBAR_EXPAND]: (state) => {
|
||||
state.sidebarExpended = true;
|
||||
},
|
||||
|
||||
[t.SIDEBAR_SHRINK]: (state) => {
|
||||
state.sidebarExpended = false;
|
||||
},
|
||||
|
||||
[t.RESET_SIDEBAR_PREVIOUS_EXPAND]: (state) => {
|
||||
state.sidebarExpended = state.previousSidebarExpended;
|
||||
[t.SIDEBAR_EXPEND_TOGGLE]: (state, action) => {
|
||||
const { toggle } = action.payload;
|
||||
state.sidebarExpended = isUndefined(toggle)
|
||||
? !state.sidebarExpended
|
||||
: !!toggle;
|
||||
},
|
||||
|
||||
[t.SET_DASHBOARD_BACK_LINK]: (state, action) => {
|
||||
|
||||
@@ -12,12 +12,6 @@ export default {
|
||||
CHANGE_PREFERENCES_PAGE_TITLE: 'CHANGE_PREFERENCES_PAGE_TITLE',
|
||||
ALTER_DASHBOARD_PAGE_SUBTITLE: 'ALTER_DASHBOARD_PAGE_SUBTITLE',
|
||||
SET_TOPBAR_EDIT_VIEW: 'SET_TOPBAR_EDIT_VIEW',
|
||||
SET_DASHBOARD_REQUEST_LOADING: 'SET_DASHBOARD_REQUEST_LOADING',
|
||||
SET_DASHBOARD_REQUEST_COMPLETED: 'SET_DASHBOARD_REQUEST_COMPLETED',
|
||||
SIDEBAR_EXPEND_TOGGLE: 'SIDEBAR_EXPEND_TOGGLE',
|
||||
SIDEBAR_EXPAND: 'SIDEBAR_EXPAND',
|
||||
SIDEBAR_SHRINK: 'SIDEBAR_SHRINK',
|
||||
RESET_SIDEBAR_PREVIOUS_EXPAND: 'RESET_SIDEBAR_PREVIOUS_EXPAND',
|
||||
RECORD_SIDEBAR_PREVIOUS_EXPAND: 'RECORD_SIDEBAR_PREVIOUS_EXPAND',
|
||||
SET_DASHBOARD_BACK_LINK: 'SET_DASHBOARD_BACK_LINK',
|
||||
};
|
||||
|
||||
@@ -307,6 +307,17 @@ $dashboard-views-bar-height: 45px;
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
&__fallback-loading{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: #fbfbfb;
|
||||
|
||||
.bp3-spinner{
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__page-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -223,13 +223,14 @@ export default class UsersController extends BaseController{
|
||||
* @param {NextFunction} next
|
||||
*/
|
||||
catchServiceErrors(error: Error, req: Request, res: Response, next: NextFunction) {
|
||||
|
||||
if (error instanceof ServiceErrors) {
|
||||
const errorReasons = [];
|
||||
|
||||
if (error.errorType === 'EMAIL_ALREADY_EXISTS') {
|
||||
|
||||
if (error.hasType('EMAIL_ALREADY_EXISTS')) {
|
||||
errorReasons.push({ type: 'EMAIL_ALREADY_EXIST', code: 100 });
|
||||
}
|
||||
if (error.errorType === 'PHONE_NUMBER_ALREADY_EXIST') {
|
||||
if (error.hasType('PHONE_NUMBER_ALREADY_EXIST')) {
|
||||
errorReasons.push({ type: 'PHONE_NUMBER_ALREADY_EXIST', code: 200 });
|
||||
}
|
||||
if (errorReasons.length > 0) {
|
||||
|
||||
@@ -2,6 +2,7 @@ import TenancyService from 'services/Tenancy/TenancyService';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { ServiceError, ServiceErrors } from 'exceptions';
|
||||
import { ISystemUser, ISystemUserDTO } from 'interfaces';
|
||||
import { SystemUser } from 'system/models';
|
||||
|
||||
const ERRORS = {
|
||||
CANNOT_DELETE_LAST_USER: 'CANNOT_DELETE_LAST_USER',
|
||||
@@ -38,20 +39,20 @@ export default class UsersService {
|
||||
): Promise<ISystemUser> {
|
||||
const { systemUserRepository } = this.repositories;
|
||||
|
||||
const userByEmail = await systemUserRepository.findOne({
|
||||
email: userDTO.email,
|
||||
id: userId,
|
||||
});
|
||||
const userByPhoneNumber = await systemUserRepository.findOne({
|
||||
phoneNumber: userDTO.phoneNumber,
|
||||
id: userId,
|
||||
});
|
||||
const userByEmail = await SystemUser.query()
|
||||
.where('email', userDTO.email)
|
||||
.whereNot('id', userId);
|
||||
|
||||
const userByPhoneNumber = await SystemUser.query()
|
||||
.where('phone_number', userDTO.phoneNumber)
|
||||
.whereNot('id', userId);
|
||||
|
||||
const serviceErrors: ServiceError[] = [];
|
||||
|
||||
if (userByEmail) {
|
||||
if (userByEmail.length > 0) {
|
||||
serviceErrors.push(new ServiceError(ERRORS.EMAIL_ALREADY_EXISTS));
|
||||
}
|
||||
if (userByPhoneNumber) {
|
||||
if (userByPhoneNumber.length > 0) {
|
||||
serviceErrors.push(new ServiceError(ERRORS.PHONE_NUMBER_ALREADY_EXIST));
|
||||
}
|
||||
if (serviceErrors.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user