feat: optimize accounts performance.

feat: optimize alerts architecture.
feat: optimize datatable architecture.
feat: optimize datatable style.
This commit is contained in:
a.bouhuolia
2021-01-26 08:44:11 +02:00
parent 0655963607
commit b26f6c937c
70 changed files with 1607 additions and 1012 deletions

View File

@@ -0,0 +1,11 @@
export default function TableBody({}) {
return (
<ScrollSyncPane>
<div {...getTableBodyProps()} className="tbody">
<div class="tbody-inner" style={{ minWidth: totalColumnsWidth }}></div>
</div>
</ScrollSyncPane>
);
}

View File

@@ -0,0 +1,52 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { If } from 'components';
import { ConditionalWrapper } from 'utils';
import TableContext from './TableContext';
/**
* Tabl cell.
*/
export default function TableCell({ cell, row, index }) {
const {
props: { expandToggleColumn, expandable }
} = useContext(TableContext);
return (
<div
{...cell.getCellProps({
className: classNames(cell.column.className, 'td', {
'is-text-overview': cell.column.textOverview,
}),
})}
>
{
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
// to build the toggle for expanding a row
}
<If
condition={
cell.row.canExpand && expandable && index === expandToggleColumn
}
>
<span
{...row.getToggleRowExpandedProps({ className: 'expand-toggle' })}
>
<span
className={classNames({
'arrow-down': row.isExpanded,
'arrow-right': !row.isExpanded,
})}
/>
</span>
</If>
<ConditionalWrapper
condition={cell.column.textOverview}
wrapper={(children) => <span class="text-overview">{children}</span>}
>
{cell.render('Cell')}
</ConditionalWrapper>
</div>
);
}

View File

@@ -0,0 +1,3 @@
import { createContext } from 'react';
export default createContext();

View File

@@ -0,0 +1,18 @@
import React, { memo } from 'react';
import TableCell from './TableCell';
function TableFastCell({ cell, row, index }) {
return <TableCell cell={cell} row={row} index={index} />;
}
export default memo(TableFastCell, (prevProps, nextProps) => {
if (
prevProps.cell.value === nextProps.cell.value &&
prevProps.cell.maxWidth === nextProps.cell.maxWidth &&
prevProps.cell.width === nextProps.cell.width
) {
return true;
} else {
return false;
}
});

View File

@@ -0,0 +1,82 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { ScrollSyncPane } from 'react-scroll-sync';
import { If } from 'components';
import TableContext from './TableContext';
function TableHeaderGroup({ headerGroup }) {
const {
table: { getToggleAllRowsExpandedProps, isAllRowsExpanded },
props: { expandable, expandToggleColumn },
} = useContext(TableContext);
return (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map((column, index) => (
<div
{...column.getHeaderProps({
className: classNames(column.className || '', 'th'),
})}
>
<If condition={expandable && index + 1 === expandToggleColumn}>
<span
{...getToggleAllRowsExpandedProps()}
className="expand-toggle"
>
<span
className={classNames({
'arrow-down': isAllRowsExpanded,
'arrow-right': !isAllRowsExpanded,
})}
/>
</span>
</If>
<div {...column.getSortByToggleProps()}>
{column.render('Header')}
<If condition={column.isSorted}>
<span
className={classNames(
{
'sort-icon--desc': column.isSortedDesc,
'sort-icon--asc': !column.isSortedDesc,
},
'sort-icon',
)}
></span>
</If>
</div>
{column.canResize && (
<div
{...column.getResizerProps()}
className={`resizer ${column.isResizing ? 'isResizing' : ''}`}
>
<div class="inner-resizer" />
</div>
)}
</div>
))}
</div>
);
}
/**
* Table header.
*/
export default function TableHeader() {
const {
table: { headerGroups },
} = useContext(TableContext);
return (
<ScrollSyncPane>
<div className="thead">
{headerGroups.map((headerGroup) => (
<TableHeaderGroup headerGroup={headerGroup} />
))}
</div>
</ScrollSyncPane>
);
}

View File

@@ -0,0 +1,12 @@
import React from 'react';
import { Checkbox } from '@blueprintjs/core';
export default function TableIndeterminateCheckboxHeader({
getToggleAllRowsSelectedProps,
}) {
return (
<div>
<Checkbox {...getToggleAllRowsSelectedProps()} />
</div>
);
}

View File

@@ -0,0 +1,10 @@
import React from 'react';
import { Checkbox } from '@blueprintjs/core';
export default function TableIndeterminateCheckboxRow({ row }) {
return (
<div>
<Checkbox {...row.getToggleRowSelectedProps()} />
</div>
);
}

View File

@@ -0,0 +1,15 @@
import React from 'react';
import { Spinner } from '@blueprintjs/core';
/**
* Table loading component.
*/
export default function TableLoading({
spinnerProps
}) {
return (
<div class="loading">
<Spinner {...spinnerProps} />
</div>
);
}

View File

@@ -0,0 +1,17 @@
import React, { useContext } from 'react';
import TableContext from './TableContext';
/**
* Table no-results row text.
*/
export default function TableNoResultsRow() {
const {
props: { noResults }
} = useContext(TableContext);
return (
<div className={'tr no-results'}>
<div class="td">{ noResults }</div>
</div>
);
}

View File

