mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 21:00:31 +00:00
chrone: sperate client and server to different repos.
This commit is contained in:
5
src/components/Datatable/Cells.js
Normal file
5
src/components/Datatable/Cells.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
export function CellTextSpan({ cell: { value } }) {
|
||||
return (<span class="cell-text">{ value }</span>)
|
||||
}
|
||||
36
src/components/Datatable/DatatableEditable.js
Normal file
36
src/components/Datatable/DatatableEditable.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { DataTable, If } from 'components';
|
||||
import 'style/components/DataTable/DataTableEditable.scss';
|
||||
|
||||
/**
|
||||
* Editable datatable.
|
||||
*/
|
||||
export default function DatatableEditable({
|
||||
totalRow = false,
|
||||
actions,
|
||||
name,
|
||||
className,
|
||||
...tableProps
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
CLASSES.DATATABLE_EDITOR,
|
||||
{
|
||||
[`${CLASSES.DATATABLE_EDITOR}--${name}`]: name,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<DataTable {...tableProps} />
|
||||
|
||||
<If condition={actions}>
|
||||
<div className={classNames(CLASSES.DATATABLE_EDITOR_ACTIONS)}>
|
||||
{actions}
|
||||
</div>
|
||||
</If>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
11
src/components/Datatable/TableBody.js
Normal file
11
src/components/Datatable/TableBody.js
Normal 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>
|
||||
);
|
||||
}
|
||||
100
src/components/Datatable/TableCell.js
Normal file
100
src/components/Datatable/TableCell.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import React, { useContext } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { If } from 'components';
|
||||
import { Skeleton } from 'components';
|
||||
import { useAppIntlContext } from 'components/AppIntlProvider';
|
||||
import TableContext from './TableContext';
|
||||
import { saveInvoke } from 'utils';
|
||||
import { isCellLoading } from './utils';
|
||||
|
||||
/**
|
||||
* Table cell.
|
||||
*/
|
||||
export default function TableCell({ cell, row, index }) {
|
||||
const { index: rowIndex, depth, getToggleRowExpandedProps, isExpanded } = row;
|
||||
const {
|
||||
props: {
|
||||
expandToggleColumn,
|
||||
expandColumnSpace,
|
||||
expandable,
|
||||
cellsLoading,
|
||||
cellsLoadingCoords,
|
||||
onCellClick,
|
||||
},
|
||||
} = useContext(TableContext);
|
||||
|
||||
const isExpandColumn = expandToggleColumn === index;
|
||||
const { skeletonWidthMax = 100, skeletonWidthMin = 40 } = {};
|
||||
|
||||
// Application intl context.
|
||||
const { isRTL } = useAppIntlContext();
|
||||
|
||||
// Detarmines whether the current cell is loading.
|
||||
const cellLoading = isCellLoading(
|
||||
cellsLoading,
|
||||
cellsLoadingCoords,
|
||||
rowIndex,
|
||||
cell.column.id,
|
||||
);
|
||||
|
||||
if (cellLoading) {
|
||||
return (
|
||||
<div
|
||||
{...cell.getCellProps({
|
||||
className: classNames(cell.column.className, 'td'),
|
||||
})}
|
||||
>
|
||||
<Skeleton minWidth={skeletonWidthMin} maxWidth={skeletonWidthMax} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Handle cell click action.
|
||||
const handleCellClick = (event) => {
|
||||
saveInvoke(onCellClick, cell, event);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
{...cell.getCellProps({
|
||||
className: classNames(cell.column.className, 'td', {
|
||||
'is-text-overview': cell.column.textOverview,
|
||||
'clickable': cell.column.clickable,
|
||||
'align-right': cell.column.align === 'right',
|
||||
}),
|
||||
onClick: handleCellClick,
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
{
|
||||
'text-overview': cell.column.textOverview,
|
||||
},
|
||||
'cell-inner',
|
||||
)}
|
||||
style={{
|
||||
[isRTL ? 'paddingRight' : 'paddingLeft']:
|
||||
isExpandColumn && expandable
|
||||
? `${depth * expandColumnSpace}rem`
|
||||
: '',
|
||||
}}
|
||||
>
|
||||
{
|
||||
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
|
||||
// to build the toggle for expanding a row
|
||||
}
|
||||
<If condition={cell.row.canExpand && expandable && isExpandColumn}>
|
||||
<span {...getToggleRowExpandedProps({ className: 'expand-toggle' })}>
|
||||
<span
|
||||
className={classNames({
|
||||
'arrow-down': isExpanded,
|
||||
'arrow-right': !isExpanded,
|
||||
})}
|
||||
/>
|
||||
</span>
|
||||
</If>
|
||||
|
||||
{cell.render('Cell')}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
3
src/components/Datatable/TableContext.js
Normal file
3
src/components/Datatable/TableContext.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
export default createContext();
|
||||
20
src/components/Datatable/TableFastCell.js
Normal file
20
src/components/Datatable/TableFastCell.js
Normal file
@@ -0,0 +1,20 @@
|
||||
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.row.canExpand === nextProps.row.canExpand &&
|
||||
prevProps.row.isExpanded === nextProps.row.isExpanded &&
|
||||
prevProps.cell.value === nextProps.cell.value &&
|
||||
prevProps.cell.maxWidth === nextProps.cell.maxWidth &&
|
||||
prevProps.cell.width === nextProps.cell.width
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
36
src/components/Datatable/TableFooter.js
Normal file
36
src/components/Datatable/TableFooter.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React, { useContext } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import TableContext from './TableContext';
|
||||
|
||||
/**
|
||||
* Table footer.
|
||||
*/
|
||||
export default function TableFooter() {
|
||||
const {
|
||||
props: { footer },
|
||||
table: { footerGroups },
|
||||
} = useContext(TableContext);
|
||||
|
||||
// Can't contiunue if the footer is disabled.
|
||||
if (!footer) { return null; }
|
||||
|
||||
return (
|
||||
<div class="tfooter">
|
||||
{footerGroups.map((group) => (
|
||||
<div {...group.getFooterGroupProps({ className: 'tr' })}>
|
||||
{group.headers.map((column) => (
|
||||
<div
|
||||
{...column.getFooterProps({
|
||||
className: classNames(column.className || '', 'td'),
|
||||
})}
|
||||
>
|
||||
<div className={'cell-inner'}>
|
||||
{column.render('Footer')}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
101
src/components/Datatable/TableHeader.js
Normal file
101
src/components/Datatable/TableHeader.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import React, { useContext } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { ScrollSyncPane } from 'react-scroll-sync';
|
||||
import { If } from 'components';
|
||||
import TableContext from './TableContext';
|
||||
import MaterialProgressBar from 'components/MaterialProgressBar';
|
||||
|
||||
function TableHeaderCell({ column, index }) {
|
||||
const {
|
||||
table: { getToggleAllRowsExpandedProps, isAllRowsExpanded },
|
||||
props: { expandable, expandToggleColumn },
|
||||
} = useContext(TableContext);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...column.getHeaderProps({
|
||||
className: classNames(column.className || '', 'th', {
|
||||
'align-right': column.align === 'right',
|
||||
}),
|
||||
})}
|
||||
>
|
||||
<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({
|
||||
className: classNames('cell-inner', {
|
||||
'text-overview': column.textOverview,
|
||||
}),
|
||||
})}
|
||||
>
|
||||
{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>
|
||||
);
|
||||
}
|
||||
|
||||
function TableHeaderGroup({ headerGroup }) {
|
||||
return (
|
||||
<div {...headerGroup.getHeaderGroupProps()} className="tr">
|
||||
{headerGroup.headers.map((column, index) => (
|
||||
<TableHeaderCell key={index} column={column} index={index} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Table header.
|
||||
*/
|
||||
export default function TableHeader() {
|
||||
const {
|
||||
table: { headerGroups, page },
|
||||
props: { TableHeaderSkeletonRenderer, headerLoading, progressBarLoading },
|
||||
} = useContext(TableContext);
|
||||
|
||||
if (headerLoading && TableHeaderSkeletonRenderer) {
|
||||
return <TableHeaderSkeletonRenderer />;
|
||||
}
|
||||
return (
|
||||
<ScrollSyncPane>
|
||||
<div className="thead">
|
||||
{headerGroups.map((headerGroup, index) => (
|
||||
<TableHeaderGroup key={index} headerGroup={headerGroup} />
|
||||
))}
|
||||
<If condition={progressBarLoading}>
|
||||
<MaterialProgressBar />
|
||||
</If>
|
||||
</div>
|
||||
</ScrollSyncPane>
|
||||
);
|
||||
}
|
||||
42
src/components/Datatable/TableHeaderSkeleton.js
Normal file
42
src/components/Datatable/TableHeaderSkeleton.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, { useContext } from 'react';
|
||||
import TableContext from './TableContext';
|
||||
import { Skeleton } from 'components';
|
||||
|
||||
function TableHeaderCell({ column }) {
|
||||
const { skeletonWidthMax = 100, skeletonWidthMin = 40 } = column;
|
||||
|
||||
return (
|
||||
<div
|
||||
{...column.getHeaderProps({
|
||||
className: 'th',
|
||||
})}
|
||||
>
|
||||
<Skeleton minWidth={skeletonWidthMin} maxWidth={skeletonWidthMax} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Table skeleton rows.
|
||||
*/
|
||||
export default function TableSkeletonHeader({}) {
|
||||
const {
|
||||
table: { headerGroups },
|
||||
} = useContext(TableContext);
|
||||
|
||||
return (
|
||||
<div class="thead">
|
||||
{headerGroups.map((headerGroup) => (
|
||||
<div
|
||||
{...headerGroup.getHeaderGroupProps({
|
||||
className: 'tr',
|
||||
})}
|
||||
>
|
||||
{headerGroup.headers.map((column) => (
|
||||
<TableHeaderCell column={column} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
12
src/components/Datatable/TableIndeterminateCheckboxHeader.js
Normal file
12
src/components/Datatable/TableIndeterminateCheckboxHeader.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Checkbox } from '@blueprintjs/core';
|
||||
|
||||
export default function TableIndeterminateCheckboxHeader({
|
||||
getToggleAllRowsSelectedProps,
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<Checkbox {...getToggleAllRowsSelectedProps()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
10
src/components/Datatable/TableIndeterminateCheckboxRow.js
Normal file
10
src/components/Datatable/TableIndeterminateCheckboxRow.js
Normal 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>
|
||||
);
|
||||
}
|
||||
15
src/components/Datatable/TableLoading.js
Normal file
15
src/components/Datatable/TableLoading.js
Normal 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>
|
||||
);
|
||||
}
|
||||
21
src/components/Datatable/TableNoResultsRow.js
Normal file
21
src/components/Datatable/TableNoResultsRow.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import React, { useContext } from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import TableContext from './TableContext';
|
||||
|
||||
/**
|
||||
* Table no-results row text.
|
||||
*/
|
||||
export default function TableNoResultsRow() {
|
||||
const {
|
||||
props: { noResults },
|
||||
} = useContext(TableContext);
|
||||
|
||||
const noResultText =
|
||||
noResults || intl.get('there_is_no_results_in_the_table');
|
||||
|
||||
return (
|
||||
<div className={'tr no-results'}>
|
||||
<div class="td">{noResultText}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
26
src/components/Datatable/TablePage.js
Normal file
26
src/components/Datatable/TablePage.js
Normal 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,
|
||||
TableNoResultsRowRenderer,
|
||||
},
|
||||
} = useContext(TableContext);
|
||||
|
||||
if (loading) {
|
||||
return <TableLoadingRenderer spinnerProps={spinnerProps} />;
|
||||
}
|
||||
if (page.length === 0) {
|
||||
return <TableNoResultsRowRenderer />;
|
||||
}
|
||||
return (<TableRowsRenderer />);
|
||||
}
|
||||
59
src/components/Datatable/TablePagination.js
Normal file
59
src/components/Datatable/TablePagination.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import React, { useCallback, useContext } from 'react';
|
||||
import { If, Pagination } from 'components';
|
||||
import TableContext from './TableContext';
|
||||
import { saveInvoke } from 'utils';
|
||||
|
||||
/**
|
||||
* Table pagination.
|
||||
*/
|
||||
export default function TablePagination() {
|
||||
const {
|
||||
table: {
|
||||
gotoPage,
|
||||
setPageSize,
|
||||
pageCount,
|
||||
state: { pageIndex, pageSize },
|
||||
},
|
||||
props: { pagination, loading, onPaginationChange },
|
||||
} = useContext(TableContext);
|
||||
|
||||
const triggerOnPaginationChange = useCallback((payload) => {
|
||||
saveInvoke(onPaginationChange, payload)
|
||||
}, [onPaginationChange]);
|
||||
|
||||
// Handles the page changing.
|
||||
const handlePageChange = useCallback(
|
||||
({ page, pageSize }) => {
|
||||
const pageIndex = page - 1;
|
||||
|
||||
gotoPage(pageIndex);
|
||||
triggerOnPaginationChange({ pageIndex, pageSize });
|
||||
},
|
||||
[gotoPage, triggerOnPaginationChange],
|
||||
);
|
||||
|
||||
// Handles the page size changing.
|
||||
const handlePageSizeChange = useCallback(
|
||||
({ pageSize, page }) => {
|
||||
const pageIndex = 0;
|
||||
|
||||
gotoPage(pageIndex);
|
||||
setPageSize(pageSize);
|
||||
|
||||
triggerOnPaginationChange({ pageIndex, pageSize });
|
||||
},
|
||||
[gotoPage, setPageSize, triggerOnPaginationChange],
|
||||
);
|
||||
|
||||
return (
|
||||
<If condition={pagination && !loading}>
|
||||
<Pagination
|
||||
currentPage={pageIndex + 1}
|
||||
total={pageSize * pageCount}
|
||||
size={pageSize}
|
||||
onPageChange={handlePageChange}
|
||||
onPageSizeChange={handlePageSizeChange}
|
||||
/>
|
||||
</If>
|
||||
);
|
||||
}
|
||||
90
src/components/Datatable/TableRow.js
Normal file
90
src/components/Datatable/TableRow.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import React, { useCallback, useContext } from 'react';
|
||||
import { ContextMenu } from 'components';
|
||||
import classNames from 'classnames';
|
||||
import useContextMenu from 'react-use-context-menu';
|
||||
|
||||
import TableContext from './TableContext';
|
||||
import { saveInvoke, ConditionalWrapper } from 'utils';
|
||||
|
||||
/**
|
||||
* Table row context wrapper.
|
||||
*/
|
||||
function TableRowContextMenu({ children, row }) {
|
||||
// Table context.
|
||||
const {
|
||||
props: { ContextMenu: ContextMenuContent },
|
||||
table,
|
||||
} = useContext(TableContext);
|
||||
|
||||
const [
|
||||
bindMenu,
|
||||
bindMenuItem,
|
||||
useContextTrigger,
|
||||
{ coords, setVisible, isVisible },
|
||||
] = useContextMenu();
|
||||
|
||||
const [bindTrigger] = useContextTrigger({
|
||||
collect: () => 'Title',
|
||||
});
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setVisible(false);
|
||||
}, [setVisible]);
|
||||
|
||||
return (
|
||||
<div class="tr-context" {...bindTrigger}>
|
||||
{children}
|
||||
|
||||
<ContextMenu
|
||||
bindMenu={bindMenu}
|
||||
isOpen={isVisible}
|
||||
coords={coords}
|
||||
onClosed={handleClose}
|
||||
>
|
||||
<ContextMenuContent {...table} row={row} />
|
||||
</ContextMenu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Table row.
|
||||
*/
|
||||
export default function TableRow({ row, className, style }) {
|
||||
const {
|
||||
props: {
|
||||
TableCellRenderer,
|
||||
rowClassNames,
|
||||
ContextMenu: ContextMenuContent,
|
||||
},
|
||||
} = useContext(TableContext);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...row.getRowProps({
|
||||
className: classNames(
|
||||
'tr',
|
||||
{ 'is-expanded': row.isExpanded && row.canExpand },
|
||||
saveInvoke(rowClassNames, row),
|
||||
className,
|
||||
),
|
||||
style,
|
||||
})}
|
||||
>
|
||||
<ConditionalWrapper
|
||||
condition={ContextMenuContent}
|
||||
wrapper={TableRowContextMenu}
|
||||
row={row}
|
||||
>
|
||||
{row.cells.map((cell, index) => (
|
||||
<TableCellRenderer
|
||||
key={index}
|
||||
cell={cell}
|
||||
row={row}
|
||||
index={index + 1}
|
||||
/>
|
||||
))}
|
||||
</ConditionalWrapper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
17
src/components/Datatable/TableRows.js
Normal file
17
src/components/Datatable/TableRows.js
Normal 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, index) => {
|
||||
prepareRow(row);
|
||||
return <TableRowRenderer key={index} row={row} TableCellRenderer={TableCellRenderer} />;
|
||||
});
|
||||
}
|
||||
44
src/components/Datatable/TableSkeletonRows.js
Normal file
44
src/components/Datatable/TableSkeletonRows.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import React, { useContext } from 'react';
|
||||
import TableContext from './TableContext';
|
||||
import { Skeleton } from 'components';
|
||||
|
||||
/**
|
||||
* Table header cell.
|
||||
*/
|
||||
function TableHeaderCell({ column }) {
|
||||
const { skeletonWidthMax = 100, skeletonWidthMin = 40 } = column;
|
||||
|
||||
return (
|
||||
<div
|
||||
{...column.getHeaderProps({
|
||||
className: 'td',
|
||||
})}
|
||||
>
|
||||
<Skeleton minWidth={skeletonWidthMin} maxWidth={skeletonWidthMax} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Table skeleton rows.
|
||||
*/
|
||||
export default function TableSkeletonRows({}) {
|
||||
const {
|
||||
table: { headerGroups },
|
||||
} = useContext(TableContext);
|
||||
const skeletonRows = 10;
|
||||
|
||||
return Array.from({ length: skeletonRows }).map(() => {
|
||||
return headerGroups.map((headerGroup) => (
|
||||
<div
|
||||
{...headerGroup.getHeaderGroupProps({
|
||||
className: 'tr',
|
||||
})}
|
||||
>
|
||||
{headerGroup.headers.map((column) => (
|
||||
<TableHeaderCell column={column} />
|
||||
))}
|
||||
</div>
|
||||
));
|
||||
});
|
||||
}
|
||||
21
src/components/Datatable/TableTBody.js
Normal file
21
src/components/Datatable/TableTBody.js
Normal 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>
|
||||
);
|
||||
}
|
||||
67
src/components/Datatable/TableVirtualizedRows.js
Normal file
67
src/components/Datatable/TableVirtualizedRows.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { WindowScroller, AutoSizer, List } from 'react-virtualized';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import TableContext from './TableContext';
|
||||
|
||||
/**
|
||||
* Table virtualized list row.
|
||||
*/
|
||||
function TableVirtualizedListRow({
|
||||
index,
|
||||
isScrolling,
|
||||
isVisible,
|
||||
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 = React.useMemo(()=> document.querySelector(
|
||||
`.${CLASSES.DASHBOARD_CONTENT_PANE}`,
|
||||
), []);
|
||||
|
||||
const rowRenderer = React.useCallback(({ key, ...args }) => (
|
||||
<TableVirtualizedListRow {...args} key={key} />
|
||||
), []);
|
||||
|
||||
return (
|
||||
<WindowScroller scrollElement={dashboardContentPane}>
|
||||
{({ height, isScrolling, onChildScroll, scrollTop }) => (
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) => (
|
||||
<List
|
||||
autoHeight={true}
|
||||
className={'List'}
|
||||
height={height}
|
||||
isScrolling={isScrolling}
|
||||
onScroll={onChildScroll}
|
||||
overscanRowCount={vListOverscanRowCount}
|
||||
rowCount={page.length}
|
||||
rowHeight={vListrowHeight}
|
||||
rowRenderer={rowRenderer}
|
||||
scrollTop={scrollTop}
|
||||
width={width}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
)}
|
||||
</WindowScroller>
|
||||
);
|
||||
}
|
||||
35
src/components/Datatable/TableWrapper.js
Normal file
35
src/components/Datatable/TableWrapper.js
Normal 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>
|
||||
);
|
||||
}
|
||||
35
src/components/Datatable/utils.js
Normal file
35
src/components/Datatable/utils.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
|
||||
export const isCellLoading = (loading, cellsCoords, rowIndex, columnId) => {
|
||||
if (!loading) {
|
||||
return false;
|
||||
}
|
||||
return !cellsCoords
|
||||
? true
|
||||
: cellsCoords.some(
|
||||
(cellCoord) => cellCoord[0] === rowIndex && cellCoord[1] === columnId,
|
||||
);
|
||||
};
|
||||
|
||||
export const useResizeObserver = (state, callback) => {
|
||||
// This Ref will contain the id of the column being resized or undefined
|
||||
const columnResizeRef = React.useRef();
|
||||
|
||||
React.useEffect(() => {
|
||||
// We are interested in calling the resize event only when "state.columnResizing?.isResizingColumn" changes from
|
||||
// a string to undefined, because it indicates that it WAS resizing but it no longer is.
|
||||
if (
|
||||
state.columnResizing &&
|
||||
!state.columnResizing?.isResizingColumn &&
|
||||
columnResizeRef.current
|
||||
) {
|
||||
// Trigger resize event
|
||||
callback(
|
||||
columnResizeRef.current,
|
||||
state.columnResizing.columnWidths[columnResizeRef.current],
|
||||
state.columnResizing,
|
||||
);
|
||||
}
|
||||
columnResizeRef.current = state.columnResizing?.isResizingColumn;
|
||||
}, [callback, state.columnResizing]);
|
||||
};
|
||||
Reference in New Issue
Block a user