mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
- Data table sticky header.
- Mini sidebar toggle. - Refactor withDashboard and withDashboardActions.
This commit is contained in:
@@ -77,12 +77,15 @@
|
|||||||
"react-redux": "^7.1.3",
|
"react-redux": "^7.1.3",
|
||||||
"react-router-breadcrumbs-hoc": "^3.2.10",
|
"react-router-breadcrumbs-hoc": "^3.2.10",
|
||||||
"react-router-dom": "^5.1.2",
|
"react-router-dom": "^5.1.2",
|
||||||
|
"react-scroll-sync": "^0.7.1",
|
||||||
"react-scrollbars-custom": "^4.0.21",
|
"react-scrollbars-custom": "^4.0.21",
|
||||||
"react-sortablejs": "^2.0.11",
|
"react-sortablejs": "^2.0.11",
|
||||||
"react-table": "^7.0.0",
|
"react-table": "^7.0.0",
|
||||||
|
"react-table-sticky": "^1.1.2",
|
||||||
"react-use": "^13.26.1",
|
"react-use": "^13.26.1",
|
||||||
"react-window": "^1.8.5",
|
"react-window": "^1.8.5",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.0.5",
|
||||||
|
"redux-localstorage": "^0.4.1",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"resolve": "1.15.0",
|
"resolve": "1.15.0",
|
||||||
"resolve-url-loader": "3.1.1",
|
"resolve-url-loader": "3.1.1",
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import PrivateRoute from 'components/PrivateRoute';
|
|||||||
import Authentication from 'components/Authentication';
|
import Authentication from 'components/Authentication';
|
||||||
import Dashboard from 'components/Dashboard/Dashboard';
|
import Dashboard from 'components/Dashboard/Dashboard';
|
||||||
import GlobalErrors from 'containers/GlobalErrors/GlobalErrors';
|
import GlobalErrors from 'containers/GlobalErrors/GlobalErrors';
|
||||||
import AuthenticationDialogs from 'containers/Authentication/AuthenticationDialogs';
|
|
||||||
|
|
||||||
import messages from 'lang/en';
|
import messages from 'lang/en';
|
||||||
import 'style/App.scss';
|
import 'style/App.scss';
|
||||||
@@ -30,7 +29,6 @@ function App({ locale }) {
|
|||||||
<Switch>
|
<Switch>
|
||||||
<Route path={'/auth'}>
|
<Route path={'/auth'}>
|
||||||
<Authentication />
|
<Authentication />
|
||||||
<AuthenticationDialogs />
|
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path={'/'}>
|
<Route path={'/'}>
|
||||||
|
|||||||
@@ -1,23 +1,30 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Switch, Route } from 'react-router';
|
import { Switch, Route } from 'react-router';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import Sidebar from 'components/Sidebar/Sidebar';
|
import Sidebar from 'components/Sidebar/Sidebar';
|
||||||
import DashboardContent from 'components/Dashboard/DashboardContent';
|
import DashboardContent from 'components/Dashboard/DashboardContent';
|
||||||
import DialogsContainer from 'components/DialogsContainer';
|
import DialogsContainer from 'components/DialogsContainer';
|
||||||
import PreferencesContent from 'components/Preferences/PreferencesContent';
|
import PreferencesContent from 'components/Preferences/PreferencesContent';
|
||||||
import PreferencesSidebar from 'components/Preferences/PreferencesSidebar';
|
import PreferencesSidebar from 'components/Preferences/PreferencesSidebar';
|
||||||
import Search from 'containers/GeneralSearch/Search';
|
import Search from 'containers/GeneralSearch/Search';
|
||||||
|
import withDashboard from 'containers/Dashboard/withDashboard';
|
||||||
|
|
||||||
export default function Dashboard() {
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
function Dashboard({ sidebarExpended }) {
|
||||||
return (
|
return (
|
||||||
<div className='dashboard'>
|
<div className={classNames('dashboard', {
|
||||||
|
'has-mini-sidebar': !sidebarExpended,
|
||||||
|
})}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/preferences'>
|
<Route path="/preferences">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<PreferencesSidebar />
|
<PreferencesSidebar />
|
||||||
<PreferencesContent />
|
<PreferencesContent />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path='/'>
|
<Route path="/">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<DashboardContent />
|
<DashboardContent />
|
||||||
</Route>
|
</Route>
|
||||||
@@ -28,3 +35,9 @@ export default function Dashboard() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withDashboard(({ sidebarExpended }) => ({
|
||||||
|
sidebarExpended,
|
||||||
|
})),
|
||||||
|
)(Dashboard);
|
||||||
|
|||||||
@@ -14,14 +14,23 @@ import DashboardBreadcrumbs from 'components/Dashboard/DashboardBreadcrumbs';
|
|||||||
import SearchConnect from 'connectors/Search.connect';
|
import SearchConnect from 'connectors/Search.connect';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
|
|
||||||
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
import withDashboard from 'containers/Dashboard/withDashboard';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
function DashboardTopbar({
|
function DashboardTopbar({
|
||||||
|
|
||||||
|
// #withDashboard
|
||||||
pageTitle,
|
pageTitle,
|
||||||
pageSubtitle,
|
pageSubtitle,
|
||||||
editViewId,
|
editViewId,
|
||||||
globalSearchShow,
|
|
||||||
|
// #withDashboardActions
|
||||||
|
toggleSidebarExpend,
|
||||||
|
|
||||||
|
// #withGlobalSearch
|
||||||
openGlobalSearch,
|
openGlobalSearch,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -38,11 +47,15 @@ function DashboardTopbar({
|
|||||||
onClick={handlerClickEditView}
|
onClick={handlerClickEditView}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleSidebarToggleBtn = () => {
|
||||||
|
toggleSidebarExpend();
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div class='dashboard__topbar'>
|
<div class='dashboard__topbar'>
|
||||||
<div class='dashboard__topbar-left'>
|
<div class='dashboard__topbar-left'>
|
||||||
<div class='dashboard__topbar-sidebar-toggle'>
|
<div class='dashboard__topbar-sidebar-toggle'>
|
||||||
<Button minimal={true}>
|
<Button minimal={true} onClick={handleSidebarToggleBtn}>
|
||||||
<svg
|
<svg
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
width='20'
|
width='20'
|
||||||
@@ -106,13 +119,10 @@ function DashboardTopbar({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
|
||||||
pageTitle: state.dashboard.pageTitle,
|
|
||||||
pageSubtitle: state.dashboard.pageSubtitle,
|
|
||||||
editViewId: state.dashboard.topbarEditViewId,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
SearchConnect,
|
SearchConnect,
|
||||||
connect(mapStateToProps)
|
withDashboard(({ pageTitle, pageSubtitle, editViewId }) => ({
|
||||||
|
pageTitle, pageSubtitle, editViewId
|
||||||
|
})),
|
||||||
|
withDashboardActions,
|
||||||
)(DashboardTopbar);
|
)(DashboardTopbar);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {useEffect, useRef, useCallback} from 'react';
|
import React, { useEffect, useRef, useCallback } from 'react';
|
||||||
import {
|
import {
|
||||||
useTable,
|
useTable,
|
||||||
useExpanded,
|
useExpanded,
|
||||||
@@ -6,19 +6,22 @@ import {
|
|||||||
usePagination,
|
usePagination,
|
||||||
useResizeColumns,
|
useResizeColumns,
|
||||||
useSortBy,
|
useSortBy,
|
||||||
useFlexLayout
|
useFlexLayout,
|
||||||
} from 'react-table';
|
} from 'react-table';
|
||||||
import { Checkbox, Spinner } from '@blueprintjs/core';
|
import { Checkbox, Spinner } from '@blueprintjs/core';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { FixedSizeList } from 'react-window'
|
import { FixedSizeList } from 'react-window';
|
||||||
|
import { useSticky } from 'react-table-sticky';
|
||||||
|
import { ScrollSync, ScrollSyncPane } from 'react-scroll-sync';
|
||||||
|
|
||||||
import { ConditionalWrapper } from 'utils';
|
import { ConditionalWrapper } from 'utils';
|
||||||
import { useUpdateEffect } from 'hooks';
|
import { useUpdateEffect } from 'hooks';
|
||||||
import { If } from 'components';
|
import { If } from 'components';
|
||||||
|
|
||||||
const IndeterminateCheckbox = React.forwardRef(
|
const IndeterminateCheckbox = React.forwardRef(
|
||||||
({ indeterminate, ...rest }, ref) => {
|
({ indeterminate, ...rest }, ref) => {
|
||||||
return (<Checkbox indeterminate={indeterminate} {...rest} />);
|
return <Checkbox indeterminate={indeterminate} {...rest} />;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function DataTable({
|
export default function DataTable({
|
||||||
@@ -34,11 +37,11 @@ export default function DataTable({
|
|||||||
noResults = 'This report does not contain any data.',
|
noResults = 'This report does not contain any data.',
|
||||||
expanded = {},
|
expanded = {},
|
||||||
rowClassNames,
|
rowClassNames,
|
||||||
stickyHeader = true,
|
sticky = false,
|
||||||
virtualizedRows = false,
|
virtualizedRows = false,
|
||||||
fixedSizeHeight = 100,
|
fixedSizeHeight = 100,
|
||||||
fixedItemSize = 30,
|
fixedItemSize = 30,
|
||||||
payload,
|
payload,
|
||||||
expandable = false,
|
expandable = false,
|
||||||
expandToggleColumn = 2,
|
expandToggleColumn = 2,
|
||||||
noInitialFetch = false,
|
noInitialFetch = false,
|
||||||
@@ -54,9 +57,10 @@ export default function DataTable({
|
|||||||
selectedFlatRows,
|
selectedFlatRows,
|
||||||
getToggleAllRowsExpandedProps,
|
getToggleAllRowsExpandedProps,
|
||||||
isAllRowsExpanded,
|
isAllRowsExpanded,
|
||||||
|
totalColumnsWidth,
|
||||||
|
|
||||||
// Get the state from the instance
|
// Get the state from the instance
|
||||||
state: { pageIndex, pageSize, sortBy, selectedRowIds},
|
state: { pageIndex, pageSize, sortBy, selectedRowIds },
|
||||||
} = useTable(
|
} = useTable(
|
||||||
{
|
{
|
||||||
columns,
|
columns,
|
||||||
@@ -67,7 +71,7 @@ export default function DataTable({
|
|||||||
// This means we'll also have to provide our own
|
// This means we'll also have to provide our own
|
||||||
// pageCount.
|
// pageCount.
|
||||||
// pageCount: controlledPageCount,
|
// pageCount: controlledPageCount,
|
||||||
getSubRows: row => row.children,
|
getSubRows: (row) => row.children,
|
||||||
manualSortBy,
|
manualSortBy,
|
||||||
expandSubRows,
|
expandSubRows,
|
||||||
payload,
|
payload,
|
||||||
@@ -79,111 +83,150 @@ export default function DataTable({
|
|||||||
usePagination,
|
usePagination,
|
||||||
useResizeColumns,
|
useResizeColumns,
|
||||||
useFlexLayout,
|
useFlexLayout,
|
||||||
hooks => {
|
useSticky,
|
||||||
hooks.visibleColumns.push(columns => [
|
(hooks) => {
|
||||||
|
hooks.visibleColumns.push((columns) => [
|
||||||
// Let's make a column for selection
|
// Let's make a column for selection
|
||||||
...(selectionColumn) ? [{
|
...(selectionColumn
|
||||||
id: 'selection',
|
? [
|
||||||
disableResizing: true,
|
{
|
||||||
minWidth: 42,
|
id: 'selection',
|
||||||
width: 42,
|
disableResizing: true,
|
||||||
maxWidth: 42,
|
minWidth: 42,
|
||||||
// The header can use the table's getToggleAllRowsSelectedProps method
|
width: 42,
|
||||||
// to render a checkbox
|
maxWidth: 42,
|
||||||
Header: ({ getToggleAllRowsSelectedProps }) => (
|
// The header can use the table's getToggleAllRowsSelectedProps method
|
||||||
<div>
|
// to render a checkbox
|
||||||
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
|
Header: ({ getToggleAllRowsSelectedProps }) => (
|
||||||
</div>
|
<div>
|
||||||
),
|
<IndeterminateCheckbox
|
||||||
// The cell can use the individual row's getToggleRowSelectedProps method
|
{...getToggleAllRowsSelectedProps()}
|
||||||
// to the render a checkbox
|
/>
|
||||||
Cell: ({ row }) => (
|
</div>
|
||||||
<div>
|
),
|
||||||
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
|
// The cell can use the individual row's getToggleRowSelectedProps method
|
||||||
</div>
|
// to the render a checkbox
|
||||||
),
|
Cell: ({ row }) => (
|
||||||
className: 'selection',
|
<div>
|
||||||
...(typeof selectionColumn === 'object') ? selectionColumn : {},
|
<IndeterminateCheckbox
|
||||||
}] : [],
|
{...row.getToggleRowSelectedProps()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
className: 'selection',
|
||||||
|
...(typeof selectionColumn === 'object' ? selectionColumn : {}),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
...columns,
|
...columns,
|
||||||
])
|
]);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const isInitialMount = useRef(noInitialFetch);
|
const isInitialMount = useRef(noInitialFetch);
|
||||||
|
|
||||||
// When these table states change, fetch new data!
|
// When these table states change, fetch new data!
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isInitialMount.current) {
|
if (isInitialMount.current) {
|
||||||
isInitialMount.current = false;
|
isInitialMount.current = false;
|
||||||
} else {
|
} else {
|
||||||
onFetchData && onFetchData({ pageIndex, pageSize, sortBy })
|
onFetchData && onFetchData({ pageIndex, pageSize, sortBy });
|
||||||
}
|
}
|
||||||
}, [pageIndex, pageSize, sortBy,onFetchData]);
|
}, [pageIndex, pageSize, sortBy, onFetchData]);
|
||||||
|
|
||||||
useUpdateEffect(() => {
|
useUpdateEffect(() => {
|
||||||
onSelectedRowsChange && onSelectedRowsChange(selectedFlatRows);
|
onSelectedRowsChange && onSelectedRowsChange(selectedFlatRows);
|
||||||
}, [selectedRowIds, onSelectedRowsChange]);
|
}, [selectedRowIds, onSelectedRowsChange]);
|
||||||
|
|
||||||
// Renders table cell.
|
// Renders table cell.
|
||||||
const RenderCell = useCallback(({ row, cell, index }) => (
|
const RenderCell = useCallback(
|
||||||
<ConditionalWrapper
|
({ row, cell, index }) => (
|
||||||
condition={expandToggleColumn === index && expandable}
|
<ConditionalWrapper
|
||||||
wrapper={(children) => (<div style={{
|
condition={expandToggleColumn === index && expandable}
|
||||||
'padding-left': `${row.depth * 1.5}rem`,
|
wrapper={(children) => (
|
||||||
}}>{children}</div>)}
|
<div
|
||||||
>
|
style={{
|
||||||
{
|
'padding-left': `${row.depth * 1.5}rem`,
|
||||||
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
|
}}
|
||||||
// to build the toggle for expanding a row
|
>
|
||||||
(row.canExpand && expandable && index === expandToggleColumn) && (
|
{children}
|
||||||
<span {...row.getToggleRowExpandedProps({
|
</div>
|
||||||
className: 'expand-toggle',
|
)}
|
||||||
})}>
|
>
|
||||||
<span className={classnames({
|
{
|
||||||
'arrow-down': row.isExpanded,
|
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
|
||||||
'arrow-right': !row.isExpanded,
|
// to build the toggle for expanding a row
|
||||||
})} />
|
row.canExpand && expandable && index === expandToggleColumn && (
|
||||||
</span>
|
<span
|
||||||
)
|
{...row.getToggleRowExpandedProps({
|
||||||
}
|
className: 'expand-toggle',
|
||||||
{ cell.render('Cell') }
|
})}
|
||||||
</ConditionalWrapper>
|
>
|
||||||
), [expandable, expandToggleColumn]);
|
<span
|
||||||
|
className={classnames({
|
||||||
|
'arrow-down': row.isExpanded,
|
||||||
|
'arrow-right': !row.isExpanded,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{cell.render('Cell')}
|
||||||
|
</ConditionalWrapper>
|
||||||
|
),
|
||||||
|
[expandable, expandToggleColumn],
|
||||||
|
);
|
||||||
|
|
||||||
// Renders table row.
|
// Renders table row.
|
||||||
const RenderRow = useCallback(({ style = {}, row }) => {
|
const RenderRow = useCallback(
|
||||||
prepareRow(row);
|
({ style = {}, row }) => {
|
||||||
const rowClasses = rowClassNames && rowClassNames(row);
|
prepareRow(row);
|
||||||
|
const rowClasses = rowClassNames && rowClassNames(row);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...row.getRowProps({
|
<div
|
||||||
className: classnames('tr', rowClasses), style
|
{...row.getRowProps({
|
||||||
})}>
|
className: classnames('tr', rowClasses),
|
||||||
{row.cells.map((cell, i) => {
|
style,
|
||||||
const index = i + 1;
|
})}
|
||||||
return <div {...cell.getCellProps({
|
>
|
||||||
className: classnames(cell.column.className || '', 'td'),
|
{row.cells.map((cell, i) => {
|
||||||
})}>
|
const index = i + 1;
|
||||||
{ RenderCell({ cell, row, index }) }
|
return (
|
||||||
</div>
|
<div
|
||||||
})}
|
{...cell.getCellProps({
|
||||||
</div>);
|
className: classnames(cell.column.className || '', 'td'),
|
||||||
}, [prepareRow, rowClassNames, expandable, RenderCell, expandToggleColumn]);
|
})}
|
||||||
|
>
|
||||||
|
{RenderCell({ cell, row, index })}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[prepareRow, rowClassNames, expandable, RenderCell, expandToggleColumn],
|
||||||
|
);
|
||||||
|
|
||||||
// Renders virtualize circle table rows.
|
// Renders virtualize circle table rows.
|
||||||
const RenderVirtualizedRows = useCallback(({ index, style }) => {
|
const RenderVirtualizedRows = useCallback(
|
||||||
const row = rows[index];
|
({ index, style }) => {
|
||||||
return RenderRow({ row, style });
|
const row = rows[index];
|
||||||
}, [RenderRow, rows]);
|
return RenderRow({ row, style });
|
||||||
|
},
|
||||||
|
[RenderRow, rows],
|
||||||
|
);
|
||||||
|
|
||||||
const RenderPage = useCallback(({ style, index } = {}) => {
|
const RenderPage = useCallback(
|
||||||
return page.map((row, index) => RenderRow({ row }));
|
({ style, index } = {}) => {
|
||||||
}, [RenderRow, page]);
|
return page.map((row, index) => RenderRow({ row }));
|
||||||
|
},
|
||||||
|
[RenderRow, page],
|
||||||
|
);
|
||||||
|
|
||||||
// Renders fixed size tbody.
|
// Renders fixed size tbody.
|
||||||
const RenderTBody = useCallback(() => {
|
const RenderTBody = useCallback(() => {
|
||||||
return (virtualizedRows) ? (
|
return virtualizedRows ? (
|
||||||
<FixedSizeList
|
<FixedSizeList
|
||||||
height={fixedSizeHeight}
|
height={fixedSizeHeight}
|
||||||
itemCount={rows.length}
|
itemCount={rows.length}
|
||||||
@@ -191,79 +234,109 @@ export default function DataTable({
|
|||||||
>
|
>
|
||||||
{RenderVirtualizedRows}
|
{RenderVirtualizedRows}
|
||||||
</FixedSizeList>
|
</FixedSizeList>
|
||||||
) : RenderPage();
|
) : (
|
||||||
}, [fixedSizeHeight, rows, fixedItemSize, virtualizedRows,
|
RenderPage()
|
||||||
RenderVirtualizedRows, RenderPage]);
|
);
|
||||||
|
}, [
|
||||||
|
fixedSizeHeight,
|
||||||
|
rows,
|
||||||
|
fixedItemSize,
|
||||||
|
virtualizedRows,
|
||||||
|
RenderVirtualizedRows,
|
||||||
|
RenderPage,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames(
|
<div
|
||||||
'bigcapital-datatable',
|
className={classnames('bigcapital-datatable', className, {
|
||||||
className,
|
'has-sticky': sticky,
|
||||||
{
|
|
||||||
'has-sticky-header': stickyHeader,
|
|
||||||
'is-expandable': expandable,
|
'is-expandable': expandable,
|
||||||
'has-virtualized-rows': virtualizedRows,
|
'has-virtualized-rows': virtualizedRows,
|
||||||
})}>
|
})}
|
||||||
<div {...getTableProps()} className="table">
|
>
|
||||||
<div className="thead">
|
<ScrollSync>
|
||||||
{headerGroups.map(headerGroup => (
|
<div
|
||||||
<div {...headerGroup.getHeaderGroupProps()} className="tr">
|
{...getTableProps({ style: { minWidth: 'none' } })}
|
||||||
{headerGroup.headers.map((column, index) => (
|
className="table"
|
||||||
<div {...column.getHeaderProps({
|
>
|
||||||
className: classnames(column.className || '', 'th'),
|
<ScrollSyncPane>
|
||||||
})}>
|
<div className="thead">
|
||||||
{(expandable && (index + 1) === expandToggleColumn) && (
|
{headerGroups.map((headerGroup) => (
|
||||||
<span
|
<div {...headerGroup.getHeaderGroupProps()} className="tr">
|
||||||
{...getToggleAllRowsExpandedProps()}
|
{headerGroup.headers.map((column, index) => (
|
||||||
className="expand-toggle">
|
|
||||||
<span className={classnames({
|
|
||||||
'arrow-down': isAllRowsExpanded,
|
|
||||||
'arrow-right': !isAllRowsExpanded,
|
|
||||||
})} />
|
|
||||||
</span>)}
|
|
||||||
|
|
||||||
<div {...column.getSortByToggleProps()}>
|
|
||||||
{column.render('Header')}
|
|
||||||
|
|
||||||
{column.isSorted && (
|
|
||||||
<span className={classnames({
|
|
||||||
'sort-icon--desc': column.isSortedDesc,
|
|
||||||
'sort-icon--asc': !column.isSortedDesc,
|
|
||||||
}, 'sort-icon')}>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{column.canResize && (
|
|
||||||
<div
|
<div
|
||||||
{...column.getResizerProps()}
|
{...column.getHeaderProps({
|
||||||
className={`resizer ${
|
className: classnames(column.className || '', 'th'),
|
||||||
column.isResizing ? 'isResizing' : ''
|
})}
|
||||||
}`}>
|
>
|
||||||
<div class="inner-resizer" />
|
{expandable && index + 1 === expandToggleColumn && (
|
||||||
|
<span
|
||||||
|
{...getToggleAllRowsExpandedProps()}
|
||||||
|
className="expand-toggle"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={classnames({
|
||||||
|
'arrow-down': isAllRowsExpanded,
|
||||||
|
'arrow-right': !isAllRowsExpanded,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div {...column.getSortByToggleProps()}>
|
||||||
|
{column.render('Header')}
|
||||||
|
|
||||||
|
{column.isSorted && (
|
||||||
|
<span
|
||||||
|
className={classnames(
|
||||||
|
{
|
||||||
|
'sort-icon--desc': column.isSortedDesc,
|
||||||
|
'sort-icon--asc': !column.isSortedDesc,
|
||||||
|
},
|
||||||
|
'sort-icon',
|
||||||
|
)}
|
||||||
|
></span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{column.canResize && (
|
||||||
|
<div
|
||||||
|
{...column.getResizerProps()}
|
||||||
|
className={`resizer ${
|
||||||
|
column.isResizing ? 'isResizing' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div class="inner-resizer" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
</ScrollSyncPane>
|
||||||
</div>
|
|
||||||
<div {...getTableBodyProps()} className="tbody">
|
|
||||||
<If condition={!loading}>
|
|
||||||
{ RenderTBody() }
|
|
||||||
</If>
|
|
||||||
|
|
||||||
<If condition={!loading && (page.length === 0)}>
|
|
||||||
<div className={'tr no-results'}>
|
|
||||||
<div class="td">{ noResults }</div>
|
|
||||||
</div>
|
|
||||||
</If>
|
|
||||||
|
|
||||||
<If condition={loading}>
|
<ScrollSyncPane>
|
||||||
<div class="loading"><Spinner size={spinnerProps.size} /></div>
|
<div {...getTableBodyProps()} className="tbody">
|
||||||
</If>
|
<div class="tbody-inner" style={{ minWidth: totalColumnsWidth }}>
|
||||||
|
<If condition={!loading}>{RenderTBody()}</If>
|
||||||
|
|
||||||
|
<If condition={!loading && page.length === 0}>
|
||||||
|
<div className={'tr no-results'}>
|
||||||
|
<div class="td">{noResults}</div>
|
||||||
|
</div>
|
||||||
|
</If>
|
||||||
|
|
||||||
|
<If condition={loading}>
|
||||||
|
<div class="loading">
|
||||||
|
<Spinner size={spinnerProps.size} />
|
||||||
|
</div>
|
||||||
|
</If>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollSyncPane>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ScrollSync>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ export default class MenuItem extends AbstractPureComponent2 {
|
|||||||
intent,
|
intent,
|
||||||
labelClassName,
|
labelClassName,
|
||||||
labelElement,
|
labelElement,
|
||||||
|
itemClassName,
|
||||||
multiline,
|
multiline,
|
||||||
popoverProps,
|
popoverProps,
|
||||||
shouldDismissPopover,
|
shouldDismissPopover,
|
||||||
@@ -185,7 +186,7 @@ export default class MenuItem extends AbstractPureComponent2 {
|
|||||||
hasSubmenu ? <Icon icon="caret-right" iconSize={caretIconSize} /> : undefined,
|
hasSubmenu ? <Icon icon="caret-right" iconSize={caretIconSize} /> : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
const liClasses = classNames({ [Classes.MENU_SUBMENU]: hasSubmenu });
|
const liClasses = classNames({ [Classes.MENU_SUBMENU]: hasSubmenu }, itemClassName);
|
||||||
return <li className={liClasses}>{
|
return <li className={liClasses}>{
|
||||||
(dropdownType === 'collapse') ?
|
(dropdownType === 'collapse') ?
|
||||||
this.maybeRenderCollapse(target, children) :
|
this.maybeRenderCollapse(target, children) :
|
||||||
|
|||||||
@@ -1,12 +1,41 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Scrollbar } from 'react-scrollbars-custom';
|
import { Scrollbar } from 'react-scrollbars-custom';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export default function SidebarContainer(props) {
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
import withDashboard from 'containers/Dashboard/withDashboard';
|
||||||
|
|
||||||
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
function SidebarContainer({
|
||||||
|
// #ownProps
|
||||||
|
children,
|
||||||
|
|
||||||
|
// #withDashboardActions
|
||||||
|
toggleSidebarExpend,
|
||||||
|
|
||||||
|
// #withDashboard
|
||||||
|
sidebarExpended,
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className='sidebar' id='sidebar'>
|
<div
|
||||||
<Scrollbar noDefaultStyles={true}>
|
className={classNames('sidebar', {
|
||||||
<div className='sidebar__inner'>{props.children}</div>
|
'sidebar--mini-sidebar': !sidebarExpended,
|
||||||
</Scrollbar>
|
})}
|
||||||
|
id="sidebar"
|
||||||
|
>
|
||||||
|
<div className={'sidebar__scroll-wrapper'}>
|
||||||
|
<Scrollbar noDefaultStyles={true}>
|
||||||
|
<div className="sidebar__inner">{children}</div>
|
||||||
|
</Scrollbar>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withDashboardActions,
|
||||||
|
withDashboard(({ sidebarExpended }) => ({
|
||||||
|
sidebarExpended,
|
||||||
|
})),
|
||||||
|
)(SidebarContainer);
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ export default function SidebarMenu() {
|
|||||||
caretIconSize={15}
|
caretIconSize={15}
|
||||||
onClick={handleItemClick}
|
onClick={handleItemClick}
|
||||||
callapseActive={!!isActive}
|
callapseActive={!!isActive}
|
||||||
className={classNames({ 'is-active': isActive })} />
|
itemClassName={classNames({
|
||||||
|
'is-active': isActive,
|
||||||
|
'has-icon': !children && item.icon,
|
||||||
|
})} />
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import React, {useMemo, useState, useEffect, useRef, useCallback} from 'react';
|
import React, {
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useCallback,
|
||||||
|
} from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { useFormik } from "formik";
|
import { useFormik } from 'formik';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
@@ -13,16 +19,18 @@ import MakeJournalEntriesTable from './MakeJournalEntriesTable';
|
|||||||
import withJournalsActions from 'containers/Accounting/withJournalsActions';
|
import withJournalsActions from 'containers/Accounting/withJournalsActions';
|
||||||
import withManualJournalDetail from 'containers/Accounting/withManualJournalDetail';
|
import withManualJournalDetail from 'containers/Accounting/withManualJournalDetail';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
import Dragzone from 'components/Dragzone';
|
import Dragzone from 'components/Dragzone';
|
||||||
import MediaConnect from 'connectors/Media.connect';
|
import MediaConnect from 'connectors/Media.connect';
|
||||||
|
|
||||||
import useMedia from 'hooks/useMedia';
|
import useMedia from 'hooks/useMedia';
|
||||||
import {compose} from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Journal entries form.
|
||||||
|
*/
|
||||||
function MakeJournalEntriesForm({
|
function MakeJournalEntriesForm({
|
||||||
// #withMedia
|
// #withMedia
|
||||||
requestSubmitMedia,
|
requestSubmitMedia,
|
||||||
@@ -39,10 +47,16 @@ function MakeJournalEntriesForm({
|
|||||||
manualJournalId,
|
manualJournalId,
|
||||||
manualJournal,
|
manualJournal,
|
||||||
onFormSubmit,
|
onFormSubmit,
|
||||||
onCancelForm,
|
onCancelForm,
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const { setFiles, saveMedia, deletedFiles, setDeletedFiles, deleteMedia } = useMedia({
|
const {
|
||||||
|
setFiles,
|
||||||
|
saveMedia,
|
||||||
|
deletedFiles,
|
||||||
|
setDeletedFiles,
|
||||||
|
deleteMedia,
|
||||||
|
} = useMedia({
|
||||||
saveCallback: requestSubmitMedia,
|
saveCallback: requestSubmitMedia,
|
||||||
deleteCallback: requestDeleteMedia,
|
deleteCallback: requestDeleteMedia,
|
||||||
});
|
});
|
||||||
@@ -51,79 +65,97 @@ function MakeJournalEntriesForm({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const savedMediaIds = useRef([]);
|
const savedMediaIds = useRef([]);
|
||||||
const clearSavedMediaIds = () => { savedMediaIds.current = []; }
|
const clearSavedMediaIds = () => {
|
||||||
|
savedMediaIds.current = [];
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (manualJournal && manualJournal.id) {
|
if (manualJournal && manualJournal.id) {
|
||||||
changePageTitle(formatMessage({id:'edit_journal'}));
|
changePageTitle(formatMessage({ id: 'edit_journal' }));
|
||||||
changePageSubtitle(`No. ${manualJournal.journal_number}`);
|
changePageSubtitle(`No. ${manualJournal.journal_number}`);
|
||||||
} else {
|
} else {
|
||||||
changePageTitle(formatMessage({id:'new_journal'}));
|
changePageTitle(formatMessage({ id: 'new_journal' }));
|
||||||
}
|
}
|
||||||
}, [changePageTitle, changePageSubtitle, manualJournal,formatMessage]);
|
}, [changePageTitle, changePageSubtitle, manualJournal, formatMessage]);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
journal_number: Yup.string().required().label(formatMessage({id:'journal_number_'})),
|
journal_number: Yup.string()
|
||||||
date: Yup.date().required().label(formatMessage({id:'date'})),
|
.required()
|
||||||
|
.label(formatMessage({ id: 'journal_number_' })),
|
||||||
|
date: Yup.date()
|
||||||
|
.required()
|
||||||
|
.label(formatMessage({ id: 'date' })),
|
||||||
reference: Yup.string(),
|
reference: Yup.string(),
|
||||||
description: Yup.string(),
|
description: Yup.string(),
|
||||||
entries: Yup.array().of(
|
entries: Yup.array().of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
credit: Yup.number().nullable(),
|
credit: Yup.number().nullable(),
|
||||||
debit: Yup.number().nullable(),
|
debit: Yup.number().nullable(),
|
||||||
account_id: Yup.number().nullable().when(['credit', 'debit'], {
|
account_id: Yup.number()
|
||||||
is: (credit, debit) => credit || debit,
|
.nullable()
|
||||||
then: Yup.number().required(),
|
.when(['credit', 'debit'], {
|
||||||
}),
|
is: (credit, debit) => credit || debit,
|
||||||
|
then: Yup.number().required(),
|
||||||
|
}),
|
||||||
note: Yup.string().nullable(),
|
note: Yup.string().nullable(),
|
||||||
}),
|
}),
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
const saveInvokeSubmit = useCallback((payload) => {
|
const saveInvokeSubmit = useCallback(
|
||||||
onFormSubmit && onFormSubmit(payload)
|
(payload) => {
|
||||||
}, [onFormSubmit]);
|
onFormSubmit && onFormSubmit(payload);
|
||||||
|
},
|
||||||
|
[onFormSubmit],
|
||||||
|
);
|
||||||
|
|
||||||
const [payload, setPayload] = useState({});
|
const [payload, setPayload] = useState({});
|
||||||
|
|
||||||
const defaultEntry = useMemo(() => ({
|
const defaultEntry = useMemo(
|
||||||
account_id: null,
|
() => ({
|
||||||
credit: 0,
|
account_id: null,
|
||||||
debit: 0,
|
credit: 0,
|
||||||
note: '',
|
debit: 0,
|
||||||
}), []);
|
note: '',
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
const defaultInitialValues = useMemo(() => ({
|
const defaultInitialValues = useMemo(
|
||||||
journal_number: '',
|
() => ({
|
||||||
date: moment(new Date()).format('YYYY-MM-DD'),
|
journal_number: '',
|
||||||
description: '',
|
date: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
reference: '',
|
description: '',
|
||||||
entries: [
|
reference: '',
|
||||||
defaultEntry,
|
entries: [defaultEntry, defaultEntry, defaultEntry, defaultEntry],
|
||||||
defaultEntry,
|
}),
|
||||||
defaultEntry,
|
[defaultEntry],
|
||||||
defaultEntry,
|
);
|
||||||
],
|
|
||||||
}), [defaultEntry]);
|
|
||||||
|
|
||||||
const initialValues = useMemo(() => ({
|
const initialValues = useMemo(
|
||||||
...(manualJournal) ? {
|
() => ({
|
||||||
...pick(manualJournal, Object.keys(defaultInitialValues)),
|
...(manualJournal
|
||||||
entries: manualJournal.entries.map((entry) => ({
|
? {
|
||||||
...pick(entry, Object.keys(defaultEntry)),
|
...pick(manualJournal, Object.keys(defaultInitialValues)),
|
||||||
})),
|
entries: manualJournal.entries.map((entry) => ({
|
||||||
} : {
|
...pick(entry, Object.keys(defaultEntry)),
|
||||||
...defaultInitialValues,
|
})),
|
||||||
}
|
}
|
||||||
}), [manualJournal, defaultInitialValues, defaultEntry]);
|
: {
|
||||||
|
...defaultInitialValues,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
[manualJournal, defaultInitialValues, defaultEntry],
|
||||||
|
);
|
||||||
|
|
||||||
const initialAttachmentFiles = useMemo(() => {
|
const initialAttachmentFiles = useMemo(() => {
|
||||||
return manualJournal && manualJournal.media
|
return manualJournal && manualJournal.media
|
||||||
? manualJournal.media.map((attach) => ({
|
? manualJournal.media.map((attach) => ({
|
||||||
preview: attach.attachment_file,
|
preview: attach.attachment_file,
|
||||||
uploaded: true,
|
uploaded: true,
|
||||||
metadata: { ...attach },
|
metadata: { ...attach },
|
||||||
})) : [];
|
}))
|
||||||
|
: [];
|
||||||
}, [manualJournal]);
|
}, [manualJournal]);
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@@ -133,113 +165,128 @@ function MakeJournalEntriesForm({
|
|||||||
...initialValues,
|
...initialValues,
|
||||||
},
|
},
|
||||||
onSubmit: async (values, { setErrors, setSubmitting, resetForm }) => {
|
onSubmit: async (values, { setErrors, setSubmitting, resetForm }) => {
|
||||||
const entries = values.entries.filter((entry) => (
|
const entries = values.entries.filter(
|
||||||
(entry.credit || entry.debit)
|
(entry) => entry.credit || entry.debit,
|
||||||
));
|
);
|
||||||
const getTotal = (type = 'credit') => {
|
const getTotal = (type = 'credit') => {
|
||||||
return entries.reduce((total, item) => {
|
return entries.reduce((total, item) => {
|
||||||
return item[type] ? item[type] + total : total;
|
return item[type] ? item[type] + total : total;
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
};
|
||||||
const totalCredit = getTotal('credit');
|
const totalCredit = getTotal('credit');
|
||||||
const totalDebit = getTotal('debit');
|
const totalDebit = getTotal('debit');
|
||||||
|
|
||||||
// Validate the total credit should be eqials total debit.
|
// Validate the total credit should be eqials total debit.
|
||||||
if (totalCredit !== totalDebit) {
|
if (totalCredit !== totalDebit) {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: formatMessage({id:'credit_and_debit_not_equal'}),
|
message: formatMessage({ id: 'credit_and_debit_not_equal' }),
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const form = { ...values, status: payload.publish, entries };
|
const form = { ...values, status: payload.publish, entries };
|
||||||
|
|
||||||
const saveJournal = (mediaIds) => new Promise((resolve, reject) => {
|
const saveJournal = (mediaIds) =>
|
||||||
const requestForm = { ...form, media_ids: mediaIds };
|
new Promise((resolve, reject) => {
|
||||||
|
const requestForm = { ...form, media_ids: mediaIds };
|
||||||
|
|
||||||
if (manualJournal && manualJournal.id) {
|
if (manualJournal && manualJournal.id) {
|
||||||
requestEditManualJournal(manualJournal.id, requestForm)
|
requestEditManualJournal(manualJournal.id, requestForm)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: formatMessage({
|
message: formatMessage(
|
||||||
id: 'the_journal_has_been_successfully_edited',
|
{ id: 'the_journal_has_been_successfully_edited' },
|
||||||
}, {
|
{ number: values.journal_number },
|
||||||
number: values.journal_number,
|
),
|
||||||
}),
|
intent: Intent.SUCCESS,
|
||||||
intent: Intent.SUCCESS,
|
|
||||||
});
|
|
||||||
setSubmitting(false);
|
|
||||||
saveInvokeSubmit({ action: 'update', ...payload });
|
|
||||||
clearSavedMediaIds([]);
|
|
||||||
resetForm();
|
|
||||||
resolve(response);
|
|
||||||
}).catch((errors) => {
|
|
||||||
if (errors.find(e => e.type === 'JOURNAL.NUMBER.ALREADY.EXISTS')) {
|
|
||||||
setErrors({
|
|
||||||
journal_number: formatMessage({ id: 'journal_number_is_already_used' }),
|
|
||||||
});
|
});
|
||||||
}
|
setSubmitting(false);
|
||||||
setSubmitting(false);
|
saveInvokeSubmit({ action: 'update', ...payload });
|
||||||
});
|
clearSavedMediaIds([]);
|
||||||
} else {
|
resetForm();
|
||||||
requestMakeJournalEntries(requestForm)
|
resolve(response);
|
||||||
.then((response) => {
|
})
|
||||||
AppToaster.show({
|
.catch((errors) => {
|
||||||
message: formatMessage({
|
if (
|
||||||
id: 'the_journal_has_been_successfully_created',
|
errors.find((e) => e.type === 'JOURNAL.NUMBER.ALREADY.EXISTS')
|
||||||
}, {
|
) {
|
||||||
number: values.journal_number,
|
setErrors({
|
||||||
}),
|
journal_number: formatMessage({
|
||||||
intent: Intent.SUCCESS,
|
id: 'journal_number_is_already_used',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setSubmitting(false);
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
} else {
|
||||||
saveInvokeSubmit({ action: 'new', ...payload });
|
requestMakeJournalEntries(requestForm)
|
||||||
clearSavedMediaIds();
|
.then((response) => {
|
||||||
resetForm();
|
AppToaster.show({
|
||||||
resolve(response);
|
message: formatMessage(
|
||||||
}).catch((errors) => {
|
{ id: 'the_journal_has_been_successfully_created' },
|
||||||
if (errors.find(e => e.type === 'JOURNAL.NUMBER.ALREADY.EXISTS')) {
|
{ number: values.journal_number },
|
||||||
setErrors({
|
),
|
||||||
journal_number: formatMessage({ id: 'journal_number_is_already_used' }),
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
}
|
setSubmitting(false);
|
||||||
setSubmitting(false);
|
saveInvokeSubmit({ action: 'new', ...payload });
|
||||||
});
|
clearSavedMediaIds();
|
||||||
}
|
resetForm();
|
||||||
});
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch((errors) => {
|
||||||
|
if (
|
||||||
|
errors.find((e) => e.type === 'JOURNAL.NUMBER.ALREADY.EXISTS')
|
||||||
|
) {
|
||||||
|
setErrors({
|
||||||
|
journal_number: formatMessage({
|
||||||
|
id: 'journal_number_is_already_used',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setSubmitting(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([saveMedia(), deleteMedia()])
|
||||||
saveMedia(),
|
.then(([savedMediaResponses]) => {
|
||||||
deleteMedia(),
|
const mediaIds = savedMediaResponses.map((res) => res.data.media.id);
|
||||||
]).then(([savedMediaResponses]) => {
|
savedMediaIds.current = mediaIds;
|
||||||
const mediaIds = savedMediaResponses.map(res => res.data.media.id);
|
|
||||||
savedMediaIds.current = mediaIds;
|
|
||||||
|
|
||||||
return savedMediaResponses;
|
return savedMediaResponses;
|
||||||
}).then(() => {
|
})
|
||||||
return saveJournal(savedMediaIds.current);
|
.then(() => {
|
||||||
});
|
return saveJournal(savedMediaIds.current);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmitClick = useCallback((payload) => {
|
const handleSubmitClick = useCallback(
|
||||||
setPayload(payload);
|
(payload) => {
|
||||||
formik.handleSubmit();
|
setPayload(payload);
|
||||||
}, [setPayload, formik]);
|
formik.handleSubmit();
|
||||||
|
},
|
||||||
|
[setPayload, formik],
|
||||||
|
);
|
||||||
|
|
||||||
const handleCancelClick = useCallback((payload) => {
|
const handleCancelClick = useCallback(
|
||||||
onCancelForm && onCancelForm(payload);
|
(payload) => {
|
||||||
}, [onCancelForm]);
|
onCancelForm && onCancelForm(payload);
|
||||||
|
},
|
||||||
|
[onCancelForm],
|
||||||
|
);
|
||||||
|
|
||||||
const handleDeleteFile = useCallback((_deletedFiles) => {
|
const handleDeleteFile = useCallback(
|
||||||
_deletedFiles.forEach((deletedFile) => {
|
(_deletedFiles) => {
|
||||||
if (deletedFile.uploaded && deletedFile.metadata.id) {
|
_deletedFiles.forEach((deletedFile) => {
|
||||||
setDeletedFiles([
|
if (deletedFile.uploaded && deletedFile.metadata.id) {
|
||||||
...deletedFiles, deletedFile.metadata.id,
|
setDeletedFiles([...deletedFiles, deletedFile.metadata.id]);
|
||||||
]);
|
}
|
||||||
}
|
});
|
||||||
});
|
},
|
||||||
}, [setDeletedFiles, deletedFiles]);
|
[setDeletedFiles, deletedFiles],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="make-journal-entries">
|
<div class="make-journal-entries">
|
||||||
@@ -249,19 +296,22 @@ function MakeJournalEntriesForm({
|
|||||||
<MakeJournalEntriesTable
|
<MakeJournalEntriesTable
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
formik={formik}
|
formik={formik}
|
||||||
defaultRow={defaultEntry} />
|
defaultRow={defaultEntry}
|
||||||
|
/>
|
||||||
|
|
||||||
<MakeJournalEntriesFooter
|
<MakeJournalEntriesFooter
|
||||||
formik={formik}
|
formik={formik}
|
||||||
onSubmitClick={handleSubmitClick}
|
onSubmitClick={handleSubmitClick}
|
||||||
onCancelClick={handleCancelClick} />
|
onCancelClick={handleCancelClick}
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<Dragzone
|
<Dragzone
|
||||||
initialFiles={initialAttachmentFiles}
|
initialFiles={initialAttachmentFiles}
|
||||||
onDrop={handleDropFiles}
|
onDrop={handleDropFiles}
|
||||||
onDeleteFile={handleDeleteFile}
|
onDeleteFile={handleDeleteFile}
|
||||||
hint={'Attachments: Maxiumum size: 20MB'} />
|
hint={'Attachments: Maxiumum size: 20MB'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -272,4 +322,4 @@ export default compose(
|
|||||||
withAccountsActions,
|
withAccountsActions,
|
||||||
withDashboardActions,
|
withDashboardActions,
|
||||||
MediaConnect,
|
MediaConnect,
|
||||||
)(MakeJournalEntriesForm);
|
)(MakeJournalEntriesForm);
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ const ActionsCellRenderer = ({
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
icon={<Icon icon='times-circle' iconSize={14} />}
|
icon={<Icon icon="times-circle" iconSize={14} />}
|
||||||
iconSize={14}
|
iconSize={14}
|
||||||
className='ml2'
|
className="ml2"
|
||||||
minimal={true}
|
minimal={true}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
onClick={onClickRemoveRole}
|
onClick={onClickRemoveRole}
|
||||||
@@ -72,7 +72,7 @@ const NoteCellRenderer = (chainedComponent) => (props) => {
|
|||||||
/**
|
/**
|
||||||
* Make journal entries table component.
|
* Make journal entries table component.
|
||||||
*/
|
*/
|
||||||
function MakeJournalEntriesTable({
|
function MakeJournalEntriesTable({
|
||||||
// #withAccounts
|
// #withAccounts
|
||||||
accounts,
|
accounts,
|
||||||
|
|
||||||
@@ -107,10 +107,10 @@ function MakeJournalEntriesTable({
|
|||||||
'entries',
|
'entries',
|
||||||
newRows.map((row) => ({
|
newRows.map((row) => ({
|
||||||
...omit(row, ['rowType']),
|
...omit(row, ['rowType']),
|
||||||
}))
|
})),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[rows, setFieldValue]
|
[rows, setFieldValue],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handles click remove datatable row.
|
// Handles click remove datatable row.
|
||||||
@@ -124,11 +124,11 @@ function MakeJournalEntriesTable({
|
|||||||
'entries',
|
'entries',
|
||||||
newRows
|
newRows
|
||||||
.filter((row) => row.rowType === 'editor')
|
.filter((row) => row.rowType === 'editor')
|
||||||
.map((row) => ({ ...omit(row, ['rowType']) }))
|
.map((row) => ({ ...omit(row, ['rowType']) })),
|
||||||
);
|
);
|
||||||
onClickRemoveRow && onClickRemoveRow(removeIndex);
|
onClickRemoveRow && onClickRemoveRow(removeIndex);
|
||||||
},
|
},
|
||||||
[rows, setFieldValue, onClickRemoveRow]
|
[rows, setFieldValue, onClickRemoveRow],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Memorized data table columns.
|
// Memorized data table columns.
|
||||||
@@ -188,7 +188,7 @@ function MakeJournalEntriesTable({
|
|||||||
width: 45,
|
width: 45,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[formatMessage]
|
[formatMessage],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handles click new line.
|
// Handles click new line.
|
||||||
@@ -201,15 +201,16 @@ function MakeJournalEntriesTable({
|
|||||||
(row) => ({
|
(row) => ({
|
||||||
'row--total': rows.length === row.index + 2,
|
'row--total': rows.length === row.index + 2,
|
||||||
}),
|
}),
|
||||||
[rows]
|
[rows],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='make-journal-entries__table'>
|
<div class="make-journal-entries__table">
|
||||||
<DataTable
|
<DataTable
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={rows}
|
data={rows}
|
||||||
rowClassNames={rowClassNames}
|
rowClassNames={rowClassNames}
|
||||||
|
sticky={true}
|
||||||
payload={{
|
payload={{
|
||||||
accounts,
|
accounts,
|
||||||
errors: errors.entries || [],
|
errors: errors.entries || [],
|
||||||
@@ -218,7 +219,7 @@ function MakeJournalEntriesTable({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class='mt1'>
|
<div class="mt1">
|
||||||
<Button
|
<Button
|
||||||
small={true}
|
small={true}
|
||||||
className={'button--secondary button--new-line'}
|
className={'button--secondary button--new-line'}
|
||||||
|
|||||||
@@ -24,26 +24,26 @@ import DialogConnect from 'connectors/Dialog.connector';
|
|||||||
import { useUpdateEffect } from 'hooks';
|
import { useUpdateEffect } from 'hooks';
|
||||||
import DataTable from 'components/DataTable';
|
import DataTable from 'components/DataTable';
|
||||||
|
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withViewDetails from 'containers/Views/withViewDetails';
|
import withViewDetails from 'containers/Views/withViewDetails';
|
||||||
import withManualJournals from 'containers/Accounting/withManualJournals';
|
import withManualJournals from 'containers/Accounting/withManualJournals';
|
||||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||||
|
|
||||||
import { If, Money } from 'components';
|
import { If, Money } from 'components';
|
||||||
|
|
||||||
|
|
||||||
function ManualJournalsDataTable({
|
function ManualJournalsDataTable({
|
||||||
loading,
|
loading,
|
||||||
|
|
||||||
manualJournals,
|
manualJournals,
|
||||||
manualJournalsLoading,
|
manualJournalsLoading,
|
||||||
|
|
||||||
|
// #withDashboardActions
|
||||||
changeCurrentView,
|
changeCurrentView,
|
||||||
changePageSubtitle,
|
changePageSubtitle,
|
||||||
|
setTopbarEditView,
|
||||||
|
|
||||||
viewId,
|
viewId,
|
||||||
viewMeta,
|
viewMeta,
|
||||||
setTopbarEditView,
|
|
||||||
|
|
||||||
onFetchData,
|
onFetchData,
|
||||||
onEditJournal,
|
onEditJournal,
|
||||||
@@ -80,21 +80,21 @@ function ManualJournalsDataTable({
|
|||||||
(journal) => () => {
|
(journal) => () => {
|
||||||
onPublishJournal && onPublishJournal(journal);
|
onPublishJournal && onPublishJournal(journal);
|
||||||
},
|
},
|
||||||
[onPublishJournal]
|
[onPublishJournal],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleEditJournal = useCallback(
|
const handleEditJournal = useCallback(
|
||||||
(journal) => () => {
|
(journal) => () => {
|
||||||
onEditJournal && onEditJournal(journal);
|
onEditJournal && onEditJournal(journal);
|
||||||
},
|
},
|
||||||
[onEditJournal]
|
[onEditJournal],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDeleteJournal = useCallback(
|
const handleDeleteJournal = useCallback(
|
||||||
(journal) => () => {
|
(journal) => () => {
|
||||||
onDeleteJournal && onDeleteJournal(journal);
|
onDeleteJournal && onDeleteJournal(journal);
|
||||||
},
|
},
|
||||||
[onDeleteJournal]
|
[onDeleteJournal],
|
||||||
);
|
);
|
||||||
|
|
||||||
// const actionMenuList = (journal) => (
|
// const actionMenuList = (journal) => (
|
||||||
@@ -118,121 +118,141 @@ function ManualJournalsDataTable({
|
|||||||
// />
|
// />
|
||||||
// </Menu>
|
// </Menu>
|
||||||
// );
|
// );
|
||||||
const actionMenuList =useCallback((journal)=>(
|
const actionMenuList = useCallback(
|
||||||
<Menu>
|
(journal) => (
|
||||||
<MenuItem text={<T id={'view_details'} />} />
|
<Menu>
|
||||||
<MenuDivider />
|
<MenuItem text={<T id={'view_details'} />} />
|
||||||
{!journal.status && (
|
<MenuDivider />
|
||||||
|
{!journal.status && (
|
||||||
|
<MenuItem
|
||||||
|
text={<T id={'publish_journal'} />}
|
||||||
|
onClick={handlePublishJournal(journal)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text={<T id={'publish_journal'} />}
|
text={<T id={'edit_journal'} />}
|
||||||
onClick={handlePublishJournal(journal)}
|
onClick={handleEditJournal(journal)}
|
||||||
/>
|
/>
|
||||||
)}
|
<MenuItem
|
||||||
<MenuItem
|
text={<T id={'delete_journal'} />}
|
||||||
text={<T id={'edit_journal'} />}
|
intent={Intent.DANGER}
|
||||||
onClick={handleEditJournal(journal)}
|
onClick={handleDeleteJournal(journal)}
|
||||||
/>
|
/>
|
||||||
<MenuItem
|
</Menu>
|
||||||
text={<T id={'delete_journal'} />}
|
),
|
||||||
intent={Intent.DANGER}
|
[handleEditJournal, handleDeleteJournal, handlePublishJournal],
|
||||||
onClick={handleDeleteJournal(journal)}
|
);
|
||||||
/>
|
|
||||||
</Menu>
|
|
||||||
),[handleEditJournal,handleDeleteJournal,handlePublishJournal]);
|
|
||||||
|
|
||||||
const columns = useMemo(() => [
|
const columns = useMemo(
|
||||||
{
|
() => [
|
||||||
id: 'date',
|
{
|
||||||
Header: formatMessage({ id: 'date' }),
|
id: 'date',
|
||||||
accessor: (r) => moment().format('YYYY-MM-DD'),
|
Header: formatMessage({ id: 'date' }),
|
||||||
disableResizing: true,
|
accessor: (r) => moment().format('YYYY-MM-DD'),
|
||||||
width: 150,
|
disableResizing: true,
|
||||||
className: 'date',
|
width: 150,
|
||||||
},
|
className: 'date',
|
||||||
{
|
|
||||||
id: 'amount',
|
|
||||||
Header: formatMessage({ id: 'amount' }),
|
|
||||||
accessor: r => (<Money amount={r.amount} currency={'USD'} />),
|
|
||||||
disableResizing: true,
|
|
||||||
className: 'amount',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'journal_number',
|
|
||||||
Header: formatMessage({ id: 'journal_no' }),
|
|
||||||
accessor: 'journal_number',
|
|
||||||
disableResizing: true,
|
|
||||||
className: 'journal_number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'status',
|
|
||||||
Header: formatMessage({ id: 'status' }),
|
|
||||||
accessor: (r) => {
|
|
||||||
return r.status
|
|
||||||
? <Tag minimal={true}><T id={'published'} /></Tag> :
|
|
||||||
<Tag minimal={true} intent={Intent.WARNING}><T id={'draft'} /></Tag>;
|
|
||||||
},
|
},
|
||||||
disableResizing: true,
|
{
|
||||||
width: 100,
|
id: 'amount',
|
||||||
className: 'status',
|
Header: formatMessage({ id: 'amount' }),
|
||||||
},
|
accessor: (r) => <Money amount={r.amount} currency={'USD'} />,
|
||||||
{
|
disableResizing: true,
|
||||||
id: 'note',
|
className: 'amount',
|
||||||
Header: formatMessage({ id: 'note' }),
|
},
|
||||||
accessor: (row) => (
|
{
|
||||||
<If condition={row.description}>
|
id: 'journal_number',
|
||||||
<Tooltip
|
Header: formatMessage({ id: 'journal_no' }),
|
||||||
className={Classes.TOOLTIP_INDICATOR}
|
accessor: 'journal_number',
|
||||||
content={row.description}
|
disableResizing: true,
|
||||||
position={Position.TOP}
|
className: 'journal_number',
|
||||||
hoverOpenDelay={250}>
|
},
|
||||||
<Icon icon={'file-alt'} iconSize={16} />
|
{
|
||||||
</Tooltip>
|
id: 'status',
|
||||||
</If>
|
Header: formatMessage({ id: 'status' }),
|
||||||
),
|
accessor: (r) => {
|
||||||
disableResizing: true,
|
return r.status ? (
|
||||||
disableSorting: true,
|
<Tag minimal={true}>
|
||||||
width: 100,
|
<T id={'published'} />
|
||||||
className: 'note',
|
</Tag>
|
||||||
},
|
) : (
|
||||||
{
|
<Tag minimal={true} intent={Intent.WARNING}>
|
||||||
id: 'transaction_type',
|
<T id={'draft'} />
|
||||||
Header: formatMessage({ id: 'transaction_type' }),
|
</Tag>
|
||||||
accessor: 'transaction_type',
|
);
|
||||||
width: 100,
|
},
|
||||||
className: 'transaction_type',
|
disableResizing: true,
|
||||||
},
|
width: 100,
|
||||||
{
|
className: 'status',
|
||||||
id: 'created_at',
|
},
|
||||||
Header: formatMessage({ id: 'created_at' }),
|
{
|
||||||
accessor: r => moment().format('YYYY-MM-DD'),
|
id: 'note',
|
||||||
disableResizing: true,
|
Header: formatMessage({ id: 'note' }),
|
||||||
width: 150,
|
accessor: (row) => (
|
||||||
className: 'created_at',
|
<If condition={row.description}>
|
||||||
},
|
<Tooltip
|
||||||
{
|
className={Classes.TOOLTIP_INDICATOR}
|
||||||
id: 'actions',
|
content={row.description}
|
||||||
Header: '',
|
position={Position.TOP}
|
||||||
Cell: ({ cell }) => (
|
hoverOpenDelay={250}
|
||||||
<Popover
|
>
|
||||||
content={actionMenuList(cell.row.original)}
|
<Icon icon={'file-alt'} iconSize={16} />
|
||||||
position={Position.RIGHT_BOTTOM}
|
</Tooltip>
|
||||||
>
|
</If>
|
||||||
<Button icon={<Icon icon='ellipsis-h' />} />
|
),
|
||||||
</Popover>
|
disableResizing: true,
|
||||||
),
|
disableSorting: true,
|
||||||
className: 'actions',
|
width: 100,
|
||||||
width: 50,
|
className: 'note',
|
||||||
disableResizing: true,
|
},
|
||||||
},
|
{
|
||||||
], [actionMenuList,formatMessage]);
|
id: 'transaction_type',
|
||||||
|
Header: formatMessage({ id: 'transaction_type' }),
|
||||||
|
accessor: 'transaction_type',
|
||||||
|
width: 100,
|
||||||
|
className: 'transaction_type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'created_at',
|
||||||
|
Header: formatMessage({ id: 'created_at' }),
|
||||||
|
accessor: (r) => moment().format('YYYY-MM-DD'),
|
||||||
|
disableResizing: true,
|
||||||
|
width: 150,
|
||||||
|
className: 'created_at',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
Header: '',
|
||||||
|
Cell: ({ cell }) => (
|
||||||
|
<Popover
|
||||||
|
content={actionMenuList(cell.row.original)}
|
||||||
|
position={Position.RIGHT_BOTTOM}
|
||||||
|
>
|
||||||
|
<Button icon={<Icon icon="ellipsis-h" />} />
|
||||||
|
</Popover>
|
||||||
|
),
|
||||||
|
className: 'actions',
|
||||||
|
width: 50,
|
||||||
|
disableResizing: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[actionMenuList, formatMessage],
|
||||||
|
);
|
||||||
|
|
||||||
const handleDataTableFetchData = useCallback((...args) => {
|
const handleDataTableFetchData = useCallback(
|
||||||
onFetchData && onFetchData(...args);
|
(...args) => {
|
||||||
}, [onFetchData]);
|
onFetchData && onFetchData(...args);
|
||||||
|
},
|
||||||
|
[onFetchData],
|
||||||
|
);
|
||||||
|
|
||||||
const handleSelectedRowsChange = useCallback((selectedRows) => {
|
const handleSelectedRowsChange = useCallback(
|
||||||
onSelectedRowsChange && onSelectedRowsChange(selectedRows.map((s) => s.original));
|
(selectedRows) => {
|
||||||
}, [onSelectedRowsChange]);
|
onSelectedRowsChange &&
|
||||||
|
onSelectedRowsChange(selectedRows.map((s) => s.original));
|
||||||
|
},
|
||||||
|
[onSelectedRowsChange],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingIndicator loading={loading} mount={false}>
|
<LoadingIndicator loading={loading} mount={false}>
|
||||||
@@ -243,6 +263,7 @@ function ManualJournalsDataTable({
|
|||||||
manualSortBy={true}
|
manualSortBy={true}
|
||||||
selectionColumn={true}
|
selectionColumn={true}
|
||||||
noInitialFetch={true}
|
noInitialFetch={true}
|
||||||
|
sticky={true}
|
||||||
loading={manualJournalsLoading && !initialMount}
|
loading={manualJournalsLoading && !initialMount}
|
||||||
onSelectedRowsChange={handleSelectedRowsChange}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
/>
|
/>
|
||||||
@@ -254,7 +275,7 @@ export default compose(
|
|||||||
DialogConnect,
|
DialogConnect,
|
||||||
withDashboardActions,
|
withDashboardActions,
|
||||||
withManualJournalsActions,
|
withManualJournalsActions,
|
||||||
withManualJournals(({ manualJournals, manualJournalsLoading, }) => ({
|
withManualJournals(({ manualJournals, manualJournalsLoading }) => ({
|
||||||
manualJournals,
|
manualJournals,
|
||||||
manualJournalsLoading,
|
manualJournalsLoading,
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import ManualJournalsViewTabs from 'containers/Accounting/ManualJournalsViewTabs
|
|||||||
import ManualJournalsDataTable from 'containers/Accounting/ManualJournalsDataTable';
|
import ManualJournalsDataTable from 'containers/Accounting/ManualJournalsDataTable';
|
||||||
import ManualJournalsActionsBar from 'containers/Accounting/ManualJournalActionsBar';
|
import ManualJournalsActionsBar from 'containers/Accounting/ManualJournalActionsBar';
|
||||||
|
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||||
import withViewsActions from 'containers/Views/withViewsActions';
|
import withViewsActions from 'containers/Views/withViewsActions';
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import Icon from 'components/Icon';
|
|||||||
|
|
||||||
import withManualJournals from './withManualJournals';
|
import withManualJournals from './withManualJournals';
|
||||||
import withManualJournalsActions from './withManualJournalsActions';
|
import withManualJournalsActions from './withManualJournalsActions';
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ function ManualJournalsViewTabs({
|
|||||||
// #withManualJournalsActions
|
// #withManualJournalsActions
|
||||||
addManualJournalsTableQueries,
|
addManualJournalsTableQueries,
|
||||||
|
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
setTopbarEditView,
|
setTopbarEditView,
|
||||||
|
|
||||||
// #ownProps
|
// #ownProps
|
||||||
@@ -121,5 +121,5 @@ export default compose(
|
|||||||
manualJournalsViews,
|
manualJournalsViews,
|
||||||
})),
|
})),
|
||||||
withManualJournalsActions,
|
withManualJournalsActions,
|
||||||
withDashboard
|
withDashboardActions
|
||||||
)(ManualJournalsViewTabs);
|
)(ManualJournalsViewTabs);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import AccountsViewsTabs from 'containers/Accounts/AccountsViewsTabs';
|
|||||||
import AccountsDataTable from 'containers/Accounts/AccountsDataTable';
|
import AccountsDataTable from 'containers/Accounts/AccountsDataTable';
|
||||||
import DashboardActionsBar from 'containers/Accounts/AccountsActionsBar';
|
import DashboardActionsBar from 'containers/Accounts/AccountsActionsBar';
|
||||||
|
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withResourceActions from 'containers/Resources/withResourcesActions';
|
import withResourceActions from 'containers/Resources/withResourcesActions';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
import withAccountsTableActions from 'containers/Accounts/withAccountsTableActions';
|
import withAccountsTableActions from 'containers/Accounts/withAccountsTableActions';
|
||||||
@@ -26,7 +26,7 @@ import { compose } from 'utils';
|
|||||||
|
|
||||||
|
|
||||||
function AccountsChart({
|
function AccountsChart({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withAccountsActions
|
// #withAccountsActions
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import DataTable from 'components/DataTable';
|
|||||||
import Money from 'components/Money';
|
import Money from 'components/Money';
|
||||||
import { useUpdateEffect } from 'hooks';
|
import { useUpdateEffect } from 'hooks';
|
||||||
|
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
import withAccounts from 'containers/Accounts/withAccounts';
|
import withAccounts from 'containers/Accounts/withAccounts';
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ import { If } from 'components';
|
|||||||
|
|
||||||
|
|
||||||
function AccountsDataTable({
|
function AccountsDataTable({
|
||||||
// #withAccounts
|
// #withDashboardActions
|
||||||
accounts,
|
accounts,
|
||||||
accountsLoading,
|
accountsLoading,
|
||||||
|
|
||||||
@@ -193,6 +193,7 @@ function AccountsDataTable({
|
|||||||
selectionColumn={selectionColumn}
|
selectionColumn={selectionColumn}
|
||||||
expandable={true}
|
expandable={true}
|
||||||
treeGraph={true}
|
treeGraph={true}
|
||||||
|
sticky={true}
|
||||||
onSelectedRowsChange={handleSelectedRowsChange}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
loading={accountsLoading && !initialMount}
|
loading={accountsLoading && !initialMount}
|
||||||
spinnerProps={{size: 30}} />
|
spinnerProps={{size: 30}} />
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import {useUpdateEffect} from 'hooks';
|
import {useUpdateEffect} from 'hooks';
|
||||||
|
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withAccounts from 'containers/Accounts/withAccounts';
|
import withAccounts from 'containers/Accounts/withAccounts';
|
||||||
import withAccountsTableActions from 'containers/Accounts/withAccountsTableActions';
|
import withAccountsTableActions from 'containers/Accounts/withAccountsTableActions';
|
||||||
import withViewDetail from 'containers/Views/withViewDetails';
|
import withViewDetail from 'containers/Views/withViewDetails';
|
||||||
@@ -34,7 +34,7 @@ function AccountsViewsTabs({
|
|||||||
addAccountsTableQueries,
|
addAccountsTableQueries,
|
||||||
changeAccountsCurrentView,
|
changeAccountsCurrentView,
|
||||||
|
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
setTopbarEditView,
|
setTopbarEditView,
|
||||||
changePageSubtitle,
|
changePageSubtitle,
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ const withAccountsViewsTabs = connect(mapStateToProps);
|
|||||||
export default compose(
|
export default compose(
|
||||||
withRouter,
|
withRouter,
|
||||||
withAccountsViewsTabs,
|
withAccountsViewsTabs,
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withAccounts(({ accountsViews }) => ({
|
withAccounts(({ accountsViews }) => ({
|
||||||
accountsViews,
|
accountsViews,
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -1,27 +1,15 @@
|
|||||||
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import t from 'store/types';
|
|
||||||
|
|
||||||
const mapActionsToProps = (dispatch) => ({
|
export default (mapState) => {
|
||||||
changePageTitle: (pageTitle) => dispatch({
|
const mapStateToProps = (state, props) => {
|
||||||
type: t.CHANGE_DASHBOARD_PAGE_TITLE, pageTitle
|
const mapped = {
|
||||||
}),
|
pageTitle: state.dashboard.pageTitle,
|
||||||
|
pageSubtitle: state.dashboard.pageSubtitle,
|
||||||
changePageSubtitle: (pageSubtitle) => dispatch({
|
editViewId: state.dashboard.topbarEditViewId,
|
||||||
type: t.ALTER_DASHBOARD_PAGE_SUBTITLE, pageSubtitle,
|
sidebarExpended: state.dashboard.sidebarExpended,
|
||||||
}),
|
};
|
||||||
|
return mapState ? mapState(mapped, state, props) : mapped;
|
||||||
setTopbarEditView: (id) => dispatch({
|
};
|
||||||
type: t.SET_TOPBAR_EDIT_VIEW, id,
|
return connect(mapStateToProps);
|
||||||
}),
|
}
|
||||||
|
|
||||||
setDashboardRequestLoading: () => dispatch({
|
|
||||||
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setDashboardRequestCompleted: () => dispatch({
|
|
||||||
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(null, mapActionsToProps);
|
|
||||||
31
client/src/containers/Dashboard/withDashboardActions.js
Normal file
31
client/src/containers/Dashboard/withDashboardActions.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import t from 'store/types';
|
||||||
|
|
||||||
|
const mapActionsToProps = (dispatch) => ({
|
||||||
|
changePageTitle: (pageTitle) => dispatch({
|
||||||
|
type: t.CHANGE_DASHBOARD_PAGE_TITLE, pageTitle
|
||||||
|
}),
|
||||||
|
|
||||||
|
changePageSubtitle: (pageSubtitle) => dispatch({
|
||||||
|
type: t.ALTER_DASHBOARD_PAGE_SUBTITLE, pageSubtitle,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setTopbarEditView: (id) => dispatch({
|
||||||
|
type: t.SET_TOPBAR_EDIT_VIEW, id,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setDashboardRequestLoading: () => dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_LOADING,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setDashboardRequestCompleted: () => dispatch({
|
||||||
|
type: t.SET_DASHBOARD_REQUEST_COMPLETED,
|
||||||
|
}),
|
||||||
|
|
||||||
|
toggleSidebarExpend: () => dispatch({
|
||||||
|
type: t.SIDEBAR_EXPEND_TOGGLE,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, mapActionsToProps);
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
import React, { useEffect, useState, useCallback,useMemo } from 'react';
|
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { Alert, Intent } from '@blueprintjs/core';
|
import { Alert, Intent } from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T, useIntl, FormattedHTMLMessage } from 'react-intl';
|
import {
|
||||||
|
FormattedMessage as T,
|
||||||
|
useIntl,
|
||||||
|
FormattedHTMLMessage,
|
||||||
|
} from 'react-intl';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
|
|
||||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||||
@@ -10,15 +14,14 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
|||||||
import ExchangeRateTable from './ExchangeRateTable';
|
import ExchangeRateTable from './ExchangeRateTable';
|
||||||
import ExchangeRateActionsBar from './ExchangeRateActionsBar';
|
import ExchangeRateActionsBar from './ExchangeRateActionsBar';
|
||||||
|
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withResourceActions from 'containers/Resources/withResourcesActions';
|
import withResourceActions from 'containers/Resources/withResourcesActions';
|
||||||
import withExchangeRatesActions from 'containers/ExchangeRates/withExchangeRatesActions';
|
import withExchangeRatesActions from 'containers/ExchangeRates/withExchangeRatesActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
|
||||||
function ExchangeRate({
|
function ExchangeRate({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
//#withResourceActions
|
//#withResourceActions
|
||||||
@@ -29,7 +32,6 @@ function ExchangeRate({
|
|||||||
requestDeleteExchangeRate,
|
requestDeleteExchangeRate,
|
||||||
addExchangeRatesTableQueries,
|
addExchangeRatesTableQueries,
|
||||||
requestDeleteBulkExchangeRates,
|
requestDeleteBulkExchangeRates,
|
||||||
|
|
||||||
}) {
|
}) {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [deleteExchangeRate, setDeleteExchangeRate] = useState(false);
|
const [deleteExchangeRate, setDeleteExchangeRate] = useState(false);
|
||||||
@@ -37,21 +39,21 @@ function ExchangeRate({
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const [bulkDelete, setBulkDelete] = useState(false);
|
const [bulkDelete, setBulkDelete] = useState(false);
|
||||||
|
|
||||||
const fetchExchangeRates = useQuery('exchange-rates-table',
|
const fetchExchangeRates = useQuery('exchange-rates-table', () =>
|
||||||
() => requestFetchExchangeRates());
|
requestFetchExchangeRates(),
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
id
|
id
|
||||||
? changePageTitle(formatMessage({id:'exchange_rate_details'}))
|
? changePageTitle(formatMessage({ id: 'exchange_rate_details' }))
|
||||||
: changePageTitle(formatMessage({id:'exchange_rate_list'}));
|
: changePageTitle(formatMessage({ id: 'exchange_rate_list' }));
|
||||||
}, [id, changePageTitle,formatMessage]);
|
}, [id, changePageTitle, formatMessage]);
|
||||||
|
|
||||||
const handelDeleteExchangeRate = useCallback(
|
const handelDeleteExchangeRate = useCallback(
|
||||||
(exchange_rate) => {
|
(exchange_rate) => {
|
||||||
setDeleteExchangeRate(exchange_rate);
|
setDeleteExchangeRate(exchange_rate);
|
||||||
},
|
},
|
||||||
[setDeleteExchangeRate]
|
[setDeleteExchangeRate],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handelEditExchangeRate = (exchange_rate) => {};
|
const handelEditExchangeRate = (exchange_rate) => {};
|
||||||
@@ -64,10 +66,12 @@ function ExchangeRate({
|
|||||||
requestDeleteExchangeRate(deleteExchangeRate.id).then(() => {
|
requestDeleteExchangeRate(deleteExchangeRate.id).then(() => {
|
||||||
setDeleteExchangeRate(false);
|
setDeleteExchangeRate(false);
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: formatMessage({id:'the_exchange_rate_has_been_successfully_deleted'}),
|
message: formatMessage({
|
||||||
|
id: 'the_exchange_rate_has_been_successfully_deleted',
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [deleteExchangeRate, requestDeleteExchangeRate,formatMessage]);
|
}, [deleteExchangeRate, requestDeleteExchangeRate, formatMessage]);
|
||||||
|
|
||||||
// Handle fetch data of Exchange_rates datatable.
|
// Handle fetch data of Exchange_rates datatable.
|
||||||
const handleFetchData = useCallback(
|
const handleFetchData = useCallback(
|
||||||
@@ -81,50 +85,50 @@ function ExchangeRate({
|
|||||||
: {}),
|
: {}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[addExchangeRatesTableQueries]
|
[addExchangeRatesTableQueries],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSelectedRowsChange = useCallback(
|
const handleSelectedRowsChange = useCallback(
|
||||||
(exchange_rates) => {
|
(exchange_rates) => {
|
||||||
setSelectedRows(exchange_rates);
|
setSelectedRows(exchange_rates);
|
||||||
},
|
},
|
||||||
[setSelectedRows]
|
[setSelectedRows],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle Exchange Rates bulk delete.
|
// Handle Exchange Rates bulk delete.
|
||||||
const handleBulkDelete = useCallback(
|
const handleBulkDelete = useCallback(
|
||||||
(exchangeRates) => {
|
(exchangeRates) => {
|
||||||
setBulkDelete(exchangeRates);
|
setBulkDelete(exchangeRates);
|
||||||
},
|
},
|
||||||
[setBulkDelete]
|
[setBulkDelete],
|
||||||
);
|
);
|
||||||
|
|
||||||
//Handel cancel itemCategories bulk delete.
|
//Handel cancel itemCategories bulk delete.
|
||||||
const handleCancelBulkDelete =useCallback(()=>{
|
const handleCancelBulkDelete = useCallback(() => {
|
||||||
setBulkDelete(false)
|
setBulkDelete(false);
|
||||||
},[])
|
}, []);
|
||||||
|
|
||||||
// handle confirm Exchange Rates bulk delete.
|
// handle confirm Exchange Rates bulk delete.
|
||||||
const handleConfirmBulkDelete = useCallback(() => {
|
const handleConfirmBulkDelete = useCallback(() => {
|
||||||
requestDeleteBulkExchangeRates(bulkDelete)
|
requestDeleteBulkExchangeRates(bulkDelete)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setBulkDelete(false);
|
setBulkDelete(false);
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: formatMessage({
|
message: formatMessage({
|
||||||
id: 'the_exchange_rates_has_been_successfully_deleted',
|
id: 'the_exchange_rates_has_been_successfully_deleted',
|
||||||
}),
|
}),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((errors) => {
|
||||||
|
setBulkDelete(false);
|
||||||
});
|
});
|
||||||
})
|
}, [requestDeleteBulkExchangeRates, bulkDelete, formatMessage]);
|
||||||
.catch((errors) => {
|
|
||||||
setBulkDelete(false);
|
|
||||||
});
|
|
||||||
}, [requestDeleteBulkExchangeRates, bulkDelete,formatMessage]);
|
|
||||||
|
|
||||||
|
|
||||||
// Calculates the data table selected rows count.
|
// Calculates the data table selected rows count.
|
||||||
const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [selectedRows]);
|
const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [
|
||||||
|
selectedRows,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardInsider>
|
<DashboardInsider>
|
||||||
@@ -132,7 +136,6 @@ const handleConfirmBulkDelete = useCallback(() => {
|
|||||||
onDeleteExchangeRate={handelDeleteExchangeRate}
|
onDeleteExchangeRate={handelDeleteExchangeRate}
|
||||||
selectedRows={selectedRows}
|
selectedRows={selectedRows}
|
||||||
onBulkDelete={handleBulkDelete}
|
onBulkDelete={handleBulkDelete}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<DashboardPageContent>
|
<DashboardPageContent>
|
||||||
<ExchangeRateTable
|
<ExchangeRateTable
|
||||||
@@ -144,32 +147,37 @@ const handleConfirmBulkDelete = useCallback(() => {
|
|||||||
<Alert
|
<Alert
|
||||||
cancelButtonText={<T id={'cancel'} />}
|
cancelButtonText={<T id={'cancel'} />}
|
||||||
confirmButtonText={<T id={'move_to_trash'} />}
|
confirmButtonText={<T id={'move_to_trash'} />}
|
||||||
icon='trash'
|
icon="trash"
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
isOpen={deleteExchangeRate}
|
isOpen={deleteExchangeRate}
|
||||||
onCancel={handelCancelExchangeRateDelete}
|
onCancel={handelCancelExchangeRateDelete}
|
||||||
onConfirm={handelConfirmExchangeRateDelete}
|
onConfirm={handelConfirmExchangeRateDelete}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
<FormattedHTMLMessage id={'once_delete_this_exchange_rate_you_will_able_to_restore_it'}/>
|
<FormattedHTMLMessage
|
||||||
|
id={'once_delete_this_exchange_rate_you_will_able_to_restore_it'}
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
<Alert
|
<Alert
|
||||||
cancelButtonText={<T id={'cancel'} />}
|
cancelButtonText={<T id={'cancel'} />}
|
||||||
confirmButtonText={`${formatMessage({id:'delete'})} (${selectedRowsCount})`}
|
confirmButtonText={`${formatMessage({
|
||||||
icon='trash'
|
id: 'delete',
|
||||||
intent={Intent.DANGER}
|
})} (${selectedRowsCount})`}
|
||||||
isOpen={bulkDelete}
|
icon="trash"
|
||||||
onCancel={handleCancelBulkDelete}
|
intent={Intent.DANGER}
|
||||||
onConfirm={handleConfirmBulkDelete}
|
isOpen={bulkDelete}
|
||||||
>
|
onCancel={handleCancelBulkDelete}
|
||||||
<p>
|
onConfirm={handleConfirmBulkDelete}
|
||||||
<FormattedHTMLMessage
|
>
|
||||||
id={'once_delete_these_exchange_rates_you_will_not_able_restore_them'}
|
<p>
|
||||||
/>
|
<FormattedHTMLMessage
|
||||||
</p>
|
id={
|
||||||
</Alert>
|
'once_delete_these_exchange_rates_you_will_not_able_restore_them'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
</DashboardPageContent>
|
</DashboardPageContent>
|
||||||
</DashboardInsider>
|
</DashboardInsider>
|
||||||
);
|
);
|
||||||
@@ -178,5 +186,5 @@ const handleConfirmBulkDelete = useCallback(() => {
|
|||||||
export default compose(
|
export default compose(
|
||||||
withExchangeRatesActions,
|
withExchangeRatesActions,
|
||||||
withResourceActions,
|
withResourceActions,
|
||||||
withDashboardActions
|
withDashboardActions,
|
||||||
)(ExchangeRate);
|
)(ExchangeRate);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
|||||||
import BalanceSheetActionsBar from './BalanceSheetActionsBar';
|
import BalanceSheetActionsBar from './BalanceSheetActionsBar';
|
||||||
import { FinancialStatement } from 'components';
|
import { FinancialStatement } from 'components';
|
||||||
|
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withSettings from 'containers/Settings/withSettings';
|
import withSettings from 'containers/Settings/withSettings';
|
||||||
import withBalanceSheetActions from './withBalanceSheetActions';
|
import withBalanceSheetActions from './withBalanceSheetActions';
|
||||||
import withBalanceSheetDetail from './withBalanceSheetDetail';
|
import withBalanceSheetDetail from './withBalanceSheetDetail';
|
||||||
@@ -21,7 +21,7 @@ import withBalanceSheetDetail from './withBalanceSheetDetail';
|
|||||||
|
|
||||||
|
|
||||||
function BalanceSheet({
|
function BalanceSheet({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withBalanceSheetActions
|
// #withBalanceSheetActions
|
||||||
@@ -100,7 +100,7 @@ function BalanceSheet({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withBalanceSheetActions,
|
withBalanceSheetActions,
|
||||||
withBalanceSheetDetail(({ balanceSheetLoading, balanceSheetFilter }) => ({
|
withBalanceSheetDetail(({ balanceSheetLoading, balanceSheetFilter }) => ({
|
||||||
balanceSheetLoading,
|
balanceSheetLoading,
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ function BalanceSheetTable({
|
|||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
expanded={expandedRows}
|
expanded={expandedRows}
|
||||||
expandSubRows={true}
|
expandSubRows={true}
|
||||||
|
sticky={true}
|
||||||
/>
|
/>
|
||||||
</FinancialSheet>
|
</FinancialSheet>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
|||||||
import GeneralLedgerActionsBar from './GeneralLedgerActionsBar';
|
import GeneralLedgerActionsBar from './GeneralLedgerActionsBar';
|
||||||
|
|
||||||
import withGeneralLedgerActions from './withGeneralLedgerActions';
|
import withGeneralLedgerActions from './withGeneralLedgerActions';
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
import withSettings from 'containers/Settings/withSettings';
|
import withSettings from 'containers/Settings/withSettings';
|
||||||
|
|
||||||
|
|
||||||
function GeneralLedger({
|
function GeneralLedger({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withGeneralLedgerActions
|
// #withGeneralLedgerActions
|
||||||
@@ -94,7 +94,7 @@ function GeneralLedger({
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withGeneralLedgerActions,
|
withGeneralLedgerActions,
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withAccountsActions,
|
withAccountsActions,
|
||||||
withSettings,
|
withSettings,
|
||||||
)(GeneralLedger);
|
)(GeneralLedger);
|
||||||
@@ -154,6 +154,7 @@ function GeneralLedgerTable({
|
|||||||
fixedSizeHeight={1000}
|
fixedSizeHeight={1000}
|
||||||
expandable={true}
|
expandable={true}
|
||||||
expandToggleColumn={1}
|
expandToggleColumn={1}
|
||||||
|
sticky={true}
|
||||||
/>
|
/>
|
||||||
</FinancialSheet>
|
</FinancialSheet>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
|||||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||||
import SettingsConnect from 'connectors/Settings.connect';
|
import SettingsConnect from 'connectors/Settings.connect';
|
||||||
|
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withJournalActions from './withJournalActions';
|
import withJournalActions from './withJournalActions';
|
||||||
|
|
||||||
function Journal({
|
function Journal({
|
||||||
// #withJournalActions
|
// #withJournalActions
|
||||||
requestFetchJournalSheet,
|
requestFetchJournalSheet,
|
||||||
|
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withPreferences
|
// #withPreferences
|
||||||
@@ -93,7 +93,7 @@ function Journal({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withJournalActions,
|
withJournalActions,
|
||||||
SettingsConnect,
|
SettingsConnect,
|
||||||
)(Journal);
|
)(Journal);
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ function JournalSheetTable({
|
|||||||
id: 'this_report_does_not_contain_any_data_between_date_period',
|
id: 'this_report_does_not_contain_any_data_between_date_period',
|
||||||
})}
|
})}
|
||||||
expanded={expandedRows}
|
expanded={expandedRows}
|
||||||
|
sticky={true}
|
||||||
/>
|
/>
|
||||||
</FinancialSheet>
|
</FinancialSheet>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import ProfitLossActionsBar from './ProfitLossActionsBar';
|
|||||||
import DashboardInsider from 'components/Dashboard/DashboardInsider'
|
import DashboardInsider from 'components/Dashboard/DashboardInsider'
|
||||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent'
|
import DashboardPageContent from 'components/Dashboard/DashboardPageContent'
|
||||||
|
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withProfitLossActions from './withProfitLossActions';
|
import withProfitLossActions from './withProfitLossActions';
|
||||||
import withProfitLoss from './withProfitLoss';
|
import withProfitLoss from './withProfitLoss';
|
||||||
import SettingsConnect from 'connectors/Settings.connect';
|
import SettingsConnect from 'connectors/Settings.connect';
|
||||||
|
|
||||||
|
|
||||||
function ProfitLossSheet({
|
function ProfitLossSheet({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withProfitLossActions
|
// #withProfitLossActions
|
||||||
@@ -85,7 +85,7 @@ function ProfitLossSheet({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withProfitLossActions,
|
withProfitLossActions,
|
||||||
withProfitLoss(({ profitLossSheetLoading }) => ({
|
withProfitLoss(({ profitLossSheetLoading }) => ({
|
||||||
profitLossSheetLoading,
|
profitLossSheetLoading,
|
||||||
|
|||||||
@@ -7,12 +7,9 @@ import DataTable from 'components/DataTable';
|
|||||||
import Money from 'components/Money';
|
import Money from 'components/Money';
|
||||||
|
|
||||||
import { compose, defaultExpanderReducer } from 'utils';
|
import { compose, defaultExpanderReducer } from 'utils';
|
||||||
import {
|
import { getFinancialSheetIndexByQuery } from 'store/financialStatement/financialStatements.selectors';
|
||||||
getFinancialSheetIndexByQuery,
|
|
||||||
} from 'store/financialStatement/financialStatements.selectors';
|
|
||||||
import withProfitLossDetail from './withProfitLoss';
|
import withProfitLossDetail from './withProfitLoss';
|
||||||
|
|
||||||
|
|
||||||
function ProfitLossSheetTable({
|
function ProfitLossSheetTable({
|
||||||
// #withProfitLoss
|
// #withProfitLoss
|
||||||
profitLossTableRows,
|
profitLossTableRows,
|
||||||
@@ -24,63 +21,79 @@ function ProfitLossSheetTable({
|
|||||||
onFetchData,
|
onFetchData,
|
||||||
companyName,
|
companyName,
|
||||||
}) {
|
}) {
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
const {formatMessage} =useIntl();
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
const columns = useMemo(() => [
|
|
||||||
{
|
|
||||||
Header: formatMessage({id:'account_name'}),
|
|
||||||
accessor: 'name',
|
|
||||||
className: "name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: formatMessage({id:'acc_code'}),
|
|
||||||
accessor: 'code',
|
|
||||||
className: "account_code",
|
|
||||||
},
|
|
||||||
...(profitLossQuery.display_columns_type === 'total') ? [
|
|
||||||
{
|
{
|
||||||
Header: formatMessage({id:'total'}),
|
Header: formatMessage({ id: 'account_name' }),
|
||||||
Cell: ({ cell }) => {
|
accessor: 'name',
|
||||||
const row = cell.row.original;
|
className: 'name',
|
||||||
if (row.total) {
|
},
|
||||||
return (<Money amount={row.total.formatted_amount} currency={'USD'} />);
|
{
|
||||||
}
|
Header: formatMessage({ id: 'acc_code' }),
|
||||||
return '';
|
accessor: 'code',
|
||||||
},
|
className: 'account_code',
|
||||||
className: "total",
|
},
|
||||||
}
|
...(profitLossQuery.display_columns_type === 'total'
|
||||||
] : [],
|
? [
|
||||||
...(profitLossQuery.display_columns_type === 'date_periods') ?
|
{
|
||||||
(profitLossColumns.map((column, index) => ({
|
Header: formatMessage({ id: 'total' }),
|
||||||
id: `date_period_${index}`,
|
Cell: ({ cell }) => {
|
||||||
Header: column,
|
const row = cell.row.original;
|
||||||
accessor: (row) => {
|
if (row.total) {
|
||||||
if (row.periods && row.periods[index]) {
|
return (
|
||||||
const amount = row.periods[index].formatted_amount;
|
<Money
|
||||||
return (<Money amount={amount} currency={'USD'} />);
|
amount={row.total.formatted_amount}
|
||||||
}
|
currency={'USD'}
|
||||||
return '';
|
/>
|
||||||
},
|
);
|
||||||
width: 100,
|
}
|
||||||
})))
|
return '';
|
||||||
: [],
|
},
|
||||||
], [profitLossQuery.display_columns_type, profitLossColumns,formatMessage]);
|
className: 'total',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(profitLossQuery.display_columns_type === 'date_periods'
|
||||||
|
? profitLossColumns.map((column, index) => ({
|
||||||
|
id: `date_period_${index}`,
|
||||||
|
Header: column,
|
||||||
|
accessor: (row) => {
|
||||||
|
if (row.periods && row.periods[index]) {
|
||||||
|
const amount = row.periods[index].formatted_amount;
|
||||||
|
return <Money amount={amount} currency={'USD'} />;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
width: 100,
|
||||||
|
}))
|
||||||
|
: []),
|
||||||
|
],
|
||||||
|
[profitLossQuery.display_columns_type, profitLossColumns, formatMessage],
|
||||||
|
);
|
||||||
|
|
||||||
// Handle data table fetch data.
|
// Handle data table fetch data.
|
||||||
const handleFetchData = useCallback((...args) => {
|
const handleFetchData = useCallback(
|
||||||
onFetchData && onFetchData(...args);
|
(...args) => {
|
||||||
}, [onFetchData]);
|
onFetchData && onFetchData(...args);
|
||||||
|
},
|
||||||
|
[onFetchData],
|
||||||
|
);
|
||||||
|
|
||||||
// Retrieve default expanded rows of balance sheet.
|
// Retrieve default expanded rows of balance sheet.
|
||||||
const expandedRows = useMemo(() =>
|
const expandedRows = useMemo(
|
||||||
defaultExpanderReducer(profitLossTableRows, 1),
|
() => defaultExpanderReducer(profitLossTableRows, 1),
|
||||||
[profitLossTableRows]);
|
[profitLossTableRows],
|
||||||
|
);
|
||||||
|
|
||||||
// Retrieve conditional datatable row classnames.
|
// Retrieve conditional datatable row classnames.
|
||||||
const rowClassNames = useCallback((row) => ({
|
const rowClassNames = useCallback(
|
||||||
[`row--${row.rowType}`]: row.rowType,
|
(row) => ({
|
||||||
}), []);
|
[`row--${row.rowType}`]: row.rowType,
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FinancialSheet
|
<FinancialSheet
|
||||||
@@ -90,8 +103,8 @@ function ProfitLossSheetTable({
|
|||||||
toDate={profitLossQuery.to_date}
|
toDate={profitLossQuery.to_date}
|
||||||
name="profit-loss-sheet"
|
name="profit-loss-sheet"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
basis={profitLossQuery.basis}>
|
basis={profitLossQuery.basis}
|
||||||
|
>
|
||||||
<DataTable
|
<DataTable
|
||||||
className="bigcapital-datatable--financial-report"
|
className="bigcapital-datatable--financial-report"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
@@ -100,7 +113,9 @@ function ProfitLossSheetTable({
|
|||||||
expanded={expandedRows}
|
expanded={expandedRows}
|
||||||
rowClassNames={rowClassNames}
|
rowClassNames={rowClassNames}
|
||||||
expandable={true}
|
expandable={true}
|
||||||
expandToggleColumn={1} />
|
expandToggleColumn={1}
|
||||||
|
sticky={true}
|
||||||
|
/>
|
||||||
</FinancialSheet>
|
</FinancialSheet>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -116,9 +131,11 @@ const withProfitLossTable = connect(mapStateToProps);
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withProfitLossTable,
|
withProfitLossTable,
|
||||||
withProfitLossDetail(({ profitLossQuery, profitLossColumns, profitLossTableRows }) => ({
|
withProfitLossDetail(
|
||||||
profitLossColumns,
|
({ profitLossQuery, profitLossColumns, profitLossTableRows }) => ({
|
||||||
profitLossQuery,
|
profitLossColumns,
|
||||||
profitLossTableRows,
|
profitLossQuery,
|
||||||
})),
|
profitLossTableRows,
|
||||||
)(ProfitLossSheetTable);
|
}),
|
||||||
|
),
|
||||||
|
)(ProfitLossSheetTable);
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
|||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
import DashboardPageContent from 'components/Dashboard/DashboardPageContent';
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withTrialBalanceActions from './withTrialBalanceActions';
|
import withTrialBalanceActions from './withTrialBalanceActions';
|
||||||
import withTrialBalance from './withTrialBalance';
|
import withTrialBalance from './withTrialBalance';
|
||||||
import withSettings from 'containers/Settings/withSettings';
|
import withSettings from 'containers/Settings/withSettings';
|
||||||
|
|
||||||
|
|
||||||
function TrialBalanceSheet({
|
function TrialBalanceSheet({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withTrialBalanceActions
|
// #withTrialBalanceActions
|
||||||
@@ -93,7 +93,7 @@ function TrialBalanceSheet({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withTrialBalanceActions,
|
withTrialBalanceActions,
|
||||||
withTrialBalance(({ trialBalanceSheetLoading }) => ({
|
withTrialBalance(({ trialBalanceSheetLoading }) => ({
|
||||||
trialBalanceSheetLoading,
|
trialBalanceSheetLoading,
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ function TrialBalanceSheetTable({
|
|||||||
onFetchData={handleFetchData}
|
onFetchData={handleFetchData}
|
||||||
expandable={true}
|
expandable={true}
|
||||||
expandToggleColumn={1}
|
expandToggleColumn={1}
|
||||||
|
sticky={true}
|
||||||
/>
|
/>
|
||||||
</FinancialSheet>
|
</FinancialSheet>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import withAccounts from 'containers/Accounts/withAccounts';
|
|||||||
import withMediaActions from 'containers/Media/withMediaActions';
|
import withMediaActions from 'containers/Media/withMediaActions';
|
||||||
import useMedia from 'hooks/useMedia';
|
import useMedia from 'hooks/useMedia';
|
||||||
import withItemDetail from 'containers/Items/withItemDetail'
|
import withItemDetail from 'containers/Items/withItemDetail'
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withAccountDetail from 'containers/Accounts/withAccountDetail';
|
import withAccountDetail from 'containers/Accounts/withAccountDetail';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
@@ -47,7 +47,7 @@ const ItemForm = ({
|
|||||||
onFormSubmit,
|
onFormSubmit,
|
||||||
onCancelForm,
|
onCancelForm,
|
||||||
|
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withItemCategories
|
// #withItemCategories
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useQuery } from 'react-query';
|
|||||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||||
import ItemForm from 'containers/Items/ItemForm';
|
import ItemForm from 'containers/Items/ItemForm';
|
||||||
|
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
import withItemCategoriesActions from 'containers/Items/withItemCategoriesActions';
|
import withItemCategoriesActions from 'containers/Items/withItemCategoriesActions';
|
||||||
import withItemsActions from './withItemsActions';
|
import withItemsActions from './withItemsActions';
|
||||||
@@ -14,7 +14,7 @@ import { compose } from 'utils';
|
|||||||
|
|
||||||
|
|
||||||
const ItemFormContainer = ({
|
const ItemFormContainer = ({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withAccountsActions
|
// #withAccountsActions
|
||||||
@@ -64,7 +64,7 @@ const handleCancel =useCallback(()=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withAccountsActions,
|
withAccountsActions,
|
||||||
withItemCategoriesActions,
|
withItemCategoriesActions,
|
||||||
withItemsActions
|
withItemsActions
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import FilterDropdown from 'components/FilterDropdown';
|
|||||||
|
|
||||||
import withResourceDetail from 'containers/Resources/withResourceDetails';
|
import withResourceDetail from 'containers/Resources/withResourceDetails';
|
||||||
import withDialog from 'connectors/Dialog.connector';
|
import withDialog from 'connectors/Dialog.connector';
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ const withItemsCategoriesActionsBar = connect(mapStateToProps);
|
|||||||
export default compose(
|
export default compose(
|
||||||
withItemsCategoriesActionsBar,
|
withItemsCategoriesActionsBar,
|
||||||
withDialog,
|
withDialog,
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withResourceDetail(({ resourceFields }) => ({
|
withResourceDetail(({ resourceFields }) => ({
|
||||||
resourceFields,
|
resourceFields,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ import AppToaster from 'components/AppToaster';
|
|||||||
|
|
||||||
import withItems from 'containers/Items/withItems';
|
import withItems from 'containers/Items/withItems';
|
||||||
import withResourceActions from 'containers/Resources/withResourcesActions';
|
import withResourceActions from 'containers/Resources/withResourcesActions';
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withItemsActions from 'containers/Items/withItemsActions';
|
import withItemsActions from 'containers/Items/withItemsActions';
|
||||||
import withViewsActions from 'containers/Views/withViewsActions';
|
import withViewsActions from 'containers/Views/withViewsActions';
|
||||||
|
|
||||||
|
|
||||||
function ItemsList({
|
function ItemsList({
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
|
|
||||||
// #withResourceActions
|
// #withResourceActions
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { compose } from 'utils';
|
|||||||
import {useUpdateEffect} from 'hooks';
|
import {useUpdateEffect} from 'hooks';
|
||||||
|
|
||||||
import withItemsActions from 'containers/Items/withItemsActions';
|
import withItemsActions from 'containers/Items/withItemsActions';
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withViewDetail from 'containers/Views/withViewDetails';
|
import withViewDetail from 'containers/Views/withViewDetails';
|
||||||
import withItems from 'containers/Items/withItems';
|
import withItems from 'containers/Items/withItems';
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ function ItemsViewsTabs({
|
|||||||
addItemsTableQueries,
|
addItemsTableQueries,
|
||||||
changeItemsCurrentView,
|
changeItemsCurrentView,
|
||||||
|
|
||||||
// #withDashboard
|
// #withDashboardActions
|
||||||
setTopbarEditView,
|
setTopbarEditView,
|
||||||
changePageSubtitle,
|
changePageSubtitle,
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ const withItemsViewsTabs = connect(mapStateToProps);
|
|||||||
export default compose(
|
export default compose(
|
||||||
withRouter,
|
withRouter,
|
||||||
withItemsViewsTabs,
|
withItemsViewsTabs,
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withItemsActions,
|
withItemsActions,
|
||||||
withViewDetail,
|
withViewDetail,
|
||||||
withItems( ({ itemsViews }) => ({
|
withItems( ({ itemsViews }) => ({
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import LoadingIndicator from 'components/LoadingIndicator';
|
|||||||
import DataTable from 'components/DataTable';
|
import DataTable from 'components/DataTable';
|
||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
|
|
||||||
import withDashboard from 'connectors/Dashboard.connector';
|
|
||||||
import withCurrencies from 'containers/Currencies/withCurrencies';
|
import withCurrencies from 'containers/Currencies/withCurrencies';
|
||||||
import withCurrenciesActions from 'containers/Currencies/withCurrenciesActions';
|
import withCurrenciesActions from 'containers/Currencies/withCurrenciesActions';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
@@ -157,5 +156,4 @@ export default compose(
|
|||||||
})),
|
})),
|
||||||
withCurrenciesActions,
|
withCurrenciesActions,
|
||||||
DialogConnect,
|
DialogConnect,
|
||||||
withDashboard
|
|
||||||
)(CurrenciesList);
|
)(CurrenciesList);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import LoadingIndicator from 'components/LoadingIndicator';
|
|||||||
import AppToaster from 'components/AppToaster';
|
import AppToaster from 'components/AppToaster';
|
||||||
|
|
||||||
import DialogConnect from 'connectors/Dialog.connector';
|
import DialogConnect from 'connectors/Dialog.connector';
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withUsers from 'containers/Users/withUsers';
|
import withUsers from 'containers/Users/withUsers';
|
||||||
import withUsersActions from 'containers/Users/withUsersActions';
|
import withUsersActions from 'containers/Users/withUsersActions';
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ function UsersListPreferences({
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
DialogConnect,
|
DialogConnect,
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withUsers,
|
withUsers,
|
||||||
withUsersActions,
|
withUsersActions,
|
||||||
)(UsersListPreferences);
|
)(UsersListPreferences);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {compose} from 'utils';
|
import {compose} from 'utils';
|
||||||
|
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import withResourceDetail from 'containers/Resources/withResourceDetails';
|
import withResourceDetail from 'containers/Resources/withResourceDetails';
|
||||||
import withViewsActions from 'containers/Views/withViewsActions';
|
import withViewsActions from 'containers/Views/withViewsActions';
|
||||||
import withViewsDetails from 'containers/Views/withViewDetails';
|
import withViewsDetails from 'containers/Views/withViewDetails';
|
||||||
@@ -16,7 +16,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const viewFormConnect = connect(mapStateToProps);
|
const viewFormConnect = connect(mapStateToProps);
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withViewsActions,
|
withViewsActions,
|
||||||
withViewsDetails,
|
withViewsDetails,
|
||||||
viewFormConnect,
|
viewFormConnect,
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ import { If } from 'components';
|
|||||||
|
|
||||||
import withResourcesActions from 'containers/Resources/withResourcesActions';
|
import withResourcesActions from 'containers/Resources/withResourcesActions';
|
||||||
import withViewsActions from 'containers/Views/withViewsActions';
|
import withViewsActions from 'containers/Views/withViewsActions';
|
||||||
import withDashboard from 'containers/Dashboard/withDashboard';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
|
||||||
|
|
||||||
// @flow
|
// @flow
|
||||||
function ViewFormPage({
|
function ViewFormPage({
|
||||||
|
// #withDashboardActions
|
||||||
changePageTitle,
|
changePageTitle,
|
||||||
changePageSubtitle,
|
changePageSubtitle,
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ function ViewFormPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDashboard,
|
withDashboardActions,
|
||||||
withViewsActions,
|
withViewsActions,
|
||||||
withResourcesActions
|
withResourcesActions
|
||||||
)(ViewFormPage);
|
)(ViewFormPage);
|
||||||
@@ -3,10 +3,12 @@ import thunkMiddleware from 'redux-thunk';
|
|||||||
import monitorReducerEnhancer from 'store/enhancers/monitorReducer';
|
import monitorReducerEnhancer from 'store/enhancers/monitorReducer';
|
||||||
import loggerMiddleware from 'middleware/logger'
|
import loggerMiddleware from 'middleware/logger'
|
||||||
import rootReducer from 'store/reducers';
|
import rootReducer from 'store/reducers';
|
||||||
import { loadState, saveState } from 'store/localStorage';
|
import persistState from 'redux-localstorage'
|
||||||
|
|
||||||
|
const persistPaths = ['dashboard', 'authentication'];
|
||||||
|
|
||||||
const createStore = (initialState = {
|
const createStore = (initialState = {
|
||||||
...loadState(),
|
// ...loadState(),
|
||||||
}) => {
|
}) => {
|
||||||
/**
|
/**
|
||||||
|--------------------------------------------------
|
|--------------------------------------------------
|
||||||
@@ -25,6 +27,7 @@ const createStore = (initialState = {
|
|||||||
*/
|
*/
|
||||||
const enhancers = [
|
const enhancers = [
|
||||||
monitorReducerEnhancer,
|
monitorReducerEnhancer,
|
||||||
|
persistState(persistPaths, { key: 'bigcapital' }),
|
||||||
];
|
];
|
||||||
let composeEnhancers = compose;
|
let composeEnhancers = compose;
|
||||||
|
|
||||||
@@ -45,12 +48,6 @@ const createStore = (initialState = {
|
|||||||
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
|
composeEnhancers(applyMiddleware(...middleware), ...enhancers)
|
||||||
);
|
);
|
||||||
store.asyncReducers = {};
|
store.asyncReducers = {};
|
||||||
|
|
||||||
store.subscribe(() => {
|
|
||||||
saveState({
|
|
||||||
authentication: store.getState().authentication,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return store;
|
return store;
|
||||||
};
|
};
|
||||||
export default createStore();
|
export default createStore();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const initialState = {
|
|||||||
pageTitle: '',
|
pageTitle: '',
|
||||||
pageSubtitle: 'Hello World',
|
pageSubtitle: 'Hello World',
|
||||||
preferencesPageTitle: '',
|
preferencesPageTitle: '',
|
||||||
|
sidebarExpended: true,
|
||||||
dialogs: {},
|
dialogs: {},
|
||||||
topbarEditViewId: null,
|
topbarEditViewId: null,
|
||||||
requestsLoading: 0,
|
requestsLoading: 0,
|
||||||
@@ -52,6 +53,10 @@ export default createReducer(initialState, {
|
|||||||
[t.SET_DASHBOARD_REQUEST_COMPLETED]: (state, action) => {
|
[t.SET_DASHBOARD_REQUEST_COMPLETED]: (state, action) => {
|
||||||
const requestsLoading = state.requestsLoading - 1;
|
const requestsLoading = state.requestsLoading - 1;
|
||||||
state.requestsLoading = Math.max(requestsLoading, 0);
|
state.requestsLoading = Math.max(requestsLoading, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
[t.SIDEBAR_EXPEND_TOGGLE]: (state) => {
|
||||||
|
state.sidebarExpended = !state.sidebarExpended;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ export default {
|
|||||||
SET_TOPBAR_EDIT_VIEW: 'SET_TOPBAR_EDIT_VIEW',
|
SET_TOPBAR_EDIT_VIEW: 'SET_TOPBAR_EDIT_VIEW',
|
||||||
SET_DASHBOARD_REQUEST_LOADING: 'SET_DASHBOARD_REQUEST_LOADING',
|
SET_DASHBOARD_REQUEST_LOADING: 'SET_DASHBOARD_REQUEST_LOADING',
|
||||||
SET_DASHBOARD_REQUEST_COMPLETED: 'SET_DASHBOARD_REQUEST_COMPLETED',
|
SET_DASHBOARD_REQUEST_COMPLETED: 'SET_DASHBOARD_REQUEST_COMPLETED',
|
||||||
|
SIDEBAR_EXPEND_TOGGLE: 'SIDEBAR_EXPEND_TOGGLE',
|
||||||
};
|
};
|
||||||
@@ -36,5 +36,4 @@ export default {
|
|||||||
...search,
|
...search,
|
||||||
...register,
|
...register,
|
||||||
...exchangeRate,
|
...exchangeRate,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,15 +11,16 @@ $menu-item-color-active: $light-gray3;
|
|||||||
|
|
||||||
$breadcrumbs-collapsed-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#6B8193' enable-background='new 0 0 16 16' xml:space='preserve'><g><circle cx='2' cy='8.03' r='2'/><circle cx='14' cy='8.03' r='2'/><circle cx='8' cy='8.03' r='2'/></g></svg>");
|
$breadcrumbs-collapsed-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#6B8193' enable-background='new 0 0 16 16' xml:space='preserve'><g><circle cx='2' cy='8.03' r='2'/><circle cx='14' cy='8.03' r='2'/><circle cx='8' cy='8.03' r='2'/></g></svg>");
|
||||||
|
|
||||||
|
$sidebar-zindex: 15;
|
||||||
|
$pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
||||||
|
|
||||||
|
|
||||||
// Blueprint framework.
|
// Blueprint framework.
|
||||||
@import '@blueprintjs/core/src/blueprint.scss';
|
@import '@blueprintjs/core/src/blueprint.scss';
|
||||||
@import '@blueprintjs/datetime/src/blueprint-datetime.scss';
|
@import '@blueprintjs/datetime/src/blueprint-datetime.scss';
|
||||||
|
|
||||||
@import 'basscss';
|
@import 'basscss';
|
||||||
|
|
||||||
$pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
|
||||||
Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, Icons16, sans-serif;
|
|
||||||
|
|
||||||
@import 'functions';
|
@import 'functions';
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
.bigcapital-datatable{
|
.bigcapital-datatable{
|
||||||
display: block;
|
display: block;
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
|
|
||||||
.dashboard__page-content &{
|
.dashboard__page-content &{
|
||||||
|
|
||||||
@@ -111,6 +109,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tbody{
|
.tbody{
|
||||||
|
width: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
|
||||||
.tr .td{
|
.tr .td{
|
||||||
border-bottom: 1px solid #E8E8E8;
|
border-bottom: 1px solid #E8E8E8;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -198,6 +199,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.has-sticky {
|
||||||
|
|
||||||
|
.thead,
|
||||||
|
.tfoot {
|
||||||
|
position: sticky;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thead {
|
||||||
|
top: 0;
|
||||||
|
// box-shadow: 0px 3px 3px #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfoot {
|
||||||
|
bottom: 0;
|
||||||
|
// box-shadow: 0px -3px 3px #ccc;
|
||||||
|
}
|
||||||
|
.tbody {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sticky-td] {
|
||||||
|
position: sticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sticky-last-left-td] {
|
||||||
|
// box-shadow: 2px 0px 3px #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sticky-first-right-td] {
|
||||||
|
// box-shadow: -2px 0px 3px #ccc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.has-virtualized-rows{
|
&.has-virtualized-rows{
|
||||||
.tbody{
|
.tbody{
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ $form-check-input-indeterminate-bg-image: url("data:image/svg+xml,<svg xmlns='ht
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 14px 16px;
|
padding: 14px 16px;
|
||||||
border-top: 1px solid #ececec;
|
border-top: 1px solid #ececec;
|
||||||
|
|
||||||
|
.has-mini-sidebar &{
|
||||||
|
left: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,6 +202,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-left: 220px;
|
margin-left: 220px;
|
||||||
|
|
||||||
|
.sidebar--mini-sidebar + &{
|
||||||
|
margin-left: 50px;
|
||||||
|
width: calc(100% - 50px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__insider{
|
&__insider{
|
||||||
@@ -215,7 +220,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__page-content{
|
&__page-content{
|
||||||
// padding: 22px;
|
|
||||||
|
|
||||||
.bigcapital-datatable{
|
.bigcapital-datatable{
|
||||||
|
|
||||||
@@ -307,9 +311,8 @@
|
|||||||
left: calc(50% - 250px);
|
left: calc(50% - 250px);
|
||||||
z-index: 21;
|
z-index: 21;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
-webkit-box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1),
|
box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1),
|
||||||
0 4px 8px rgba(16, 22, 26, 0.2), 0 18px 46px 6px rgba(16, 22, 26, 0.2);
|
0 4px 8px rgba(16, 22, 26, 0.2),
|
||||||
box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1), 0 4px 8px rgba(16, 22, 26, 0.2),
|
|
||||||
0 18px 46px 6px rgba(16, 22, 26, 0.2);
|
0 18px 46px 6px rgba(16, 22, 26, 0.2);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&__header.is-hidden + .financial-statement__body{
|
&__header.is-hidden + .financial-statement__body{
|
||||||
border-top: 20px solid #FDFDFD;
|
border-top: 20px solid #FDFDFD;
|
||||||
|
|
||||||
@@ -84,17 +83,26 @@
|
|||||||
&__table{
|
&__table{
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
|
|
||||||
.tbody{
|
.table{
|
||||||
.code.td{
|
.tbody,
|
||||||
color: #777;
|
.thead{
|
||||||
|
.tr .td,
|
||||||
|
.tr .th{
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.tbody{
|
||||||
.tr.no-results{
|
.code.td{
|
||||||
.td{
|
color: #777;
|
||||||
flex-direction: column;
|
}
|
||||||
padding: 20px;
|
}
|
||||||
color: #666;
|
.tr.no-results{
|
||||||
align-items: center;
|
.td{
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
color: #666;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
background: $sidebar-background;
|
background: $sidebar-background;
|
||||||
color: $sidebar-text-color;
|
|
||||||
width: $sidebar-width;
|
width: $sidebar-width;
|
||||||
|
color: $sidebar-text-color;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
z-index: $sidebar-zindex;
|
||||||
|
|
||||||
.ScrollbarsCustom-Track {
|
.ScrollbarsCustom-Track {
|
||||||
&.ScrollbarsCustom-TrackY,
|
&.ScrollbarsCustom-TrackY,
|
||||||
@@ -45,6 +46,10 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__scroll-wrapper{
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
&-menu {
|
&-menu {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -120,4 +125,75 @@ $sidebar-popover-submenu-bg: rgb(1, 20, 62);
|
|||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--mini-sidebar{
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 50px;
|
||||||
|
|
||||||
|
|
||||||
|
// Hide text of bigcapital logo.
|
||||||
|
.sidebar__head-logo{
|
||||||
|
|
||||||
|
.bp3-icon-bigcapital{
|
||||||
|
path:not(.path-1):not(.path-2) {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide text of menu items and right caret icon.
|
||||||
|
.bp3-collapse,
|
||||||
|
.bp3-icon-caret-right,
|
||||||
|
.bp3-menu-item .bp3-text-overflow-ellipsis{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__menu{
|
||||||
|
|
||||||
|
.bp3-menu{
|
||||||
|
> li:not(.bp3-submenu):not(.bp3-menu-divider):not(.has-icon){
|
||||||
|
|
||||||
|
.bp3-menu-item{
|
||||||
|
&:before{
|
||||||
|
content: "";
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' data-icon='ellipsis-h' width='18' height='18' fill='%235c7080' viewBox='0 0 512 512'%3E%3Cdesc%3Eellipsis-h%3C/desc%3E%3Cpath d='M304 256c0 26.5-21.5 48-48 48s-48-21.5-48-48 21.5-48 48-48 48 21.5 48 48zm120-48c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48zm-336 0c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z' class='path-1' fill-rule='evenodd'%3E%3C/path%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__scroll-wrapper{
|
||||||
|
background: $sidebar-background;
|
||||||
|
transition: min-width 0.15s ease-in-out;
|
||||||
|
min-width: 50px;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
min-width: $sidebar-width;
|
||||||
|
|
||||||
|
.sidebar__head-logo{
|
||||||
|
|
||||||
|
.bp3-icon-bigcapital{
|
||||||
|
path:not(.path-1):not(.path-2) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bp3-collapse,
|
||||||
|
.bp3-icon-caret-right,
|
||||||
|
.bp3-menu-item .bp3-text-overflow-ellipsis{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.sidebar__menu .bp3-menu > li:not(.bp3-submenu):not(.bp3-menu-divider) .bp3-menu-item{
|
||||||
|
|
||||||
|
&:before{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,6 @@ exports.up = function(knex) {
|
|||||||
table.string('invoice_interval');
|
table.string('invoice_interval');
|
||||||
|
|
||||||
table.timestamps();
|
table.timestamps();
|
||||||
}).then(() => {
|
|
||||||
return knex.seed.run({
|
|
||||||
specific: 'seed_subscriptions_plans.js'
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user