diff --git a/ui/package-lock.json b/ui/package-lock.json index 76f7903..65e8047 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -14,6 +14,7 @@ "@tanstack/react-query": "^5.44.0", "@tanstack/react-query-devtools": "^5.44.0", "@tanstack/react-router": "^1.35.3", + "@tanstack/react-table": "^8.17.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.394.0", @@ -1968,6 +1969,25 @@ "react-dom": ">=16" } }, + "node_modules/@tanstack/react-table": { + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.17.3.tgz", + "integrity": "sha512-5gwg5SvPD3lNAXPuJJz1fOCEZYk9/GeBFH3w/hCgnfyszOIzwkwgp5I7Q4MJtn0WECp84b5STQUDdmvGi8m3nA==", + "dependencies": { + "@tanstack/table-core": "8.17.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/@tanstack/router-devtools": { "version": "1.36.0", "resolved": "https://registry.npmjs.org/@tanstack/router-devtools/-/router-devtools-1.36.0.tgz", @@ -2048,6 +2068,18 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tanstack/table-core": { + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.17.3.tgz", + "integrity": "sha512-mPBodDGVL+fl6d90wUREepHa/7lhsghg2A3vFpakEhrhtbIlgNAZiMr7ccTgak5qbHqF14Fwy+W1yFWQt+WmYQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", diff --git a/ui/package.json b/ui/package.json index 55099f5..e96ae1a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -17,6 +17,7 @@ "@tanstack/react-query": "^5.44.0", "@tanstack/react-query-devtools": "^5.44.0", "@tanstack/react-router": "^1.35.3", + "@tanstack/react-table": "^8.17.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.394.0", diff --git a/ui/src/components/ui/data-table.tsx b/ui/src/components/ui/data-table.tsx new file mode 100644 index 0000000..fc5d7a4 --- /dev/null +++ b/ui/src/components/ui/data-table.tsx @@ -0,0 +1,107 @@ +import { + ColumnDef, + flexRender, + getCoreRowModel, + getPaginationRowModel, + useReactTable, +} from "@tanstack/react-table"; +import { Button } from "@/components/ui/button"; + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; + +interface DataTableProps { + columns: ColumnDef[]; + data: TData[]; +} + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + }); + + return ( +
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext(), + )} + + ); + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+
+ + +
+
+ ); +} diff --git a/ui/src/routes/tables.lazy.tsx b/ui/src/routes/tables.lazy.tsx index bc8dbb5..6281c1c 100644 --- a/ui/src/routes/tables.lazy.tsx +++ b/ui/src/routes/tables.lazy.tsx @@ -1,19 +1,18 @@ -import "react-data-grid/lib/styles.css"; - import { HardDrive, DatabaseZap, TableProperties, Table as TableIcon, } from "lucide-react"; -import DataGrid from "react-data-grid"; import { CodeBlock } from "react-code-blocks"; import { useQuery } from "@tanstack/react-query"; import { createFileRoute } from "@tanstack/react-router"; +import { ColumnDef } from "@tanstack/react-table"; import { fetchTable, fetchTables } from "@/api"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsList, TabsContent, TabsTrigger } from "@/components/ui/tabs"; +import { DataTable } from "@/components/ui/data-table"; export const Route = createFileRoute("/tables")({ component: Tables, @@ -52,7 +51,13 @@ function Table({ name }: Props) { if (!data) return; - const columns = data.columns.map((col) => ({ key: col, name: col })); + type Column = { + [key: string]: string; + }; + const columns: ColumnDef[] = data.columns.map((col) => ({ + accessorKey: col.toLowerCase(), + header: col, + })); const rows = data.rows.map((row) => row.reduce((acc, curr, i) => { acc[data.columns[i]] = curr; @@ -120,8 +125,7 @@ function Table({ name }: Props) { - - + ); }