import React, { useEffect, useRef, useCallback } from 'react'; import { useTable, useExpanded, useRowSelect, usePagination, useResizeColumns, useSortBy, useFlexLayout, } from 'react-table'; import { Checkbox, Spinner } from '@blueprintjs/core'; import classnames from 'classnames'; 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, Pagination } from 'components'; const IndeterminateCheckbox = React.forwardRef( ({ indeterminate, ...rest }, ref) => { return ; }, ); export default function DataTable({ columns, data, loading, onFetchData, onSelectedRowsChange, manualSortBy = 'false', selectionColumn = false, expandSubRows = true, className, noResults = 'This report does not contain any data.', expanded = {}, rowClassNames, sticky = false, virtualizedRows = false, fixedSizeHeight = 100, fixedItemSize = 30, payload, expandable = false, expandToggleColumn = 2, noInitialFetch = false, spinnerProps = { size: 40 }, pagination = false, pagesCount: controlledPageCount, initialPageIndex, initialPageSize, }) { const { getTableProps, getTableBodyProps, headerGroups, prepareRow, page, rows, selectedFlatRows, getToggleAllRowsExpandedProps, isAllRowsExpanded, totalColumnsWidth, // page, pageCount, canPreviousPage, canNextPage, gotoPage, previousPage, nextPage, setPageSize, // Get the state from the instance state: { pageIndex, pageSize, sortBy, selectedRowIds }, } = useTable( { columns, data: data, initialState: { pageIndex: initialPageIndex, pageSize: initialPageSize, expanded, }, // Pass our hoisted table state manualPagination: true, pageCount: controlledPageCount, getSubRows: (row) => row.children, manualSortBy, expandSubRows, payload, autoResetSelectedRows: false, }, useSortBy, useExpanded, useRowSelect, useResizeColumns, useFlexLayout, useSticky, usePagination, (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 }) => (
), // The cell can use the individual row's getToggleRowSelectedProps method // to the render a checkbox Cell: ({ row }) => (
), 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 }); } }, [pageIndex, pageSize, sortBy, onFetchData]); useUpdateEffect(() => { onSelectedRowsChange && onSelectedRowsChange(selectedFlatRows); }, [selectedRowIds, onSelectedRowsChange]); // Renders table cell. const RenderCell = useCallback( ({ row, cell, index }) => ( (
{children}
)} > { // Use the row.canExpand and row.getToggleRowExpandedProps prop getter // to build the toggle for expanding a row row.canExpand && expandable && index === expandToggleColumn && ( ) } {cell.render('Cell')}
), [expandable, expandToggleColumn], ); // Renders table row. const RenderRow = useCallback( ({ style = {}, row }) => { prepareRow(row); const rowClasses = rowClassNames && rowClassNames(row); return (
{row.cells.map((cell, i) => { const index = i + 1; return (
{RenderCell({ cell, row, index })}
); })}
); }, [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 RenderPage = useCallback( ({ style, index } = {}) => { return page.map((row, index) => RenderRow({ row })); }, [RenderRow, page], ); // Renders fixed size tbody. const RenderTBody = useCallback(() => { return virtualizedRows ? ( {RenderVirtualizedRows} ) : ( RenderPage() ); }, [ fixedSizeHeight, rows, fixedItemSize, virtualizedRows, RenderVirtualizedRows, RenderPage, ]); return (
{headerGroups.map((headerGroup) => (
{headerGroup.headers.map((column, index) => (
{expandable && index + 1 === expandToggleColumn && ( )}
{column.render('Header')} {column.isSorted && ( )}
{column.canResize && (
)}
))}
))}
{RenderTBody()}
{noResults}
{ gotoPage(currentPage - 1); }} onPageSizeChange={(pageSize, currentPage) => { gotoPage(currentPage - 1); setPageSize(pageSize); }} />
); }