Move Uptime after the bar block in platform top tables

Uptime placement was the most visibly drifty ordering on platform top
tables: Proxmox and TrueNAS sat it at position 3 (before any bars),
Docker / vSphere at position 8 (after bars), Kubernetes Nodes at the
very end (after Capacity). Same monitoring concept rendered in three
different positions depending on the table.

Lock in the convention: Uptime is monitoring state, not identity. It
canonically sits between the bar block (CPU / Memory / Disk / Storage,
plus the Temp diagnostic) and the inventory counts.

Apply that rule:
  - Proxmox host model: Uptime moves from position 3 to position 7
    (Node, Version, CPU, Memory, Disk, Temp, Uptime, VMs, CTs, Cluster).
  - TrueNAS systems table: Uptime moves from position 3 to position 7
    (System, Version, CPU, Memory, Storage, Temp, Uptime, Pools,
    Datasets, Disks, Apps).
  - Kubernetes nodes table: Uptime swaps with Capacity so Uptime sits
    between the bars and the Capacity inventory string (Node, Cluster,
    Roles, Kubelet, Runtime, CPU, Memory, Uptime, Capacity).

The columnAlignment.ts docstring now documents the recommended column
ordering (identity → context → state → bars → diagnostic → time →
inventory → external) alongside the kind-to-align mapping, so the
ordering convention sits in the same source-of-truth file every agent
already reads when editing a platform table.

