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) => {