Clarify infrastructure grouping label

This commit is contained in:
rcourtman
2026-04-28 21:26:23 +01:00
parent 8109fa63d4
commit 870958ef2a
4 changed files with 51 additions and 14 deletions
@@ -188,6 +188,11 @@ work extends shared components instead of creating new local variants.
grouped resource labels operator-readable: count-led labels may aggregate
repeated resources, but uncountable or category-like resource types such as
storage must use resource wording instead of naive pluralization.
Infrastructure filter chrome under `frontend-modern/src/features/infrastructure/`
must use mode-oriented labels for table presentation controls: grouped table
mode is `Grouped`, not `Cluster`, because cluster remains a
platform/resource concept for Proxmox, Kubernetes, and similar inventory
details.
2. Route new top-level settings surfaces through the canonical settings shell
instead of introducing page-local framing.
Shared shells and primitives that need websocket or dark-mode context must
@@ -137,6 +137,11 @@ cross-source deduplication.
infrastructure platform first, while full merged-source detail remains
available for tooltips, accessibility metadata, and routing. Agent telemetry
is collection-method detail when a provider/API platform is also present.
Infrastructure table presentation controls must describe the table mode
rather than a platform-specific resource concept: the grouped/flat toggle
uses operator-facing `Grouped` and `List` wording, while Proxmox,
Kubernetes, and other platform clusters stay reserved for actual resource
identity, filters, and detail surfaces.
Resource detail mappers now reuse the shared
`frontend-modern/src/utils/textPresentation.ts` title-case helper for sensor
@@ -236,7 +236,7 @@ export function InfrastructurePageSurface() {
options={[
{
value: 'grouped',
title: 'Group by cluster',
title: 'Grouped table view',
label: (
<>
<svg
@@ -248,7 +248,7 @@ export function InfrastructurePageSurface() {
>
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2v11z" />
</svg>
Cluster
Grouped
</>
),
},
@@ -11,7 +11,9 @@ describe('InfrastructurePageSurface guardrails', () => {
it('keeps the feature shell separate from route-sync and page-model ownership', () => {
expect(infrastructurePageSurfaceSource).toContain('useInfrastructurePageState');
expect(infrastructurePageSurfaceSource).toContain('useNavigate');
expect(infrastructurePageSurfaceSource).toContain("import { PageHeader } from '@/components/shared/PageHeader';");
expect(infrastructurePageSurfaceSource).toContain(
"import { PageHeader } from '@/components/shared/PageHeader';",
);
expect(infrastructurePageSurfaceSource).toContain('<PageHeader');
expect(infrastructurePageSurfaceSource).toContain('title="Infrastructure"');
expect(infrastructurePageSurfaceSource).not.toContain('useLocation(');
@@ -36,7 +38,9 @@ describe('InfrastructurePageSurface guardrails', () => {
expect(infrastructurePageRouteStateSource).toContain('buildInfrastructurePath');
expect(infrastructurePageRouteStateSource).toContain('areSearchParamsEquivalent');
expect(infrastructurePageModelSource).toContain('export function buildInfrastructurePageFilterDerivation');
expect(infrastructurePageModelSource).toContain(
'export function buildInfrastructurePageFilterDerivation',
);
expect(infrastructurePageModelSource).toContain('collectAvailableSources');
expect(infrastructurePageModelSource).toContain('collectAvailableStatuses');
expect(infrastructurePageModelSource).toContain('buildStatusOptions');
@@ -45,20 +49,41 @@ describe('InfrastructurePageSurface guardrails', () => {
});
it('keeps summary-to-table coordination on the page-state owner', () => {
expect(infrastructurePageSurfaceSource).toContain('showJumpToActiveRow={shouldShowJumpToActiveResourceRow()}');
expect(infrastructurePageSurfaceSource).toContain('onJumpToActiveRow={jumpToActiveResourceRow}');
expect(infrastructurePageSurfaceSource).toContain('hoveredGroupScope={hoveredSummaryResourceGroupScope()}');
expect(infrastructurePageSurfaceSource).toContain('focusedGroupScope={focusedSummaryResourceGroupScope()}');
expect(infrastructurePageSurfaceSource).toContain('activeSummaryGroupScope={activeSummaryResourceGroupScope()}');
expect(infrastructurePageSurfaceSource).toContain('hoveredSummaryGroupScope={hoveredSummaryResourceGroupScope()}');
expect(infrastructurePageSurfaceSource).toContain('focusedSummaryGroupScope={focusedSummaryResourceGroupScope()}');
expect(infrastructurePageSurfaceSource).toContain('onGroupHoverChange={setHoveredResourceGroupScope}');
expect(infrastructurePageSurfaceSource).toContain(
'showJumpToActiveRow={shouldShowJumpToActiveResourceRow()}',
);
expect(infrastructurePageSurfaceSource).toContain(
'onJumpToActiveRow={jumpToActiveResourceRow}',
);
expect(infrastructurePageSurfaceSource).toContain(
'hoveredGroupScope={hoveredSummaryResourceGroupScope()}',
);
expect(infrastructurePageSurfaceSource).toContain(
'focusedGroupScope={focusedSummaryResourceGroupScope()}',
);
expect(infrastructurePageSurfaceSource).toContain(
'activeSummaryGroupScope={activeSummaryResourceGroupScope()}',
);
expect(infrastructurePageSurfaceSource).toContain(
'hoveredSummaryGroupScope={hoveredSummaryResourceGroupScope()}',
);
expect(infrastructurePageSurfaceSource).toContain(
'focusedSummaryGroupScope={focusedSummaryResourceGroupScope()}',
);
expect(infrastructurePageSurfaceSource).toContain(
'onGroupHoverChange={setHoveredResourceGroupScope}',
);
expect(infrastructurePageSurfaceSource).toContain('setSummaryClearSurfaceRootRef');
expect(infrastructurePageSurfaceSource).toContain('setTableRootRef={setSummaryTableRootRef}');
expect(infrastructurePageSurfaceSource).toContain('data-testid="infrastructure-page"');
expect(infrastructurePageSurfaceSource).toContain('ref={setSummaryClearSurfaceRootRef}');
expect(infrastructurePageSurfaceSource).toContain('data-testid="infrastructure-interaction-surface"');
expect(infrastructurePageSurfaceSource).toContain(
'data-testid="infrastructure-interaction-surface"',
);
expect(infrastructurePageSurfaceSource).toContain('data-summary-clear-ignore');
expect(infrastructurePageSurfaceSource).toContain("title: 'Grouped table view'");
expect(infrastructurePageSurfaceSource).toContain('Grouped');
expect(infrastructurePageSurfaceSource).not.toContain("title: 'Group by cluster'");
expect(infrastructurePageSurfaceSource).not.toContain('SummaryScopeBar');
expect(infrastructurePageSurfaceSource).not.toContain('searchTrailing={pinnedScopeFallback()}');
expect(infrastructurePageSurfaceSource).not.toContain('mobileTrailing={pinnedScopeFallback()}');
@@ -80,7 +105,9 @@ describe('InfrastructurePageSurface guardrails', () => {
expect(infrastructurePageStateSource).not.toContain('consumeNextFocusedRevealSkip');
expect(infrastructurePageStateSource).not.toContain('setSkipNextFocusedReveal(true)');
expect(infrastructurePageStateSource).not.toContain('querySelector<HTMLElement>(');
expect(infrastructurePageStateSource).not.toContain('scrollIntoView({ behavior: \'smooth\', block: \'center\' })');
expect(infrastructurePageStateSource).not.toContain(
"scrollIntoView({ behavior: 'smooth', block: 'center' })",
);
expect(unifiedResourceTableSource).toContain('data-summary-clear-surface');
expect(unifiedResourceTableSource).toContain('data-testid="infrastructure-table-surface"');