From 9758a9371a19880a9498c24c8d04cf138fcf534c Mon Sep 17 00:00:00 2001 From: David Crespo Date: Wed, 18 Dec 2024 12:20:17 -0600 Subject: [PATCH] use beautiful column grouping --- app/pages/system/UtilizationPage.tsx | 4 +- app/pages/system/inventory/SledsTab.tsx | 70 ++++++++++++++++--------- app/table/Table.tsx | 36 ++++++++----- 3 files changed, 71 insertions(+), 39 deletions(-) diff --git a/app/pages/system/UtilizationPage.tsx b/app/pages/system/UtilizationPage.tsx index 9c690b2637..2442f3cf24 100644 --- a/app/pages/system/UtilizationPage.tsx +++ b/app/pages/system/UtilizationPage.tsx @@ -162,7 +162,7 @@ function UsageTab() { - Silo + {/* data-test-ignore makes the row asserts work in the e2e tests */} Provisioned / Quota @@ -173,7 +173,7 @@ function UsageTab() { - + Silo CPU Memory Storage diff --git a/app/pages/system/inventory/SledsTab.tsx b/app/pages/system/inventory/SledsTab.tsx index 1e4362aae9..6054cde1c9 100644 --- a/app/pages/system/inventory/SledsTab.tsx +++ b/app/pages/system/inventory/SledsTab.tsx @@ -11,10 +11,14 @@ import { getListQFn, queryClient, type Sled, - type SledProvisionPolicy, + type SledPolicy, type SledState, } from '@oxide/api' -import { Servers24Icon } from '@oxide/design-system/icons/react' +import { + Checkmark12Icon, + Close12Icon, + Servers24Icon, +} from '@oxide/design-system/icons/react' import { makeLinkCell } from '~/table/cells/LinkCell' import { useQueryTable } from '~/table/QueryTable' @@ -22,11 +26,6 @@ import { Badge, type BadgeColor } from '~/ui/lib/Badge' import { EmptyMessage } from '~/ui/lib/EmptyMessage' import { pb } from '~/util/path-builder' -const PROV_POLICY_DISP: Record = { - provisionable: ['Provisionable', 'default'], - non_provisionable: ['Not provisionable', 'neutral'], -} - const STATE_BADGE_COLORS: Record = { active: 'default', decommissioned: 'neutral', @@ -45,24 +44,45 @@ const staticCols = [ cell: makeLinkCell((sledId) => pb.sled({ sledId })), }), // TODO: colHelper.accessor('baseboard.serviceAddress', { header: 'service address' }), - colHelper.accessor('baseboard.part', { header: 'part number' }), - colHelper.accessor('baseboard.serial', { header: 'serial number' }), - colHelper.accessor('baseboard.revision', { header: 'revision' }), - colHelper.accessor('policy', { - header: 'policy', - cell: (info) => { - const policy = info.getValue() - if (policy.kind === 'expunged') return Expunged - const [label, color] = PROV_POLICY_DISP[policy.provisionPolicy] - return ( -
- In service - - {label} - -
- ) - }, + colHelper.group({ + id: 'baseboard', + header: 'Baseboard', + columns: [ + colHelper.accessor('baseboard.part', { header: 'part number' }), + colHelper.accessor('baseboard.serial', { header: 'serial number' }), + colHelper.accessor('baseboard.revision', { header: 'revision' }), + ], + }), + colHelper.group({ + id: 'policy', + header: 'Policy', + columns: [ + colHelper.accessor('policy', { + header: 'Kind', + cell: (info) => { + // need to cast because inference is broken inside groups + // https://github.com/TanStack/table/issues/5065 + const policy: SledPolicy = info.getValue() + return policy.kind === 'expunged' ? ( + Expunged + ) : ( + In service + ) + }, + }), + colHelper.accessor('policy', { + header: 'Provisionable', + cell: (info) => { + const policy: SledPolicy = info.getValue() + if (policy.kind === 'expunged') return + return policy.provisionPolicy === 'provisionable' ? ( + + ) : ( + + ) + }, + }), + ], }), colHelper.accessor('state', { cell: (info) => ( diff --git a/app/table/Table.tsx b/app/table/Table.tsx index 759ea6800a..266ae51805 100644 --- a/app/table/Table.tsx +++ b/app/table/Table.tsx @@ -29,18 +29,30 @@ export const Table = ({ }: TableProps) => ( - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => ( - - {flexRender(header.column.columnDef.header, header.getContext())} - - ))} - - ))} + {table.getHeaderGroups().map((headerGroup) => { + console.log(headerGroup) + return ( + + {headerGroup.headers.map((header) => ( + + { + // Placeholder concept is for when grouped columns are + // combined with regular columns. The regular column only + // needs one entry in the stack of header cells, so the others + // have isPlacholder=true. See sleds table for an example. + header.isPlaceholder + ? null + : flexRender(header.column.columnDef.header, header.getContext()) + } + + ))} + + ) + })} {table.getRowModel().rows.map((row) => {