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