mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
Merge branch 'master' of https://github.com/abouolia/Bigcapital
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
|
||||
const CLASSES = {
|
||||
DASHBOARD_DATATABLE: 'dashboard__datatable',
|
||||
DATATABLE_EDITOR: 'datatable-editor',
|
||||
DATATABLE_EDITOR_ACTIONS: 'datatable-editor__actions',
|
||||
DATATABLE_EDITOR_ITEMS_ENTRIES: 'items-entries-table',
|
||||
@@ -30,8 +31,11 @@ const CLASSES = {
|
||||
CLOUD_SPINNER: 'cloud-spinner',
|
||||
IS_LOADING: 'is-loading',
|
||||
|
||||
DATATABLE_EMPTY_STATE: 'datatable-empty-state',
|
||||
DATATABLE_EMPTY_STATE_TITLE: 'datatable-empty-state__title',
|
||||
DATATABLE_EMPTY_STATUS: 'datatable-empty-status',
|
||||
DATATABLE_EMPTY_STATUS_TITLE: 'datatable-empty-status__title',
|
||||
DATATABLE_EMPTY_STATUS_DESC: 'datatable-empty-status__desc',
|
||||
DATATABLE_EMPTY_STATUS_ACTIONS: 'datatable-empty-status__actions',
|
||||
|
||||
...Classes,
|
||||
};
|
||||
|
||||
|
||||
22
client/src/components/EmptyStatus.js
Normal file
22
client/src/components/EmptyStatus.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from 'common/classes';
|
||||
|
||||
export default function EmptyStatuts({ title, description, action, children }) {
|
||||
return (
|
||||
<div className={classNames(CLASSES.DATATABLE_EMPTY_STATUS)}>
|
||||
<h1 className={classNames(CLASSES.DATATABLE_EMPTY_STATUS_TITLE)}>
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
<div className={classNames(CLASSES.DATATABLE_EMPTY_STATUS_DESC)}>
|
||||
{description}
|
||||
</div>
|
||||
|
||||
<div className={classNames(CLASSES.DATATABLE_EMPTY_STATUS_ACTIONS)}>
|
||||
{action}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,39 +1,53 @@
|
||||
import React, {useState, useEffect, useMemo} from 'react';
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { Spinner } from '@blueprintjs/core';
|
||||
|
||||
export default function LoadingIndicator({
|
||||
loading,
|
||||
spinnerSize = 40,
|
||||
children,
|
||||
mount = true,
|
||||
mount = false,
|
||||
}) {
|
||||
const [rendered, setRendered] = useState(mount);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) { setRendered(true); }
|
||||
if (!loading) {
|
||||
setRendered(true);
|
||||
}
|
||||
}, [loading]);
|
||||
|
||||
const componentStyle = useMemo(() => {
|
||||
return {display: !loading ? 'block' : 'none'};
|
||||
return { display: !loading ? 'block' : 'none' };
|
||||
}, [loading]);
|
||||
|
||||
const loadingComponent = useMemo(() => (
|
||||
<div class='dashboard__loading-indicator'>
|
||||
<Spinner size={spinnerSize} value={null} />
|
||||
</div>
|
||||
), [spinnerSize]);
|
||||
const loadingComponent = useMemo(
|
||||
() => (
|
||||
<div class="dashboard__loading-indicator">
|
||||
<Spinner size={spinnerSize} value={null} />
|
||||
</div>
|
||||
),
|
||||
[spinnerSize],
|
||||
);
|
||||
|
||||
const renderComponent = useMemo(() => (
|
||||
<div style={componentStyle}>{ children }</div>
|
||||
), [children, componentStyle]);
|
||||
// Renders children with wrapper or without wrapper, in mount mode
|
||||
// rendering with wrapper.
|
||||
const renderChildren = useMemo(
|
||||
() => (mount ? <div style={componentStyle}>{children}</div> : children),
|
||||
[children, mount, componentStyle],
|
||||
);
|
||||
|
||||
const maybeRenderComponent = (rendered && children) && renderComponent;
|
||||
// Render children component or not in loading and in mount mode rendering
|
||||
// anyway.
|
||||
const renderComponent = useMemo(
|
||||
() => (!loading || mount ? renderChildren : null),
|
||||
[renderChildren, loading, mount],
|
||||
);
|
||||
const maybeRenderComponent = rendered && children && renderComponent;
|
||||
const maybeRenderLoadingSpinner = loading && loadingComponent;
|
||||
|
||||
return (
|
||||
<>
|
||||
{ maybeRenderLoadingSpinner }
|
||||
{ maybeRenderComponent }
|
||||
{maybeRenderLoadingSpinner}
|
||||
{maybeRenderComponent}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import If from './Utils/If';
|
||||
import Money from './Money';
|
||||
import Icon from './Icon';
|
||||
@@ -36,6 +37,7 @@ import SalutationList from './SalutationList';
|
||||
import DisplayNameList from './DisplayNameList';
|
||||
import MoneyInputGroup from './MoneyInputGroup';
|
||||
import Dragzone from './Dragzone';
|
||||
import EmptyStatus from './EmptyStatus';
|
||||
|
||||
const Hint = FieldHint;
|
||||
|
||||
@@ -79,4 +81,5 @@ export {
|
||||
SalutationList,
|
||||
MoneyInputGroup,
|
||||
Dragzone,
|
||||
EmptyStatus
|
||||
};
|
||||
|
||||
@@ -25,6 +25,8 @@ import {
|
||||
} from 'components';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import ManualJournalsEmptyStatus from './ManualJournalsEmptyStatus';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withManualJournals from 'containers/Accounting/withManualJournals';
|
||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||
@@ -76,6 +78,7 @@ function ManualJournalsDataTable({
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
manualJournalsCurrentViewId,
|
||||
|
||||
// #withManualJournalsActions
|
||||
addManualJournalsTableQueries,
|
||||
@@ -248,26 +251,39 @@ function ManualJournalsDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
manualJournalsCurrentViewId === -1,
|
||||
manualJournalsCurrentPage.length === 0,
|
||||
].every(condition => condition === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator loading={manualJournalsLoading && !isLoadedBefore}>
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={manualJournalsCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
expandable={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagesCount={manualJournalsPagination.pagesCount}
|
||||
pagination={true}
|
||||
initialPageSize={manualJournalsTableQuery.page_size}
|
||||
initialPageIndex={manualJournalsTableQuery.page - 1}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
/>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<ManualJournalsEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={manualJournalsCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
expandable={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagesCount={manualJournalsPagination.pagesCount}
|
||||
pagination={true}
|
||||
initialPageSize={manualJournalsTableQuery.page_size}
|
||||
initialPageIndex={manualJournalsTableQuery.page - 1}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
@@ -282,11 +298,13 @@ export default compose(
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
manualJournalsCurrentViewId,
|
||||
}) => ({
|
||||
manualJournalsCurrentPage,
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
manualJournalsCurrentViewId
|
||||
}),
|
||||
),
|
||||
)(ManualJournalsDataTable);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function ManualJournalsEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={'Create your first journal entries on accounts chart.'}
|
||||
description={
|
||||
<p>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/invoices/new');
|
||||
}}
|
||||
>
|
||||
Make journal
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -4,10 +4,12 @@ import {
|
||||
getManualJournalsItems,
|
||||
getManualJournalsPagination,
|
||||
getManualJournalsTableQuery,
|
||||
getManualJournalsCurrentViewIdFactory
|
||||
} from 'store/manualJournals/manualJournals.selectors';
|
||||
|
||||
|
||||
export default (mapState) => {
|
||||
const getManualJournalsCurrentViewId = getManualJournalsCurrentViewIdFactory();
|
||||
const mapStateToProps = (state, props) => {
|
||||
const query = getManualJournalsTableQuery(state, props);
|
||||
|
||||
@@ -21,6 +23,8 @@ export default (mapState) => {
|
||||
manualJournalsLoading: state.manualJournals.loading,
|
||||
|
||||
journalNumberChanged: state.manualJournals.journalNumberChanged,
|
||||
|
||||
manualJournalsCurrentViewId: getManualJournalsCurrentViewId(state, props),
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useRef, useEffect, useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Popover,
|
||||
@@ -11,8 +11,8 @@ import {
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import { DataTable, Icon, Money } from 'components';
|
||||
import CustomersEmptyStatus from './CustomersEmptyStatus';
|
||||
import { DataTable, Icon, Money, Choose, LoadingIndicator } from 'components';
|
||||
|
||||
import withCustomers from './withCustomers';
|
||||
import withCustomersActions from './withCustomersActions';
|
||||
@@ -29,6 +29,7 @@ const CustomerTable = ({
|
||||
customersLoading,
|
||||
customerPagination,
|
||||
customersTableQuery,
|
||||
customersCurrentViewId,
|
||||
|
||||
// #withCustomersActions
|
||||
addCustomersTableQueries,
|
||||
@@ -182,31 +183,44 @@ const CustomerTable = ({
|
||||
onDeleteCustomer,
|
||||
});
|
||||
|
||||
const showEmptyStatus = [
|
||||
customersCurrentViewId === -1,
|
||||
customers.length === 0,
|
||||
].every(condition => condition === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator
|
||||
loading={customersLoading && !isLoadedBefore}
|
||||
mount={false}
|
||||
>
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={customers}
|
||||
// loading={customersLoading}
|
||||
onFetchData={handleFetchData}
|
||||
selectionColumn={true}
|
||||
expandable={false}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
spinnerProps={{ size: 30 }}
|
||||
rowContextMenu={rowContextMenu}
|
||||
pagination={true}
|
||||
manualSortBy={true}
|
||||
pagesCount={customerPagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={customersTableQuery.page_size}
|
||||
initialPageIndex={customersTableQuery.page - 1}
|
||||
/>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<CustomersEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={customers}
|
||||
// loading={customersLoading}
|
||||
onFetchData={handleFetchData}
|
||||
selectionColumn={true}
|
||||
expandable={false}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
spinnerProps={{ size: 30 }}
|
||||
rowContextMenu={rowContextMenu}
|
||||
pagination={true}
|
||||
manualSortBy={true}
|
||||
pagesCount={customerPagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={customersTableQuery.page_size}
|
||||
initialPageIndex={customersTableQuery.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
};
|
||||
@@ -218,11 +232,13 @@ export default compose(
|
||||
customersLoading,
|
||||
customerPagination,
|
||||
customersTableQuery,
|
||||
customersCurrentViewId,
|
||||
}) => ({
|
||||
customers,
|
||||
customersLoading,
|
||||
customerPagination,
|
||||
customersTableQuery,
|
||||
customersCurrentViewId
|
||||
}),
|
||||
),
|
||||
withCustomersActions,
|
||||
|
||||
37
client/src/containers/Customers/CustomersEmptyStatus.js
Normal file
37
client/src/containers/Customers/CustomersEmptyStatus.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function CustomersEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={"Create and manage your organization's customers."}
|
||||
description={
|
||||
<p>
|
||||
Here a list of your organization products and services, to be used
|
||||
when you create invoices or bills to your customers or vendors.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/customers/new');
|
||||
}}
|
||||
>
|
||||
New customer
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -4,11 +4,13 @@ import {
|
||||
getCustomerCurrentPageFactory,
|
||||
getCustomerPaginationMetaFactory,
|
||||
getCustomerTableQueryFactory,
|
||||
getCustomersCurrentViewIdFactory,
|
||||
} from 'store/customers/customers.selectors';
|
||||
|
||||
export default (mapState) => {
|
||||
const getCustomersList = getCustomerCurrentPageFactory();
|
||||
const getCustomerPaginationMeta = getCustomerPaginationMetaFactory();
|
||||
const getCustomersCurrentViewId = getCustomersCurrentViewIdFactory();
|
||||
const getCustomerTableQuery = getCustomerTableQueryFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
@@ -21,6 +23,7 @@ export default (mapState) => {
|
||||
customerPagination: getCustomerPaginationMeta(state, props, query),
|
||||
customersLoading: state.customers.loading,
|
||||
customersItems: state.customers.items,
|
||||
customersCurrentViewId: getCustomersCurrentViewId(state, props),
|
||||
// customerErrors: state.customers.errors,
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
|
||||
@@ -20,9 +20,9 @@ import Icon from 'components/Icon';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import { If, Money } from 'components';
|
||||
import { If, Money, Choose, LoadingIndicator } from 'components';
|
||||
import DataTable from 'components/DataTable';
|
||||
import ExpensesEmptyStatus from './ExpensesEmptyStatus';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
@@ -37,6 +37,7 @@ function ExpensesDataTable({
|
||||
expensesLoading,
|
||||
expensesPagination,
|
||||
expensesTableQuery,
|
||||
expensesCurrentViewId,
|
||||
|
||||
// #withExpensesActions
|
||||
addExpensesTableQueries,
|
||||
@@ -265,28 +266,41 @@ function ExpensesDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
expensesCurrentViewId === -1,
|
||||
expensesCurrentPage.length === 0
|
||||
].every(condition => condition === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator
|
||||
loading={expensesLoading && !isLoadedBefore}
|
||||
mount={false}
|
||||
>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={expensesCurrentPage}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
onFetchData={handleFetchData}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={expensesPagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={expensesTableQuery.page_size}
|
||||
initialPageIndex={expensesTableQuery.page - 1}
|
||||
/>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<ExpensesEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={expensesCurrentPage}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
onFetchData={handleFetchData}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={expensesPagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={expensesTableQuery.page_size}
|
||||
initialPageIndex={expensesTableQuery.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
@@ -303,11 +317,13 @@ export default compose(
|
||||
expensesLoading,
|
||||
expensesPagination,
|
||||
expensesTableQuery,
|
||||
expensesCurrentViewId,
|
||||
}) => ({
|
||||
expensesCurrentPage,
|
||||
expensesLoading,
|
||||
expensesPagination,
|
||||
expensesTableQuery,
|
||||
expensesCurrentViewId,
|
||||
}),
|
||||
),
|
||||
withViewDetails(),
|
||||
|
||||
40
client/src/containers/Expenses/ExpensesEmptyState.js
Normal file
40
client/src/containers/Expenses/ExpensesEmptyState.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
|
||||
function DatatableEmptyState({
|
||||
title,
|
||||
description,
|
||||
newButtonText,
|
||||
newButtonUrl,
|
||||
|
||||
learnMoreButtonText,
|
||||
learnMoreButtonUrl,
|
||||
}) {
|
||||
|
||||
|
||||
return (
|
||||
<div class={'datatable-empty-state'}>
|
||||
<h1 class={CLASSES.DATATABLE_EMPTY_STATE_TITLE}>
|
||||
{ title }
|
||||
</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default function ExpensesEmptyState({
|
||||
|
||||
}) {
|
||||
|
||||
|
||||
return (
|
||||
<DatatableEmptyState
|
||||
title={''}
|
||||
description={''}
|
||||
newButtonText={''}
|
||||
newButtonUrl={''}
|
||||
|
||||
learnMoreButtonText={''}
|
||||
learnMoreButtonUrl={''}
|
||||
/>
|
||||
);
|
||||
}
|
||||
37
client/src/containers/Expenses/ExpensesEmptyStatus.js
Normal file
37
client/src/containers/Expenses/ExpensesEmptyStatus.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function InvoicesEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={"Create and manage your organization's expenses"}
|
||||
description={
|
||||
<p>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/expenses/new');
|
||||
}}
|
||||
>
|
||||
New expense
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -5,11 +5,13 @@ import {
|
||||
getExpenseByIdFactory,
|
||||
getExpensesTableQuery,
|
||||
getExpensesPaginationMetaFactory,
|
||||
getExpensesCurrentViewIdFactory,
|
||||
} from 'store/expenses/expenses.selectors';
|
||||
|
||||
export default (mapState) => {
|
||||
const getExpensesItems = getExpensesCurrentPageFactory();
|
||||
const getExpensesPaginationMeta = getExpensesPaginationMetaFactory();
|
||||
const getExpensesCurrentViewId = getExpensesCurrentViewIdFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const query = getExpensesTableQuery(state, props);
|
||||
@@ -21,6 +23,7 @@ export default (mapState) => {
|
||||
expensesTableQuery: query,
|
||||
expensesPagination: getExpensesPaginationMeta(state, props),
|
||||
expensesLoading: state.expenses.loading,
|
||||
expensesCurrentViewId: getExpensesCurrentViewId(state, props),
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -50,7 +50,6 @@ const ItemFormContainer = ({
|
||||
);
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
// history.push('/items');
|
||||
history.goBack();
|
||||
}, [history]);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Popover,
|
||||
@@ -10,14 +10,18 @@ import {
|
||||
Tag,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import { Icon, DataTable, Money } from 'components';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { Icon, DataTable, Money, LoadingIndicator, Choose } from 'components';
|
||||
import ItemsEmptyStatus from './ItemsEmptyStatus';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
import { CLASSES } from 'common/classes';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import withItems from 'containers/Items/withItems';
|
||||
import withItemsActions from 'containers/Items/withItemsActions';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
|
||||
// Items datatable.
|
||||
function ItemsDataTable({
|
||||
// #withItems
|
||||
itemsTableLoading,
|
||||
@@ -181,31 +185,38 @@ function ItemsDataTable({
|
||||
);
|
||||
|
||||
return (
|
||||
<LoadingIndicator
|
||||
loading={itemsTableLoading && !isLoadedBefore}
|
||||
mount={false}
|
||||
>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={itemsCurrentPage}
|
||||
onFetchData={handleFetchData}
|
||||
noInitialFetch={true}
|
||||
expandable={true}
|
||||
selectionColumn={true}
|
||||
spinnerProps={{ size: 30 }}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={handleRowContextMenu}
|
||||
sticky={true}
|
||||
pagination={true}
|
||||
pagesCount={2}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={itemsTableQuery.page_size}
|
||||
initialPageIndex={itemsTableQuery.page - 1}
|
||||
/>
|
||||
</LoadingIndicator>
|
||||
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
||||
<LoadingIndicator loading={itemsTableLoading && !isLoadedBefore}>
|
||||
<Choose>
|
||||
<Choose.When condition={true}>
|
||||
<ItemsEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={itemsCurrentPage}
|
||||
onFetchData={handleFetchData}
|
||||
noInitialFetch={true}
|
||||
expandable={true}
|
||||
selectionColumn={true}
|
||||
spinnerProps={{ size: 30 }}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={handleRowContextMenu}
|
||||
sticky={true}
|
||||
pagination={true}
|
||||
pagesCount={2}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={itemsTableQuery.page_size}
|
||||
initialPageIndex={itemsTableQuery.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withItems(({ itemsCurrentPage, itemsTableLoading, itemsTableQuery }) => ({
|
||||
|
||||
36
client/src/containers/Items/ItemsEmptyStatus.js
Normal file
36
client/src/containers/Items/ItemsEmptyStatus.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function ItemsEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={'Manage the organization’s services and products.'}
|
||||
description={
|
||||
<p>
|
||||
Here a list of your organization products and services, to be used when you create invoices or bills to your customers or vendors.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/items/new');
|
||||
}}
|
||||
>
|
||||
New Item
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ function ItemsList({
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle(formatMessage({ id: 'items_list' }));
|
||||
}, [changePageTitle]);
|
||||
}, [changePageTitle, formatMessage]);
|
||||
|
||||
// Handle fetching the resource views.
|
||||
const fetchResourceViews = useQuery(
|
||||
|
||||
@@ -19,8 +19,9 @@ import Icon from 'components/Icon';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import { LoadingIndicator, Choose } from 'components';
|
||||
import DataTable from 'components/DataTable';
|
||||
import BillsEmptyStatus from './BillsEmptyStatus';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
@@ -30,11 +31,13 @@ import withBills from './withBills';
|
||||
import withBillActions from './withBillActions';
|
||||
import withCurrentView from 'containers/Views/withCurrentView';
|
||||
|
||||
// Bills transactions datatable.
|
||||
function BillsDataTable({
|
||||
//#withBills
|
||||
// #withBills
|
||||
billsCurrentPage,
|
||||
billsLoading,
|
||||
billsPageination,
|
||||
billsCurrentViewId,
|
||||
|
||||
// #withDashboardActions
|
||||
changeCurrentView,
|
||||
@@ -215,23 +218,36 @@ function BillsDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
billsCurrentViewId === -1,
|
||||
billsCurrentPage.length === 0,
|
||||
].every(condition => condition === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator loading={billsLoading && !isLoadedBefore} mount={false}>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={billsCurrentPage}
|
||||
onFetchData={handleFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={billsPageination.pagesCount}
|
||||
initialPageSize={billsPageination.pageSize}
|
||||
initialPageIndex={billsPageination.page - 1}
|
||||
/>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<BillsEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={billsCurrentPage}
|
||||
onFetchData={handleFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={billsPageination.pagesCount}
|
||||
initialPageSize={billsPageination.pageSize}
|
||||
initialPageIndex={billsPageination.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
@@ -248,11 +264,13 @@ export default compose(
|
||||
billsLoading,
|
||||
billsPageination,
|
||||
billsTableQuery,
|
||||
billsCurrentViewId
|
||||
}) => ({
|
||||
billsCurrentPage,
|
||||
billsLoading,
|
||||
billsPageination,
|
||||
billsTableQuery,
|
||||
billsCurrentViewId
|
||||
}),
|
||||
),
|
||||
withViewDetails(),
|
||||
|
||||
36
client/src/containers/Purchases/Bill/BillsEmptyStatus.js
Normal file
36
client/src/containers/Purchases/Bill/BillsEmptyStatus.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function BillsEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={'Manage the organization’s services and products.'}
|
||||
description={
|
||||
<p>
|
||||
Here a list of your organization products and services, to be used when you create invoices or bills to your customers or vendors.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/bills/new');
|
||||
}}
|
||||
>
|
||||
New bill
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
getBillTableQueryFactory,
|
||||
getVendorPayableBillsFactory,
|
||||
getVendorPayableBillsEntriesFactory,
|
||||
getBillsCurrentViewIdFactory,
|
||||
} from 'store/Bills/bills.selectors';
|
||||
|
||||
export default (mapState) => {
|
||||
@@ -14,12 +15,14 @@ export default (mapState) => {
|
||||
const getBillTableQuery = getBillTableQueryFactory();
|
||||
const getVendorPayableBills = getVendorPayableBillsFactory();
|
||||
const getVendorPayableBillsEntries = getVendorPayableBillsEntriesFactory();
|
||||
const getBillsCurrentViewId = getBillsCurrentViewIdFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const tableQuery = getBillTableQuery(state, props);
|
||||
|
||||
const mapped = {
|
||||
billsCurrentPage: getBillsItems(state, props, tableQuery),
|
||||
billsCurrentViewId: getBillsCurrentViewId(state),
|
||||
billsViews: getResourceViews(state, props, 'bills'),
|
||||
billsItems: state.bills.items,
|
||||
billsTableQuery: tableQuery,
|
||||
@@ -29,6 +32,7 @@ export default (mapState) => {
|
||||
nextBillNumberChanged: state.bills.nextBillNumberChanged,
|
||||
vendorPayableBills: getVendorPayableBills(state, props),
|
||||
vendorPayableBillsEntries: getVendorPayableBillsEntries(state, props),
|
||||
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -15,8 +15,8 @@ import moment from 'moment';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import { DataTable, Money, Icon } from 'components';
|
||||
import { DataTable, Money, Icon, Choose, LoadingIndicator } from 'components';
|
||||
import PaymentMadesEmptyStatus from './PaymentMadesEmptyStatus';
|
||||
|
||||
import withPaymentMade from './withPaymentMade';
|
||||
import withPaymentMadeActions from './withPaymentMadeActions';
|
||||
@@ -31,6 +31,7 @@ function PaymentMadeDataTable({
|
||||
paymentMadePageination,
|
||||
paymentMadesLoading,
|
||||
paymentMadeTableQuery,
|
||||
paymentMadesCurrentViewId,
|
||||
|
||||
// #withPaymentMadeActions
|
||||
addPaymentMadesTableQueries,
|
||||
@@ -178,25 +179,38 @@ function PaymentMadeDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatuts = [
|
||||
paymentMadeCurrentPage.length === 0,
|
||||
paymentMadesCurrentViewId === -1,
|
||||
].every(condition => condition === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator loading={paymentMadesLoading && !isLoaded} mount={false}>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={paymentMadeCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={paymentMadePageination.pagesCount}
|
||||
initialPageSize={paymentMadeTableQuery.page_size}
|
||||
initialPageIndex={paymentMadeTableQuery.page - 1}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
/>
|
||||
<LoadingIndicator loading={paymentMadesLoading && !isLoaded}>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatuts}>
|
||||
<PaymentMadesEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={paymentMadeCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={paymentMadePageination.pagesCount}
|
||||
initialPageSize={paymentMadeTableQuery.page_size}
|
||||
initialPageIndex={paymentMadeTableQuery.page - 1}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
@@ -211,11 +225,13 @@ export default compose(
|
||||
paymentMadesLoading,
|
||||
paymentMadePageination,
|
||||
paymentMadeTableQuery,
|
||||
paymentMadesCurrentViewId
|
||||
}) => ({
|
||||
paymentMadeCurrentPage,
|
||||
paymentMadesLoading,
|
||||
paymentMadePageination,
|
||||
paymentMadeTableQuery,
|
||||
paymentMadesCurrentViewId
|
||||
}),
|
||||
),
|
||||
)(PaymentMadeDataTable);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function PaymentMadesEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={'The organization does not have invoices, yet!'}
|
||||
description={
|
||||
<p>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/payment-made/new');
|
||||
}}
|
||||
>
|
||||
New bill payment
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,20 +1,22 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getResourceViews } from 'store/customViews/customViews.selectors';
|
||||
import {
|
||||
getPaymentMadeCurrentPageFactory,
|
||||
getPaymentMadePaginationMetaFactory,
|
||||
getPaymentMadeTableQuery,
|
||||
getPaymentMadeEntriesFactory
|
||||
getPaymentMadeEntriesFactory,
|
||||
getPaymentMadesCurrentViewIdFactory
|
||||
} from 'store/PaymentMades/paymentMade.selector';
|
||||
|
||||
export default (mapState) => {
|
||||
const getPyamentMadesItems = getPaymentMadeCurrentPageFactory();
|
||||
const getPyamentMadesPaginationMeta = getPaymentMadePaginationMetaFactory();
|
||||
const getPaymentMadeEntries = getPaymentMadeEntriesFactory();
|
||||
const getPaymentMadesCurrentViewId = getPaymentMadesCurrentViewIdFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const query = getPaymentMadeTableQuery(state, props);
|
||||
|
||||
const mapped = {
|
||||
paymentMadeCurrentPage: getPyamentMadesItems(state, props, query),
|
||||
paymentMadeViews: getResourceViews(state, props, 'bill_payments'),
|
||||
@@ -28,6 +30,8 @@ export default (mapState) => {
|
||||
paymentMadesLoading: state.paymentMades.loading,
|
||||
nextPaymentNumberChanged: state.paymentMades.nextPaymentNumberChanged,
|
||||
paymentMadeEntries: getPaymentMadeEntries(state, props),
|
||||
|
||||
paymentMadesCurrentViewId: getPaymentMadesCurrentViewId(state, props),
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -76,7 +76,6 @@ function EstimateViewTabs({
|
||||
history.push('/custom_views/estimates/new');
|
||||
};
|
||||
|
||||
console.log(estimateViews, 'estimateViews');
|
||||
return (
|
||||
<Navbar className={'navbar--dashboard-views'}>
|
||||
<NavbarGroup align={Alignment.LEFT}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useCallback, useState, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
@@ -8,15 +8,17 @@ import {
|
||||
MenuDivider,
|
||||
Position,
|
||||
} from '@blueprintjs/core';
|
||||
import { withRouter } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import moment from 'moment';
|
||||
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import { DataTable, Money, Icon } from 'components';
|
||||
import { DataTable, Money, Choose, Icon } from 'components';
|
||||
import EstimatesEmptyStatus from './EstimatesEmptyStatus';
|
||||
|
||||
import withEstimates from './withEstimates';
|
||||
import withEstimateActions from './withEstimateActions';
|
||||
@@ -28,6 +30,7 @@ function EstimatesDataTable({
|
||||
estimatesLoading,
|
||||
estimatesPageination,
|
||||
estimatesTableQuery,
|
||||
estimatesCurrentViewId,
|
||||
|
||||
// #withEstimatesActions
|
||||
addEstimatesTableQueries,
|
||||
@@ -177,35 +180,57 @@ function EstimatesDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
estimatesCurrentPage.length === 0,
|
||||
estimatesCurrentViewId === -1,
|
||||
].every(d => d === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator loading={estimatesLoading && !isLoaded} mount={false}>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={estimatesCurrentPage}
|
||||
onFetchData={handleFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={estimatesPageination.pagesCount}
|
||||
initialPageSize={estimatesTableQuery.page_size}
|
||||
initialPageIndex={estimatesTableQuery.page - 1}
|
||||
/>
|
||||
</LoadingIndicator>
|
||||
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
||||
<LoadingIndicator loading={estimatesLoading && !isLoaded} mount={false}>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<EstimatesEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={estimatesCurrentPage}
|
||||
onFetchData={handleFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={estimatesPageination.pagesCount}
|
||||
initialPageSize={estimatesTableQuery.page_size}
|
||||
initialPageIndex={estimatesTableQuery.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withEstimateActions,
|
||||
withEstimates(
|
||||
({ estimatesCurrentPage, estimatesLoading, estimatesPageination, estimatesTableQuery }) => ({
|
||||
({
|
||||
estimatesCurrentPage,
|
||||
estimatesLoading,
|
||||
estimatesPageination,
|
||||
estimatesTableQuery
|
||||
estimatesTableQuery,
|
||||
estimatesCurrentViewId,
|
||||
}) => ({
|
||||
estimatesCurrentPage,
|
||||
estimatesLoading,
|
||||
estimatesPageination,
|
||||
estimatesTableQuery,
|
||||
estimatesCurrentViewId,
|
||||
}),
|
||||
),
|
||||
)(EstimatesDataTable);
|
||||
|
||||
36
client/src/containers/Sales/Estimate/EstimatesEmptyStatus.js
Normal file
36
client/src/containers/Sales/Estimate/EstimatesEmptyStatus.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function EstimatesEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={"It's time to send estimates to your customers."}
|
||||
description={
|
||||
<p>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/estimates/new');
|
||||
}}
|
||||
>
|
||||
New sale estimate
|
||||
</Button>
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -4,18 +4,22 @@ import {
|
||||
getEstimateCurrentPageFactory,
|
||||
getEstimatesTableQueryFactory,
|
||||
getEstimatesPaginationMetaFactory,
|
||||
getEstimatesCurrentViewIdFactory,
|
||||
} from 'store/Estimate/estimates.selectors';
|
||||
|
||||
export default (mapState) => {
|
||||
const getEstimatesItems = getEstimateCurrentPageFactory();
|
||||
const getEstimatesPaginationMeta = getEstimatesPaginationMetaFactory();
|
||||
const getEstimatesTableQuery = getEstimatesTableQueryFactory();
|
||||
const getEstimatesCurrentViewId = getEstimatesCurrentViewIdFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const query = getEstimatesTableQuery(state, props);
|
||||
|
||||
const mapped = {
|
||||
estimatesCurrentPage: getEstimatesItems(state, props, query),
|
||||
estimatesCurrentViewId: getEstimatesCurrentViewId(state, props),
|
||||
|
||||
estimateViews: getResourceViews(state, props, 'sales_estimates'),
|
||||
estimateItems: state.salesEstimates.items,
|
||||
|
||||
|
||||
@@ -11,12 +11,15 @@ import {
|
||||
import { withRouter } from 'react-router';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import moment from 'moment';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { CLASSES } from 'common/classes';
|
||||
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import { DataTable, Money, Icon } from 'components';
|
||||
import { LoadingIndicator, Choose, DataTable, Money, Icon } from 'components';
|
||||
import InvoicesEmptyStatus from './InvoicesEmptyStatus';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
@@ -32,6 +35,7 @@ function InvoicesDataTable({
|
||||
invoicesCurrentPage,
|
||||
invoicesLoading,
|
||||
invoicesPageination,
|
||||
invoicesCurrentViewId,
|
||||
|
||||
// #withInvoicesActions
|
||||
addInvoiceTableQueries,
|
||||
@@ -186,29 +190,41 @@ function InvoicesDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
invoicesCurrentPage.length === 0,
|
||||
invoicesCurrentViewId === -1,
|
||||
].every((d) => d === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator
|
||||
loading={invoicesLoading && !isLoadedBefore}
|
||||
mount={false}
|
||||
>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={invoicesCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
pagesCount={invoicesPageination.pagesCount}
|
||||
initialPageSize={invoicesPageination.pageSize}
|
||||
initialPageIndex={invoicesPageination.page - 1}
|
||||
/>
|
||||
</LoadingIndicator>
|
||||
<div className={classNames(CLASSES.DASHBOARD_DATATABLE)}>
|
||||
<LoadingIndicator loading={invoicesLoading && !isLoadedBefore}>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<InvoicesEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={invoicesCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
pagesCount={invoicesPageination.pagesCount}
|
||||
initialPageSize={invoicesPageination.pageSize}
|
||||
initialPageIndex={invoicesPageination.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -224,11 +240,13 @@ export default compose(
|
||||
invoicesLoading,
|
||||
invoicesPageination,
|
||||
invoicesTableQuery,
|
||||
invoicesCurrentViewId,
|
||||
}) => ({
|
||||
invoicesCurrentPage,
|
||||
invoicesLoading,
|
||||
invoicesPageination,
|
||||
invoicesTableQuery,
|
||||
invoicesCurrentViewId,
|
||||
}),
|
||||
),
|
||||
withViewDetails(),
|
||||
|
||||
37
client/src/containers/Sales/Invoice/InvoicesEmptyStatus.js
Normal file
37
client/src/containers/Sales/Invoice/InvoicesEmptyStatus.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function EstimatesEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={'The organization does not have invoices, yet!'}
|
||||
description={
|
||||
<p>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/invoices/new');
|
||||
}}
|
||||
>
|
||||
New sale invoice
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
getInvoicePaginationMetaFactory,
|
||||
getInvoiceTableQueryFactory,
|
||||
getCustomerReceivableInvoicesEntriesFactory,
|
||||
getInvoicesCurrentViewIdFactory,
|
||||
} from 'store/Invoice/invoices.selector';
|
||||
|
||||
export default (mapState) => {
|
||||
@@ -15,11 +16,15 @@ export default (mapState) => {
|
||||
|
||||
const getCustomerReceivableInvoicesEntries = getCustomerReceivableInvoicesEntriesFactory();
|
||||
|
||||
const getInvoicesCurrentViewId = getInvoicesCurrentViewIdFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const query = getInvoiceTableQuery(state, props);
|
||||
|
||||
const mapped = {
|
||||
invoicesCurrentPage: getInvoicesItems(state, props, query),
|
||||
invoicesCurrentViewId: getInvoicesCurrentViewId(state, props),
|
||||
|
||||
invoicesViews: getResourceViews(state, props, 'sales_invoices'),
|
||||
invoicesItems: state.salesInvoices.items,
|
||||
invoicesTableQuery: query,
|
||||
|
||||
@@ -15,8 +15,8 @@ import moment from 'moment';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import LoadingIndicator from 'components/LoadingIndicator';
|
||||
import { DataTable, Money, Icon } from 'components';
|
||||
import PaymentReceivesEmptyStatus from './PaymentReceivesEmptyStatus';
|
||||
import { LoadingIndicator, DataTable, Choose, Money, Icon } from 'components';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
@@ -32,6 +32,7 @@ function PaymentReceivesDataTable({
|
||||
paymentReceivesPageination,
|
||||
paymentReceivesLoading,
|
||||
paymentReceivesTableQuery,
|
||||
paymentReceivesCurrentViewId,
|
||||
|
||||
// #withPaymentReceivesActions
|
||||
addPaymentReceivesTableQueries,
|
||||
@@ -179,28 +180,41 @@ function PaymentReceivesDataTable({
|
||||
[actionMenuList, formatMessage],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
paymentReceivesCurrentViewId === -1,
|
||||
PaymentReceivesCurrentPage.length === 0,
|
||||
].every(condition => condition === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator
|
||||
loading={paymentReceivesLoading && !isLoaded}
|
||||
mount={false}
|
||||
>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={PaymentReceivesCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
pagesCount={paymentReceivesPageination.pagesCount}
|
||||
initialPageSize={paymentReceivesTableQuery.page_size}
|
||||
initialPageIndex={paymentReceivesTableQuery.page - 1}
|
||||
/>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<PaymentReceivesEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={PaymentReceivesCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
pagesCount={paymentReceivesPageination.pagesCount}
|
||||
initialPageSize={paymentReceivesTableQuery.page_size}
|
||||
initialPageIndex={paymentReceivesTableQuery.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
@@ -216,12 +230,14 @@ export default compose(
|
||||
PaymentReceivesCurrentPage,
|
||||
paymentReceivesLoading,
|
||||
paymentReceivesPageination,
|
||||
paymentReceivesTableQuery
|
||||
paymentReceivesTableQuery,
|
||||
paymentReceivesCurrentViewId,
|
||||
}) => ({
|
||||
PaymentReceivesCurrentPage,
|
||||
paymentReceivesLoading,
|
||||
paymentReceivesPageination,
|
||||
paymentReceivesTableQuery
|
||||
paymentReceivesTableQuery,
|
||||
paymentReceivesCurrentViewId,
|
||||
}),
|
||||
),
|
||||
withViewDetails(),
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function PaymentReceivesEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={"The organization does't receive money, yet!"}
|
||||
description={
|
||||
<p>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/payment-receive/new');
|
||||
}}
|
||||
>
|
||||
New payment receive
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -4,11 +4,14 @@ import {
|
||||
getPaymentReceiveCurrentPageFactory,
|
||||
getPaymentReceivePaginationMetaFactory,
|
||||
getPaymentReceiveTableQuery,
|
||||
getPaymentReceivesCurrentViewIdFactory,
|
||||
} from 'store/PaymentReceive/paymentReceive.selector';
|
||||
|
||||
export default (mapState) => {
|
||||
const getPyamentReceivesItems = getPaymentReceiveCurrentPageFactory();
|
||||
const getPyamentReceivesPaginationMeta = getPaymentReceivePaginationMetaFactory();
|
||||
const getPaymentReceivesCurrentViewId = getPaymentReceivesCurrentViewIdFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const query = getPaymentReceiveTableQuery(state, props);
|
||||
const mapped = {
|
||||
@@ -23,6 +26,7 @@ export default (mapState) => {
|
||||
),
|
||||
paymentReceivesLoading: state.paymentReceives.loading,
|
||||
paymentReceiveNumberChanged: state.paymentReceives.journalNumberChanged,
|
||||
paymentReceivesCurrentViewId: getPaymentReceivesCurrentViewId(state, props),
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -15,7 +15,9 @@ import moment from 'moment';
|
||||
import { compose, saveInvoke } from 'utils';
|
||||
import { useIsValuePassed } from 'hooks';
|
||||
|
||||
import { LoadingIndicator, DataTable, Money, Icon } from 'components';
|
||||
import { Choose, LoadingIndicator, DataTable, Money, Icon } from 'components';
|
||||
|
||||
import ReceiptsEmptyStatus from './ReceiptsEmptyStatus';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
@@ -24,16 +26,17 @@ import withReceipts from './withReceipts';
|
||||
import withReceiptActions from './withReceiptActions';
|
||||
|
||||
function ReceiptsDataTable({
|
||||
//#withReceipts
|
||||
// #withReceipts
|
||||
receiptsCurrentPage,
|
||||
receiptsLoading,
|
||||
receiptsPagination,
|
||||
receiptTableQuery,
|
||||
receiptsCurrentViewId,
|
||||
|
||||
// #withReceiptsActions
|
||||
addReceiptsTableQueries,
|
||||
|
||||
// #Own Props
|
||||
// #ownProps
|
||||
loading,
|
||||
onEditReceipt,
|
||||
onDeleteReceipt,
|
||||
@@ -186,28 +189,38 @@ function ReceiptsDataTable({
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const showEmptyStatus = [
|
||||
receiptsCurrentViewId === -1,
|
||||
receiptsCurrentPage.length === 0,
|
||||
].every(condition => condition === true);
|
||||
|
||||
return (
|
||||
<LoadingIndicator
|
||||
loading={receiptsLoading && !isLoadedBefore}
|
||||
mount={false}
|
||||
>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={receiptsCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={receiptsPagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={receiptTableQuery.page_size}
|
||||
initialPageIndex={receiptTableQuery.page - 1}
|
||||
/>
|
||||
<LoadingIndicator loading={receiptsLoading && !isLoadedBefore}>
|
||||
<Choose>
|
||||
<Choose.When condition={showEmptyStatus}>
|
||||
<ReceiptsEmptyStatus />
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={receiptsCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
rowContextMenu={onRowContextMenu}
|
||||
pagination={true}
|
||||
pagesCount={receiptsPagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
initialPageSize={receiptTableQuery.page_size}
|
||||
initialPageIndex={receiptTableQuery.page - 1}
|
||||
/>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
@@ -223,11 +236,13 @@ export default compose(
|
||||
receiptsLoading,
|
||||
receiptsPagination,
|
||||
receiptTableQuery,
|
||||
receiptsCurrentViewId
|
||||
}) => ({
|
||||
receiptsCurrentPage,
|
||||
receiptsLoading,
|
||||
receiptsPagination,
|
||||
receiptTableQuery,
|
||||
receiptsCurrentViewId
|
||||
}),
|
||||
),
|
||||
)(ReceiptsDataTable);
|
||||
|
||||
36
client/src/containers/Sales/Receipt/ReceiptsEmptyStatus.js
Normal file
36
client/src/containers/Sales/Receipt/ReceiptsEmptyStatus.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
|
||||
export default function ReceiptsEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={'Manage the organization’s services and products.'}
|
||||
description={
|
||||
<p>
|
||||
Here a list of your organization products and services, to be used when you create invoices or bills to your customers or vendors.
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/receipts/new');
|
||||
}}
|
||||
>
|
||||
New receipt
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import {
|
||||
getReceiptCurrentPageFactory,
|
||||
getReceiptsTableQueryFactory,
|
||||
getReceiptsPaginationMetaFactory,
|
||||
getReceiptsCurrentViewIdFactory
|
||||
} from 'store/receipt/receipt.selector';
|
||||
|
||||
export default (mapState) => {
|
||||
const getReceiptsItems = getReceiptCurrentPageFactory();
|
||||
const getReceiptPaginationMeta = getReceiptsPaginationMetaFactory();
|
||||
const getReceiptsTableQuery = getReceiptsTableQueryFactory();
|
||||
const getReceiptsCurrentViewId = getReceiptsCurrentViewIdFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const tableQuery = getReceiptsTableQuery(state, props);
|
||||
@@ -23,6 +25,8 @@ export default (mapState) => {
|
||||
|
||||
receiptsLoading: state.salesReceipts.loading,
|
||||
receiptNumberChanged: state.salesReceipts.journalNumberChanged,
|
||||
|
||||
receiptsCurrentViewId: getReceiptsCurrentViewId(state, props),
|
||||
};
|
||||
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
|
||||
@@ -31,6 +31,8 @@ const billPaginationSelector = (state, props) => {
|
||||
return state.bills.views?.[viewId];
|
||||
};
|
||||
|
||||
const getBillsCurrentViewIdSelector = (state) => state.bills.currentViewId;
|
||||
|
||||
export const getBillTableQueryFactory = () =>
|
||||
createSelector(
|
||||
paginationLocationQuery,
|
||||
@@ -108,3 +110,12 @@ export const getVendorPayableBillsEntriesFactory = () =>
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
// Retreive the current bills view id.
|
||||
export const getBillsCurrentViewIdFactory = () =>
|
||||
createSelector(
|
||||
getBillsCurrentViewIdSelector,
|
||||
(currentViewId) => {
|
||||
return currentViewId;
|
||||
}
|
||||
);
|
||||
@@ -19,6 +19,10 @@ const estimatesPageSelector = (state, props, query) => {
|
||||
return state.salesEstimates.views?.[viewId]?.pages?.[currentPageId];
|
||||
};
|
||||
|
||||
const getEstimatesCurrentViewIdSelector = (state, props) => {
|
||||
return state.salesEstimates.currentViewId;
|
||||
};
|
||||
|
||||
// Retrieve estimates table query.
|
||||
export const getEstimatesTableQueryFactory = () =>
|
||||
createSelector(
|
||||
@@ -58,3 +62,12 @@ export const getEstimatesPaginationMetaFactory = () =>
|
||||
...(estimateView?.paginationMeta || {}),
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
// Retrieve estimates current view id.
|
||||
export const getEstimatesCurrentViewIdFactory = () =>
|
||||
createSelector(
|
||||
getEstimatesCurrentViewIdSelector,
|
||||
(currentViewId) => {
|
||||
return currentViewId;
|
||||
});
|
||||
@@ -27,6 +27,8 @@ const invoicesItemsSelector = (state) => state.salesInvoices.items;
|
||||
const invoicesReceiableCustomerSelector = (state, props) =>
|
||||
state.salesInvoices.receivable.byCustomerId[props.customerId];
|
||||
|
||||
const getInvoicesCurrentViewIdSelector = (state) => state.salesInvoices.currentViewId;
|
||||
|
||||
export const getInvoiceTableQueryFactory = () =>
|
||||
createSelector(
|
||||
paginationLocationQuery,
|
||||
@@ -51,6 +53,8 @@ export const getInvoiceCurrentPageFactory = () =>
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Retrieve specific invoice by the passed invoice id.
|
||||
export const getInvoiecsByIdFactory = () =>
|
||||
createSelector(invoicesByIdSelector, (invoice) => {
|
||||
@@ -83,3 +87,12 @@ export const getCustomerReceivableInvoicesEntriesFactory = () =>
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
// Retrieve sale invoices current view id.
|
||||
export const getInvoicesCurrentViewIdFactory = () =>
|
||||
createSelector(
|
||||
getInvoicesCurrentViewIdSelector,
|
||||
(currentViewId) => {
|
||||
return currentViewId;
|
||||
}
|
||||
);
|
||||
@@ -27,12 +27,17 @@ const paymentMadeById = (state, props) =>
|
||||
state.paymentMades.items[props.paymentMadeId];
|
||||
|
||||
const paymentMadeEntries = (state, props) => props.paymentMadeEntries;
|
||||
|
||||
const billsItemsSelector = (state, props) => state.bills.items;
|
||||
|
||||
const billsPayableByPaymentMadeSelector = (state, props) =>
|
||||
state.bills.payable.byBillPayamentId[props.paymentMadeId];
|
||||
|
||||
const paymentMadeBillsSelector = (state, props) =>
|
||||
state.bills.byBillPayamentId[props.paymentMadeId];
|
||||
|
||||
const paymentMadesCurrentViewIdSelector = (state) => state.paymentMades.currentViewId;
|
||||
|
||||
export const getPaymentMadeCurrentPageFactory = () =>
|
||||
createSelector(
|
||||
paymentMadesPageSelector,
|
||||
@@ -113,3 +118,12 @@ export const getPaymentMadeEntriesFactory = () =>
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Retrieve payment mades current view id.
|
||||
export const getPaymentMadesCurrentViewIdFactory = () =>
|
||||
createSelector(
|
||||
paymentMadesCurrentViewIdSelector,
|
||||
(currentViewId) => {
|
||||
return currentViewId;
|
||||
}
|
||||
);
|
||||
@@ -35,6 +35,9 @@ const paymentReceiveInvoicesSelector = (state, props) =>
|
||||
const paymentReceiveByIdSelector = (state, props) =>
|
||||
state.paymentReceives.items[props.paymentReceiveId];
|
||||
|
||||
const paymentReceivesCurrentViewIdSelector = (state) =>
|
||||
state.paymentReceives.currentViewId;
|
||||
|
||||
// Retrieve payment receive current page results.
|
||||
export const getPaymentReceiveCurrentPageFactory = () =>
|
||||
createSelector(
|
||||
@@ -124,3 +127,10 @@ export const getPaymentReceiveEntriesFactory = () =>
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Retrieve payment receives current view id.
|
||||
export const getPaymentReceivesCurrentViewIdFactory = () =>
|
||||
createSelector(
|
||||
paymentReceivesCurrentViewIdSelector,
|
||||
(currentViewId) => currentViewId,
|
||||
);
|
||||
|
||||
@@ -26,6 +26,8 @@ const customerPageSelector = (state, props) => {
|
||||
|
||||
const customersItemsSelector = (state) => state.customers.items;
|
||||
|
||||
const customersCurrentViewIdSelector = (state) => state.customers.currentViewId;
|
||||
|
||||
export const getCustomerTableQueryFactory = () =>
|
||||
createSelector(
|
||||
paginationLocationQuery,
|
||||
@@ -61,3 +63,8 @@ export const getCustomerPaginationMetaFactory = () =>
|
||||
...(customerPage?.paginationMeta || {}),
|
||||
};
|
||||
});
|
||||
|
||||
export const getCustomersCurrentViewIdFactory = () =>
|
||||
createSelector(customersCurrentViewIdSelector, (currentViewId) => {
|
||||
return currentViewId;
|
||||
});
|
||||
|
||||
@@ -8,6 +8,8 @@ const getPageExpensesQuery = (state, props) => {
|
||||
return currentPageId || 0;
|
||||
};
|
||||
|
||||
const getExpensesCurrentViewIdSelector = (state) => state.expenses.currentViewId;
|
||||
|
||||
const expensesPageSelector = (state, props, query) => {
|
||||
const viewId = state.expenses.currentViewId;
|
||||
const currentPageId = getPageExpensesQuery(state, { viewId });
|
||||
@@ -60,4 +62,12 @@ export const getExpensesPaginationMetaFactory = () => createSelector(
|
||||
(expensesPage) => {
|
||||
return expensesPage?.paginationMeta || {};
|
||||
},
|
||||
);
|
||||
|
||||
// Retrieve expenses current view id.
|
||||
export const getExpensesCurrentViewIdFactory = () => createSelector(
|
||||
getExpensesCurrentViewIdSelector,
|
||||
(currentViewId) => {
|
||||
return currentViewId;
|
||||
},
|
||||
);
|
||||
@@ -1,6 +1,8 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { pickItemsFromIds, paginationLocationQuery, defaultPaginationMeta } from 'store/selectors';
|
||||
|
||||
const manualJournalsCurrentViewIdSelector = (state) => state.manualJournals.currentViewId;
|
||||
|
||||
const manualJournalsPageSelector = (state) => {
|
||||
const viewId = state.manualJournals.currentViewId;
|
||||
const currentView = state.manualJournals.views?.[viewId];
|
||||
@@ -51,3 +53,12 @@ export const getManualJournalsTableQuery = createSelector(
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// Retrieve manual journals current view id.
|
||||
export const getManualJournalsCurrentViewIdFactory = () =>
|
||||
createSelector(
|
||||
manualJournalsCurrentViewIdSelector,
|
||||
(currentViewId) => {
|
||||
return currentViewId;
|
||||
},
|
||||
);
|
||||
@@ -20,6 +20,8 @@ const receiptTableQuery = (state) => state.salesReceipts.tableQuery;
|
||||
|
||||
const receiptByIdSelector = (state, props) => state.salesReceipts.items[props.receiptId];
|
||||
|
||||
const receiptsCurrentViewIdSelector = (state) => state.salesReceipts.currentViewId;
|
||||
|
||||
// Retrieve current page sale receipts results.
|
||||
export const getReceiptCurrentPageFactory = () =>
|
||||
createSelector(
|
||||
@@ -56,3 +58,9 @@ export const getReceiptsPaginationMetaFactory = () =>
|
||||
createSelector(receiptsPaginationSelector, (receiptPage) => {
|
||||
return receiptPage?.paginationMeta || {};
|
||||
});
|
||||
|
||||
// Retrieve receipts current view id.
|
||||
export const getReceiptsCurrentViewIdFactory = () =>
|
||||
createSelector(
|
||||
receiptsCurrentViewIdSelector,
|
||||
(currentViewId) => currentViewId);
|
||||
@@ -462,4 +462,41 @@ body.authentication {
|
||||
min-width: 70px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.datatable-empty-status{
|
||||
max-width: 550px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
margin-top: 200px;
|
||||
|
||||
&__title{
|
||||
font-size: 20px;
|
||||
color: #2c3a5d;
|
||||
font-weight: 600;
|
||||
margin-left: auto;
|
||||
margin-bottom: 12px;
|
||||
margin-right: auto;
|
||||
margin-top: 0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
&__desc{
|
||||
font-size: 16px;
|
||||
color: #1f3255;
|
||||
opacity: 0.8;
|
||||
line-height: 1.6;
|
||||
}
|
||||
&__actions{
|
||||
margin-top: 26px;
|
||||
|
||||
.bp3-button{
|
||||
min-height: 36px;
|
||||
|
||||
& + .bp3-button{
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bp3-button:not([class*="bp3-intent-"]):not(.bp3-minimal){
|
||||
.bp3-button{
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.bp3-button:not([class*="bp3-intent-"]):not(.bp3-minimal){
|
||||
background-color: #E6EFFB;
|
||||
color: #555555;
|
||||
box-shadow: 0 0 0 transparent;
|
||||
|
||||
@@ -239,6 +239,7 @@
|
||||
}
|
||||
&__insider{
|
||||
margin-bottom: 40px;
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
&__offline-badge{
|
||||
@@ -276,16 +277,19 @@
|
||||
}
|
||||
|
||||
&__insider{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&--loading{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
> .dashboard__loading-indicator{
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__page-content{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 0;
|
||||
|
||||
.bigcapital-datatable{
|
||||
|
||||
@@ -305,6 +309,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__datatable{
|
||||
display: flex;
|
||||
flex: 1 0 0;
|
||||
flex-direction: column;
|
||||
|
||||
.datatable-empty-status{
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
&__preferences-topbar{
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
// height: 70px;
|
||||
|
||||
Reference in New Issue
Block a user