diff --git a/src/app/base/components/GenericTable/GenericTable.test.tsx b/src/app/base/components/GenericTable/GenericTable.test.tsx
index 45c1cc3867..ded178d575 100644
--- a/src/app/base/components/GenericTable/GenericTable.test.tsx
+++ b/src/app/base/components/GenericTable/GenericTable.test.tsx
@@ -67,7 +67,6 @@ describe("GenericTable", () => {
const mockFilterCells = vi.fn(() => true);
const mockFilterHeaders = vi.fn(() => true);
- const mockGetRowId = vi.fn((row) => row.id.toString());
it("renders table with headers and rows", () => {
render(
@@ -76,7 +75,6 @@ describe("GenericTable", () => {
data={data}
filterCells={mockFilterCells}
filterHeaders={mockFilterHeaders}
- getRowId={mockGetRowId}
rowSelection={{}}
setRowSelection={vi.fn}
/>
@@ -96,7 +94,6 @@ describe("GenericTable", () => {
data={[]}
filterCells={mockFilterCells}
filterHeaders={mockFilterHeaders}
- getRowId={mockGetRowId}
noData={No data}
rowSelection={{}}
setRowSelection={vi.fn}
@@ -113,7 +110,6 @@ describe("GenericTable", () => {
data={data}
filterCells={mockFilterCells}
filterHeaders={mockFilterHeaders}
- getRowId={mockGetRowId}
rowSelection={{}}
setRowSelection={vi.fn}
/>
diff --git a/src/app/base/components/GenericTable/GenericTable.tsx b/src/app/base/components/GenericTable/GenericTable.tsx
index 31182b802f..2bbfe4a662 100644
--- a/src/app/base/components/GenericTable/GenericTable.tsx
+++ b/src/app/base/components/GenericTable/GenericTable.tsx
@@ -1,59 +1,61 @@
-import type { Dispatch, ReactNode, SetStateAction } from "react";
-import { useMemo, useState } from "react";
+import {
+ type Dispatch,
+ type ReactNode,
+ type SetStateAction,
+ useMemo,
+ useState,
+} from "react";
import { DynamicTable } from "@canonical/maas-react-components";
-import { Button } from "@canonical/react-components";
import type {
Column,
+ Row,
ColumnDef,
ColumnSort,
- ExpandedState,
GroupingState,
+ ExpandedState,
+ SortingState,
Header,
- Row,
RowSelectionState,
- SortingState,
} from "@tanstack/react-table";
import {
+ flexRender,
getCoreRowModel,
getExpandedRowModel,
getGroupedRowModel,
useReactTable,
- flexRender,
} from "@tanstack/react-table";
import classNames from "classnames";
+import TableCheckbox from "@/app/base/components/GenericTable/TableCheckbox";
+import TableHeader from "@/app/base/components/GenericTable/TableHeader";
+
import "./_index.scss";
-import SortingIndicator from "./SortingIndicator";
type GenericTableProps = {
- ariaLabel?: string;
+ canSelect?: boolean;
columns: ColumnDef>[];
data: T[];
- filterCells: (row: Row, column: Column) => boolean;
- filterHeaders: (header: Header) => boolean;
- getRowId: (
- originalRow: T,
- index: number,
- parent?: Row | undefined
- ) => string;
+ filterCells?: (row: Row, column: Column) => boolean;
+ filterHeaders?: (header: Header) => boolean;
groupBy?: string[];
noData?: ReactNode;
+ pin?: { value: string; isTop: boolean }[];
sortBy?: ColumnSort[];
- rowSelection: RowSelectionState;
+ rowSelection?: RowSelectionState;
setRowSelection?: Dispatch>;
};
const GenericTable = ({
- ariaLabel,
+ canSelect = false,
columns,
data,
- filterCells,
- filterHeaders,
- getRowId,
+ filterCells = () => true,
+ filterHeaders = () => true,
groupBy,
- sortBy,
noData,
+ pin,
+ sortBy,
rowSelection,
setRowSelection,
}: GenericTableProps) => {
@@ -61,8 +63,62 @@ const GenericTable = ({
const [expanded, setExpanded] = useState(true);
const [sorting, setSorting] = useState(sortBy ?? []);
- const sortedData = useMemo(() => {
+ if (canSelect) {
+ columns = [
+ {
+ id: "select",
+ accessorKey: "id",
+ enableSorting: false,
+ header: "",
+ cell: ({ row }) =>
+ !row.getIsGrouped() ? : null,
+ },
+ ...columns,
+ ];
+
+ if (groupBy) {
+ columns = [
+ {
+ id: "group-select",
+ accessorKey: "id",
+ enableSorting: false,
+ header: ({ table }) => ,
+ cell: ({ row }) =>
+ row.getIsGrouped() ? : null,
+ },
+ ...columns,
+ ];
+ }
+ }
+
+ data = useMemo(() => {
return [...data].sort((a, b) => {
+ if (pin && pin.length > 0 && grouping.length > 0) {
+ for (const { value, isTop } of pin) {
+ const groupId = grouping[0];
+ const aValue = a[groupId as keyof typeof a];
+ const bValue = b[groupId as keyof typeof b];
+
+ if (aValue === value && bValue !== value) {
+ return isTop ? -1 : 1;
+ }
+ if (bValue === value && aValue !== value) {
+ return isTop ? 1 : -1;
+ }
+ }
+ }
+
+ for (const groupId of grouping) {
+ const aGroupValue = a[groupId as keyof typeof a];
+ const bGroupValue = b[groupId as keyof typeof b];
+ if (aGroupValue < bGroupValue) {
+ return -1;
+ }
+ if (aGroupValue > bGroupValue) {
+ return 1;
+ }
+ }
+
for (const { id, desc } of sorting) {
const aValue = a[id as keyof typeof a];
const bValue = b[id as keyof typeof b];
@@ -75,10 +131,10 @@ const GenericTable = ({
}
return 0;
});
- }, [data, sorting]);
+ }, [data, sorting, grouping, pin]);
const table = useReactTable({
- data: sortedData,
+ data,
columns,
state: {
grouping,
@@ -101,40 +157,15 @@ const GenericTable = ({
groupedColumnMode: false,
enableRowSelection: true,
enableMultiRowSelection: true,
- getRowId,
});
return (
-
+
{table.getHeaderGroups().map((headerGroup) => (
{headerGroup.headers.filter(filterHeaders).map((header) => (
-
- {header.column.getCanSort() ? (
-
- ) : (
- flexRender(
- header.column.columnDef.header,
- header.getContext()
- )
- )}
- |
+
))}
))}
diff --git a/src/app/base/components/GenericTable/TableCheckbox/TableCheckbox.tsx b/src/app/base/components/GenericTable/TableCheckbox/TableCheckbox.tsx
index 6f3cad8a42..75777497a3 100644
--- a/src/app/base/components/GenericTable/TableCheckbox/TableCheckbox.tsx
+++ b/src/app/base/components/GenericTable/TableCheckbox/TableCheckbox.tsx
@@ -24,7 +24,7 @@ const TableAllCheckbox = ({ table, ...props }: TableCheckboxProps) => {
}
return (
-