diff --git a/frontend/src/components/Table/InsightsTable.tsx b/frontend/src/components/Table/InsightsTable.tsx index aeb5d638..6ee893c1 100644 --- a/frontend/src/components/Table/InsightsTable.tsx +++ b/frontend/src/components/Table/InsightsTable.tsx @@ -1,9 +1,17 @@ "use client"; -import React, { useState } from "react"; +import React, { useMemo, useState } from "react"; import { CSVLink } from "react-csv"; import { DebounceInput } from "react-debounce-input"; -import { MdAdd, MdClose, MdCloudDownload, MdColorLens, MdRemove, MdSearch } from "react-icons/md"; +import { + MdAdd, + MdClose, + MdCloudDownload, + MdColorLens, + MdFormatListNumbered, + MdRemove, + MdSearch, +} from "react-icons/md"; import { ColumnDef } from "@tanstack/react-table"; @@ -21,6 +29,7 @@ const InsightsTable = ({ csvFilename, toggleDisableHighlight, includeKey = true, + defaultShowRowNumbers = true, }: { title: string; data: any[]; @@ -31,9 +40,11 @@ const InsightsTable = ({ csvFilename: string; toggleDisableHighlight?: () => void; includeKey?: boolean; + defaultShowRowNumbers?: boolean; }) => { const [showSearch, setShowSearch] = useState(false); const [search, setSearch] = useState(""); + const [showRowNumbers, setShowRowNumbers] = useState(defaultShowRowNumbers); const [expanded, setExpanded] = useState(false); @@ -41,8 +52,14 @@ const InsightsTable = ({ const currData = expanded ? detailedData : data; const currColumns = expanded ? detailedColumns : columns; - const filteredData = currData.filter((row) => - searchCols.some((col) => row[col].toString().toLowerCase().includes(search.toLowerCase())) + // Memoized so toggling display-only state (e.g. row numbers) does not hand + // TanStack a new data array, which would reset pagination to page 1. + const filteredData = useMemo( + () => + currData.filter((row) => + searchCols.some((col) => row[col].toString().toLowerCase().includes(search.toLowerCase())) + ), + [currData, search, searchCols] ); const headerClassName = () => "border-b-2 border-gray-800"; @@ -86,6 +103,12 @@ const InsightsTable = ({
setShowSearch(!showSearch)} />
+
+ setShowRowNumbers(!showRowNumbers)} + /> +
{toggleDisableHighlight && (
@@ -121,6 +144,7 @@ const InsightsTable = ({ headerCellClassName={headerCellClassName} rowClassName={rowClassName} cellClassName={cellClassName} + showRowNumbers={showRowNumbers} />
{includeKey && } diff --git a/frontend/src/components/Table/Table.tsx b/frontend/src/components/Table/Table.tsx index a664e886..b49c2a35 100644 --- a/frontend/src/components/Table/Table.tsx +++ b/frontend/src/components/Table/Table.tsx @@ -23,6 +23,7 @@ const Table = ({ headerCellClassName, rowClassName, cellClassName, + showRowNumbers = false, }: { data: any[]; columns: ColumnDef[]; @@ -31,6 +32,7 @@ const Table = ({ headerCellClassName: (header: any) => string; rowClassName: (row: any) => string; cellClassName: (cell: any) => string; + showRowNumbers?: boolean; }) => { const [sorting, setSorting] = useState([]); @@ -68,6 +70,10 @@ const Table = ({ .slice(0, -1); const showColDividers = table.getHeaderGroups().length > 1; + const numHeaderRows = table.getHeaderGroups().length; + + // Row numbers follow the current sort and filter, and continue across pages + const rowNumberClassName = "px-1 md:px-2 text-xs text-gray-500"; return (
@@ -75,6 +81,11 @@ const Table = ({ {table.getHeaderGroups().map((headerGroup, i) => ( + {showRowNumbers && i === 0 && ( + + # + + )} {headerGroup.headers.map((header, j) => { return ( - {table.getRowModel().rows.map((row) => ( + {table.getRowModel().rows.map((row, i) => ( + {showRowNumbers && ( + {pageIndex * pageSize + i + 1} + )} {row.getVisibleCells().map((cell, j) => (