Refine availability probe row presentation

Refs #1460
This commit is contained in:
rcourtman
2026-05-06 14:35:02 +01:00
parent 66668a7f05
commit 4a981fe85d
5 changed files with 25 additions and 32 deletions
@@ -2810,7 +2810,8 @@ drawers still derive `Availability` and `Network Endpoint` labels from the
shared resource presentation helpers rather than from preset-local copy.
Infrastructure rows for those same agentless endpoints must surface probe
evidence directly in the row, not just as a green status dot or an
`Availability` badge. The shared row presentation must expose the probe method,
latest latency or failure result, and recent check timing from the canonical
availability payload so operators can understand what was actually measured
without opening the drawer.
`Availability` badge. The shared row presentation must expose the probe method
and latest latency or failure result once, inline in the agentless endpoint's
metric slot, while keeping recent check timing and fuller failure context in
the tooltip or drawer so operators can understand what was measured without
duplicated row chrome.
@@ -973,11 +973,12 @@ visible table density.
That hot-path contract now includes policy badge rendering on resource rows.
Agentless availability evidence belongs on that same bounded row path.
Infrastructure `network-endpoint` rows may replace otherwise empty host metric
slots with compact probe method/result text and may add one compact resource
subline for latency, failure, and recent check timing, but they must derive
that text from the existing resource payload and shared presentation helper
instead of adding a per-row fetch, extra hydration pass, or unbounded badge
stack.
slots with one compact inline probe method/result readout. Recent check timing,
latency history, and fuller failure context may stay in bounded tooltip or
drawer detail, but the table must not duplicate the same probe evidence across
the resource identity cell and metric cells. That text must derive from the
existing resource payload and shared presentation helper instead of adding a
per-row fetch, extra hydration pass, or unbounded badge stack.
The infrastructure summary hot path is now explicit shared ownership too:
`InfrastructureSummary.tsx` stays a render shell,
`useInfrastructureSummaryState.ts` owns chart polling and cache lifecycle, and
@@ -528,10 +528,11 @@ availability data is still `platformType=availability`, `sourceType=api`, and
must not regress to a generic platform badge in infrastructure rows or drawers.
Infrastructure row presentation must also consume that availability payload as
operator evidence, not only as badge identity. `network-endpoint` rows should
surface the probe method, latest latency or failure result, and recent check
timing from either the top-level availability field or the live-state
`platformData.availability` mirror, so REST and realtime paths answer what was
measured without requiring the drawer.
surface one visible probe readout, method plus latest latency or failure
result, from either the top-level availability field or the live-state
`platformData.availability` mirror. Recent check timing and fuller failure
context may stay in tooltip or drawer detail, but the table row must not show
the same probe evidence in both the resource identity cell and metric cell.
That same frontend-owned compatibility boundary must remain intentionally
narrow. Shared resource adapters may admit explicit aliases such as `host`,
`truenas`, and `ceph`, and VMware detail mappers may project typed metadata
@@ -403,18 +403,6 @@ export const UnifiedResourceHostTableCard: Component<UnifiedResourceHostTableCar
counts={resource.facetCounts}
class="mt-0.5"
/>
<Show when={availabilityProbe()}>
{(probe) => (
<div class="mt-0.5 flex min-w-0 items-center">
<span
class={`min-w-0 truncate text-[9px] leading-tight ${probe().toneClassName}`}
title={probe().detailLabel}
>
{probe().rowLabel}
</span>
</div>
)}
</Show>
</div>
<Show when={workloadsHref()}>
{(href) => (
@@ -540,14 +528,14 @@ export const UnifiedResourceHostTableCard: Component<UnifiedResourceHostTableCar
>
{(probe) => (
<div
class="mx-auto flex max-w-full flex-col items-center justify-center leading-tight"
class="mx-auto inline-flex max-w-full min-w-0 items-baseline justify-center gap-1 whitespace-nowrap text-[11px] leading-tight"
title={probe().detailLabel}
>
<span class="max-w-full truncate text-[9px] tracking-normal text-muted">
{probe().methodLabel}
<span class="min-w-0 truncate text-muted">
{probe().methodLabel}:
</span>
<span
class={`max-w-full truncate text-[11px] font-medium tabular-nums ${probe().toneClassName}`}
class={`shrink-0 font-medium tabular-nums ${probe().toneClassName}`}
>
{probe().resultLabel}
</span>
@@ -248,7 +248,7 @@ describe('UnifiedResourceTable performance contract', () => {
}),
];
const { getByText, getAllByText } = render(() => (
const { getByText, getAllByText, queryByText } = render(() => (
<UnifiedResourceTable
resources={resources}
expandedResourceId={null}
@@ -258,9 +258,11 @@ describe('UnifiedResourceTable performance contract', () => {
));
await waitFor(() => {
expect(getByText('TCP 1883 - 7 ms - checked 14s ago')).toBeInTheDocument();
expect(getByText('TCP 1883:')).toBeInTheDocument();
expect(getByText('7 ms')).toBeInTheDocument();
});
expect(getAllByText('7 ms').length).toBeGreaterThanOrEqual(1);
expect(queryByText('TCP 1883 - 7 ms - checked 14s ago')).toBeNull();
expect(getAllByText('7 ms')).toHaveLength(1);
});
it('adapts host columns from the measured table surface width instead of the window width', async () => {