Skip to content

Commit

Permalink
[ui] Upgrade react-table to v8 (#13219)
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 65955114b5d293e84d15b8e62122ba6f3160fc10
  • Loading branch information
coreymartin authored and Lightspark Eng committed Nov 4, 2024
1 parent d72f2ba commit c4b1c7f
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 78 deletions.
3 changes: 1 addition & 2 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"@rollup/plugin-url": "^8.0.2",
"@simbathesailor/use-what-changed": "^2.0.0",
"@svgr/core": "^8.1.0",
"@tanstack/react-table": "^8.20.5",
"@wojtekmaj/react-daterange-picker": "^5.5.0",
"@wojtekmaj/react-datetimerange-picker": "^5.5.0",
"@zxing/browser": "^0.1.1",
Expand All @@ -81,7 +82,6 @@
"react-dom": "^18.1.0",
"react-router-dom": "6.11.2",
"react-select": "^5.4.0",
"react-table": "^7.8.0",
"react-tooltip": "^5.10.1",
"uuid": "^9.0.0"
},
Expand All @@ -97,7 +97,6 @@
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^29.5.3",
"@types/prismjs": "^1.26.0",
"@types/react-table": "^7.7.18",
"esbuild": "0.19.1",
"esbuild-plugin-copy": "^2.1.1",
"esbuild-plugin-svgr": "^2.1.0",
Expand Down
36 changes: 18 additions & 18 deletions packages/ui/src/components/DataManagerTable/DataManagerTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function initialFilterState<T extends Record<string, unknown>>(
filters.forEach((filter) => {
state = {
...state,
[filter.accessor]: getDefaultFilterState<T>(filter),
[filter.accessorKey]: getDefaultFilterState<T>(filter),
};
});

Expand Down Expand Up @@ -219,7 +219,7 @@ export function DataManagerTable<
return (state: FilterState) => {
setFilterStates((prevState) => ({
...prevState,
[filter.accessor]: state,
[filter.accessorKey]: state,
}));
};
}
Expand Down Expand Up @@ -249,14 +249,14 @@ export function DataManagerTable<
);
if (validResult) {
// Apply the result of the validation for refetching data
appliedFilterStates[filter.accessor] = validResult;
appliedFilterStates[filter.accessorKey] = validResult;

// Update UI filter state as a result of applying if needed
if (isIdFilterState(filterState)) {
const appliedValues = (validResult as IdFilterState).appliedValues;
const isApplied = !!appliedValues?.length;
updateFilterState(filter)({
...filterStates[filter.accessor],
...filterStates[filter.accessorKey],
value: "",
appliedValues: appliedValues ? [...appliedValues] : [],
isApplied,
Expand Down Expand Up @@ -298,14 +298,14 @@ export function DataManagerTable<
updatedAppliedValues.push(value);

const newFilterState = {
...filterStates[filter.accessor],
...filterStates[filter.accessorKey],
value: "",
appliedValues: updatedAppliedValues,
isApplied: !!updatedAppliedValues.length,
} as StringFilterState;

// Apply the result of the validation for refetching data
appliedFilterStates[filter.accessor] = newFilterState;
appliedFilterStates[filter.accessorKey] = newFilterState;
// Update UI filter state as a result of applying if needed
updateFilterState(filter)(newFilterState);
} else if (filterState.appliedValues?.length === 0) {
Expand All @@ -316,14 +316,14 @@ export function DataManagerTable<
} else if (isEnumFilterState(filterState)) {
if (filterState.value) {
const newFilterState = {
...filterStates[filter.accessor],
...filterStates[filter.accessorKey],
value: "",
appliedValues: filterState.appliedValues,
isApplied: !!filterState.appliedValues?.length,
} as EnumFilterState;

// Apply the result of the validation for refetching data
appliedFilterStates[filter.accessor] = newFilterState;
appliedFilterStates[filter.accessorKey] = newFilterState;
// Update UI filter state as a result of applying if needed
updateFilterState(filter)(newFilterState);
} else if (filterState.appliedValues?.length === 0) {
Expand Down Expand Up @@ -477,10 +477,10 @@ export function DataManagerTable<
updateFilterState={(state) => {
setFilterStates((prevState) => ({
...prevState,
[filter.accessor]: state,
[filter.accessorKey]: state,
}));
}}
state={filterStates[filter.accessor] as DateFilterState}
state={filterStates[filter.accessorKey] as DateFilterState}
/>
</div>
);
Expand All @@ -491,13 +491,13 @@ export function DataManagerTable<
updateFilterState={(state) => {
setFilterStates((prevState) => ({
...prevState,
[filter.accessor]: state,
[filter.accessorKey]: state,
}));
}}
options={filter.enumValues}
label={filter.label}
placeholder={filter.placeholder}
state={filterStates[filter.accessor] as EnumFilterState}
state={filterStates[filter.accessorKey] as EnumFilterState}
isMulti={filter.isMulti}
/>
</div>
Expand All @@ -509,12 +509,12 @@ export function DataManagerTable<
updateFilterState={(state) => {
setFilterStates((prevState) => ({
...prevState,
[filter.accessor]: state,
[filter.accessorKey]: state,
}));
}}
label={filter.label}
placeholder={filter.placeholder}
state={filterStates[filter.accessor] as StringFilterState}
state={filterStates[filter.accessorKey] as StringFilterState}
/>
</div>
);
Expand All @@ -525,12 +525,12 @@ export function DataManagerTable<
updateFilterState={(state) => {
setFilterStates((prevState) => ({
...prevState,
[filter.accessor]: state,
[filter.accessorKey]: state,
}));
}}
label={filter.label}
placeholder={filter.placeholder}
state={filterStates[filter.accessor] as IdFilterState}
state={filterStates[filter.accessorKey] as IdFilterState}
/>
</div>
);
Expand All @@ -541,11 +541,11 @@ export function DataManagerTable<
updateFilterState={(state) => {
setFilterStates((prevState) => ({
...prevState,
[filter.accessor]: state,
[filter.accessorKey]: state,
}));
}}
label={filter.label}
state={filterStates[filter.accessor] as BooleanFilterState}
state={filterStates[filter.accessorKey] as BooleanFilterState}
/>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/DataManagerTable/filters.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
interface FilterBase<T extends Record<string, unknown>> {
type: FilterType;
label: string;
// This is the accessor for the column in the data
accessor: keyof T;
// This is the accessorKey for the column in the data
accessorKey: keyof T;
value?: string | boolean;
// Placeholder for any string filters
placeholder?: string;
Expand Down
127 changes: 71 additions & 56 deletions packages/ui/src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { css } from "@emotion/react";
import styled from "@emotion/styled";

import {
flexRender,
getCoreRowModel,
getSortedRowModel,
useReactTable,
type CellContext,
type ColumnSort,
type HeaderContext,
type Row,
} from "@tanstack/react-table";
import { isObject } from "lodash-es";
import type { KeyboardEvent, MouseEvent, ReactNode } from "react";
import { Fragment, useCallback, useMemo } from "react";
import { useTable, type Row } from "react-table";
import { Fragment, useCallback, useMemo, useState } from "react";
import { useClipboard } from "../../hooks/useClipboard.js";
import {
Link,
Expand Down Expand Up @@ -32,7 +41,12 @@ import { Loading } from "../Loading.js";

export type TableColumnHeaderInfo = string | { name: string; tooltip?: string };

export type TableCell = string | LinkCell | ClipboardCell | ReactNode;
export type TableCell =
| string
| LinkCell
| ClipboardCell
| MultilineCell
| ReactNode;

type ObjectCell = {
text: string;
Expand Down Expand Up @@ -80,8 +94,8 @@ const isMultilineCell = (value: unknown): value is MultilineCell => {
};

interface Column<T extends Record<string, unknown>> {
Header: TableColumnHeaderInfo;
accessor: keyof T;
header: TableColumnHeaderInfo;
accessorKey: keyof T;
}

export type TableProps<T extends Record<string, unknown>> = {
Expand All @@ -104,6 +118,7 @@ export function Table<T extends Record<string, unknown>>({
clipboardCallbacks,
}: TableProps<T>) {
const navigate = useNavigate();
const [sorting, setSorting] = useState<ColumnSort[]>([]);

const { canWriteToClipboard, writeTextToClipboard } =
useClipboard(clipboardCallbacks);
Expand All @@ -119,22 +134,24 @@ export function Table<T extends Record<string, unknown>>({
() =>
columns.map((column) => ({
...column,
Header:
typeof column.Header === "string" ? (
column.Header
header: (context: HeaderContext<T, TableCell>) =>
typeof column.header === "string" ? (
column.header
) : (
<div>
{column.Header.name}
{column.header.name}
<InfoIconTooltip
id={`tooltip-${column.Header.name}`}
content={column.Header.tooltip || ""}
id={`tooltip-${column.header.name}`}
content={column.header.tooltip || ""}
verticalAlign={-2}
/>
</div>
),
accessor: column.accessor.toString(),
Cell: ({ value }: { value: unknown }) => {
let content = value as ReactNode;
accessorKey: column.accessorKey.toString(),
cell: (context: CellContext<T, TableCell>) => {
const value = context.getValue();

let content: ReactNode = null;
let icon = null;
if (isObjectCell(value)) {
icon = value.icon ? (
Expand All @@ -155,6 +172,8 @@ export function Table<T extends Record<string, unknown>>({
</Fragment>
);
}
} else {
content = value;
}

if (isLinkAndClipboardCell(value)) {
Expand Down Expand Up @@ -265,10 +284,17 @@ export function Table<T extends Record<string, unknown>>({
[columns, canWriteToClipboard, onClickCopy, clipboardCallbacks],
);

const tableInstance = useTable({ columns: mappedColumns, data });

const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
tableInstance;
const tableInstance = useReactTable({
columns: mappedColumns,
data,
state: {
sorting,
},
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
// debugTable: true
});

function onClickDataRow(
event: MouseEvent<HTMLTableRowElement> | KeyboardEvent<HTMLTableRowElement>,
Expand All @@ -292,40 +318,35 @@ export function Table<T extends Record<string, unknown>>({

return (
<TableWrapper>
<StyledTable {...getTableProps()} clickable={Boolean(onClickRow)}>
<StyledTable clickable={Boolean(onClickRow)}>
<thead>
{
// Loop over the header rows
headerGroups.map((headerGroup) => (
// Apply the header row props
<tr {...headerGroup.getHeaderGroupProps()}>
{
// Loop over the headers in each row
headerGroup.headers.map((column) => (
// Apply the header cell props
<th {...column.getHeaderProps()}>
{
// Render the header
column.render("Header")
}
tableInstance.getHeaderGroups().map((headerGroup) => {
return (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</th>
))
}
</tr>
))
))}
</tr>
);
})
}
</thead>
{/* Apply the table body props */}
<tbody {...getTableBodyProps()}>
<tbody>
{
// Loop over the table rows
rows.map((row) => {
// Prepare the row for display
prepareRow(row);
tableInstance.getRowModel().rows.map((row) => {
return (
// Apply the row props
<tr
{...row.getRowProps()}
key={row.id}
onClick={(event) => onClickDataRow(event, row)}
onKeyDown={(event) => {
if (event.key === "Enter") {
Expand All @@ -334,20 +355,14 @@ export function Table<T extends Record<string, unknown>>({
}}
tabIndex={0}
>
{
// Loop over the rows cells
row.cells.map((cell) => {
// Apply the cell props
return (
<td {...cell.getCellProps()}>
{
// Render the cell contents
cell.render("Cell")
}
</td>
);
})
}
{row.getVisibleCells().map((cell) => (
<td key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</td>
))}
</tr>
);
})
Expand Down

0 comments on commit c4b1c7f

Please sign in to comment.