mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
feat: optimize sidebar and datatable expandable rows.
This commit is contained in:
@@ -68,45 +68,6 @@ function AccountsDataTable({
|
||||
</Menu>
|
||||
);
|
||||
const columns = useMemo(() => [
|
||||
{
|
||||
// Build our expander column
|
||||
id: 'expander', // Make sure it has an ID
|
||||
className: 'expander',
|
||||
Header: ({
|
||||
getToggleAllRowsExpandedProps,
|
||||
isAllRowsExpanded
|
||||
}) => (
|
||||
<span {...getToggleAllRowsExpandedProps()} className="toggle">
|
||||
{isAllRowsExpanded ?
|
||||
(<span class="arrow-down" />) :
|
||||
(<span class="arrow-right" />)
|
||||
}
|
||||
</span>
|
||||
),
|
||||
Cell: ({ row }) =>
|
||||
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
|
||||
// to build the toggle for expanding a row
|
||||
row.canExpand ? (
|
||||
<span
|
||||
{...row.getToggleRowExpandedProps({
|
||||
style: {
|
||||
// We can even use the row.depth property
|
||||
// and paddingLeft to indicate the depth
|
||||
// of the row
|
||||
paddingLeft: `${row.depth * 2}rem`,
|
||||
},
|
||||
className: 'toggle',
|
||||
})}
|
||||
>
|
||||
{row.isExpanded ?
|
||||
(<span class="arrow-down" />) :
|
||||
(<span class="arrow-right" />)
|
||||
}
|
||||
</span>
|
||||
) : null,
|
||||
width: 20,
|
||||
disableResizing: true,
|
||||
},
|
||||
{
|
||||
id: 'name',
|
||||
Header: 'Account Name',
|
||||
@@ -197,7 +158,9 @@ function AccountsDataTable({
|
||||
data={accounts}
|
||||
onFetchData={handleDatatableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={selectionColumn} />
|
||||
selectionColumn={selectionColumn}
|
||||
expandable={true}
|
||||
treeGraph={true} />
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import {Checkbox} from '@blueprintjs/core';
|
||||
import classnames from 'classnames';
|
||||
import { FixedSizeList } from 'react-window'
|
||||
import Icon from 'components/Icon';
|
||||
import { ConditionalWrapper } from 'utils';
|
||||
|
||||
const IndeterminateCheckbox = React.forwardRef(
|
||||
({ indeterminate, ...rest }, ref) => {
|
||||
@@ -38,6 +38,8 @@ export default function DataTable({
|
||||
fixedSizeHeight = 100,
|
||||
fixedItemSize = 30,
|
||||
payload,
|
||||
expandable = false,
|
||||
expandToggleColumn = 2,
|
||||
}) {
|
||||
const {
|
||||
getTableProps,
|
||||
@@ -56,6 +58,8 @@ export default function DataTable({
|
||||
setPageSize,
|
||||
selectedFlatRows,
|
||||
totalColumnsWidth,
|
||||
getToggleAllRowsExpandedProps,
|
||||
isAllRowsExpanded,
|
||||
|
||||
// Get the state from the instance
|
||||
state: { pageIndex, pageSize, sortBy, selectedRowIds },
|
||||
@@ -116,6 +120,32 @@ export default function DataTable({
|
||||
onFetchData && onFetchData({ pageIndex, pageSize, sortBy })
|
||||
}, [pageIndex, pageSize, sortBy]);
|
||||
|
||||
// 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]);
|
||||
|
||||
// Renders table row.
|
||||
const RenderRow = useCallback(({ style = {}, row }) => {
|
||||
prepareRow(row);
|
||||
@@ -123,16 +153,18 @@ export default function DataTable({
|
||||
|
||||
return (
|
||||
<div {...row.getRowProps({
|
||||
className: classnames('tr', rowClasses),
|
||||
style
|
||||
className: classnames('tr', rowClasses), style
|
||||
})}>
|
||||
{row.cells.map((cell) => {
|
||||
{row.cells.map((cell, i) => {
|
||||
const index = i + 1;
|
||||
return <div {...cell.getCellProps({
|
||||
className: classnames(cell.column.className || '', 'td'),
|
||||
})}>{ cell.render('Cell') }</div>
|
||||
})}>
|
||||
{ RenderCell({ cell, row, index }) }
|
||||
</div>
|
||||
})}
|
||||
</div>);
|
||||
}, [prepareRow, rowClassNames]);
|
||||
}, [prepareRow, rowClassNames, expandable, RenderCell, expandToggleColumn]);
|
||||
|
||||
// Renders virtualize circle table rows.
|
||||
const RenderVirtualizedRows = useCallback(({ index, style }) => {
|
||||
@@ -144,6 +176,7 @@ export default function DataTable({
|
||||
return page.map((row, index) => RenderRow({ row }));
|
||||
}, [RenderRow, page]);
|
||||
|
||||
// Renders fixed size tbody.
|
||||
const RenderTBody = useCallback(() => {
|
||||
return (virtualizedRows) ? (
|
||||
<FixedSizeList
|
||||
@@ -154,19 +187,31 @@ export default function DataTable({
|
||||
{RenderVirtualizedRows}
|
||||
</FixedSizeList>
|
||||
) : RenderPage();
|
||||
}, [fixedSizeHeight, rows, fixedItemSize, virtualizedRows,
|
||||
RenderVirtualizedRows, 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-header': stickyHeader, 'is-expandable': expandable})}>
|
||||
<div {...getTableProps()} className="table">
|
||||
<div className="thead">
|
||||
{headerGroups.map(headerGroup => (
|
||||
<div {...headerGroup.getHeaderGroupProps()} className="tr">
|
||||
{headerGroup.headers.map(column => (
|
||||
{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')}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ export default class MenuItem extends AbstractPureComponent2 {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isCollapseActive: false,
|
||||
isCollapseActive: this.props.callapseActive || false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -193,6 +193,13 @@ export default class MenuItem extends AbstractPureComponent2 {
|
||||
}</li>;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(nextProps.callapseActive!==this.props.callapseActive){
|
||||
//Perform some operation
|
||||
this.setState({ isCollapseActive: nextProps.callapseActive });
|
||||
}
|
||||
}
|
||||
|
||||
maybeRenderLabel(labelElement) {
|
||||
const { label, labelClassName } = this.props;
|
||||
if (label == null && labelElement == null) {
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
import React, { useState } from 'react';
|
||||
import {Menu, MenuDivider, Collapse} from "@blueprintjs/core";
|
||||
import {useHistory} from 'react-router-dom';
|
||||
import {useHistory, useLocation} from 'react-router-dom';
|
||||
import sidebarMenuList from 'config/sidebarMenu';
|
||||
import Icon from 'components/Icon';
|
||||
import MenuItem from 'components/MenuItem';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export default function SidebarMenu() {
|
||||
let history = useHistory();
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
|
||||
const menuItemsMapper = (list) => {
|
||||
return list.map((item, index) => {
|
||||
const children = Array.isArray(item.children) ? menuItemsMapper(item.children) : null;
|
||||
const isActive = (item.href && item.href === location.pathname) ||
|
||||
(item.children && item.children.some((c) => c.href === location.pathname));
|
||||
|
||||
const handleItemClick = () => {
|
||||
if (item.href) { history.push(item.href); }
|
||||
};
|
||||
return (
|
||||
(item.divider) ?
|
||||
<MenuDivider
|
||||
title={item.title} /> :
|
||||
<MenuDivider title={item.title} /> :
|
||||
<MenuItem
|
||||
active={isActive}
|
||||
icon={<Icon icon={item.icon} iconSize={item.iconSize} />}
|
||||
text={item.text}
|
||||
label={item.label}
|
||||
@@ -24,11 +31,9 @@ export default function SidebarMenu() {
|
||||
children={children}
|
||||
dropdownType={item.dropdownType || 'collapse'}
|
||||
caretIconSize={15}
|
||||
onClick={() => {
|
||||
if (item.href) {
|
||||
history.push(item.href);
|
||||
}
|
||||
}} />
|
||||
onClick={handleItemClick}
|
||||
callapseActive={!!isActive}
|
||||
className={classNames({ 'is-active': isActive })} />
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user