feat: optimize sidebar and datatable expandable rows.

This commit is contained in:
Ahmed Bouhuolia
2020-04-14 15:04:58 +02:00
parent fb6b31d922
commit f8c268434a
9 changed files with 128 additions and 105 deletions

View File

@@ -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>
);
}

View File

@@ -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')}

View File

@@ -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) {

View File

@@ -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 })} />
);
});
};