react-table#usePagination TypeScript Examples
The following examples show how to use
react-table#usePagination.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Table.tsx From crossfeed with Creative Commons Zero v1.0 Universal | 5 votes |
Table = <T extends object>(props: TableProps<T>) => { const { columns, data, initialSortBy, initialFilterBy, pageCount = 0, pageSize = 20, fetchData, disableFilters = false, renderPagination, renderExpanded, tableRef } = props; const stateReducer = (nextState: any, action: any, prevState: any) => { if (action.type === 'toggleSortBy' || action.type === 'setGlobalFilter') { return { ...nextState, pageIndex: 0 }; } return nextState; }; const instance = useTable( { columns, data, disableMultiSort: true, manualSortBy: Boolean(fetchData), manualPagination: Boolean(fetchData), manualFilters: Boolean(fetchData), autoResetSortBy: false, disableFilters, pageCount, stateReducer, initialState: { sortBy: initialSortBy ?? [], pageSize, pageIndex: 0, filters: initialFilterBy ?? [], globalFilter: [] } }, useFilters, useSortBy, useExpanded, usePagination ); useImperativeHandle(tableRef, () => instance); const { state: { sortBy, pageIndex, filters } } = instance; useEffect(() => { fetchData && fetchData({ sort: sortBy, page: pageIndex + 1, pageSize, filters }); }, [fetchData, sortBy, filters, pageIndex, pageSize]); return ( <div className={classes.root}> <div className={classes.tableInner}> <UsaTable {...instance.getTableProps()} bordered={false}> <TableHead<T> {...instance} /> <TableBody<T> {...instance} renderExpanded={renderExpanded} /> </UsaTable> </div> {props.noResults && ( <NoResults message={props.noResultsMessage!}></NoResults> )} {renderPagination && renderPagination(instance)} </div> ); }
Example #2
Source File: Table.tsx From solo with MIT License | 5 votes |
Table = <T extends object>({ columns, data, initialSortBy, manualPagination = true, manualSortBy = true, pageCount = 0, fetchData, onSelectedRowsChange, renderSubComponent, renderPagination, renderFilterControls }: TableProps<T>) => { const stateReducer = (nextState: any, action: any, prevState: any) => { if (action.type === "toggleSortBy" || action.type === "setGlobalFilter") { return { ...nextState, pageIndex: 0 }; } return nextState; }; const instance = useTable( { columns, data, manualGlobalFilter: true, disableMultiSort: true, manualSortBy, manualPagination, autoResetSortBy: !manualSortBy, pageCount, stateReducer, initialState: { sortBy: initialSortBy ?? [], pageSize: 20, globalFilter: [] } }, useGlobalFilter, useSortBy, useExpanded, usePagination, useRowSelect ); const { state: { sortBy, pageIndex, globalFilter, selectedRowIds } } = instance; useEffect(() => { fetchData && fetchData({ sort: sortBy, page: pageIndex + 1, filters: globalFilter }); }, [fetchData, sortBy, globalFilter, pageIndex]); useEffect(() => { onSelectedRowsChange && onSelectedRowsChange(instance); }, [selectedRowIds, instance, onSelectedRowsChange]); return ( <> {renderFilterControls && renderFilterControls(instance)} <USWDSTable {...instance.getTableProps()}> <TableHead headerGroups={instance.headerGroups} /> <TableBody {...instance} renderSubComponent={renderSubComponent} /> </USWDSTable> {renderPagination && renderPagination(instance)} </> ); }
Example #3
Source File: FeTable.tsx From frontegg-react with MIT License | 5 votes |
FeTable: FC<TableProps> = <T extends object>(props: TableProps<T>) => { const tableRef = useRef<HTMLDivElement>(null); const firstRender = useRef<boolean>(true); const columns = useMemo(() => { const columns = props.columns.map( ({ sortable, Filter, Header, ...rest }) => ({ ...rest, disableSortBy: !sortable, disableFilters: !Filter, Filter, Header: Header ?? <div style={{ minWidth: rest.minWidth, maxWidth: rest.maxWidth }} />, } as FeTableColumnOptions<T>) ); if (props.expandable) { columns.unshift({ id: 'fe-expander', minWidth: 60, maxWidth: '60px' as any, Header: <div style={{ minWidth: '2rem', maxWidth: '2rem' }} />, Cell: (cell: Cell<T>) => { const row = cell.row as Row<T> & UseExpandedRowProps<T>; return ( <FeButton className={classNames('fe-table__expand-button', { 'is-expanded': row.isExpanded })} {...row.getToggleRowExpandedProps()} variant={row.isExpanded ? 'primary' : undefined} > <FeIcon name='right-arrow' /> </FeButton> ); }, }); } if (props.selection) { columns.unshift({ id: 'fe-selection', minWidth: 60, maxWidth: '60px' as any, Cell: (cell: Cell<T>) => { const row = cell.row as Row<T> & UseRowSelectRowProps<T>; return ( <FeCheckbox {...row.getToggleRowSelectedProps()} checked={row.isSelected} onChange={(e) => onRowSelected(row.original, e.target.checked)} /> ); }, }); } return columns as Column<T>[]; }, [props.columns, props.expandable]); const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, state, // The page controls ;) page, canPreviousPage, canNextPage, pageOptions, pageCount, gotoPage, nextPage, previousPage, setPageSize, // select props toggleAllRowsSelected, isAllRowsSelected, selectedFlatRows, toggleRowSelected, } = useTable( { columns, data: props.data, getRowId: (row: any) => row[props.rowKey], manualSortBy: !!props.onSortChange, manualFilters: !!props.onFilterChange, manualPagination: !!props.onPageChange, manualRowSelectedKey: props.rowKey, pageCount: !!props.onPageChange ? props.pageCount : undefined, autoResetPage: !props.onPageChange, useControlledState: (state1: any, meta) => ({ ...state1, sortBy: props.sortBy ?? state1.sortBy, filters: props.filters ?? state1.filters, selectedRowIds: props.selectedRowIds ?? state1.selectedRowIds, } as FeTableState<T>), expandSubRows: false, autoResetExpanded: false, initialState: { pageIndex: 0, pageSize: props.pageSize, selectedRowIds: props.selectedRowIds || {}, }, } as FeUseTable<T>, useFilters, useSortBy, useExpanded, usePagination, useRowSelect, useFlexLayout ) as FeTableInstance<T>; checkTableProps(props); const tableState = state as UseSortByState<T> & UseFiltersState<T> & UsePaginationState<T> & UseRowSelectState<T>; const onSortChange = useCallback( (column: FeTableColumnProps<T>) => { if (props.hasOwnProperty('sortBy')) { const sortBy = props.isMultiSort ? tableState.sortBy.filter(({ id }) => id !== column.id) : []; if (!column.isSorted) { sortBy.push({ id: column.id, desc: false }); } else if (!column.isSortedDesc) { sortBy.push({ id: column.id, desc: true }); } props.onSortChange?.(sortBy); } else { if (column.isSorted && column.isSortedDesc) { column.clearSortBy(); } else { column.toggleSortBy(column.isSorted, props.isMultiSort ?? false); } } }, [props.onSortChange] ); const onFilterChange = useCallback( (column: FeTableColumnProps<T>, filterValue?: any) => { if (props.hasOwnProperty('filters')) { const filters = tableState.filters.filter(({ id }) => id !== column.id); if (filterValue != null) { filters.push({ id: column.id, value: filterValue }); } props.onFilterChange?.(filters); } else { column.setFilter(filterValue); } }, [props.onFilterChange, tableState] ); const onToggleAllRowsSelected = useCallback( (value: boolean) => { if (props.hasOwnProperty('selectedRowIds')) { const selectedIds = props.data.reduce((p, n: any) => ({ ...p, [n[props.rowKey]]: true }), {}); props.onRowSelected?.(value ? selectedIds : {}); } else { toggleAllRowsSelected(value); } }, [props.onRowSelected] ); const onRowSelected = useCallback( (row: any, value: boolean) => { const id = row[props.rowKey]; if (props.hasOwnProperty('selectedRowIds')) { const newSelectedRows: any = { ...props.selectedRowIds }; if (value) { newSelectedRows[id] = true; } else { delete newSelectedRows[id]; } props.onRowSelected?.(newSelectedRows); } else { toggleRowSelected(id, value); } }, [props.onRowSelected] ); const handleOnPageChange = useCallback(() => { if (pagination === 'pages') { tableRef.current?.querySelector(`.${prefixCls}__tbody`)?.scroll?.({ top: 0, left: 0, behavior: 'smooth' }); } props.onPageChange?.(tableState.pageSize, tableState.pageIndex); }, [tableState.pageIndex]); useEffect(() => { !props.hasOwnProperty('sortBy') && props.onSortChange?.(tableState.sortBy); }, [props.sortBy, tableState.sortBy]); useEffect(() => { !props.hasOwnProperty('filters') && props.onFilterChange?.(tableState.filters); }, [props.filters, tableState.filters]); useEffect(() => { firstRender.current ? (firstRender.current = false) : handleOnPageChange(); }, [tableState.pageIndex]); useEffect(() => { !props.hasOwnProperty('selectedRowIds') && props.onRowSelected?.(tableState.selectedRowIds as any); }, [tableState.selectedRowIds]); const tableHeadProps: FeTableTHeadProps<T> = { prefixCls, headerGroups, onSortChange, onFilterChange, toggleAllRowsSelected, isAllRowsSelected, selectedFlatRows, }; const tableRows: (Row<T> & UseExpandedRowProps<T>)[] = useMemo( () => (props.pagination ? page : rows) as (Row<T> & UseExpandedRowProps<T>)[], [page, rows, props.pagination] ); const tablePaginationProps: FeTablePaginationProps<T> = { pageIndex: tableState.pageIndex, pageSize: tableState.pageSize, canPreviousPage, canNextPage, pageOptions, pageCount, gotoPage, nextPage, previousPage, setPageSize, }; const { className, toolbar, loading, pagination, pageSize } = props; return ( <div className='fe-table__container'> <div ref={tableRef} className={classNames(prefixCls, className)} {...getTableProps()}> {toolbar && <FeTableToolbar />} <div className={classNames( `${prefixCls}__table-container`, loading && pagination === 'pages' && `${prefixCls}__table-container-loading` )} > <FeTableTBody pageSize={pageSize} pagination={pagination} onInfiniteScroll={handleOnPageChange} loading={props.loading} prefixCls={prefixCls} prepareRow={prepareRow} getTableBodyProps={getTableBodyProps} renderExpandedComponent={props.renderExpandedComponent} rows={tableRows} /> <FeTableTHead {...tableHeadProps} /> </div> {loading && pagination === 'pages' && rows.length > 0 && <FeLoader center size={24} />} {pagination === 'pages' && <FeTablePagination {...tablePaginationProps} />} </div> </div> ); }
Example #4
Source File: table.container.tsx From master-frontend-lemoncode with MIT License | 5 votes |
TableContainer: React.FunctionComponent<Props> = props => {
const { className } = props;
const labels = { ...createEmptyLabelProps(), ...props.labels };
const columns = React.useMemo(
() => mapColumnListFromStringToColumn(props.columns),
[props.columns]
);
const data = React.useMemo(() => props.rows, [props.rows]);
const {
getTableProps,
headerGroups,
rows,
prepareRow,
page,
gotoPage,
pageOptions,
state,
} = useTable(
{
columns,
data,
initialState: { pageSize: props.pageSize } as any,
},
usePagination
) as TableProps;
const { pageIndex } = state as any;
const {
isOpen,
itemToDelete,
onOpenDialog,
onClose,
onAccept,
} = useConfirmationDialog();
const handleDelete = () => {
if (props.onDelete) {
props.onDelete(itemToDelete.id);
onAccept();
}
};
return (
<TableComponent
className={className}
tableProps={{ ...getTableProps() }}
headerGroups={headerGroups}
rows={props.enablePagination ? page : rows}
prepareRow={prepareRow}
rowRenderer={rowProps =>
props.rowRenderer({
...rowProps,
onEdit: props.onEdit,
onDelete: Boolean(props.onDelete) ? onOpenDialog : undefined,
})
}
labels={labels}
enableSearch={props.enableSearch}
search={props.search}
onSearch={props.onSearch}
enablePagination={Boolean(
props.enablePagination && pageOptions.length > 1
)}
pageIndex={pageIndex}
pageCount={pageOptions.length}
goToPage={gotoPage}
onCreate={props.onCreate}
onDelete={Boolean(props.onDelete) ? handleDelete : undefined}
isOpenConfirmation={isOpen}
onCloseConfirmation={onClose}
itemToDeleteName={itemToDelete.name}
/>
);
}
Example #5
Source File: index.tsx From admin with MIT License | 4 votes |
CollectionsTable: React.FC = () => {
const [filteringOptions, setFilteringOptions] = useState<
FilteringOptionProps[]
>([])
const [offset, setOffset] = useState(0)
const limit = DEFAULT_PAGE_SIZE
const [query, setQuery] = useState("")
const [numPages, setNumPages] = useState(0)
const debouncedSearchTerm = useDebounce(query, 500)
const { collections, isLoading, isRefetching, count } = useAdminCollections({
q: debouncedSearchTerm,
offset: offset,
limit,
})
useEffect(() => {
if (typeof count !== "undefined") {
const controlledPageCount = Math.ceil(count / limit)
setNumPages(controlledPageCount)
}
}, [count])
const [columns] = useCollectionTableColumn()
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
canPreviousPage,
canNextPage,
pageCount,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex },
} = useTable(
{
columns,
data: collections || [],
manualPagination: true,
initialState: {
pageIndex: Math.floor(offset / limit),
pageSize: limit,
},
pageCount: numPages,
autoResetPage: false,
},
usePagination
)
const handleNext = () => {
if (canNextPage) {
setOffset(offset + limit)
nextPage()
}
}
const handleSearch = (q) => {
setOffset(0)
setQuery(q)
}
const handlePrev = () => {
if (canPreviousPage) {
setOffset(offset - limit)
previousPage()
}
}
useEffect(() => {
setFilteringOptions([
{
title: "Sort",
options: [
{
title: "All",
count: collections?.length || 0,
onClick: () => console.log("Not implemented yet"),
},
],
},
])
}, [collections])
return (
<div className="w-full h-full overflow-y-auto">
<Table
enableSearch
handleSearch={handleSearch}
searchPlaceholder="Search Collections"
filteringOptions={filteringOptions}
{...getTableProps()}
>
<Table.Head>
{headerGroups?.map((headerGroup) => (
<Table.HeadRow {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((col) => (
<Table.HeadCell
className="min-w-[100px]"
{...col.getHeaderProps()}
>
{col.render("Header")}
</Table.HeadCell>
))}
</Table.HeadRow>
))}
</Table.Head>
{isLoading || isRefetching || !collections ? (
<div className="w-full pt-2xlarge flex items-center justify-center">
<Spinner size={"large"} variant={"secondary"} />
</div>
) : (
<Table.Body {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row)
return <CollectionRow row={row} />
})}
</Table.Body>
)}
</Table>
<TablePagination
count={count!}
limit={limit}
offset={offset}
pageSize={offset + rows.length}
title="Collections"
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</div>
)
}
Example #6
Source File: selectable-table.tsx From admin with MIT License | 4 votes |
SelectableTable: React.FC<SelectableTableProps> = ({
showSearch = true,
label,
objectName,
selectedIds = [],
isLoading,
pagination,
totalCount,
data,
columns,
onPaginationChange,
onChange,
onSearch,
}) => {
const handleQueryChange = (newQuery) => {
onPaginationChange(newQuery)
}
const currentPage = useMemo(() => {
return Math.floor(pagination.offset / pagination.limit)
}, [pagination])
const numPages = useMemo(() => {
if (totalCount && pagination.limit) {
return Math.ceil(totalCount / pagination.limit)
}
return 0
}, [totalCount, pagination])
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
canPreviousPage,
canNextPage,
pageCount,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex, pageSize, selectedRowIds },
} = useTable(
{
columns,
data: data || [],
manualPagination: true,
initialState: {
pageIndex: currentPage,
pageSize: pagination.limit,
selectedRowIds: selectedIds.reduce((prev, id) => {
prev[id] = true
return prev
}, {}),
},
pageCount: numPages,
autoResetSelectedRows: false,
autoResetPage: false,
getRowId: (row) => row.id,
},
usePagination,
useRowSelect,
(hooks) => {
hooks.visibleColumns.push((columns) => [
// Let's make a column for selection
{
id: "selection",
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => {
return (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
)
},
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => {
return (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
)
},
},
...columns,
])
}
)
useEffect(() => {
onChange(Object.keys(selectedRowIds))
}, [selectedRowIds])
const handleNext = () => {
if (canNextPage) {
handleQueryChange({
...pagination,
offset: pagination.offset + pagination.limit,
})
nextPage()
}
}
const handlePrev = () => {
if (canPreviousPage) {
handleQueryChange({
...pagination,
offset: Math.max(pagination.offset - pagination.limit, 0),
})
previousPage()
}
}
return (
<div>
<div className="inter-base-semibold my-large">{label}</div>
<Table
immediateSearchFocus={showSearch}
enableSearch={showSearch}
searchPlaceholder="Search Products.."
handleSearch={onSearch}
{...getTableProps()}
>
<Table.Body {...getTableBodyProps()}>
{isLoading ? (
<Spinner size="large" />
) : (
rows.map((row, i) => {
prepareRow(row)
return (
<Table.Row {...row.getRowProps()}>
{row.cells.map((cell) => {
return (
<Table.Cell {...cell.getCellProps()}>
{cell.render("Cell")}
</Table.Cell>
)
})}
</Table.Row>
)
})
)}
</Table.Body>
</Table>
<TablePagination
count={totalCount!}
limit={pagination.limit}
offset={pagination.offset}
pageSize={pagination.offset + rows.length}
title={objectName}
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</div>
)
}
Example #7
Source File: products.tsx From admin with MIT License | 4 votes |
RMASelectProductSubModal: React.FC<RMASelectProductSubModalProps> = ({
onSubmit,
selectedItems,
isLargeModal = true,
}) => {
const PAGE_SIZE = 12
const { pop } = useContext(LayeredModalContext)
const [query, setQuery] = useState("")
const [offset, setOffset] = useState(0)
const [numPages, setNumPages] = useState(0)
const [currentPage, setCurrentPage] = useState(0)
const [selectedVariants, setSelectedVariants] = useState<any[]>([])
const debouncedSearchTerm = useDebounce(query, 500)
const { isLoading, count, variants } = useAdminVariants({
q: debouncedSearchTerm,
limit: PAGE_SIZE,
offset,
})
useEffect(() => {
if (typeof count !== "undefined") {
setNumPages(Math.ceil(count / PAGE_SIZE))
}
}, [count])
const columns = useMemo(() => {
return [
{
Header: "Name",
accessor: "title",
Cell: ({ row: { original } }) => {
return (
<div className="flex items-center">
<div className="h-[40px] w-[30px] my-1.5 flex items-center mr-4">
{original.product.thumbnail ? (
<img
src={original.product.thumbnail}
className="h-full object-cover rounded-soft"
/>
) : (
<div className="flex items-center justify-center w-full h-full rounded-soft bg-grey-10">
<ImagePlaceholder size={16} />
</div>
)}
</div>
<div className="flex flex-col">
<span>{original.product.title}</span>
{original.title}
</div>
</div>
)
},
},
{
Header: "Status",
accessor: "status",
Cell: ({ row: { original } }) => (
<StatusIndicator
title={`${original.product.status
.charAt(0)
.toUpperCase()}${original.product.status.slice(1)}`}
variant={getProductStatusVariant(original.product.status)}
/>
),
},
{
Header: <div className="text-right">In Stock</div>,
accessor: "inventory_quantity",
Cell: ({ row: { original } }) => (
<div className="text-right">{original.inventory_quantity}</div>
),
},
]
}, [])
const {
getTableProps,
getTableBodyProps,
rows,
prepareRow,
canPreviousPage,
canNextPage,
pageCount,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex, pageSize, selectedRowIds },
} = useTable(
{
columns,
data: variants || [],
manualPagination: true,
initialState: {
pageIndex: currentPage,
pageSize: PAGE_SIZE,
selectedRowIds: selectedItems.reduce((prev, { id }) => {
prev[id] = true
return prev
}, {}),
},
pageCount: numPages,
autoResetSelectedRows: false,
autoResetPage: false,
getRowId: (row) => row.id,
},
usePagination,
useRowSelect,
(hooks) => {
hooks.visibleColumns.push((columns) => [
// Let's make a column for selection
{
id: "selection",
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => {
return (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
)
},
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => {
return (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
)
},
},
...columns,
])
}
)
useEffect(() => {
setSelectedVariants((selectedVariants) => [
...selectedVariants.filter(
(sv) => Object.keys(selectedRowIds).findIndex((id) => id === sv.id) > -1
),
...(variants?.filter(
(v) =>
selectedVariants.findIndex((sv) => sv.id === v.id) < 0 &&
Object.keys(selectedRowIds).findIndex((id) => id === v.id) > -1
) || []),
])
}, [selectedRowIds])
const handleNext = () => {
if (canNextPage) {
setOffset((old) => old + pageSize)
setCurrentPage((old) => old + 1)
nextPage()
}
}
const handlePrev = () => {
if (canPreviousPage) {
setOffset((old) => Math.max(old - pageSize, 0))
setCurrentPage((old) => old - 1)
previousPage()
}
}
const handleSearch = (q) => {
setOffset(0)
setCurrentPage(0)
setQuery(q)
}
const handleSubmit = () => {
onSubmit(selectedVariants)
pop()
}
return (
<>
<Modal.Content isLargeModal={isLargeModal}>
<div className="min-h-[680px]">
<Table
immediateSearchFocus
enableSearch
searchPlaceholder="Search Products.."
handleSearch={handleSearch}
{...getTableProps()}
>
<Table.Body {...getTableBodyProps()}>
{isLoading ? (
<Spinner size="large" />
) : (
rows.map((row, i) => {
prepareRow(row)
return (
<Table.Row {...row.getRowProps()}>
{row.cells.map((cell) => {
return (
<Table.Cell {...cell.getCellProps()}>
{cell.render("Cell")}
</Table.Cell>
)
})}
</Table.Row>
)
})
)}
</Table.Body>
</Table>
<TablePagination
count={count!}
limit={PAGE_SIZE}
offset={offset}
pageSize={offset + rows.length}
title="Products"
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</div>
</Modal.Content>
<Modal.Footer isLargeModal={isLargeModal}>
<div className="flex w-full justify-end gap-x-xsmall">
<Button
variant="ghost"
size="small"
className="w-[112px]"
onClick={() => pop()}
>
Back
</Button>
<Button
variant="primary"
className="w-[112px]"
size="small"
onClick={handleSubmit}
>
Add
</Button>
</div>
</Modal.Footer>
</>
)
}
Example #8
Source File: selectable-table.tsx From admin with MIT License | 4 votes |
SelectableTable = < T extends | Product | CustomerGroup | ProductCollection | ProductTag | ProductType >({ label, resourceName = "", selectedIds = [], isLoading, totalCount = 0, data, columns, onChange, options, renderRow, renderHeaderGroup, setQuery, queryObject, paginate, }: SelectableTableProps<T>) => { const table = useTable<T>( { columns, data: data || [], manualPagination: true, initialState: { pageIndex: queryObject.offset / queryObject.limit, pageSize: queryObject.limit, selectedRowIds: selectedIds.reduce((prev, id) => { prev[id] = true return prev }, {} as Record<string, boolean>), }, pageCount: Math.ceil(totalCount / queryObject.limit), autoResetSelectedRows: false, autoResetPage: false, getRowId: (row: any) => row.id, }, useSortBy, usePagination, useRowSelect, useSelectionColumn ) useEffect(() => { onChange(Object.keys(table.state.selectedRowIds)) }, [table.state.selectedRowIds]) const handleNext = () => { if (!table.canNextPage) { return } paginate(1) table.nextPage() } const handlePrev = () => { if (!table.canPreviousPage) { return } paginate(-1) table.previousPage() } const handleSearch = (text: string) => { setQuery(text) if (text) { table.gotoPage(0) } } const debouncedSearch = React.useMemo(() => debounce(handleSearch, 300), []) return ( <div> <div className="inter-base-semibold my-large">{label}</div> <Table {...options} {...table.getTableProps()} handleSearch={options.enableSearch ? debouncedSearch : undefined} > {renderHeaderGroup && ( <Table.Head> {table.headerGroups?.map((headerGroup) => renderHeaderGroup({ headerGroup }) )} </Table.Head> )} <Table.Body {...table.getTableBodyProps()}> {isLoading ? ( <Spinner size="large" /> ) : ( table.rows.map((row) => { table.prepareRow(row) return renderRow({ row }) }) )} </Table.Body> </Table> <TablePagination count={totalCount!} limit={queryObject.limit} offset={queryObject.offset} pageSize={queryObject.offset + table.rows.length} title={resourceName} currentPage={table.state.pageIndex + 1} pageCount={table.pageCount} nextPage={handleNext} prevPage={handlePrev} hasNext={table.canNextPage} hasPrev={table.canPreviousPage} /> </div> ) }
Example #9
Source File: index.tsx From admin with MIT License | 4 votes |
SelectableTable = < T extends Product | CustomerGroup | ProductCollection | ProductTag >({ label, resourceName = "", selectedIds = [], isLoading, totalCount = 0, data, columns, onChange, options, renderRow, renderHeaderGroup, setQuery, queryObject, paginate, }: SelectableTableProps<T>) => { const table = useTable<T>( { columns, data: data || [], manualPagination: true, initialState: { pageIndex: queryObject.offset / queryObject.limit, pageSize: queryObject.limit, selectedRowIds: selectedIds.reduce((prev, id) => { prev[id] = true return prev }, {} as Record<string, boolean>), }, pageCount: Math.ceil(totalCount / queryObject.limit), autoResetSelectedRows: false, autoResetPage: false, getRowId: (row: any) => row.id, }, useSortBy, usePagination, useRowSelect, useSelectionColumn ) useEffect(() => { if (onChange) { onChange(Object.keys(table.state.selectedRowIds)) } }, [table.state.selectedRowIds]) const handleNext = () => { if (!table.canNextPage) { return } paginate(1) table.nextPage() } const handlePrev = () => { if (!table.canPreviousPage) { return } paginate(-1) table.previousPage() } const handleSearch = (text: string) => { setQuery(text) if (text) { table.gotoPage(0) } } const debouncedSearch = React.useMemo(() => debounce(handleSearch, 300), []) return ( <div> {label && <div className="inter-base-semibold my-large">{label}</div>} <Table {...options} {...table.getTableProps()} handleSearch={options.enableSearch ? debouncedSearch : undefined} > {renderHeaderGroup && ( <Table.Head> {table.headerGroups?.map((headerGroup) => renderHeaderGroup({ headerGroup }) )} </Table.Head> )} <Table.Body {...table.getTableBodyProps()}> {isLoading ? ( <Spinner size="large" /> ) : ( table.rows.map((row, i) => { table.prepareRow(row) return renderRow({ row }) }) )} </Table.Body> </Table> <TablePagination count={totalCount!} limit={queryObject.limit} offset={queryObject.offset} pageSize={queryObject.offset + table.rows.length} title={resourceName} currentPage={table.state.pageIndex + 1} pageCount={table.pageCount} nextPage={handleNext} prevPage={handlePrev} hasNext={table.canNextPage} hasPrev={table.canPreviousPage} /> </div> ) }
Example #10
Source File: index.tsx From admin with MIT License | 4 votes |
ProductTable: React.FC<ProductTableProps> = () => {
const location = useLocation()
const {
removeTab,
setTab,
saveTab,
availableTabs: filterTabs,
activeFilterTab,
reset,
paginate,
setFilters,
setLimit,
filters,
setQuery: setFreeText,
queryObject,
representationObject,
} = useProductFilters(location.search, defaultQueryProps)
const offs = parseInt(queryObject.offset) || 0
const limit = parseInt(queryObject.limit)
const [query, setQuery] = useState(queryObject.query)
const [numPages, setNumPages] = useState(0)
const clearFilters = () => {
reset()
setQuery("")
}
const { products, isLoading, isRefetching, count } = useAdminProducts({
...queryObject,
})
useEffect(() => {
if (typeof count !== "undefined") {
const controlledPageCount = Math.ceil(count / limit)
setNumPages(controlledPageCount)
}
}, [count])
const updateUrlFromFilter = (obj = {}) => {
const stringified = qs.stringify(obj)
window.history.replaceState(`/a/products`, "", `${`?${stringified}`}`)
}
const refreshWithFilters = () => {
const filterObj = representationObject
if (isEmpty(filterObj)) {
updateUrlFromFilter({ offset: 0, limit: DEFAULT_PAGE_SIZE })
} else {
updateUrlFromFilter(filterObj)
}
}
useEffect(() => {
refreshWithFilters()
}, [representationObject])
const setTileView = () => {
setLimit(DEFAULT_PAGE_SIZE_TILE_VIEW)
setShowList(false)
}
const setListView = () => {
setLimit(DEFAULT_PAGE_SIZE)
setShowList(true)
}
const [showList, setShowList] = React.useState(true)
const [columns] = useProductTableColumn({
setTileView,
setListView,
showList,
})
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
gotoPage,
canPreviousPage,
canNextPage,
pageCount,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data: products || [],
manualPagination: true,
initialState: {
pageIndex: Math.floor(offs / limit),
pageSize: limit,
},
pageCount: numPages,
autoResetPage: false,
},
usePagination
)
// Debounced search
useEffect(() => {
const delayDebounceFn = setTimeout(() => {
if (query) {
setFreeText(query)
gotoPage(0)
} else {
if (typeof query !== "undefined") {
// if we delete query string, we reset the table view
reset()
}
}
}, 400)
return () => clearTimeout(delayDebounceFn)
}, [query])
const handleNext = () => {
if (canNextPage) {
paginate(1)
nextPage()
}
}
const handlePrev = () => {
if (canPreviousPage) {
paginate(-1)
previousPage()
}
}
return (
<div className="w-full h-full overflow-y-auto">
<>
<Table
filteringOptions={
<ProductsFilter
filters={filters}
submitFilters={setFilters}
clearFilters={clearFilters}
tabs={filterTabs}
onTabClick={setTab}
activeTab={activeFilterTab}
onRemoveTab={removeTab}
onSaveTab={saveTab}
/>
}
enableSearch
handleSearch={setQuery}
{...getTableProps()}
>
{showList ? (
<>
<Table.Head>
{headerGroups?.map((headerGroup) => (
<Table.HeadRow {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((col) => (
<Table.HeadCell
className="min-w-[100px]"
{...col.getHeaderProps()}
>
{col.render("Header")}
</Table.HeadCell>
))}
</Table.HeadRow>
))}
</Table.Head>
<LoadingContainer
isLoading={isLoading || isRefetching || !products}
>
<Table.Body {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row)
return <ProductRow row={row} />
})}
</Table.Body>
</LoadingContainer>
</>
) : (
<LoadingContainer
isLoading={isLoading || isRefetching || !products}
>
<ProductOverview
products={products}
toggleListView={setListView}
/>
</LoadingContainer>
)}
</Table>
<TablePagination
count={count!}
limit={limit}
offset={offs}
pageSize={offs + rows.length}
title="Products"
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</>
</div>
)
}
Example #11
Source File: price-list-table.tsx From admin with MIT License | 4 votes |
/*
* Root component of the price lists table.
*/
export function PriceListTable(props: PriceListTableProps) {
const {
priceLists,
queryObject,
count,
paginate,
setQuery,
columns,
options,
} = props
const tableConfig: TableOptions<PriceList> = {
columns: columns,
data: priceLists || [],
initialState: {
pageSize: queryObject.limit,
pageIndex: queryObject.offset / queryObject.limit,
},
pageCount: Math.ceil(count / queryObject.limit),
manualPagination: true,
autoResetPage: false,
}
const table = useTable(tableConfig, useSortBy, usePagination, useRowSelect)
// ********* HANDLERS *********
const handleNext = () => {
if (!table.canNextPage) {
return
}
paginate(1)
table.nextPage()
}
const handlePrev = () => {
if (!table.canPreviousPage) {
return
}
paginate(-1)
table.previousPage()
}
const handleSearch = (text: string) => {
setQuery(text)
if (text) {
table.gotoPage(0)
}
}
const debouncedSearch = React.useMemo(() => debounce(handleSearch, 300), [])
// ********* RENDER *********
return (
<>
<Table
{...table.getTableProps()}
{...options}
enableSearch={options.enableSearch}
handleSearch={options.enableSearch ? debouncedSearch : undefined}
filteringOptions={options.filter}
>
{/* HEAD */}
<Table.Head>
{table.headerGroups?.map((headerGroup, ind) => (
<PriceListTableHeaderRow key={ind} headerGroup={headerGroup} />
))}
</Table.Head>
{/* BODY */}
<Table.Body {...table.getTableBodyProps()}>
{table.rows.map((row) => {
table.prepareRow(row)
return <PriceListTableRow row={row} />
})}
</Table.Body>
</Table>
{/* PAGINATION */}
<TablePagination
count={count}
limit={queryObject.limit}
offset={queryObject.offset}
pageSize={queryObject.offset + table.rows.length}
title="Price Lists"
currentPage={table.state.pageIndex + 1}
pageCount={table.pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={table.canNextPage}
hasPrev={table.canPreviousPage}
/>
</>
)
}
Example #12
Source File: index.tsx From admin with MIT License | 4 votes |
OrderTable: React.FC<RouteComponentProps> = () => { const location = useLocation() const { removeTab, setTab, saveTab, availableTabs: filterTabs, activeFilterTab, reset, paginate, setFilters, filters, setQuery: setFreeText, queryObject, representationObject, } = useOrderFilters(location.search, defaultQueryProps) const filtersOnLoad = queryObject const offs = parseInt(filtersOnLoad?.offset) || 0 const lim = parseInt(filtersOnLoad.limit) || DEFAULT_PAGE_SIZE const [query, setQuery] = useState(filtersOnLoad?.query) const [numPages, setNumPages] = useState(0) const { orders, isLoading, count } = useAdminOrders(queryObject) useEffect(() => { const controlledPageCount = Math.ceil(count! / queryObject.limit) setNumPages(controlledPageCount) }, [orders]) const [columns] = useOrderTableColums() const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, canPreviousPage, canNextPage, pageCount, gotoPage, nextPage, previousPage, // Get the state from the instance state: { pageIndex }, } = useTable( { columns, data: orders || [], manualPagination: true, initialState: { pageSize: lim, pageIndex: offs / lim, }, pageCount: numPages, autoResetPage: false, }, usePagination ) // Debounced search useEffect(() => { const delayDebounceFn = setTimeout(() => { if (query) { setFreeText(query) gotoPage(0) } else { // if we delete query string, we reset the table view reset() } }, 400) return () => clearTimeout(delayDebounceFn) }, [query]) const handleNext = () => { if (canNextPage) { paginate(1) nextPage() } } const handlePrev = () => { if (canPreviousPage) { paginate(-1) previousPage() } } const updateUrlFromFilter = (obj = {}) => { const stringified = qs.stringify(obj) window.history.replaceState(`/a/orders`, "", `${`?${stringified}`}`) } const refreshWithFilters = () => { const filterObj = representationObject if (isEmpty(filterObj)) { updateUrlFromFilter({ offset: 0, limit: DEFAULT_PAGE_SIZE }) } else { updateUrlFromFilter(filterObj) } } const clearFilters = () => { reset() setQuery("") } useEffect(() => { refreshWithFilters() }, [representationObject]) return ( <div className="w-full overflow-y-auto flex flex-col justify-between min-h-[300px] h-full "> <Table filteringOptions={ <OrderFilters filters={filters} submitFilters={setFilters} clearFilters={clearFilters} tabs={filterTabs} onTabClick={setTab} activeTab={activeFilterTab} onRemoveTab={removeTab} onSaveTab={saveTab} /> } enableSearch handleSearch={setQuery} searchValue={query} {...getTableProps()} className={clsx({ ["relative"]: isLoading })} > <Table.Head> {headerGroups?.map((headerGroup, index) => ( <Table.HeadRow {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map((col, headerIndex) => ( <Table.HeadCell {...col.getHeaderProps()}> {col.render("Header")} </Table.HeadCell> ))} </Table.HeadRow> ))} </Table.Head> {isLoading || !orders ? ( <div className="flex w-full h-full absolute items-center justify-center mt-10"> <div className=""> <Spinner size={"large"} variant={"secondary"} /> </div> </div> ) : ( <Table.Body {...getTableBodyProps()}> {rows.map((row) => { prepareRow(row) return ( <Table.Row color={"inherit"} linkTo={row.original.id} {...row.getRowProps()} className="group" > {row.cells.map((cell, index) => { return cell.render("Cell", { index }) })} </Table.Row> ) })} </Table.Body> )} </Table> <TablePagination count={count!} limit={queryObject.limit} offset={queryObject.offset} pageSize={queryObject.offset + rows.length} title="Orders" currentPage={pageIndex + 1} pageCount={pageCount} nextPage={handleNext} prevPage={handlePrev} hasNext={canNextPage} hasPrev={canPreviousPage} /> </div> ) }
Example #13
Source File: index.tsx From admin with MIT License | 4 votes |
DraftOrderTable: React.FC<RouteComponentProps> = () => { const location = useLocation() const { reset, paginate, setQuery: setFreeText, queryObject, } = useDraftOrderFilters(location.search, {}) const filtersOnLoad = queryObject const offs = parseInt(filtersOnLoad?.offset) || 0 const lim = parseInt(filtersOnLoad?.limit) || DEFAULT_PAGE_SIZE const [query, setQuery] = useState(filtersOnLoad?.query) const [numPages, setNumPages] = useState(0) const { draft_orders, isLoading, isRefetching, count } = useAdminDraftOrders( queryObject ) useEffect(() => { const controlledPageCount = Math.ceil(count! / queryObject.limit) setNumPages(controlledPageCount) }, [count, queryObject]) const [columns] = useDraftOrderTableColumns() const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, canPreviousPage, canNextPage, pageCount, gotoPage, nextPage, previousPage, // Get the state from the instance state: { pageIndex }, } = useTable( { columns, data: draft_orders || [], manualPagination: true, initialState: { pageSize: lim, pageIndex: offs / lim, }, pageCount: numPages, autoResetPage: false, }, usePagination ) // Debounced search useEffect(() => { const delayDebounceFn = setTimeout(() => { if (query) { setFreeText(query) gotoPage(0) } else { // if we delete query string, we reset the table view reset() } }, 400) return () => clearTimeout(delayDebounceFn) }, [query]) const handleNext = () => { if (canNextPage) { paginate(1) nextPage() } } const handlePrev = () => { if (canPreviousPage) { paginate(-1) previousPage() } } return ( <div className="w-full h-full overflow-y-auto flex flex-col justify-between"> {isLoading || isRefetching || !draft_orders ? ( <div className="w-full pt-2xlarge flex items-center justify-center"> <Spinner size={"large"} variant={"secondary"} /> </div> ) : ( <> <Table filteringOptions={[]} enableSearch handleSearch={setQuery} searchValue={query} {...getTableProps()} > <Table.Head> {headerGroups?.map((headerGroup, index) => ( <Table.HeadRow {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map((col, headerIndex) => ( <Table.HeadCell className="w-[100px]" {...col.getHeaderProps()} > {col.render("Header")} </Table.HeadCell> ))} </Table.HeadRow> ))} </Table.Head> <Table.Body {...getTableBodyProps()}> {rows.map((row) => { prepareRow(row) return ( <Table.Row color={"inherit"} linkTo={`/a/draft-orders/${row.original.id}`} {...row.getRowProps()} > {row.cells.map((cell, index) => { return cell.render("Cell", { index }) })} </Table.Row> ) })} </Table.Body> </Table> <TablePagination count={count!} limit={queryObject.limit} offset={queryObject.offset} pageSize={queryObject.offset + rows.length} title="Draft Orders" currentPage={pageIndex + 1} pageCount={pageCount} nextPage={handleNext} prevPage={handlePrev} hasNext={canNextPage} hasPrev={canPreviousPage} /> </> )} </div> ) }
Example #14
Source File: index.tsx From admin with MIT License | 4 votes |
DiscountTable: React.FC = () => { const { removeTab, setTab, saveTab, availableTabs: filterTabs, activeFilterTab, reset, paginate, setFilters, filters, setQuery: setFreeText, queryObject, representationObject, } = usePromotionFilters(location.search, defaultQueryProps) const offs = parseInt(queryObject?.offset) || 0 const lim = parseInt(queryObject.limit) || DEFAULT_PAGE_SIZE const { discounts, isLoading, count } = useAdminDiscounts({ is_dynamic: false, expand: "rule,rule.conditions,rule.conditions.products", ...queryObject, }) const [query, setQuery] = useState("") const [numPages, setNumPages] = useState(0) useEffect(() => { if (count && queryObject.limit) { const controlledPageCount = Math.ceil(count! / queryObject.limit) if (controlledPageCount !== numPages) { setNumPages(controlledPageCount) } } }, [count, queryObject.limit]) const [columns] = usePromotionTableColumns() const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, canPreviousPage, canNextPage, pageCount, gotoPage, nextPage, previousPage, // Get the state from the instance state: { pageIndex }, } = useTable( { columns, data: discounts || [], manualPagination: true, initialState: { pageSize: lim, pageIndex: offs / lim, }, pageCount: numPages, autoResetPage: false, }, usePagination ) // Debounced search useEffect(() => { const delayDebounceFn = setTimeout(() => { if (query) { setFreeText(query) gotoPage(0) } else { // if we delete query string, we reset the table view reset() } }, 400) return () => clearTimeout(delayDebounceFn) }, [query]) const handleNext = () => { if (canNextPage) { paginate(1) nextPage() } } const handlePrev = () => { if (canPreviousPage) { paginate(-1) previousPage() } } const updateUrlFromFilter = (obj = {}) => { const stringified = qs.stringify(obj) window.history.replaceState(`/a/discounts`, "", `${`?${stringified}`}`) } const refreshWithFilters = () => { const filterObj = representationObject if (isEmpty(filterObj)) { updateUrlFromFilter({ offset: 0, limit: DEFAULT_PAGE_SIZE }) } else { updateUrlFromFilter(filterObj) } } const clearFilters = () => { reset() setQuery("") } useEffect(() => { refreshWithFilters() }, [representationObject]) return ( <div className="w-full overflow-y-auto flex flex-col justify-between min-h-[300px] h-full "> <Table filteringOptions={ <DiscountFilters filters={filters} submitFilters={setFilters} clearFilters={clearFilters} tabs={filterTabs} onTabClick={setTab} activeTab={activeFilterTab} onRemoveTab={removeTab} onSaveTab={saveTab} /> } enableSearch handleSearch={setQuery} searchPlaceholder="Search by code or description..." searchValue={query} {...getTableProps()} className={clsx({ ["relative"]: isLoading })} > <Table.Head> {headerGroups?.map((headerGroup, index) => ( <Table.HeadRow {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map((col, headerIndex) => ( <Table.HeadCell {...col.getHeaderProps()}> {col.render("Header")} </Table.HeadCell> ))} </Table.HeadRow> ))} </Table.Head> {isLoading || !discounts ? ( <div className="flex w-full h-full absolute items-center justify-center mt-10"> <div className=""> <Spinner size={"large"} variant={"secondary"} /> </div> </div> ) : ( <Table.Body {...getTableBodyProps()}> {rows.map((row, rowIndex) => { prepareRow(row) return <PromotionRow row={row} /> })} </Table.Body> )} </Table> <TablePagination count={count!} limit={queryObject.limit} offset={queryObject.offset} pageSize={queryObject.offset + rows.length} title="Discounts" currentPage={pageIndex + 1} pageCount={pageCount} nextPage={handleNext} prevPage={handlePrev} hasNext={canNextPage} hasPrev={canPreviousPage} /> </div> ) }
Example #15
Source File: index.tsx From admin with MIT License | 4 votes |
CustomerTable: React.FC<RouteComponentProps> = () => {
const {
reset,
paginate,
setQuery: setFreeText,
queryObject,
representationObject,
} = useCustomerFilters(location.search, defaultQueryProps)
const offs = parseInt(queryObject.offset) || 0
const lim = parseInt(queryObject.limit) || DEFAULT_PAGE_SIZE
const { customers, isLoading, count } = useAdminCustomers({
...queryObject,
})
const [query, setQuery] = useState(queryObject.query)
const [numPages, setNumPages] = useState(0)
useEffect(() => {
if (typeof count !== "undefined") {
const controlledPageCount = Math.ceil(count / lim)
setNumPages(controlledPageCount)
}
}, [count])
const [columns] = useCustomerColumns()
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
canPreviousPage,
canNextPage,
pageCount,
gotoPage,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex },
} = useTable(
{
columns,
data: customers || [],
manualPagination: true,
initialState: {
pageSize: lim,
pageIndex: offs / lim,
},
pageCount: numPages,
autoResetPage: false,
},
usePagination
)
// Debounced search
useEffect(() => {
const delayDebounceFn = setTimeout(() => {
if (query) {
setFreeText(query)
gotoPage(0)
} else {
if (typeof query !== "undefined") {
// if we delete query string, we reset the table view
reset()
}
}
}, 400)
return () => clearTimeout(delayDebounceFn)
}, [query])
const handleNext = () => {
if (canNextPage) {
paginate(1)
nextPage()
}
}
const handlePrev = () => {
if (canPreviousPage) {
paginate(-1)
previousPage()
}
}
const updateUrlFromFilter = (obj = {}) => {
const stringified = qs.stringify(obj)
window.history.replaceState(`/a/discounts`, "", `${`?${stringified}`}`)
}
const refreshWithFilters = () => {
const filterObj = representationObject
if (isEmpty(filterObj)) {
updateUrlFromFilter({ offset: 0, limit: DEFAULT_PAGE_SIZE })
} else {
updateUrlFromFilter(filterObj)
}
}
useEffect(() => {
refreshWithFilters()
}, [representationObject])
return (
<div className="w-full h-full overflow-y-auto flex flex-col justify-between">
<Table enableSearch handleSearch={setQuery} {...getTableProps()}>
<Table.Head>
{headerGroups?.map((headerGroup) => (
<Table.HeadRow {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((col) => (
<Table.HeadCell className="w-[100px]" {...col.getHeaderProps()}>
{col.render("Header")}
</Table.HeadCell>
))}
</Table.HeadRow>
))}
</Table.Head>
{isLoading || !customers ? (
<div className="flex w-full h-full absolute items-center justify-center mt-10">
<div className="">
<Spinner size={"large"} variant={"secondary"} />
</div>
</div>
) : (
<Table.Body {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row)
return (
<Table.Row
color={"inherit"}
actions={[
{
label: "Edit",
onClick: () => navigate(row.original.id),
icon: <EditIcon size={20} />,
},
{
label: "Details",
onClick: () => navigate(row.original.id),
icon: <DetailsIcon size={20} />,
},
]}
linkTo={row.original.id}
{...row.getRowProps()}
>
{row.cells.map((cell, index) => {
return (
<Table.Cell {...cell.getCellProps()}>
{cell.render("Cell", { index })}
</Table.Cell>
)
})}
</Table.Row>
)
})}
</Table.Body>
)}
</Table>
<TablePagination
count={count!}
limit={queryObject.limit}
offset={queryObject.offset}
pageSize={queryObject.offset + rows.length}
title="Customers"
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</div>
)
}
Example #16
Source File: edit-customers-table.tsx From admin with MIT License | 4 votes |
/*
* Container for the "edit customers" table.
*/
function EditCustomersTable(props: EditCustomersTableProps) {
const {
setSelectedCustomerIds,
selectedCustomerIds,
handleSubmit,
onClose,
} = props
const {
paginate,
setQuery,
setFilters,
filters,
queryObject,
} = useQueryFilters(defaultQueryProps)
const [numPages, setNumPages] = useState(0)
const [activeGroupId, setActiveGroupId] = useState()
const { customer_groups } = useAdminCustomerGroups({ expand: "customers" })
const { customers = [], count = 0 } = useAdminCustomers({
...queryObject,
groups: activeGroupId ? [activeGroupId] : null,
})
useEffect(() => {
if (typeof count !== "undefined") {
const controlledPageCount = Math.ceil(count / queryObject.limit)
setNumPages(controlledPageCount)
}
}, [count])
const tableConfig = {
columns: CUSTOMER_GROUPS_CUSTOMERS_TABLE_COLUMNS,
data: customers,
initialState: {
pageSize: queryObject.limit,
pageIndex: queryObject.offset / queryObject.limit,
selectedRowIds: selectedCustomerIds.reduce((prev, id) => {
prev[id] = true
return prev
}, {}),
},
pageCount: numPages,
autoResetSelectedRows: false,
manualPagination: true,
autoResetPage: false,
getRowId: (row) => row.id,
}
const table = useTable(tableConfig, usePagination, useRowSelect)
useEffect(() => {
setSelectedCustomerIds(Object.keys(table.state.selectedRowIds))
}, [table.state.selectedRowIds])
useEffect(() => {
setFilters("offset", 0)
table.gotoPage(0)
}, [activeGroupId])
const filteringOptions = [
{
title: "Groups",
options: [
{
title: "All",
onClick: () => setActiveGroupId(null),
},
...(customer_groups || []).map((g) => ({
title: g.name,
count: g.customers.length,
onClick: () => setActiveGroupId(g.id),
})),
],
},
]
const handleNext = () => {
if (!table.canNextPage) {
return
}
paginate(1)
table.nextPage()
}
const handlePrev = () => {
if (!table.canPreviousPage) {
return
}
paginate(-1)
table.previousPage()
}
const handleSearch = (text: string) => {
setQuery(text)
if (text) {
table.gotoPage(0)
}
}
return (
<Modal handleClose={onClose}>
<Modal.Body>
<Modal.Header handleClose={onClose}>
<h3 className="inter-xlarge-semibold">Edit Customers</h3>
</Modal.Header>
<Modal.Content>
<div className="w-full flex flex-col justify-between h-[650px]">
<Table
filteringOptions={filteringOptions}
enableSearch
handleSearch={handleSearch}
searchValue={queryObject.q}
{...table.getTableProps()}
>
<Table.Head>
{table.headerGroups?.map((headerGroup) => (
<EditCustomersTableHeaderRow headerGroup={headerGroup} />
))}
</Table.Head>
<Table.Body {...table.getTableBodyProps()}>
{table.rows.map((row) => {
table.prepareRow(row)
return <EditCustomersTableRow row={row} />
})}
</Table.Body>
</Table>
<TablePagination
count={count!}
limit={queryObject.limit}
offset={queryObject.offset}
pageSize={queryObject.offset + table.rows.length}
title="Customers"
currentPage={table.state.pageIndex + 1}
pageCount={table.pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={table.canNextPage}
hasPrev={table.canPreviousPage}
/>
</div>
</Modal.Content>
<Modal.Footer>
<div className="flex items-center justify-end gap-x-xsmall w-full">
<Button
variant="ghost"
size="small"
className="w-eventButton"
onClick={onClose}
>
Cancel
</Button>
<Button
variant="primary"
size="small"
className="w-eventButton"
onClick={handleSubmit}
>
Save
</Button>
</div>
</Modal.Footer>
</Modal.Body>
</Modal>
)
}
Example #17
Source File: customers-list-table.tsx From admin with MIT License | 4 votes |
/*
* Render a list of customers that belong to a customer group.
*/
function CustomersListTable(props: CustomersListTableProps) {
const {
customers,
removeCustomers,
setQuery,
paginate,
filteringOptions,
query,
queryObject,
count,
} = props
const tableConfig = {
data: customers,
columns: CUSTOMER_GROUPS_CUSTOMERS_LIST_TABLE_COLUMNS,
initialState: {
pageSize: queryObject.limit,
pageIndex: queryObject.offset / queryObject.limit,
},
pageCount: Math.ceil(count / queryObject.limit),
manualPagination: true,
autoResetPage: false,
}
const table = useTable(tableConfig, useSortBy, usePagination)
// ********* HANDLERS *********
const handleNext = () => {
if (!table.canNextPage) {
return
}
paginate(1)
table.nextPage()
}
const handlePrev = () => {
if (!table.canPreviousPage) {
return
}
paginate(-1)
table.previousPage()
}
const handleSearch = (text: string) => {
setQuery(text)
if (text) {
table.gotoPage(0)
}
}
return (
<>
<Table
enableSearch
handleSearch={handleSearch}
searchValue={query}
filteringOptions={filteringOptions}
{...table.getTableProps()}
>
<Table.Head>
{table.headerGroups?.map((headerGroup, index) => (
<CustomersListTableHeaderRow
key={index}
headerGroup={headerGroup}
/>
))}
</Table.Head>
<Table.Body {...table.getTableBodyProps()}>
{table.rows.map((row) => {
table.prepareRow(row)
return (
<CustomersListTableRow
row={row}
key={row.id}
removeCustomers={removeCustomers}
/>
)
})}
</Table.Body>
</Table>
<TablePagination
count={count!}
limit={queryObject.limit}
offset={queryObject.offset}
pageSize={queryObject.offset + table.rows.length}
title="Customers"
currentPage={table.state.pageIndex + 1}
pageCount={table.pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={table.canNextPage}
hasPrev={table.canPreviousPage}
/>
</>
)
}
Example #18
Source File: customer-groups-table.tsx From admin with MIT License | 4 votes |
/*
* Root component of the customer groups table.
*/
function CustomerGroupsTable(props: CustomerGroupsTableProps) {
const { customerGroups, queryObject, count, paginate, setQuery } = props
const tableConfig: TableOptions<CustomerGroup> = {
columns: CUSTOMER_GROUPS_TABLE_COLUMNS,
data: customerGroups || [],
initialState: {
pageSize: queryObject.limit,
pageIndex: queryObject.offset / queryObject.limit,
},
pageCount: Math.ceil(count / queryObject.limit),
manualPagination: true,
autoResetPage: false,
}
const table: TableInstance<CustomerGroup> = useTable(
tableConfig,
useSortBy,
usePagination
)
// ********* HANDLERS *********
const handleNext = () => {
if (!table.canNextPage) {
return
}
paginate(1)
table.nextPage()
}
const handlePrev = () => {
if (!table.canPreviousPage) {
return
}
paginate(-1)
table.previousPage()
}
const handleSearch = (text: string) => {
setQuery(text)
if (text) {
table.gotoPage(0)
}
}
// ********* RENDER *********
return (
<div className="w-full h-full overflow-y-auto flex flex-col justify-between">
<Table
enableSearch
handleSearch={handleSearch}
searchValue={queryObject.q}
{...table.getTableProps()}
>
{/* HEAD */}
<Table.Head>
{table.headerGroups?.map((headerGroup, ind) => (
<CustomerGroupsTableHeaderRow key={ind} headerGroup={headerGroup} />
))}
</Table.Head>
{/* BODY */}
<Table.Body {...table.getTableBodyProps()}>
{table.rows.map((row) => {
table.prepareRow(row)
return (
<CustomerGroupContextContainer key={row.id} group={row.original}>
<CustomerGroupsTableRow row={row} />
</CustomerGroupContextContainer>
)
})}
</Table.Body>
</Table>
{/* PAGINATION */}
<TablePagination
count={count}
limit={queryObject.limit}
offset={queryObject.offset}
pageSize={queryObject.offset + table.rows.length}
title="Customers"
currentPage={table.state.pageIndex + 1}
pageCount={table.pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={table.canNextPage}
hasPrev={table.canPreviousPage}
/>
</div>
)
}
Example #19
Source File: view-products-table.tsx From admin with MIT License | 4 votes |
ViewProductsTable: React.FC<ViewProductsTableProps> = ({
collectionId,
refetchCollection,
}) => {
const limit = 10
const [query, setQuery] = useState("")
const [offset, setOffset] = useState(0)
const [numPages, setNumPages] = useState(0)
const [currentPage, setCurrentPage] = useState(0)
const debouncedSearchTerm = useDebounce(query, 500)
const [showDelete, setShowDelete] = useState(false)
const [idToDelete, setIdToDelete] = useState<string | undefined>(undefined)
const { isLoading, count, products, refetch } = useAdminProducts({
q: debouncedSearchTerm,
collection_id: [collectionId],
limit: limit,
offset,
})
useEffect(() => {
refetch() // Ensure we get the latest data
}, [collectionId])
const handleRemoveProduct = () => {
if (idToDelete) {
Medusa.products
.update(idToDelete, {
collection_id: null,
})
.then(() => {
refetch()
refetchCollection()
})
}
}
const columns = useViewProductColumns()
// const [sorted, sortingOptions] = useSortingOptions(products ?? []) TODO: Implement this with server side sorting
const {
rows,
prepareRow,
getTableBodyProps,
getTableProps,
canPreviousPage,
canNextPage,
pageCount,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex, pageSize },
} = useTable(
{
data: products || [],
columns: columns,
manualPagination: true,
initialState: {
pageIndex: currentPage,
pageSize: limit,
},
pageCount: numPages,
getRowId: (row) => row.id,
},
usePagination,
(hooks) => {
hooks.visibleColumns.push((columns) => [
...columns,
{
id: "actions",
Cell: ({ row }) => {
return (
<Table.Cell className="w-[0%] pr-2xsmall">
<Button
variant="ghost"
size="small"
className="text-grey-40"
onClick={() => {
setIdToDelete(row.original.id)
setShowDelete(true)
}}
>
<TrashIcon size={20} />
</Button>
</Table.Cell>
)
},
},
])
}
)
useEffect(() => {
const controlledPageCount = Math.ceil(count! / limit)
setNumPages(controlledPageCount)
}, [products, count, limit])
const handleNext = () => {
if (canNextPage) {
setOffset((old) => old + pageSize)
setCurrentPage((old) => old + 1)
nextPage()
}
}
const handlePrev = () => {
if (canPreviousPage) {
setOffset((old) => old - pageSize)
setCurrentPage((old) => old - 1)
previousPage()
}
}
const handleSearch = (q) => {
setOffset(0)
setQuery(q)
}
return (
<>
<div className="w-full h-full flex flex-col justify-between overflow-y-auto">
<Table
enableSearch
handleSearch={handleSearch}
searchPlaceholder="Search Products"
{...getTableProps()}
className="h-full"
>
{!products?.length ? (
<div className="inter-small-regular text-grey-40 flex flex-grow justify-center items-center">
{isLoading ? (
<Spinner size="large" variant="secondary" />
) : (
"No products yet"
)}
</div>
) : (
<Table.Body {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row)
return (
<Table.Row
color={"inherit"}
{...row.getRowProps()}
className="px-base"
>
{row.cells.map((cell, index) => {
return cell.render("Cell", { index })
})}
</Table.Row>
)
})}
</Table.Body>
)}
</Table>
<TablePagination
count={count!}
limit={limit}
offset={offset}
pageSize={offset + rows.length}
title="Products"
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</div>
{showDelete && (
<DeletePrompt
onDelete={async () => handleRemoveProduct()}
handleClose={() => setShowDelete(!showDelete)}
heading="Remove product from collection"
successText="Product removed from collection"
/>
)}
</>
)
}
Example #20
Source File: index.tsx From admin with MIT License | 4 votes |
CollectionProductTable: React.FC<CollectionProductTableProps> = ({
addedProducts,
setProducts,
}) => {
const [query, setQuery] = useState("")
const [limit, setLimit] = useState(10)
const [offset, setOffset] = useState(0)
const [numPages, setNumPages] = useState(0)
const [currentPage, setCurrentPage] = useState(0)
const [filteringOptions, setFilteringOptions] = useState<
FilteringOptionProps[]
>([])
const [selectedProducts, setSelectedProducts] = useState<any[]>([])
const debouncedSearchTerm = useDebounce(query, 500)
const { isLoading, count, products } = useAdminProducts({
q: debouncedSearchTerm,
limit: limit,
offset,
})
useEffect(() => {
setFilteringOptions([
{
title: "Sort by",
options: [
{
title: "All",
onClick: () => {},
},
{
title: "Newest",
onClick: () => {},
},
{
title: "Oldest",
onClick: () => {},
},
],
},
])
}, [products])
const columns = useCollectionProductColumns() as readonly Column<any[]>[]
const {
rows,
prepareRow,
getTableBodyProps,
getTableProps,
canPreviousPage,
canNextPage,
pageCount,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex, pageSize, selectedRowIds },
} = useTable(
{
data: products || [],
columns: columns,
manualPagination: true,
initialState: {
pageIndex: currentPage,
pageSize: limit,
selectedRowIds: addedProducts?.reduce((prev, { id }) => {
prev[id] = true
return prev
}, {}),
},
pageCount: numPages,
autoResetSelectedRows: false,
autoResetPage: false,
getRowId: (row) => row.id,
},
usePagination,
useRowSelect,
(hooks) => {
hooks.visibleColumns.push((columns) => [
{
id: "selection",
Cell: ({ row }) => {
return (
<Table.Cell className="w-[5%] pl-base">
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</Table.Cell>
)
},
},
...columns,
])
}
)
useEffect(() => {
setSelectedProducts((selectedProducts) => [
...selectedProducts.filter(
(sv) => Object.keys(selectedRowIds).findIndex((id) => id === sv.id) > -1
),
...(products?.filter(
(p) =>
selectedProducts.findIndex((sv) => sv.id === p.id) < 0 &&
Object.keys(selectedRowIds).findIndex((id) => id === p.id) > -1
) || []),
])
}, [selectedRowIds])
const handleNext = () => {
if (canNextPage) {
setOffset((old) => old + pageSize)
setCurrentPage((old) => old + 1)
nextPage()
}
}
const handlePrev = () => {
if (canPreviousPage) {
setOffset((old) => old - pageSize)
setCurrentPage((old) => old - 1)
previousPage()
}
}
const handleSearch = (q) => {
setOffset(0)
setQuery(q)
}
useEffect(() => {
console.log("products", selectedProducts)
}, [selectedProducts])
return (
<div className="w-full h-full flex flex-col justify-between overflow-y-auto">
<Table
enableSearch
handleSearch={handleSearch}
searchPlaceholder="Search Products"
filteringOptions={filteringOptions}
{...getTableProps()}
className="h-full"
>
{isLoading || !products ? null : (
<Table.Body {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row)
return (
<Table.Row
color={"inherit"}
{...row.getRowProps()}
className="px-base"
>
{row.cells.map((cell, index) => {
return cell.render("Cell", { index })
})}
</Table.Row>
)
})}
</Table.Body>
)}
</Table>
<TablePagination
count={count!}
limit={limit}
offset={offset}
pageSize={offset + rows.length}
title="Products"
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</div>
)
}
Example #21
Source File: add-product-table.tsx From admin with MIT License | 4 votes |
AddProductsTable: React.FC<AddProductsTableProps> = ({
existingRelations,
onSubmit,
onClose,
}) => {
const PAGE_SIZE = 10
const [query, setQuery] = useState("")
const [offset, setOffset] = useState(0)
const [numPages, setNumPages] = useState(0)
const [currentPage, setCurrentPage] = useState(0)
const [selectedProducts, setSelectedProducts] = useState<any[]>([])
const [removedProducts, setRemovedProducts] = useState<any[]>([])
const debouncedSearchTerm = useDebounce(query, 500)
const { isLoading, count, products } = useAdminProducts({
q: debouncedSearchTerm,
limit: PAGE_SIZE,
offset,
})
const columns = useCollectionProductColumns()
const {
rows,
prepareRow,
getTableBodyProps,
getTableProps,
canPreviousPage,
canNextPage,
pageCount,
nextPage,
previousPage,
state: { pageIndex, pageSize, selectedRowIds },
} = useTable(
{
data: products || [],
columns: columns,
manualPagination: true,
initialState: {
pageIndex: currentPage,
pageSize: PAGE_SIZE,
selectedRowIds: existingRelations.reduce((prev, { id }) => {
prev[id] = true
return prev
}, {}),
},
pageCount: numPages,
autoResetSelectedRows: false,
autoResetPage: false,
getRowId: (row) => row.id,
},
usePagination,
useRowSelect,
(hooks) => {
hooks.visibleColumns.push((columns) => [
{
id: "selection",
Cell: ({ row }) => {
return (
<Table.Cell className="w-[5%] pl-base">
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</Table.Cell>
)
},
},
...columns,
])
}
)
useEffect(() => {
setSelectedProducts((selectedProducts) =>
[
...selectedProducts.filter(
(sv) =>
Object.keys(selectedRowIds).findIndex((id) => id === sv.id) > -1
),
...(products?.filter(
(p) =>
selectedProducts.findIndex((sv) => sv.id === p.id) < 0 &&
Object.keys(selectedRowIds).findIndex((id) => id === p.id) > -1
) || []),
].filter((p) => existingRelations.findIndex((ap) => ap.id === p.id) < 0)
)
setRemovedProducts([
...existingRelations.filter(
(ap) => Object.keys(selectedRowIds).findIndex((id) => id === ap.id) < 0
),
])
}, [selectedRowIds])
useEffect(() => {
const controlledPageCount = Math.ceil(count! / PAGE_SIZE)
setNumPages(controlledPageCount)
}, [products, count, PAGE_SIZE])
const handleNext = () => {
if (canNextPage) {
setOffset((old) => old + pageSize)
setCurrentPage((old) => old + 1)
nextPage()
}
}
const handlePrev = () => {
if (canPreviousPage) {
setOffset((old) => old - pageSize)
setCurrentPage((old) => old - 1)
previousPage()
}
}
const handleSearch = (q) => {
setOffset(0)
setQuery(q)
}
const [disabled, setDisabled] = useState(true)
useEffect(() => {
if (selectedProducts.length > 0 || removedProducts.length > 0) {
setDisabled(false)
return
}
setDisabled(true)
}, [selectedProducts, removedProducts])
const handleSubmit = () => {
onSubmit(
selectedProducts.map((p) => p.id),
removedProducts.map((p) => p.id)
)
}
return (
<Modal handleClose={onClose}>
<Modal.Body>
<Modal.Header handleClose={onClose}>
<h3 className="inter-xlarge-semibold">Add Products</h3>
</Modal.Header>
<Modal.Content>
<div className="w-full flex flex-col justify-between h-[650px]">
<Table
enableSearch
handleSearch={handleSearch}
searchPlaceholder="Search Products"
{...getTableProps()}
className="flex-grow"
>
{isLoading || !products ? (
<div className="inter-small-regular text-grey-40 flex flex-grow justify-center items-center">
<Spinner size="large" variant="secondary" />
</div>
) : (
<Table.Body {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row)
return (
<Table.Row
color={"inherit"}
{...row.getRowProps()}
className="px-base"
>
{row.cells.map((cell, index) => {
return cell.render("Cell", { index })
})}
</Table.Row>
)
})}
</Table.Body>
)}
</Table>
<TablePagination
count={count!}
limit={PAGE_SIZE}
offset={offset}
pageSize={offset + rows.length}
title="Products"
currentPage={pageIndex + 1}
pageCount={pageCount}
nextPage={handleNext}
prevPage={handlePrev}
hasNext={canNextPage}
hasPrev={canPreviousPage}
/>
</div>
</Modal.Content>
<Modal.Footer>
<div className="flex items-center justify-end gap-x-xsmall w-full">
<Button
variant="ghost"
size="small"
className="w-eventButton"
onClick={onClose}
>
Cancel
</Button>
<Button
variant="primary"
size="small"
className="w-eventButton"
onClick={handleSubmit}
disabled={disabled}
>
Save
</Button>
</div>
</Modal.Footer>
</Modal.Body>
</Modal>
)
}
Example #22
Source File: index.tsx From livepeer-com with MIT License | 4 votes |
Table = <T extends Record<string, unknown>>({ columns, data, header, pageSize = 100, rowSelection, onRowSelectionChange, initialSortBy, filters, showOverflow, }: Props<T>) => { const someColumnCanSort = useMemo(() => { // To see if we show the sort help tooltip or not // @ts-ignore return columns.some((column) => !column.disableSortBy); }, [columns]); const getRowId = useCallback((row, relativeIndex, parent) => { return row?.id ? row.id : relativeIndex; }, []); const { getTableProps, getTableBodyProps, prepareRow, headerGroups, // @ts-ignore page, // @ts-ignore nextPage, // @ts-ignore previousPage, // @ts-ignore canPreviousPage, // @ts-ignore canNextPage, // @ts-ignore toggleAllRowsSelected, // @ts-ignore selectedFlatRows, // @ts-ignore setFilter, // @ts-ignore state: { filters: currentFilters }, } = useTable( { // @ts-ignore columns, data, getRowId, initialState: { // @ts-ignore pageSize, pageIndex: 0, ...(initialSortBy ? { sortBy: initialSortBy } : undefined), }, manualSortBy: false, autoResetFilters: false, autoResetSortBy: false, autoResetPage: false, autoResetSelectedRows: false, }, useFilters, useSortBy, usePagination, useRowSelect, (hooks) => { if (rowSelection) { const isIndividualSelection = rowSelection === "individual"; hooks.visibleColumns.push((columns) => [ // Let's make a column for selection { id: "selection", // The header can use the table's getToggleAllRowsSelectedProps method // to render a checkbox // @ts-ignore Header: ({ getToggleAllPageRowsSelectedProps }) => { const props = getToggleAllPageRowsSelectedProps(); return isIndividualSelection ? null : ( <Checkbox onClick={props.onChange} value={props.checked} /> ); }, // The cell can use the individual row's getToggleRowSelectedProps method // to the render a checkbox Cell: ({ row }) => { return ( <Checkbox // @ts-ignore value={row.isSelected} onClick={() => { isIndividualSelection && toggleAllRowsSelected(false); // @ts-ignore row.toggleRowSelected(!row.isSelected); }} /> ); }, }, ...columns, ]); } } ); useEffect(() => { onRowSelectionChange?.(selectedFlatRows); }, [selectedFlatRows, onRowSelectionChange]); return ( <div> {header || filters ? ( <Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mb: 3, }}> <div>{header}</div> {filters ? ( <Box sx={{ flex: "1", display: "flex", alignItems: "center", justifyContent: "flex-end", }}> {filters.map((f) => { let filter: JSX.Element; switch (f.type) { case "text": filter = ( <TextFilter {...f.props} setFilter={setFilter} currentFilters={currentFilters} /> ); break; case "checkbox": filter = ( <CheckboxFilter {...f.props} setFilter={setFilter} currentFilters={currentFilters} /> ); break; default: return null; } return ( <Box key={`${f.type}-${f.props.columnId}`} sx={{ ":not(:last-of-type)": { mr: 3 } }}> {filter} </Box> ); })} </Box> ) : null} </Box> ) : null} <Box sx={{ overflow: showOverflow ? "visible" : "hidden" }}> <Box sx={{ overflowX: showOverflow ? "visible" : "auto" }}> <Box as="table" {...getTableProps()} sx={{ minWidth: "100%", borderCollapse: "separate", borderSpacing: 0, }}> <thead> {headerGroups.map((headerGroup) => ( <Box as="tr" {...headerGroup.getHeaderGroupProps()} sx={{ borderRadius: "8px" }}> {headerGroup.headers.map((column, i) => { const withHelpTooltip = someColumnCanSort && i === headerGroup.headers.length - 1; return ( <Box as="th" scope="col" {...column.getHeaderProps( // @ts-ignore column.getSortByToggleProps() )} sx={{ textTransform: "uppercase", bg: "rgba(0,0,0,.03)", border: 0, borderBottom: "1px solid", borderTop: "1px solid", borderColor: "muted", fontSize: 0, color: "gray", px: 4, py: 2, fontWeight: 400, position: "relative", "&:first-of-type": { borderLeft: "1px solid", borderColor: "muted", borderTopLeftRadius: 6, borderBottomLeftRadius: 6, }, "&:last-of-type": { borderRight: "1px solid", borderColor: "muted", borderTopRightRadius: 6, borderBottomRightRadius: 6, }, }}> <Box sx={{ display: "flex", alignItems: "center", mr: withHelpTooltip ? 3 : 0, }}> <Box as="span" sx={{ whiteSpace: "nowrap" }}> {column.render("Header")} </Box> {/*@ts-ignore */} {column.canSort && ( <Box as="span" sx={{ ml: 2 }}> {/* @ts-ignore */} {column.isSorted ? // @ts-ignore column.isSortedDesc ? " ⭣" : " ⭡" : " ⭥"} </Box> )} </Box> {withHelpTooltip && ( <Box sx={{ alignItems: "center", display: "flex", position: "absolute", right: 3, top: "50%", transform: "translateY(-50%)", }}> <ReactTooltip id={`tooltip-multiorder`} className="tooltip" place="top" type="dark" effect="solid"> To multi-sort (sort by two column simultaneously) hold shift while clicking on second column name. </ReactTooltip> <Help data-tip data-for={`tooltip-multiorder`} sx={{ cursor: "pointer", ml: 1, }} /> </Box> )} </Box> ); })} </Box> ))} </thead> <tbody {...getTableBodyProps()}> {page.map((row: Row<object>) => { prepareRow(row); return ( <tr {...row.getRowProps()}> {row.cells.map((cell) => ( <Box as="td" {...cell.getCellProps()} sx={{ px: 4, py: 3, border: 0, borderBottom: "1px solid", borderBottomColor: "muted", bg: "background", fontSize: 1, }}> {cell.render("Cell")} </Box> ))} </tr> ); })} </tbody> </Box> </Box> <Paginator canPreviousPage={canPreviousPage} canNextPage={canNextPage} onPreviousPage={previousPage} onNextPage={nextPage} /> </Box> </div> ); }
Example #23
Source File: Table.tsx From opensaas with MIT License | 4 votes |
Table: React.FC<TableProps> = <T extends object>(props: TableProps<T>) => { const { expandable, selection, pagination, sortBy, pageCount, data, selectedRowIds, pageSize, rowKey, loading, isMultiSort, renderExpandedComponent, onPageChange, filters: propsFilters, onSortChange: propsOnSortChange, onRowSelected: propsOnRowSelected, onFilterChange: propsOnFilterChange, columns: propsColumns, } = props; const classes = useStyles(); const tableRef = useRef<HTMLTableElement>(null); const hasSortBy = props.hasOwnProperty('sortBy'); const hasFilters = props.hasOwnProperty('filters'); const hasPagination = props.hasOwnProperty('pagination'); const hasOnPageChange = props.hasOwnProperty('onPageChange'); const hasSelectedRowIds = props.hasOwnProperty('selectedRowIds'); const onRowSelected = useCallback( (row: UseRowSelectRowProps<T> & Row<T> & UseTableRowProps<T>, value: boolean) => { const id = (row.original as any)[rowKey]; if (hasSelectedRowIds) { const newSelectedRows: any = { ...selectedRowIds }; if (value) { newSelectedRows[id] = true; } else { delete newSelectedRows[id]; } propsOnRowSelected?.(newSelectedRows); } else { row.toggleRowSelected(value); } }, [hasSelectedRowIds, rowKey, selectedRowIds, propsOnRowSelected], ); const columns = useMemo(() => { const columns = propsColumns.map( ({ sortable, Filter, Header, ...rest }) => ({ ...rest, disableSortBy: !sortable, disableFilters: !Filter, Filter, Header: Header ?? <div style={{ minWidth: rest.minWidth, maxWidth: rest.maxWidth }} />, } as TableColumnOptions<T>), ); if (expandable) { columns.unshift({ id: 'expander', minWidth: 60, maxWidth: '60px' as any, Cell: (cell: UseTableCellProps<T>) => { const row = cell.row as Row<T> & UseExpandedRowProps<T>; return ( <IconButton className={classes.expandIcon} {...row.getToggleRowExpandedProps()}> {row.isExpanded ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} </IconButton> ); }, }); } if (selection) { columns.unshift({ id: 'selection', minWidth: 60, maxWidth: '60px' as any, Cell: (cell: UseTableCellProps<T>) => { const row = cell.row as UseRowSelectRowProps<T> & Row<T> & UseTableRowProps<T>; return ( <Checkbox className={classes.checkBox} {...row.getToggleRowSelectedProps()} checked={row.isSelected} onChange={(e) => onRowSelected(row, e.target.checked)} /> ); }, }); } return columns as Column<T>[]; }, [propsColumns, expandable, classes, selection, onRowSelected]); const tableHooks: PluginHook<T>[] = [useFilters, useSortBy]; if (expandable) { tableHooks.push(useExpanded); } if (pagination) { tableHooks.push(usePagination); } if (selection) { tableHooks.push(useRowSelect); } tableHooks.push(useFlexLayout); const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, state, page, pageOptions, gotoPage, nextPage, previousPage, toggleAllRowsSelected, isAllRowsSelected, selectedFlatRows, } = useTable( { columns, data, getRowId: (row: any) => row[rowKey], manualSortBy: !!propsOnSortChange, manualFilters: !!propsOnFilterChange, manualPagination: !!onPageChange, manualRowSelectedKey: rowKey, pageCount: pageCount ?? 0, useControlledState: (state1: any) => ({ ...state1, sortBy: sortBy ?? state1.sortBy, filters: propsFilters ?? state1.filters, selectedRowIds: selectedRowIds ?? state1.selectedRowIds, } as TableState<T> & UseFiltersState<T> & UseSortByState<T> & UseRowSelectState<T>), expandSubRows: false, initialState: { pageIndex: 0, pageSize: pageSize ?? 0, selectedRowIds: selectedRowIds || {}, }, } as UseTableOptions<T> & UseFiltersOptions<T> & UseSortByOptions<T> & UseExpandedOptions<T> & UseRowSelectOptions<T> & UsePaginationOptions<T>, ...tableHooks, ) as TableInstance<T> & UseTableInstanceProps<T> & UsePaginationInstanceProps<T> & UseRowSelectInstanceProps<T>; if (expandable && !renderExpandedComponent) { throw Error('Table: you must provide renderExpandedComponent property if the table is expandable'); } if (hasSortBy && !propsOnSortChange) { throw Error('Table: you must provide onSortChange property if sortBy is controlled'); } if (hasFilters && !propsOnFilterChange) { throw Error('Table: you must provide onFilterChange property if filters is controlled'); } if (hasPagination && !pageSize) { throw Error('Table: you must provide pageSize property if pagination enabled'); } if (hasOnPageChange && !pageCount) { throw Error('Table: you must provide pageCount property if onPageChange is controlled'); } const tableState = state as UseSortByState<T> & UseFiltersState<T> & UsePaginationState<T> & UseRowSelectState<T>; const onSortChange = useCallback( (column: TableColumnProps<T>) => { if (hasSortBy) { const sortBy = isMultiSort ? tableState.sortBy.filter(({ id }) => id !== column.id) : []; if (!column.isSorted) { sortBy.push({ id: column.id, desc: false }); } else if (!column.isSortedDesc) { sortBy.push({ id: column.id, desc: true }); } propsOnSortChange?.(sortBy); } else { if (column.isSorted && column.isSortedDesc) { column.clearSortBy(); } else { column.toggleSortBy(column.isSorted, isMultiSort ?? false); } } }, [hasSortBy, isMultiSort, tableState.sortBy, propsOnSortChange], ); const onFilterChange = useCallback( (column: TableColumnProps<T>, filterValue?: any) => { if (hasFilters) { const filters = tableState.filters.filter(({ id }) => id !== column.id); if (filterValue != null) { filters.push({ id: column.id, value: filterValue }); } propsOnFilterChange?.(filters); } else { column.setFilter(filterValue); } }, [propsOnFilterChange, hasFilters, tableState.filters], ); const onToggleAllRowsSelected = useCallback( (value: boolean) => { if (hasSelectedRowIds) { const selectedIds = data.reduce((p, n: any) => ({ ...p, [n[rowKey]]: true }), {}); propsOnRowSelected?.(value ? selectedIds : {}); } else { toggleAllRowsSelected(value); } }, [hasSelectedRowIds, data, rowKey, propsOnRowSelected, toggleAllRowsSelected], ); useEffect(() => { if (!hasSortBy) propsOnSortChange?.(tableState.sortBy); }, [hasSortBy, propsOnSortChange, tableState.sortBy]); useEffect(() => { if (!hasFilters) propsOnFilterChange?.(tableState.filters); }, [hasFilters, propsOnFilterChange, tableState.filters]); useEffect(() => { tableRef.current?.querySelector('.table-tbody')?.scroll?.({ top: 0, left: 0, behavior: 'smooth' }); onPageChange?.(tableState.pageSize, tableState.pageIndex); }, [onPageChange, tableState.pageSize, tableState.pageIndex]); useEffect(() => { if (!hasSelectedRowIds) propsOnRowSelected?.(tableState.selectedRowIds as any); }, [hasSelectedRowIds, propsOnRowSelected, tableState.selectedRowIds]); const onPageChangeHandler = (page: number) => { if (page > tableState.pageIndex) { nextPage(); } else { previousPage(); } }; return ( <Paper className={classes.paper}> <MaterialUITable className={classes.table} ref={tableRef} {...getTableProps()}> <TableHead headerGroups={headerGroups} onSortChange={onSortChange} onFilterChange={onFilterChange} toggleAllRowsSelected={onToggleAllRowsSelected} isAllRowsSelected={isAllRowsSelected} selectedFlatRows={selectedFlatRows} /> <TableBody getTableBodyProps={getTableBodyProps} prepareRow={prepareRow} loading={loading} rows={(pagination ? page : rows) as (Row<T> & UseExpandedRowProps<T>)[]} renderExpandedComponent={renderExpandedComponent} /> </MaterialUITable> {pagination === 'pages' && ( <TablePagination className={classes.footer} rowsPerPageOptions={[]} component='div' count={rows.length} rowsPerPage={tableState.pageSize} page={tableState.pageIndex} onChangePage={(e, page) => onPageChangeHandler(page)} ActionsComponent={(props) => ( <TablePaginationActions {...props} gotoPage={gotoPage} pageOptions={pageOptions} /> )} /> )} </Paper> ); }
Example #24
Source File: Table.tsx From frontegg-react with MIT License | 4 votes |
Table: FC<TableProps> = <T extends object>(props: TableProps<T>) => { const classes = useStyles(); const tableRef = useRef<HTMLTableElement>(null); const firstRender = useRef<boolean>(true); const columns = useMemo(() => { const columns = props.columns.map( ({ sortable, Filter, Header, ...rest }) => ({ ...rest, disableSortBy: !sortable, disableFilters: !Filter, Filter, Header: Header ?? <div style={{ minWidth: rest.minWidth, maxWidth: rest.maxWidth }} />, } as FeTableColumnOptions<T>) ); if (props.expandable) { columns.unshift({ id: 'fe-expander', minWidth: 60, maxWidth: '60px' as any, Header: <div style={{ minWidth: '1.5rem', maxWidth: '1.5rem' }} />, Cell: (cell: Cell<T>) => { const row = cell.row as Row<T> & UseExpandedRowProps<T>; return ( <IconButton className={classes.expandIcon} {...row.getToggleRowExpandedProps()}> {row.isExpanded ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} </IconButton> ); }, }); } if (props.selection) { columns.unshift({ id: 'fe-selection', minWidth: 60, maxWidth: '60px' as any, Cell: (cell: Cell<T>) => { const row = cell.row as Row<T> & UseRowSelectRowProps<T>; return ( <Checkbox className={classes.checkBox} {...row.getToggleRowSelectedProps()} checked={row.isSelected} onChange={(e) => onRowSelected(row.original, e.target.checked)} /> ); }, }); } return columns as Column<T>[]; }, [props.columns, props.expandable]); const tableHooks: PluginHook<T>[] = [useFilters, useSortBy]; if (props.expandable) { tableHooks.push(useExpanded); } if (props.pagination) { tableHooks.push(usePagination); } if (props.selection) { tableHooks.push(useRowSelect); } tableHooks.push(useFlexLayout); const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, state, // The page controls ;) page, // canPreviousPage, // canNextPage, pageOptions, pageCount, gotoPage, nextPage, previousPage, // setPageSize, // select props toggleAllRowsSelected, isAllRowsSelected, selectedFlatRows, toggleRowSelected, } = useTable( { columns, data: props.data, getRowId: (row: any) => row[props.rowKey], manualSortBy: !!props.onSortChange, manualFilters: !!props.onFilterChange, manualPagination: !!props.onPageChange, manualRowSelectedKey: props.rowKey, pageCount: !!props.onPageChange ? props.pageCount : undefined, autoResetPage: !props.onPageChange, useControlledState: (state1: any) => { return { ...state1, sortBy: props.sortBy ?? state1.sortBy, filters: props.filters ?? state1.filters, selectedRowIds: props.selectedRowIds ?? state1.selectedRowIds, } as TableState<T> & UseFiltersState<T> & UseSortByState<T> & UseRowSelectState<T>; }, expandSubRows: false, initialState: { pageIndex: 0, pageSize: props.pageSize ?? 0, selectedRowIds: props.selectedRowIds || {}, }, } as UseTableOptions<T> & UseFiltersOptions<T> & UseSortByOptions<T> & UseExpandedOptions<T> & UseRowSelectOptions<T> & UsePaginationOptions<T>, ...tableHooks ) as TableInstance<T> & UseTableInstanceProps<T> & UsePaginationInstanceProps<T> & UseRowSelectInstanceProps<T>; if (props.expandable && !props.renderExpandedComponent) { throw Error('FeTable: you must provide renderExpandedComponent property if the table is expandable'); } if (props.hasOwnProperty('sortBy') && !props.onSortChange) { throw Error('FeTable: you must provide onSortChange property if sortBy is controlled'); } if (props.hasOwnProperty('filters') && !props.onFilterChange) { throw Error('FeTable: you must provide onFilterChange property if filters is controlled'); } if (props.hasOwnProperty('pagination') && !props.pageSize) { throw Error('FeTable: you must provide pageSize property if pagination enabled'); } if (props.hasOwnProperty('onPageChange') && !props.pageCount) { throw Error('FeTable: you must provide pageCount property if onPageChange is controlled'); } const tableState = state as UseSortByState<T> & UseFiltersState<T> & UsePaginationState<T> & UseRowSelectState<T>; const onSortChange = useCallback( (column: FeTableColumnProps<T>) => { if (props.hasOwnProperty('sortBy')) { const sortBy = props.isMultiSort ? tableState.sortBy.filter(({ id }) => id !== column.id) : []; if (!column.isSorted) { sortBy.push({ id: column.id, desc: false }); } else if (!column.isSortedDesc) { sortBy.push({ id: column.id, desc: true }); } props.onSortChange?.(sortBy); } else { if (column.isSorted && column.isSortedDesc) { column.clearSortBy(); } else { column.toggleSortBy(column.isSorted, props.isMultiSort ?? false); } } }, [props.onSortChange] ); const onFilterChange = useCallback( (column: FeTableColumnProps<T>, filterValue?: any) => { if (props.hasOwnProperty('filters')) { const filters = tableState.filters.filter(({ id }) => id !== column.id); if (filterValue != null) { filters.push({ id: column.id, value: filterValue }); } props.onFilterChange?.(filters); } else { column.setFilter(filterValue); } }, [props.onFilterChange, tableState] ); const onToggleAllRowsSelected = useCallback( (value: boolean) => { if (props.hasOwnProperty('selectedRowIds')) { const selectedIds = props.data.reduce((p, n: any) => ({ ...p, [n[props.rowKey]]: true }), {}); props.onRowSelected?.(value ? selectedIds : {}); } else { toggleAllRowsSelected(value); } }, [props.onRowSelected] ); const onRowSelected = useCallback( (row: any, value: boolean) => { const id = row[props.rowKey]; if (props.hasOwnProperty('selectedRowIds')) { const newSelectedRows: any = { ...props.selectedRowIds }; if (value) { newSelectedRows[id] = true; } else { delete newSelectedRows[id]; } props.onRowSelected?.(newSelectedRows); } else { toggleRowSelected(id, value); } }, [props.onRowSelected] ); const handleOnPageChange = useCallback(() => { if (pagination === 'pages') { tableRef.current?.scroll?.({ top: 0, left: 0, behavior: 'smooth' }); } props.onPageChange?.(tableState.pageSize, tableState.pageIndex); }, [tableState.pageIndex]); useEffect(() => { !props.hasOwnProperty('sortBy') && props.onSortChange?.(tableState.sortBy); }, [props.sortBy, tableState.sortBy]); useEffect(() => { !props.hasOwnProperty('filters') && props.onFilterChange?.(tableState.filters); }, [props.filters, tableState.filters]); useEffect(() => { firstRender.current ? (firstRender.current = false) : handleOnPageChange(); }, [tableState.pageIndex]); useEffect(() => { !props.hasOwnProperty('selectedRowIds') && props.onRowSelected?.(tableState.selectedRowIds as any); }, [tableState.selectedRowIds]); const onPageChangeHandler = (page: number) => { if (page > tableState.pageIndex) { nextPage(); } else { previousPage(); } }; const { className, loading, pagination, totalData, pageSize } = props; return ( <Paper ref={tableRef} className={classes.paper}> <MaUTable className={classNames(classes.table, className)} {...getTableProps()}> <TableHead headerGroups={headerGroups} onSortChange={onSortChange} onFilterChange={onFilterChange} toggleAllRowsSelected={onToggleAllRowsSelected} isAllRowsSelected={isAllRowsSelected} selectedFlatRows={selectedFlatRows} /> <TableBody pageSize={pageSize} pagination={pagination} getTableBodyProps={getTableBodyProps} prepareRow={prepareRow} loading={loading} rows={(pagination ? page : rows) as (Row<T> & UseExpandedRowProps<T>)[]} renderExpandedComponent={props.renderExpandedComponent} onInfiniteScroll={handleOnPageChange} /> </MaUTable> {loading && pagination === 'pages' && rows.length > 0 && <Loader center size={24} />} {pagination === 'pages' && ( <TablePagination className={classes.footer} rowsPerPageOptions={[]} component='div' count={totalData || rows.length} rowsPerPage={tableState.pageSize} page={tableState.pageIndex} onChangePage={(e, page) => onPageChangeHandler(page)} ActionsComponent={(props) => ( <TablePaginationActions {...props} gotoPage={gotoPage} pageOptions={pageOptions} /> )} /> )} </Paper> ); }
Example #25
Source File: index.tsx From platform with MIT License | 4 votes |
function Table({ columns, data, searchPlaceholder = "games...", colour = "bg-teal-700" }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state,
preGlobalFilteredRows,
setGlobalFilter,
} = useTable(
{
columns,
data,
initialState: {
hiddenColumns: [
"id",
"whiteMemberId",
"blackMemberId",
"liChessUrl",
"chesscomUrl",
"eventId",
"formArray",
"bulletDiff",
"blitzDiff",
"rapidDiff",
"isOnline",
"standardChange",
"rapidChange"
]
}
},
useFilters,
useGlobalFilter,
useSortBy,
usePagination
);
return (
<>
<div className="sm:gap-x-2">
<GlobalFilter
preGlobalFilteredRows={preGlobalFilteredRows}
globalFilter={state.globalFilter}
setGlobalFilter={setGlobalFilter}
searchPlaceholder={searchPlaceholder}
/>
{headerGroups.map((headerGroup) =>
headerGroup.headers.map((column) =>
column.Filter ? (
<div className="mt-0" key={column.id}>
{column.render("Filter")}
</div>
) : null
)
)}
</div>
{/* table */}
<div className="relative mt-4 sm:flex sm:flex-col">
<div className="overflow-auto w-full shadow border-b border-gray-200 rounded-lg">
<table
{...getTableProps()}
className="w-full table-auto divide-y divide-gray-200"
>
<thead className="">
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
scope="col"
className={classNames(colour, "group px-2 py-3 text-center text-xs font-medium text-gray-100 uppercase")}
{...column.getHeaderProps(column.getSortByToggleProps())}
>
<div className=" flex items-center text-center justify-between">
{column.render("Header")}
{/* Add a sort direction indicator */}
<span>
{column.isSorted ? (
column.isSortedDesc ? (
<SortDownIcon className="w-4 h-4 text-gray-200" />
) : (
<SortUpIcon className="w-4 h-4 text-gray-200" />
)
) : (
<SortIcon className="w-4 h-4 text-gray-400 opacity-0 group-hover:opacity-100" />
)}
</span>
</div>
</th>
))}
</tr>
))}
</thead>
<tbody
{...getTableBodyProps()}
className="bg-white divide-y divide-gray-200"
>
{page.map((row, i) => {
// new
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => {
return (
<td
{...cell.getCellProps()}
className="py-4 px-2 whitespace-nowrap"
role="cell"
>
{cell.column.Cell.name === "defaultRenderer" ? (
<div className="text-sm text-gray-500">
{cell.render("Cell")}
</div>
) : (
cell.render("Cell")
)}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</div>
</div>
{/* Pagination */}
<div className="py-3 flex items-center justify-between">
<div className="flex-1 flex items-center justify-between">
<div className="flex gap-x-2 items-baseline">
<span className="text-xs text-gray-700">
Page <span className="font-medium">{state.pageIndex + 1}</span> of{" "}
<span className="font-medium">{pageOptions.length}</span>
</span>
<label>
<span className="sr-only">Items Per Page</span>
<select
className="mt-1 block w-full text-xs rounded-md border-gray-300 shadow-sm focus:border-teal-300 focus:ring focus:ring-teal-500 focus:ring-opacity-50"
value={state.pageSize}
onChange={(e) => {
setPageSize(Number(e.target.value));
}}
>
{[5, 10, 20].map((pageSize) => (
<option
className="hover:bg-teal-200"
key={pageSize}
value={pageSize}
>
Show {pageSize}
</option>
))}
</select>
</label>
</div>
<div>
<nav
className="relative mt-1 sm:mt-0 z-0 inline-flex rounded-md shadow-sm -space-x-px"
aria-label="Pagination"
>
<PageButton
className="rounded-l-md -mr-1 hidden sm:block"
onClick={() => gotoPage(0)}
disabled={!canPreviousPage}
>
<span className="sr-only">First</span>
<ChevronDoubleLeftIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</PageButton>
<PageButton
className="rounded-l-md sm:rounded-none"
onClick={() => previousPage()}
disabled={!canPreviousPage}
>
<span className="sr-only">Previous</span>
<ChevronLeftIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</PageButton>
<PageButton
className="rounded-r-md sm:rounded-none"
onClick={() => nextPage()}
disabled={!canNextPage}
>
<span className="sr-only">Next</span>
<ChevronRightIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</PageButton>
<PageButton
className="rounded-r-md hidden sm:block"
onClick={() => gotoPage(pageCount - 1)}
disabled={!canNextPage}
>
<span className="sr-only">Last</span>
<ChevronDoubleRightIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</PageButton>
</nav>
</div>
</div>
</div>
</>
);
}
Example #26
Source File: index.tsx From ke with MIT License | 4 votes |
Table = ({
resourceName,
listFilters,
listFilterTemplates,
columns,
data,
pageCount: controlledPageCount,
setBackendPage,
user,
analytics,
filterable = false,
provider,
}: TableProps): JSX.Element => {
const {
getTableProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
gotoPage,
nextPage,
previousPage,
pageCount,
state: { pageIndex },
} = useTable(
{
columns,
data,
manualPagination: true,
initialState: { pageIndex: 0 },
pageCount: controlledPageCount,
autoResetPage: false,
stateReducer: (newState: TableState, action: ActionType) => {
if (action.type === 'gotoPage' && setBackendPage) {
const newPageIndex = newState.pageIndex
setBackendPage(newPageIndex + 1)
}
return newState
},
},
useFilters,
usePagination
)
return (
<Flex flexDirection="row" width="100%" flex={1} bg="gray.50" p={4}>
<Flex
flexDirection="column"
flex={1}
maxWidth="100%"
bg="white"
width="auto"
rounded="md"
borderWidth="1px"
onClick={() => false}
>
{filterable && listFilters && (
<FilterBlock
listFilters={listFilters}
listFilterTemplates={listFilterTemplates}
user={user}
analytics={analytics}
resourceName={resourceName}
provider={provider}
gotoPage={gotoPage}
/>
)}
<StyledTable {...getTableProps()}>
<TableHead>{mountHeader(headerGroups)}</TableHead>
<Flex flexDirection="column">{mountRows(page, prepareRow)}</Flex>
</StyledTable>
<Bottom
analytics={analytics}
resourceName={resourceName}
pageIndex={pageIndex}
canPreviousPage={canPreviousPage}
canNextPage={canNextPage}
pageOptions={pageOptions}
pageCount={pageCount}
gotoPage={gotoPage}
nextPage={nextPage}
previousPage={previousPage}
/>
</Flex>
</Flex>
)
}
Example #27
Source File: ViewAllTable.tsx From devex with GNU General Public License v3.0 | 4 votes |
ViewAllTable: React.FC<IViewAllTableParams<DsBlockObj | TxBlockObj | TransactionDetails>> =
({ columns, data, isLoading, fetchData, pageCount: controlledPageCount }) => {
const { getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageCount,
gotoPage,
nextPage,
previousPage,
// Get the state from the instance
state: { pageIndex } } = useTable<DsBlockObj | TxBlockObj | TransactionDetails>({
columns,
data,
initialState: { pageIndex: 0 },
manualPagination: true,
pageCount: controlledPageCount,
}, usePagination)
const fetchDataDebounce = useAsyncDebounce(fetchData, 300)
useEffect(() => {
fetchDataDebounce({ pageIndex })
// fetchDataDebounce changes when fetchData function changes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pageIndex, fetchData])
const generatePagination = useCallback((currentPage: number, pageCount: number, delta = 2) => {
const separate = (a: number, b: number, isLower: boolean) => {
const temp = b - a
if (temp === 0)
return [a]
else if (temp === 1)
return [a, b]
else if (temp === 2)
return [a, a + 1, b]
else
return [a, isLower ? -1 : -2, b]
}
return Array(delta * 2 + 1)
.fill(0)
.map((_, index) => currentPage - delta + index)
.filter(page => 0 < page && page <= pageCount)
.flatMap((page, index, { length }) => {
if (!index) {
return separate(1, page, true)
}
if (index === length - 1) {
return separate(page, pageCount, false)
}
return [page]
})
}, [])
return (
<>
<BRow>
<BCol className='align-self-center pl-3'>
{data.length === 0
? null
: <span className='subtext'>Items Per Page: <strong>10</strong></span>}
</BCol>
<BCol>
<Pagination className='justify-content-end'>
<Pagination.Prev onClick={() => previousPage()} disabled={!canPreviousPage} />
{generatePagination(pageIndex + 1, pageCount).map((page) => {
if (page === -1)
return <Pagination.Ellipsis key={page} onClick={() => gotoPage(pageIndex - 5)} />
else if (page === -2)
return <Pagination.Ellipsis key={page} onClick={() => gotoPage(pageIndex + 5)} />
else if (page === pageIndex + 1)
return <Pagination.Item key={page} active>{page}</Pagination.Item>
else
return <Pagination.Item key={page} onClick={() => gotoPage(Number(page) - 1)}>{page}</Pagination.Item>
})}
<Pagination.Next onClick={() => nextPage()} disabled={!canNextPage} />
</Pagination>
</BCol>
</BRow>
<div className='viewall-table table'>
{isLoading ? <div className='center-spinner mt-4'><Spinner animation="border" /></div> : null}
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup: HeaderGroup<DsBlockObj | TxBlockObj | TransactionDetails>) => (
<tr {...headerGroup.getHeaderGroupProps()} key={headerGroup.getHeaderGroupProps().key} >
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps()} key={column.getHeaderProps().key} id={column.id}>
{column.render('Header')}
</th>
))}
</tr>
))}
</thead>
<tbody style={isLoading ? { opacity: '0.5' } : {}}{...getTableBodyProps()}>
{page.map((row: Row<DsBlockObj | TxBlockObj | TransactionDetails>) => {
prepareRow(row)
return (
<tr {...row.getRowProps()} key={row.getRowProps().key}>
{row.cells.map((cell: Cell<DsBlockObj | TxBlockObj | TransactionDetails>) => {
return (
<td {...cell.getCellProps()}
key={cell.getCellProps().key}>
{cell.render('Cell')}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
</div>
</>
)
}
Example #28
Source File: MinerTable.tsx From devex with GNU General Public License v3.0 | 4 votes |
MinerTable: React.FC<IMinerTableParams> = ({ addresses }) => {
const generatePagination = useCallback((currentPage: number, pageCount: number, delta = 1) => {
const separate = (a: number, b: number, isLower: boolean) => {
const temp = b - a
if (temp === 0)
return [a]
else if (temp === 1)
return [a, b]
else if (temp === 2)
return [a, a + 1, b]
else
return [a, isLower ? -1 : -2, b]
}
return Array(delta * 2 + 1)
.fill(0)
.map((_, index) => currentPage - delta + index)
.filter(page => 0 < page && page <= pageCount)
.flatMap((page, index, { length }) => {
if (!index) {
return separate(1, page, true)
}
if (index === length - 1) {
return separate(page, pageCount, false)
}
return [page]
})
}, [])
const columns = useMemo(
() => [{
id: 'address-col',
Header: 'Addresses',
accessor: 'address',
// eslint-disable-next-line react/display-name
Cell: (props: Cell<IMinerObj>) =>
(<>
[{props.row.index}]
{' '}
<QueryPreservingLink to={`/address/${pubKeyToZilAddr(props.value)}`}>{pubKeyToZilAddr(props.value)}</QueryPreservingLink>
</>)
}], []
) as Array<Column<IMinerObj>>
const data = useMemo(() => (addresses.map((x) => ({ address: x })) as IMinerObj[]), [addresses])
const {
getTableProps,
getTableBodyProps,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageCount,
gotoPage,
nextPage,
previousPage,
state: { pageIndex },
} = useTable<IMinerObj>({
columns,
data,
initialState: { pageIndex: 0 },
}, usePagination)
return (
<>
<div className='py-3'>
<table {...getTableProps()}>
<tbody {...getTableBodyProps()}>
{page.map((row: Row<IMinerObj>) => {
prepareRow(row)
return (
<tr {...row.getRowProps()} key={row.getRowProps().key}>
{row.cells.map((cell: Cell<IMinerObj>) => {
return (
<td {...cell.getCellProps()} key={cell.getCellProps().key}>
{cell.render('Cell')}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
</div>
<div className='mx-auto'>
{data.length !== 0 &&
<Pagination className='viewall-pagination'>
<Pagination.Prev onClick={() => previousPage()} disabled={!canPreviousPage} />
{generatePagination(pageIndex + 1, pageCount).map((page) => {
if (page === -1)
return <Pagination.Ellipsis key={page} onClick={() => gotoPage(pageIndex - 5)} />
else if (page === -2)
return <Pagination.Ellipsis key={page} onClick={() => gotoPage(pageIndex + 5)} />
else if (page === pageIndex + 1)
return <Pagination.Item key={page} active>{page}</Pagination.Item>
else
return <Pagination.Item key={page} onClick={() => gotoPage(Number(page) - 1)}>{page}</Pagination.Item>
})}
<Pagination.Next onClick={() => nextPage()} disabled={!canNextPage} />
</Pagination>
}
</div>
</>
)
}