From 9df4d2923686c1c978f82fe7502fc9bebb3ba3db Mon Sep 17 00:00:00 2001 From: Sven van Ginkel Date: Mon, 27 Oct 2025 16:43:23 +0100 Subject: [PATCH] Add sorting to the smart table (#1333) --- .../components/routes/system/smart-table.tsx | 144 ++++++++---------- 1 file changed, 66 insertions(+), 78 deletions(-) diff --git a/internal/site/src/components/routes/system/smart-table.tsx b/internal/site/src/components/routes/system/smart-table.tsx index d01578b4..2a3ca0f7 100644 --- a/internal/site/src/components/routes/system/smart-table.tsx +++ b/internal/site/src/components/routes/system/smart-table.tsx @@ -3,6 +3,7 @@ import { t } from "@lingui/core/macro" import { ColumnDef, ColumnFiltersState, + Column, flexRender, getCoreRowModel, getFilteredRowModel, @@ -10,7 +11,7 @@ import { SortingState, useReactTable, } from "@tanstack/react-table" -import { Activity, Box, Clock, HardDrive, HashIcon, CpuIcon, BinaryIcon, RotateCwIcon, LoaderCircleIcon, CheckCircle2Icon, XCircleIcon, ArrowLeftRightIcon } from "lucide-react" +import { Activity, Box, Clock, HardDrive, HashIcon, CpuIcon, BinaryIcon, RotateCwIcon, LoaderCircleIcon, CheckCircle2Icon, XCircleIcon, ArrowLeftRightIcon, ArrowUpDownIcon } from "lucide-react" import { Card, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet" import { Input } from "@/components/ui/input" @@ -23,9 +24,10 @@ import { TableRow, } from "@/components/ui/table" import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" import { pb } from "@/lib/api" import { SmartData, SmartAttribute } from "@/types" -import { formatBytes, toFixedFloat, formatTemperature } from "@/lib/utils" +import { formatBytes, toFixedFloat, formatTemperature, cn } from "@/lib/utils" import { Trans } from "@lingui/react/macro" import { ThermometerIcon } from "@/components/ui/icons" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" @@ -106,105 +108,82 @@ function convertSmartDataToDiskInfo(smartDataRecord: Record): export const columns: ColumnDef[] = [ { accessorKey: "device", - header: () => ( -
- - Device -
- ), + sortingFn: (a, b) => a.original.device.localeCompare(b.original.device), + header: ({ column }) => , cell: ({ row }) => ( -
{row.getValue("device")}
+
{row.getValue("device")}
), }, { accessorKey: "model", - header: () => ( -
- - Model -
- ), + sortingFn: (a, b) => a.original.model.localeCompare(b.original.model), + header: ({ column }) => , cell: ({ row }) => ( -
+
{row.getValue("model")}
), }, { accessorKey: "capacity", - header: () => ( -
- - Capacity -
+ header: ({ column }) => , + cell: ({ getValue }) => ( + {getValue() as string} ), }, { accessorKey: "temperature", - header: () => ( -
- - Temp -
- ), + invertSorting: true, + header: ({ column }) => , cell: ({ getValue }) => { const { value, unit } = formatTemperature(getValue() as number) - return `${value} ${unit}` + return {`${value} ${unit}`} }, }, { accessorKey: "status", - header: () => ( -
- - Status -
- ), + header: ({ column }) => , cell: ({ getValue }) => { const status = getValue() as string return ( - - {status} - +
+ + {status} + +
) }, }, { accessorKey: "deviceType", - header: () => ( -
- - Type -
- ), + sortingFn: (a, b) => a.original.deviceType.localeCompare(b.original.deviceType), + header: ({ column }) => , cell: ({ getValue }) => ( - - {getValue() as string} - +
+ + {getValue() as string} + +
), }, { accessorKey: "powerOnHours", - header: () => ( -
- - Power On -
- ), + invertSorting: true, + header: ({ column }) => , cell: ({ row }) => { const hours = row.getValue("powerOnHours") as number | undefined if (!hours && hours !== 0) { return ( -
+
N/A
) } const days = Math.floor(hours / 24) return ( -
+
{hours.toLocaleString()} hours
{days} days
@@ -213,46 +192,55 @@ export const columns: ColumnDef[] = [ }, { accessorKey: "powerCycles", - header: () => ( -
- - Cycles -
- ), + invertSorting: true, + header: ({ column }) => , cell: ({ getValue }) => { const cycles = getValue() as number | undefined if (!cycles && cycles !== 0) { return ( -
+
N/A
) } - return cycles + return {cycles} }, }, { accessorKey: "serialNumber", - header: () => ( -
- - Serial Number -
+ sortingFn: (a, b) => a.original.serialNumber.localeCompare(b.original.serialNumber), + header: ({ column }) => , + cell: ({ getValue }) => ( + {getValue() as string} ), }, { accessorKey: "firmwareVersion", - header: () => ( -
- - Firmware -
+ sortingFn: (a, b) => a.original.firmwareVersion.localeCompare(b.original.firmwareVersion), + header: ({ column }) => , + cell: ({ getValue }) => ( + {getValue() as string} ), }, ] +function HeaderButton({ column, name, Icon }: { column: Column; name: string; Icon: React.ElementType }) { + const isSorted = column.getIsSorted() + return ( + + ) +} + export default function DisksTable({ systemId }: { systemId: string }) { - // const [sorting, setSorting] = React.useState([{ id: "device", desc: false }]) + const [sorting, setSorting] = React.useState([{ id: "device", desc: false }]) const [columnFilters, setColumnFilters] = React.useState([]) const [rowSelection, setRowSelection] = React.useState({}) const [smartData, setSmartData] = React.useState | undefined>(undefined) @@ -284,14 +272,14 @@ export default function DisksTable({ systemId }: { systemId: string }) { const table = useReactTable({ data: diskData, columns: columns, - // onSortingChange: setSorting, + onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), onRowSelectionChange: setRowSelection, state: { - // sorting, + sorting, columnFilters, rowSelection, }, @@ -331,7 +319,7 @@ export default function DisksTable({ systemId }: { systemId: string }) { {headerGroup.headers.map((header) => { return ( - + {header.isPlaceholder ? null : flexRender(