@@ -0,0 +1,26 @@
import React, { useContext } from 'react';
import TableContext from './TableContext';
/**
* Table page.
*/
export default function TablePage() {
const {
table: { page },
props: {
spinnerProps,
loading,
TableRowsRenderer,
TableLoadingRenderer,
TableNoResultsRow,
},
} = useContext(TableContext);
if (loading) {
return <TableLoadingRenderer spinnerProps={spinnerProps} />;
}
if (page.length === 0) {
return <TableNoResultsRow />;
}
return (<TableRowsRenderer />);
}

View File

@@ -0,0 +1,45 @@
import React, { useCallback, useContext } from 'react';
import { If, Pagination } from 'components';
import TableContext from './TableContext';
/**
* Table pagination.
*/
export default function TablePagination({}) {
const {
table: {
gotoPage,
setPageSize,
pageCount,
state: { pageIndex, pageSize },
},
props: { pagination, loading },
} = useContext(TableContext);
const handlePageChange = useCallback(
(currentPage) => {
gotoPage(currentPage - 1);
},
[gotoPage],
);
const handlePageSizeChange = useCallback(
(pageSize, currentPage) => {
gotoPage(0);
setPageSize(pageSize);
},
[gotoPage, setPageSize],
);
return (
<If condition={pagination && !loading}>
<Pagination
initialPage={pageIndex + 1}
total={pageSize * pageCount}
size={pageSize}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
/>
</If>
);
}

View File

@@ -0,0 +1,51 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { ContextMenu } from '@blueprintjs/core';
import TableContext from './TableContext';
import { saveInvoke } from 'utils';
/**
* Table row.
*/
export default function TableRow({ row, className, style }) {
const {
props: { TableCellRenderer, rowContextMenu, rowClassNames },
} = useContext(TableContext);
// Handle rendering row context menu.
const handleRowContextMenu = (row) => (e) => {
if (typeof rowContextMenu === 'function') {
e.preventDefault();
const tr = e.currentTarget.closest('.tr');
tr.classList.add('is-context-menu-active');
const DropdownEl = rowContextMenu({ row });
ContextMenu.show(DropdownEl, { left: e.clientX, top: e.clientY }, () => {
tr.classList.remove('is-context-menu-active');
});
}
};
return (
<div
{...row.getRowProps({
className: classNames(
'tr',
{
'is-expanded': row.isExpanded && row.canExpand,
},
saveInvoke(rowClassNames, row),
className,
),
style,
onContextMenu: handleRowContextMenu(row)
})}
>
{row.cells.map((cell, index) => (
<TableCellRenderer cell={cell} row={row} index={index + 1} />
))}
</div>
);
}

View File

@@ -0,0 +1,17 @@
import React, { useContext } from "react";
import TableContext from "./TableContext";
/**
* Table rows.
*/
export default function TableRows() {
const {
table: { prepareRow, page },
props: { TableRowRenderer, TableCellRenderer },
} = useContext(TableContext);
return page.map((row) => {
prepareRow(row);
return <TableRowRenderer row={row} TableCellRenderer={TableCellRenderer} />;
});
}

View File

@@ -0,0 +1,21 @@
import React, { useContext } from 'react';
import { ScrollSyncPane } from 'react-scroll-sync';
import TableContext from './TableContext';
export default function TableTBody({
children
}) {
const {
table: { getTableBodyProps }
} = useContext(TableContext);
return (
<ScrollSyncPane>
<div {...getTableBodyProps()} className="tbody">
<div class="tbody-inner">
{ children }
</div>
</div>
</ScrollSyncPane>
);
}

View File

@@ -0,0 +1,66 @@
import React, { useContext } from 'react';
import { WindowScroller, AutoSizer, List } from 'react-virtualized';
import { CLASSES } from 'common/classes';
import TableContext from './TableContext';
function TableVirtualizedListRow({
index,
isScrolling,
isVisible,
key,
style,
}) {
const {
table: { page, prepareRow },
props: { TableRowRenderer },
} = useContext(TableContext);
const row = page[index];
prepareRow(row);
return <TableRowRenderer row={row} style={style} />;
}
/**
* Table virtualized list rows.
*/
export default function TableVirtualizedListRows() {
const {
table: { page },
props: { vListrowHeight, vListOverscanRowCount }
} = useContext(TableContext);
// Dashboard content pane.
const dashboardContentPane = document.querySelector(
`.${CLASSES.DASHBOARD_CONTENT_PANE}`,
);
return (
<WindowScroller scrollElement={dashboardContentPane}>
{({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (
<div className={'WindowScrollerWrapper'}>
<AutoSizer disableHeight>
{({ width }) => (
<div ref={registerChild}>
<List
autoHeight={true}
className={'List'}
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
overscanRowCount={vListOverscanRowCount}
rowCount={page.length}
rowHeight={vListrowHeight}
rowRenderer={({ ...args }) => {
return <TableVirtualizedListRow {...args} />;
}}
scrollTop={scrollTop}
width={width}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
);
}

View File

@@ -0,0 +1,35 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import { ScrollSync } from 'react-scroll-sync';
import TableContext from './TableContext';
/**
* Table wrapper.
*/
export default function TableWrapper({ children }) {
const {
table: { getTableProps },
props: { sticky, pagination, loading, expandable, virtualizedRows, className },
} = useContext(TableContext);
return (
<div
className={classNames('bigcapital-datatable', className, {
'has-sticky': sticky,
'has-pagination': pagination,
'is-expandable': expandable,
'is-loading': loading,
'has-virtualized-rows': virtualizedRows,
})}
>
<ScrollSync>
<div
{...getTableProps({ style: { minWidth: 'none' } })}
className="table"
>
{children}
</div>
</ScrollSync>
</div>
);
}