Skip to content

Commit

Permalink
feat!: option to add row count on tables (#284)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fran McDade authored and Fran McDade committed Nov 25, 2024
1 parent b5aae14 commit 5c5e3d8
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 45 deletions.
9 changes: 7 additions & 2 deletions src/components/Detail/components/Table/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import {
useBreakpointHelper,
} from "../../../../hooks/useBreakpointHelper";
import { TABLET } from "../../../../theme/common/breakpoints";
import { COLUMN_DEF } from "../../../Table/common/columnDef";
import { ROW_DIRECTION } from "../../../Table/common/entities";
import { TableHead } from "../../../Table/components/TableHead/tableHead";
import { ROW_POSITION } from "../../../Table/features/RowPosition/constants";
import { ROW_PREVIEW } from "../../../Table/features/RowPreview/constants";
import { GridTable } from "../../../Table/table.styles";
import { generateColumnDefinitions } from "./common/utils";
Expand Down Expand Up @@ -56,8 +58,11 @@ export const Table = <T extends RowData>({
const { stickyHeader = false } = table || {};
const { sx: tableContainerSx } = tableContainer || {};
const tableInstance = useReactTable({
_features: [ROW_PREVIEW],
columns: generateColumnDefinitions(columns),
_features: [ROW_POSITION, ROW_PREVIEW],
columns: generateColumnDefinitions([
COLUMN_DEF.ROW_POSITION as ColumnDef<T>,
...columns,
]),
data: items,
enableSorting: false,
getCoreRowModel: getCoreRowModel(),
Expand Down
8 changes: 7 additions & 1 deletion src/components/Table/common/columnDef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ import { RowPositionCell } from "../components/TableCell/components/RowPositionC
export const COLUMN_DEF: Record<string, ColumnDef<RowData>> = {
ROW_POSITION: {
cell: RowPositionCell,
enableHiding: false,
enableSorting: false,
header: "",
id: ACCESSOR_KEYS.ROW_POSITION,
meta: { align: TABLE_CELL_PROPS.ALIGN.RIGHT, header: "" },
meta: {
align: TABLE_CELL_PROPS.ALIGN.RIGHT,
header: "",
width: "max-content",
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { CellContext, RowData } from "@tanstack/react-table";
import React from "react";
import { BaseComponentProps } from "../../../../../types";
import { TYPOGRAPHY_PROPS } from "./constants";
import { getRowPosition } from "./utils";

export const RowPositionCell = <TData extends RowData, TValue>({
className,
...cellContext
}: BaseComponentProps & CellContext<TData, TValue>): JSX.Element => {
return (
<Typography {...TYPOGRAPHY_PROPS} className={className} component="div">
{getRowPosition(cellContext)}
{cellContext.row.getRowPosition()}
</Typography>
);
};

This file was deleted.

34 changes: 34 additions & 0 deletions src/components/Table/features/RowPosition/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
Cell,
Column,
Row,
RowData,
RowModel,
Table,
TableFeature,
TableState,
} from "@tanstack/react-table";
import { InitialTableState } from "@tanstack/table-core/src/types";
import { getRowModel, getRowPosition, initInitialState } from "./utils";

export const ROW_POSITION: TableFeature = {
createCell: <T extends RowData, TValue>(
cell: Cell<T, TValue>,
column: Column<T>,
row: Row<T>,
table: Table<T>
): void => {
row.getRowPosition = (): number => {
return getRowPosition(row.id, table);
};
},
createTable: <T extends RowData>(table: Table<T>): void => {
const originalGetRowModel = table.getRowModel.bind(table);
table.getRowModel = (): RowModel<T> => {
return getRowModel(table, originalGetRowModel);
};
},
getInitialState: (initialState?: InitialTableState): Partial<TableState> => {
return initInitialState(initialState);
},
};
3 changes: 3 additions & 0 deletions src/components/Table/features/RowPosition/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface RowPositionRow {
getRowPosition: () => number;
}
80 changes: 80 additions & 0 deletions src/components/Table/features/RowPosition/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
InitialTableState,
RowData,
RowModel,
Table,
TableState,
} from "@tanstack/react-table";
import { ACCESSOR_KEYS } from "../../../TableCreator/common/constants";
import { DEFAULT_PAGINATION } from "../constants";

/**
* Returns row model, with getter for row position.
* @param table - Table.
* @param getRowModel - Table getRowModel function.
* @returns row model.
*/
export function getRowModel<T extends RowData>(
table: Table<T>,
getRowModel: Table<T>[`getRowModel`]
): RowModel<T> {
const rowModel = getRowModel();
rowModel.rows.forEach(({ id }, i) => {
rowModel.rowsById[id].getRowPosition = (): number =>
calculateRowPosition(table, i);
});
return rowModel;
}

/**
* Returns the position of the row in the table.
* @param rowId - Row ID.
* @param table - Table.
* @returns row position.
*/
export function getRowPosition<T extends RowData>(
rowId: string,
table: Table<T>
): number {
const { getRowModel } = table;
const { rowsById } = getRowModel();
return rowsById[rowId].getRowPosition();
}

/**
* Calculates the position of the row in the table.
* @param table - Table.
* @param index - Row index.
* @returns row position.
*/
function calculateRowPosition<T extends RowData>(
table: Table<T>,
index: number
): number {
const { getState } = table;
const {
pagination: { pageIndex, pageSize },
} = getState();
return pageIndex * pageSize + (index + 1);
}

/**
* Returns the initial table state.
* @param initialState - Initial state.
* @returns initial state.
*/
export function initInitialState(
initialState?: InitialTableState
): Partial<TableState> {
return {
...initialState,
columnVisibility: {
[ACCESSOR_KEYS.ROW_POSITION]: false,
...initialState?.columnVisibility,
},
pagination: {
...DEFAULT_PAGINATION,
...initialState?.pagination,
},
};
}
10 changes: 10 additions & 0 deletions src/components/Table/features/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PaginationState } from "@tanstack/react-table";

/**
* Default TanStack pagination state.
* See https://tanstack.com/table/latest/docs/guide/custom-features#getinitialstate.
*/
export const DEFAULT_PAGINATION: PaginationState = {
pageIndex: 0,
pageSize: 10,
};
3 changes: 2 additions & 1 deletion src/components/Table/features/entities.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { RowData } from "@tanstack/react-table";
import { RowPositionRow } from "./RowPosition/types";
import {
RowPreviewInstance,
RowPreviewOptions,
Expand All @@ -9,5 +10,5 @@ import {
export type CustomFeatureInitialTableState = Partial<RowPreviewTableState>;
export type CustomFeatureInstance<T extends RowData> = RowPreviewInstance<T>;
export type CustomFeatureOptions = RowPreviewOptions;
export type CustomFeatureRow = RowPreviewRow;
export type CustomFeatureRow = RowPositionRow & RowPreviewRow;
export type CustomFeatureTableState = RowPreviewTableState;
5 changes: 3 additions & 2 deletions src/components/Table/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { Pagination as DXPagination } from "./components/Pagination/pagination";
import { TableBody } from "./components/TableBody/tableBody";
import { TableHead } from "./components/TableHead/tableHead";
import { TableToolbar } from "./components/TableToolbar/tableToolbar";
import { ROW_POSITION } from "./features/RowPosition/constants";
import { ROW_PREVIEW } from "./features/RowPreview/constants";
import { RowPreviewState } from "./features/RowPreview/entities";
import { GridTable } from "./table.styles";
Expand Down Expand Up @@ -174,7 +175,7 @@ TableProps<T>): JSX.Element => {
const { initialState: _initialState, ...restTableOptions } =
tableOptions ?? {};
const tableInstance = useReactTable({
_features: [ROW_PREVIEW],
_features: [ROW_POSITION, ROW_PREVIEW],
columns,
data: items,
enableColumnFilters: true, // client-side filtering.
Expand All @@ -193,7 +194,7 @@ TableProps<T>): JSX.Element => {
getPaginationRowModel: getPaginationRowModel(),
getRowId,
getSortedRowModel: clientFiltering ? getSortedRowModel() : undefined,
initialState: { ...initialState, ..._initialState }, // Currently, `sorting` and `columnVisibility` are managed by the ExploreState.
initialState: { ...initialState, ..._initialState }, // `sorting` and `columnVisibility` are managed by the ExploreState.
manualPagination: true,
manualSorting: !clientFiltering,
onColumnVisibilityChange,
Expand Down
2 changes: 1 addition & 1 deletion src/components/TableCreator/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const COLUMN_CONFIGS: Record<
> = {
ROW_POSITION: {
columnPinned: false,
columnVisible: true,
columnVisible: false,
componentConfig: {
component: RowPositionCell,
viewBuilder: (_, viewContext) => viewContext?.cellContext,
Expand Down
3 changes: 3 additions & 0 deletions src/components/TableCreator/tableCreator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import { PAPER_PANEL_STYLE } from "../common/Paper/paper";
import { ComponentCreator } from "../ComponentCreator/ComponentCreator";
import { Loading } from "../Loading/loading";
import { COLUMN_DEF } from "../Table/common/columnDef";
import {
arrIncludesSome,
getInitialState,
Expand Down Expand Up @@ -82,6 +83,8 @@ export const TableCreator = <T extends RowData>({
return acc;
},
[
/* Initialize column definitions with the "row position" column */
COLUMN_DEF.ROW_POSITION,
/* Initialize column definitions with the "select" column */
{
...buildBaseColumnDef(COLUMN_CONFIGS.SELECT),
Expand Down
7 changes: 6 additions & 1 deletion src/providers/exploreState/initializer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,17 @@ function initCategoryGroups(
*/
function initColumnVisibility(entityConfig: EntityConfig): VisibilityState {
const {
list: { columns },
list: {
columns,
tableOptions: { initialState: { columnVisibility = {} } = {} } = {},
},
listView: { enableRowSelection = false } = {},
} = entityConfig;
return {
[ACCESSOR_KEYS.ROW_POSITION]: false, // Explicitly setting row position to false; required - currently `columnVisibilty` is initialized from columns configuration.
[ACCESSOR_KEYS.SELECT]: enableRowSelection,
...getInitialTableColumnVisibility(columns),
...columnVisibility, // `columnVisibility` is managed by ExploreState; use table options to override this setting.
};
}

Expand Down

0 comments on commit 5c5e3d8

Please sign in to comment.