mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-22 11:45:52 +00:00
Register platform loading template governance
This commit is contained in:
@@ -2393,6 +2393,11 @@ Docker, Kubernetes, Proxmox, Standalone, TrueNAS, vSphere, and future platform
|
||||
feature tables; source-specific consumers own only the empty-state icon, title,
|
||||
description, and actions. Platform feature tables must not import
|
||||
`EmptyState` directly or recreate a `Card`-wrapped empty-state shell.
|
||||
Platform table loading states are registry-backed too.
|
||||
`PlatformTableLoadingState` owns the repeated table-card compact
|
||||
`role="status"` loading row for platform pages and tables; platform consumers
|
||||
own only the title and description copy. Platform feature surfaces must not
|
||||
recreate the `TableCard` plus compact status-row shell locally.
|
||||
Filter bars are registry-backed too. `FilterBar` owns resource-list filtering
|
||||
as a catalog of `FilterDef` entries, while `filterChipStatusDot` owns the
|
||||
small leading status-dot glyph used by filter options. Page and feature
|
||||
|
||||
@@ -114,6 +114,29 @@
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "platform-table-loading-state",
|
||||
"category": "platform-table-loading-state",
|
||||
"summary": "Platform page and table loading states must compose PlatformTableLoadingState instead of recreating local TableCard status rows.",
|
||||
"canonical": {
|
||||
"path": "src/features/platformPage/sharedPlatformPage.tsx",
|
||||
"export": "PlatformTableLoadingState"
|
||||
},
|
||||
"requiredConsumers": [
|
||||
{ "path": "src/features/docker/DockerPageSurface.tsx" },
|
||||
{ "path": "src/features/kubernetes/KubernetesPageSurface.tsx" },
|
||||
{ "path": "src/features/proxmox/ProxmoxPageSurface.tsx" },
|
||||
{ "path": "src/features/standalone/StandalonePageSurface.tsx" },
|
||||
{ "path": "src/features/truenas/TrueNASPageSurface.tsx" },
|
||||
{ "path": "src/features/truenas/TrueNASProtectionTable.tsx" },
|
||||
{ "path": "src/features/vmware/VmwarePageSurface.tsx" }
|
||||
],
|
||||
"proof": [
|
||||
"src/components/shared/SharedPrimitives.guardrails.test.ts",
|
||||
"src/features/platformPage/__tests__/platformOverviewLayout.guardrails.test.ts",
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "filter-bar-catalog-shell",
|
||||
"category": "filter-bar",
|
||||
@@ -217,6 +240,31 @@
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "platform-table-loading-state-local-status-row",
|
||||
"category": "platform-table-loading-state",
|
||||
"summary": "Platform feature loading states must compose PlatformTableLoadingState instead of recreating the compact TableCard status row locally.",
|
||||
"canonical": {
|
||||
"path": "src/features/platformPage/sharedPlatformPage.tsx",
|
||||
"export": "PlatformTableLoadingState"
|
||||
},
|
||||
"scopes": [
|
||||
"src/features/docker",
|
||||
"src/features/kubernetes",
|
||||
"src/features/proxmox",
|
||||
"src/features/standalone",
|
||||
"src/features/truenas",
|
||||
"src/features/vmware"
|
||||
],
|
||||
"extensions": [".tsx"],
|
||||
"allPatterns": ["role=\"status\"", "px-3 py-2 text-xs text-muted"],
|
||||
"legacyReason": "Retired migration debt. Platform table loading states must use PlatformTableLoadingState; no compact local status-row exceptions are currently allowed.",
|
||||
"allowedPaths": [],
|
||||
"proof": [
|
||||
"src/components/shared/SharedPrimitives.guardrails.test.ts",
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "filter-bar-consumer-legacy-page-controls",
|
||||
"category": "filter-bar",
|
||||
|
||||
@@ -92,8 +92,15 @@ import webInterfaceUrlFieldStateSource from '@/components/shared/useWebInterface
|
||||
import webInterfaceNameLinkSource from '@/components/shared/WebInterfaceNameLink.tsx?raw';
|
||||
import inlineDetailTableRowSource from '@/components/shared/InlineDetailTableRow.tsx?raw';
|
||||
import sharedTemplateRegistrySource from '../../../scripts/shared-template-registry.json?raw';
|
||||
import dockerPageSurfaceSource from '@/features/docker/DockerPageSurface.tsx?raw';
|
||||
import kubernetesPageSurfaceSource from '@/features/kubernetes/KubernetesPageSurface.tsx?raw';
|
||||
import proxmoxPageSurfaceSource from '@/features/proxmox/ProxmoxPageSurface.tsx?raw';
|
||||
import standalonePageSurfaceSource from '@/features/standalone/StandalonePageSurface.tsx?raw';
|
||||
import sharedPlatformPageSource from '@/features/platformPage/sharedPlatformPage.tsx?raw';
|
||||
import platformResourceDetailTableRowSource from '@/features/platformPage/PlatformResourceDetailTableRow.tsx?raw';
|
||||
import truenasPageSurfaceSource from '@/features/truenas/TrueNASPageSurface.tsx?raw';
|
||||
import truenasProtectionTableSource from '@/features/truenas/TrueNASProtectionTable.tsx?raw';
|
||||
import vmwarePageSurfaceSource from '@/features/vmware/VmwarePageSurface.tsx?raw';
|
||||
import upgradeNavigationSource from '@/utils/upgradeNavigation.ts?raw';
|
||||
import guestRowSource from '@/components/Workloads/GuestRow.tsx?raw';
|
||||
import workloadsTableSource from '@/components/Workloads/WorkloadsTable.tsx?raw';
|
||||
@@ -1065,6 +1072,82 @@ describe('shared primitive guardrails', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('keeps platform table loading states on the shared status-row template', () => {
|
||||
const registry = JSON.parse(sharedTemplateRegistrySource) as {
|
||||
rules?: Array<{
|
||||
id: string;
|
||||
canonical?: { path?: string; export?: string };
|
||||
requiredConsumers?: Array<{ path?: string }>;
|
||||
}>;
|
||||
patternGuards?: Array<{
|
||||
id: string;
|
||||
canonical?: { path?: string; export?: string };
|
||||
allPatterns?: string[];
|
||||
scopes?: string[];
|
||||
allowedPaths?: string[];
|
||||
}>;
|
||||
};
|
||||
const registeredRule = registry.rules?.find(
|
||||
(rule) => rule.id === 'platform-table-loading-state',
|
||||
);
|
||||
const registeredGuard = registry.patternGuards?.find(
|
||||
(guard) => guard.id === 'platform-table-loading-state-local-status-row',
|
||||
);
|
||||
const requiredConsumerPaths = [
|
||||
'src/features/docker/DockerPageSurface.tsx',
|
||||
'src/features/kubernetes/KubernetesPageSurface.tsx',
|
||||
'src/features/proxmox/ProxmoxPageSurface.tsx',
|
||||
'src/features/standalone/StandalonePageSurface.tsx',
|
||||
'src/features/truenas/TrueNASPageSurface.tsx',
|
||||
'src/features/truenas/TrueNASProtectionTable.tsx',
|
||||
'src/features/vmware/VmwarePageSurface.tsx',
|
||||
];
|
||||
|
||||
expect(registeredRule?.canonical?.path).toBe(
|
||||
'src/features/platformPage/sharedPlatformPage.tsx',
|
||||
);
|
||||
expect(registeredRule?.canonical?.export).toBe('PlatformTableLoadingState');
|
||||
expect(registeredRule?.requiredConsumers?.map((consumer) => consumer.path)).toEqual(
|
||||
expect.arrayContaining(requiredConsumerPaths),
|
||||
);
|
||||
expect(registeredGuard?.canonical?.path).toBe(
|
||||
'src/features/platformPage/sharedPlatformPage.tsx',
|
||||
);
|
||||
expect(registeredGuard?.canonical?.export).toBe('PlatformTableLoadingState');
|
||||
expect(registeredGuard?.allPatterns).toEqual([
|
||||
'role="status"',
|
||||
'px-3 py-2 text-xs text-muted',
|
||||
]);
|
||||
expect(registeredGuard?.allowedPaths ?? []).toHaveLength(0);
|
||||
expect(registeredGuard?.scopes).toEqual(
|
||||
expect.arrayContaining([
|
||||
'src/features/docker',
|
||||
'src/features/kubernetes',
|
||||
'src/features/proxmox',
|
||||
'src/features/standalone',
|
||||
'src/features/truenas',
|
||||
'src/features/vmware',
|
||||
]),
|
||||
);
|
||||
|
||||
expect(sharedPlatformPageSource).toContain('export function PlatformTableLoadingState');
|
||||
expect(sharedPlatformPageSource).toContain('role="status"');
|
||||
expect(sharedPlatformPageSource).toContain('px-3 py-2 text-xs text-muted');
|
||||
|
||||
for (const source of [
|
||||
dockerPageSurfaceSource,
|
||||
kubernetesPageSurfaceSource,
|
||||
proxmoxPageSurfaceSource,
|
||||
standalonePageSurfaceSource,
|
||||
truenasPageSurfaceSource,
|
||||
truenasProtectionTableSource,
|
||||
vmwarePageSurfaceSource,
|
||||
]) {
|
||||
expect(source).toContain('PlatformTableLoadingState');
|
||||
expect(source).not.toContain('<div class="px-3 py-2 text-xs text-muted" role="status">');
|
||||
}
|
||||
});
|
||||
|
||||
it('keeps platform row-detail disclosure controls on the shared toggle primitive', () => {
|
||||
const registry = JSON.parse(sharedTemplateRegistrySource) as {
|
||||
requiredPatternGuards?: Array<{
|
||||
|
||||
Reference in New Issue
Block a user