mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
chrone: sperate client and server to different repos.
This commit is contained in:
145
src/containers/Expenses/ExpensesLanding/ExpenseActionsBar.js
Normal file
145
src/containers/Expenses/ExpensesLanding/ExpenseActionsBar.js
Normal file
@@ -0,0 +1,145 @@
|
||||
import React from 'react';
|
||||
import Icon from 'components/Icon';
|
||||
import {
|
||||
Button,
|
||||
NavbarGroup,
|
||||
Classes,
|
||||
NavbarDivider,
|
||||
Intent,
|
||||
Alignment,
|
||||
} from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { FormattedMessage as T } from 'components';
|
||||
|
||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
|
||||
import {
|
||||
If,
|
||||
DashboardActionViewsList,
|
||||
DashboardFilterButton,
|
||||
AdvancedFilterPopover,
|
||||
} from 'components';
|
||||
|
||||
import { useRefreshExpenses } from 'hooks/query/expenses';
|
||||
import { useExpensesListContext } from './ExpensesListProvider';
|
||||
|
||||
import withExpensesActions from './withExpensesActions';
|
||||
import withExpenses from './withExpenses';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Expenses actions bar.
|
||||
*/
|
||||
function ExpensesActionsBar({
|
||||
//#withExpensesActions
|
||||
setExpensesTableState,
|
||||
|
||||
// #withExpenses
|
||||
expensesFilterConditions,
|
||||
}) {
|
||||
// History context.
|
||||
const history = useHistory();
|
||||
|
||||
// Expenses list context.
|
||||
const { expensesViews, fields } = useExpensesListContext();
|
||||
|
||||
// Expenses refresh action.
|
||||
const { refresh } = useRefreshExpenses();
|
||||
|
||||
// Handles the new expense buttn click.
|
||||
const onClickNewExpense = () => {
|
||||
history.push('/expenses/new');
|
||||
};
|
||||
|
||||
// Handle delete button click.
|
||||
const handleBulkDelete = () => {};
|
||||
|
||||
// Handles the tab chaning.
|
||||
const handleTabChange = (view) => {
|
||||
setExpensesTableState({
|
||||
viewSlug: view ? view.slug : null,
|
||||
});
|
||||
};
|
||||
|
||||
// Handle click a refresh
|
||||
const handleRefreshBtnClick = () => {
|
||||
refresh();
|
||||
};
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<NavbarGroup>
|
||||
<DashboardActionViewsList
|
||||
resourceName={'expenses'}
|
||||
views={expensesViews}
|
||||
allMenuItem={true}
|
||||
onChange={handleTabChange}
|
||||
/>
|
||||
<NavbarDivider />
|
||||
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="plus" />}
|
||||
text={<T id={'new_expense'} />}
|
||||
onClick={onClickNewExpense}
|
||||
/>
|
||||
<AdvancedFilterPopover
|
||||
advancedFilterProps={{
|
||||
conditions: expensesFilterConditions,
|
||||
defaultFieldKey: 'reference_no',
|
||||
fields: fields,
|
||||
onFilterChange: (filterConditions) => {
|
||||
setExpensesTableState({ filterRoles: filterConditions });
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DashboardFilterButton
|
||||
conditionsCount={expensesFilterConditions.length}
|
||||
/>
|
||||
</AdvancedFilterPopover>
|
||||
|
||||
<If condition={false}>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="trash-16" iconSize={16} />}
|
||||
text={<T id={'delete'} />}
|
||||
intent={Intent.DANGER}
|
||||
onClick={handleBulkDelete}
|
||||
/>
|
||||
</If>
|
||||
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="print-16" iconSize={16} />}
|
||||
text={<T id={'print'} />}
|
||||
/>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="file-import-16" iconSize={16} />}
|
||||
text={<T id={'import'} />}
|
||||
/>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="file-export-16" iconSize={16} />}
|
||||
text={<T id={'export'} />}
|
||||
/>
|
||||
</NavbarGroup>
|
||||
<NavbarGroup align={Alignment.RIGHT}>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="refresh-16" iconSize={14} />}
|
||||
onClick={handleRefreshBtnClick}
|
||||
/>
|
||||
</NavbarGroup>
|
||||
</DashboardActionsBar>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withDialogActions,
|
||||
withExpensesActions,
|
||||
withExpenses(({ expensesTableState }) => ({
|
||||
expensesFilterConditions: expensesTableState.filterRoles,
|
||||
})),
|
||||
)(ExpensesActionsBar);
|
||||
138
src/containers/Expenses/ExpensesLanding/ExpenseDataTable.js
Normal file
138
src/containers/Expenses/ExpensesLanding/ExpenseDataTable.js
Normal file
@@ -0,0 +1,138 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import { compose } from 'utils';
|
||||
import { useExpensesListContext } from './ExpensesListProvider';
|
||||
import { useMemorizedColumnsWidths } from 'hooks';
|
||||
import { TABLES } from 'common/tables';
|
||||
|
||||
import { DashboardContentTable } from 'components';
|
||||
import DataTable from 'components/DataTable';
|
||||
import ExpensesEmptyStatus from './ExpensesEmptyStatus';
|
||||
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
|
||||
import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
|
||||
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withExpensesActions from './withExpensesActions';
|
||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||
|
||||
import { ActionsMenu, useExpensesTableColumns } from './components';
|
||||
|
||||
/**
|
||||
* Expenses datatable.
|
||||
*/
|
||||
function ExpensesDataTable({
|
||||
// #withExpensesActions
|
||||
setExpensesTableState,
|
||||
|
||||
// #withDrawerActions
|
||||
openDrawer,
|
||||
|
||||
// #withAlertsActions
|
||||
openAlert,
|
||||
}) {
|
||||
// Expenses list context.
|
||||
const {
|
||||
expenses,
|
||||
pagination,
|
||||
|
||||
isExpensesLoading,
|
||||
isExpensesFetching,
|
||||
isEmptyStatus,
|
||||
} = useExpensesListContext();
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
// Expenses table columns.
|
||||
const columns = useExpensesTableColumns();
|
||||
|
||||
// Local storage memorizing columns widths.
|
||||
const [initialColumnsWidths, , handleColumnResizing] =
|
||||
useMemorizedColumnsWidths(TABLES.EXPENSES);
|
||||
|
||||
// Handle fetch data of manual jouranls datatable.
|
||||
const handleFetchData = useCallback(
|
||||
({ pageIndex, pageSize, sortBy }) => {
|
||||
setExpensesTableState({
|
||||
pageIndex,
|
||||
pageSize,
|
||||
sortBy,
|
||||
});
|
||||
},
|
||||
[setExpensesTableState],
|
||||
);
|
||||
|
||||
// Handle the expense publish action.
|
||||
const handlePublishExpense = (expense) => {
|
||||
openAlert('expense-publish', { expenseId: expense.id });
|
||||
};
|
||||
|
||||
// Handle the expense edit action.
|
||||
const handleEditExpense = ({ id }) => {
|
||||
history.push(`/expenses/${id}/edit`);
|
||||
};
|
||||
|
||||
// Handle the expense delete action.
|
||||
const handleDeleteExpense = (expense) => {
|
||||
openAlert('expense-delete', { expenseId: expense.id });
|
||||
};
|
||||
|
||||
// Handle view detail expense.
|
||||
const handleViewDetailExpense = ({ id }) => {
|
||||
openDrawer('expense-drawer', {
|
||||
expenseId: id,
|
||||
});
|
||||
};
|
||||
|
||||
// Handle cell click.
|
||||
const handleCellClick = (cell, event) => {
|
||||
openDrawer('expense-drawer', { expenseId: cell.row.original.id });
|
||||
};
|
||||
|
||||
// Display empty status instead of the table.
|
||||
if (isEmptyStatus) {
|
||||
return <ExpensesEmptyStatus />;
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardContentTable>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={expenses}
|
||||
loading={isExpensesLoading}
|
||||
headerLoading={isExpensesLoading}
|
||||
progressBarLoading={isExpensesFetching}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
onFetchData={handleFetchData}
|
||||
pagination={true}
|
||||
manualSortBy={true}
|
||||
manualPagination={true}
|
||||
pagesCount={pagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
TableLoadingRenderer={TableSkeletonRows}
|
||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
||||
ContextMenu={ActionsMenu}
|
||||
onCellClick={handleCellClick}
|
||||
initialColumnsWidths={initialColumnsWidths}
|
||||
onColumnResizing={handleColumnResizing}
|
||||
payload={{
|
||||
onPublish: handlePublishExpense,
|
||||
onDelete: handleDeleteExpense,
|
||||
onEdit: handleEditExpense,
|
||||
onViewDetails: handleViewDetailExpense,
|
||||
}}
|
||||
/>
|
||||
</DashboardContentTable>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withDashboardActions,
|
||||
withAlertsActions,
|
||||
withDrawerActions,
|
||||
withExpensesActions,
|
||||
)(ExpensesDataTable);
|
||||
57
src/containers/Expenses/ExpensesLanding/ExpenseViewTabs.js
Normal file
57
src/containers/Expenses/ExpensesLanding/ExpenseViewTabs.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import { Alignment, Navbar, NavbarGroup } from '@blueprintjs/core';
|
||||
|
||||
import { DashboardViewsTabs } from 'components';
|
||||
|
||||
import { useExpensesListContext } from './ExpensesListProvider';
|
||||
import withExpenses from './withExpenses';
|
||||
import withExpensesActions from './withExpensesActions';
|
||||
|
||||
import { compose, transfromViewsToTabs } from 'utils';
|
||||
|
||||
/**
|
||||
* Expesne views tabs.
|
||||
*/
|
||||
function ExpenseViewTabs({
|
||||
// #withExpensesActions
|
||||
setExpensesTableState,
|
||||
|
||||
// #withExpenses
|
||||
expensesCurrentView,
|
||||
}) {
|
||||
// Expenses list context.
|
||||
const { expensesViews } = useExpensesListContext();
|
||||
|
||||
// Handle the tabs change.
|
||||
const handleTabChange = (viewSlug) => {
|
||||
setExpensesTableState({
|
||||
viewSlug: viewSlug || null,
|
||||
});
|
||||
};
|
||||
|
||||
const tabs = transfromViewsToTabs(expensesViews);
|
||||
|
||||
// Handle click a new view tab.
|
||||
const handleClickNewView = () => {};
|
||||
|
||||
return (
|
||||
<Navbar className={'navbar--dashboard-views'}>
|
||||
<NavbarGroup align={Alignment.LEFT}>
|
||||
<DashboardViewsTabs
|
||||
currentViewSlug={expensesCurrentView}
|
||||
resourceName={'expenses'}
|
||||
tabs={tabs}
|
||||
onNewViewTabClick={handleClickNewView}
|
||||
onChange={handleTabChange}
|
||||
/>
|
||||
</NavbarGroup>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withExpensesActions,
|
||||
withExpenses(({ expensesTableState }) => ({
|
||||
expensesCurrentView: expensesTableState.viewSlug,
|
||||
})),
|
||||
)(ExpenseViewTabs);
|
||||
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EmptyStatus } from 'components';
|
||||
import { FormattedMessage as T } from 'components';
|
||||
|
||||
export default function InvoicesEmptyStatus() {
|
||||
const history = useHistory();
|
||||
|
||||
return (
|
||||
<EmptyStatus
|
||||
title={<T id={'expenses.empty_status.title'} />}
|
||||
description={
|
||||
<p>
|
||||
<T id={'expenses.empty_status.description'} />
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<>
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
large={true}
|
||||
onClick={() => {
|
||||
history.push('/expenses/new');
|
||||
}}
|
||||
>
|
||||
<T id={'new_expense'} />
|
||||
</Button>
|
||||
|
||||
<Button intent={Intent.NONE} large={true}>
|
||||
<T id={'learn_more'} />
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
60
src/containers/Expenses/ExpensesLanding/ExpensesList.js
Normal file
60
src/containers/Expenses/ExpensesLanding/ExpensesList.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import 'style/pages/Expense/List.scss';
|
||||
|
||||
import { DashboardContentTable, DashboardPageContent } from 'components';
|
||||
|
||||
import ExpenseActionsBar from './ExpenseActionsBar';
|
||||
import ExpenseViewTabs from './ExpenseViewTabs';
|
||||
import ExpenseDataTable from './ExpenseDataTable';
|
||||
import ExpensesAlerts from '../ExpensesAlerts';
|
||||
|
||||
import withExpenses from './withExpenses';
|
||||
import withExpensesActions from './withExpensesActions';
|
||||
|
||||
import { compose, transformTableStateToQuery } from 'utils';
|
||||
import { ExpensesListProvider } from './ExpensesListProvider';
|
||||
|
||||
/**
|
||||
* Expenses list.
|
||||
*/
|
||||
function ExpensesList({
|
||||
// #withExpenses
|
||||
expensesTableState,
|
||||
expensesTableStateChanged,
|
||||
|
||||
// #withExpensesActions
|
||||
resetExpensesTableState,
|
||||
}) {
|
||||
// Resets the accounts table state once the page unmount.
|
||||
useEffect(
|
||||
() => () => {
|
||||
resetExpensesTableState();
|
||||
},
|
||||
[resetExpensesTableState],
|
||||
);
|
||||
|
||||
return (
|
||||
<ExpensesListProvider
|
||||
query={transformTableStateToQuery(expensesTableState)}
|
||||
tableStateChanged={expensesTableStateChanged}
|
||||
>
|
||||
<ExpenseActionsBar />
|
||||
|
||||
<DashboardPageContent>
|
||||
<ExpenseViewTabs />
|
||||
<ExpenseDataTable />
|
||||
</DashboardPageContent>
|
||||
|
||||
<ExpensesAlerts />
|
||||
</ExpensesListProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withExpenses(({ expensesTableState, expensesTableStateChanged }) => ({
|
||||
expensesTableState,
|
||||
expensesTableStateChanged,
|
||||
})),
|
||||
withExpensesActions,
|
||||
)(ExpensesList);
|
||||
@@ -0,0 +1,66 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { useExpenses, useResourceMeta, useResourceViews } from 'hooks/query';
|
||||
import { getFieldsFromResourceMeta } from 'utils';
|
||||
|
||||
const ExpensesListContext = createContext();
|
||||
|
||||
/**
|
||||
* Accounts chart data provider.
|
||||
*/
|
||||
function ExpensesListProvider({ query, tableStateChanged, ...props }) {
|
||||
// Fetch accounts resource views and fields.
|
||||
const { data: expensesViews, isLoading: isViewsLoading } =
|
||||
useResourceViews('expenses');
|
||||
|
||||
// Fetches the expenses with pagination meta.
|
||||
const {
|
||||
data: { expenses, pagination, filterMeta },
|
||||
isLoading: isExpensesLoading,
|
||||
isFetching: isExpensesFetching,
|
||||
} = useExpenses(query, { keepPreviousData: true });
|
||||
|
||||
// Fetch the expenses resource fields.
|
||||
const {
|
||||
data: resourceMeta,
|
||||
isLoading: isResourceMetaLoading,
|
||||
isFetching: isResourceMetaFetching,
|
||||
} = useResourceMeta('expenses');
|
||||
|
||||
// Detarmines the datatable empty status.
|
||||
const isEmptyStatus =
|
||||
isEmpty(expenses) && !isExpensesLoading && !tableStateChanged;
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
expensesViews,
|
||||
expenses,
|
||||
pagination,
|
||||
|
||||
fields: getFieldsFromResourceMeta(resourceMeta.fields),
|
||||
resourceMeta,
|
||||
isResourceMetaLoading,
|
||||
isResourceMetaFetching,
|
||||
|
||||
isViewsLoading,
|
||||
isExpensesLoading,
|
||||
isExpensesFetching,
|
||||
|
||||
isEmptyStatus,
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isViewsLoading || isExpensesLoading || isResourceMetaLoading}
|
||||
name={'expenses'}
|
||||
>
|
||||
<ExpensesListContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
const useExpensesListContext = () => React.useContext(ExpensesListContext);
|
||||
|
||||
export { ExpensesListProvider, useExpensesListContext };
|
||||
188
src/containers/Expenses/ExpensesLanding/components.js
Normal file
188
src/containers/Expenses/ExpensesLanding/components.js
Normal file
@@ -0,0 +1,188 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
Classes,
|
||||
Popover,
|
||||
Tooltip,
|
||||
Position,
|
||||
Tag,
|
||||
MenuItem,
|
||||
Menu,
|
||||
MenuDivider,
|
||||
} from '@blueprintjs/core';
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
import {
|
||||
FormatDateCell,
|
||||
FormattedMessage as T,
|
||||
Money,
|
||||
Icon,
|
||||
If,
|
||||
} from 'components';
|
||||
import { safeCallback } from 'utils';
|
||||
|
||||
/**
|
||||
* Description accessor.
|
||||
*/
|
||||
export function DescriptionAccessor(row) {
|
||||
return (
|
||||
<If condition={row.description}>
|
||||
<Tooltip
|
||||
className={Classes.TOOLTIP_INDICATOR}
|
||||
content={row.description}
|
||||
position={Position.TOP}
|
||||
hoverOpenDelay={250}
|
||||
>
|
||||
<Icon icon={'file-alt'} iconSize={16} />
|
||||
</Tooltip>
|
||||
</If>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions menu.
|
||||
*/
|
||||
export function ActionsMenu({
|
||||
row: { original },
|
||||
payload: { onPublish, onEdit, onDelete, onViewDetails },
|
||||
}) {
|
||||
return (
|
||||
<Menu>
|
||||
<MenuItem
|
||||
icon={<Icon icon="reader-18" />}
|
||||
text={intl.get('view_details')}
|
||||
onClick={safeCallback(onViewDetails, original)}
|
||||
/>
|
||||
<MenuDivider />
|
||||
<If condition={!original.is_published}>
|
||||
<MenuItem
|
||||
icon={<Icon icon={'arrow-to-top'} size={16} />}
|
||||
text={intl.get('publish_expense')}
|
||||
onClick={safeCallback(onPublish, original)}
|
||||
/>
|
||||
</If>
|
||||
<MenuItem
|
||||
icon={<Icon icon="pen-18" />}
|
||||
text={intl.get('edit_expense')}
|
||||
onClick={safeCallback(onEdit, original)}
|
||||
/>
|
||||
<MenuItem
|
||||
icon={<Icon icon="trash-16" iconSize={16} />}
|
||||
text={intl.get('delete_expense')}
|
||||
intent={Intent.DANGER}
|
||||
onClick={safeCallback(onDelete, original)}
|
||||
/>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Total amount accessor.
|
||||
*/
|
||||
export function TotalAmountAccessor(row) {
|
||||
return <Money amount={row.total_amount} currency={row.currency_code} />;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish accessor.
|
||||
*/
|
||||
export function PublishAccessor(row) {
|
||||
return row.is_published ? (
|
||||
<Tag minimal={true}>
|
||||
<T id={'published'} />
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag minimal={true} intent={Intent.WARNING}>
|
||||
<T id={'draft'} />
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expense account accessor.
|
||||
*/
|
||||
export function ExpenseAccountAccessor(expense) {
|
||||
if (expense.categories.length === 1) {
|
||||
return expense.categories[0].expense_account.name;
|
||||
} else if (expense.categories.length > 1) {
|
||||
return <T id={'expense.column.multi_categories'} />;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the expenses table columns.
|
||||
*/
|
||||
export function useExpensesTableColumns() {
|
||||
return React.useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'payment_date',
|
||||
Header: intl.get('payment_date'),
|
||||
accessor: 'payment_date',
|
||||
Cell: FormatDateCell,
|
||||
width: 140,
|
||||
className: 'payment_date',
|
||||
clickable: true,
|
||||
},
|
||||
{
|
||||
id: 'amount',
|
||||
Header: intl.get('full_amount'),
|
||||
accessor: TotalAmountAccessor,
|
||||
className: 'amount',
|
||||
align: 'right',
|
||||
width: 150,
|
||||
clickable: true,
|
||||
},
|
||||
{
|
||||
id: 'payment_account',
|
||||
Header: intl.get('payment_account'),
|
||||
accessor: 'payment_account.name',
|
||||
className: 'payment_account',
|
||||
width: 150,
|
||||
clickable: true,
|
||||
},
|
||||
{
|
||||
id: 'expense_account',
|
||||
Header: intl.get('expense_account'),
|
||||
accessor: ExpenseAccountAccessor,
|
||||
width: 160,
|
||||
className: 'expense_account',
|
||||
disableSortBy: true,
|
||||
clickable: true,
|
||||
},
|
||||
{
|
||||
id: 'published',
|
||||
Header: intl.get('publish'),
|
||||
accessor: PublishAccessor,
|
||||
width: 100,
|
||||
className: 'publish',
|
||||
clickable: true,
|
||||
},
|
||||
{
|
||||
id: 'description',
|
||||
Header: intl.get('description'),
|
||||
accessor: DescriptionAccessor,
|
||||
width: 150,
|
||||
className: 'description',
|
||||
disableSortBy: true,
|
||||
clickable: true,
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
}
|
||||
19
src/containers/Expenses/ExpensesLanding/withExpenses.js
Normal file
19
src/containers/Expenses/ExpensesLanding/withExpenses.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
expensesTableStateChangedFactory,
|
||||
getExpensesTableStateFactory,
|
||||
} from 'store/expenses/expenses.selectors';
|
||||
|
||||
export default (mapState) => {
|
||||
const getExpensesTableState = getExpensesTableStateFactory();
|
||||
const expensesTableStateChanged = expensesTableStateChangedFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const mapped = {
|
||||
expensesTableState: getExpensesTableState(state, props),
|
||||
expensesTableStateChanged: expensesTableStateChanged(state, props),
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
return connect(mapStateToProps);
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
setExpensesTableState,
|
||||
resetExpensesTableState,
|
||||
} from 'store/expenses/expenses.actions';
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setExpensesTableState: (state) => dispatch(setExpensesTableState(state)),
|
||||
resetExpensesTableState: (state) => dispatch(resetExpensesTableState(state)),
|
||||
});
|
||||
|
||||
export default connect(null, mapDispatchToProps);
|
||||
Reference in New Issue
Block a user