diff --git a/app/pages/system/UtilizationPage.tsx b/app/pages/system/UtilizationPage.tsx index 9c690b263..2442f3cf2 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 1e4362aae..ee6b84d8a 100644 --- a/app/pages/system/inventory/SledsTab.tsx +++ b/app/pages/system/inventory/SledsTab.tsx @@ -10,11 +10,16 @@ import { createColumnHelper } from '@tanstack/react-table' import { getListQFn, queryClient, + SledPolicy, type Sled, type SledProvisionPolicy, 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' @@ -45,24 +50,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 759ea6800..266ae5180 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) => {