Other ordering questions (where integer counts sit relative to bars;
where the cluster-reference column sits) are left as each table's
current choice. They are defensible either way and have a real visible
UX cost to change. Revisit if drift surfaces.
This commit is contained in:
rcourtman
2026-05-20 12:16:37 +01:00
parent b94c6164d7
commit 300af43128
4 changed files with 46 additions and 17 deletions
@@ -173,12 +173,12 @@ export const KubernetesNodesTable: Component<{
<TableHead class={`${getPlatformTableHeadClassForKind('metric-bar')} md:w-[11%]`}>
Memory
</TableHead>
<TableHead class={`${getPlatformTableHeadClassForKind('numeric-value')} md:w-[14%]`}>
Capacity
</TableHead>
<TableHead class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden md:table-cell md:w-[6%]`}>
Uptime
</TableHead>
<TableHead class={`${getPlatformTableHeadClassForKind('numeric-value')} md:w-[14%]`}>
Capacity
</TableHead>
</TableRow>
</TableHeader>
<TableBody class={PLATFORM_TABLE_BODY_CLASS}>
@@ -289,17 +289,17 @@ export const KubernetesNodesTable: Component<{
/>
</Show>
</TableCell>
<TableCell
class={`${getPlatformTableCellClassForKind('numeric-value')} hidden text-base-content md:table-cell`}
>
{formatUptime(node.uptime)}
</TableCell>
<TableCell
class={`${getPlatformTableCellClassForKind('numeric-value')} text-base-content tabular-nums`}
>
<span class="md:hidden">{compactCapacityLabel()}</span>
<span class="hidden md:inline">{capacityLabel()}</span>
</TableCell>
<TableCell
class={`${getPlatformTableCellClassForKind('numeric-value')} hidden text-base-content md:table-cell`}
>
{formatUptime(node.uptime)}
</TableCell>
</TableRow>
<PlatformResourceDetailTableRow
resource={node}
@@ -57,6 +57,31 @@ import type { PlatformTableCellAlign } from './sharedPlatformPage';
* change automatically. `scripts/canonical-platform-audit.mjs` enforces
* that platform tables use canonical alignments for well-known column
* labels, so drift breaks pre-push.
*
* Recommended column ordering within a platform table:
*
* 1. Identity ('name') — always the first column.
* 2. Context / owner ('text') — Version, Datacenter, Cluster, Context,
* Runtime, Kubelet, Image, Ports, vCenter, Roles, Power, Swarm role.
* External management references (vCenter, swarm cluster name)
* conventionally sit at the end of the row even though they share
* the 'text' kind.
* 3. Resource usage bars ('metric-bar') — always rendered as the
* contiguous block CPU → Memory → Disk/Storage in that order. Do
* not interleave bars with other column kinds.
* 4. Diagnostic ('numeric-value') — Temperature.
* 5. Time ('numeric-value') — Uptime always sits between the bar
* block (plus Temp) and the inventory counts. It is monitoring
* state, not identity, so it does not belong near the front of
* the row.
* 6. Inventory counts ('numeric-value') — Containers, VMs, CTs, Pods,
* Pools, Datasets, Datastores, Disks, Apps, Desired / Updated /
* Ready / Available, Capacity.
*
* Tables with bespoke columns (e.g. Kubernetes deployments, Docker
* services) can deviate from the inventory-counts order when their
* content demands it; the bar block contiguity and the Uptime-after-bars
* rule are the load-bearing parts of the convention.
*/
export type PlatformTableColumnKind =
| 'name'
@@ -84,14 +84,18 @@ const HOST_COLUMN_RESPONSIVE_WEIGHTS: Record<
const formatPercentage = (value: number): string => `${Number(value.toFixed(4))}%`;
// Column order follows the canonical recommended ordering documented in
// columnAlignment.ts: identity → context → bars (CPU/Memory/Disk
// contiguous) → diagnostic (Temp) → time (Uptime) → inventory counts
// → external owner reference at end.
export const PROXMOX_HOST_TABLE_COLUMNS: ProxmoxHostTableColumn[] = [
{ id: 'node', label: 'Node', kind: 'name' },
{ id: 'version', label: 'Version', kind: 'text' },
{ id: 'uptime', label: 'Uptime', kind: 'numeric-value' },
{ id: 'cpu', label: 'CPU', kind: 'metric-bar' },
{ id: 'memory', label: 'Memory', kind: 'metric-bar' },
{ id: 'disk', label: 'Disk', kind: 'metric-bar' },
{ id: 'temp', label: 'Temp', kind: 'numeric-value' },
{ id: 'uptime', label: 'Uptime', kind: 'numeric-value' },
{ id: 'vms', label: 'VMs', kind: 'numeric-value' },
{ id: 'cts', label: 'CTs', kind: 'numeric-value' },
{ id: 'cluster', label: 'Cluster', kind: 'text' },
@@ -179,9 +179,6 @@ export const TrueNASSystemsTable: Component<{
<TableHead class={`${getPlatformTableHeadClassForKind('text')} hidden md:table-cell md:w-[14%]`}>
Version
</TableHead>
<TableHead class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden md:table-cell md:w-[6%]`}>
Uptime
</TableHead>
<TableHead class={`${getPlatformTableHeadClassForKind('metric-bar')} md:w-[11%]`}>
CPU
</TableHead>
@@ -194,6 +191,9 @@ export const TrueNASSystemsTable: Component<{
<TableHead class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden md:table-cell md:w-[6%]`}>
Temp
</TableHead>
<TableHead class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden md:table-cell md:w-[6%]`}>
Uptime
</TableHead>
<TableHead class={`${getPlatformTableHeadClassForKind('numeric-value')} hidden md:table-cell md:w-[6%]`}>
Pools
</TableHead>
@@ -271,11 +271,6 @@ export const TrueNASSystemsTable: Component<{
>
{version()}
</TableCell>
<TableCell
class={`${getPlatformTableCellClassForKind('numeric-value')} hidden text-base-content md:table-cell`}
>
{formatUptime(system.uptime)}
</TableCell>
<TableCell
class={`${getPlatformTableCellClassForKind('metric-bar')} w-[20%] md:w-auto`}
>
@@ -313,6 +308,11 @@ export const TrueNASSystemsTable: Component<{
>
{formatTemperature(system.temperature)}
</TableCell>
<TableCell
class={`${getPlatformTableCellClassForKind('numeric-value')} hidden text-base-content md:table-cell`}
>
{formatUptime(system.uptime)}
</TableCell>
<TableCell
class={`${getPlatformTableCellClassForKind('numeric-value')} hidden text-base-content tabular-nums md:table-cell`}
>