From ddc70d2c95d3bc552ddcc748a265538599c0fae3 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 29 Apr 2026 20:52:14 +0100 Subject: [PATCH] Canonicalize PMG drawer table shell --- .../subsystems/frontend-primitives.md | 6 +- .../v6/internal/subsystems/registry.json | 2 + .../internal/subsystems/unified-resources.md | 120 +++++----- .../src/components/PMG/PMGInstanceDrawer.tsx | 214 +++++++++--------- .../SharedPrimitives.guardrails.test.ts | 2 + .../frontendResourceTypeBoundaries.test.ts | 2 + 6 files changed, 172 insertions(+), 174 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index d50fe8d45..bf887f7ec 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -188,9 +188,9 @@ work extends shared components instead of creating new local variants. nesting another card or scroll wrapper. If a framed table needs bounded vertical height, that constraint belongs on `Table.wrapperClass` so the shared table shell still owns overflow behavior. Resource-detail drawer - tables that consume `Table`, including Docker Swarm services and Kubernetes - namespaces/deployments, inherit the same scroll-shell owner instead of - carrying drawer-local `overflow-x-auto` wrappers. + tables that consume `Table`, including Docker Swarm services, Kubernetes + namespaces/deployments, and PMG detail tables, inherit the same scroll-shell + owner instead of carrying drawer-local `overflow-x-auto` wrappers. Product-table subgroup/header rows must likewise consume the shared `frontend-modern/src/components/shared/groupedTableRowPresentation.ts` helper and `.grouped-table-row` CSS token contract instead of local diff --git a/docs/release-control/v6/internal/subsystems/registry.json b/docs/release-control/v6/internal/subsystems/registry.json index 85350c1c8..105411040 100644 --- a/docs/release-control/v6/internal/subsystems/registry.json +++ b/docs/release-control/v6/internal/subsystems/registry.json @@ -4894,6 +4894,7 @@ "frontend-modern/src/components/Infrastructure/useUnifiedResourceTableViewportSync.ts", "frontend-modern/src/components/Kubernetes/K8sDeploymentsDrawer.tsx", "frontend-modern/src/components/Kubernetes/K8sNamespacesDrawer.tsx", + "frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx", "frontend-modern/src/components/PMG/ServiceHealthBadge.tsx", "frontend-modern/src/features/infrastructure/infrastructurePageModel.ts", "frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx", @@ -5016,6 +5017,7 @@ "frontend-modern/src/components/Infrastructure/useUnifiedResourceTableViewportSync.ts", "frontend-modern/src/components/Kubernetes/K8sDeploymentsDrawer.tsx", "frontend-modern/src/components/Kubernetes/K8sNamespacesDrawer.tsx", + "frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx", "frontend-modern/src/features/infrastructure/infrastructurePageModel.ts", "frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx", "frontend-modern/src/features/infrastructure/useInfrastructurePageRouteState.ts", diff --git a/docs/release-control/v6/internal/subsystems/unified-resources.md b/docs/release-control/v6/internal/subsystems/unified-resources.md index f925677c9..43fb2a31d 100644 --- a/docs/release-control/v6/internal/subsystems/unified-resources.md +++ b/docs/release-control/v6/internal/subsystems/unified-resources.md @@ -55,60 +55,61 @@ cross-source deduplication. 31. `frontend-modern/src/components/Docker/SwarmServicesDrawer.tsx` 32. `frontend-modern/src/components/Kubernetes/K8sDeploymentsDrawer.tsx` 33. `frontend-modern/src/components/Kubernetes/K8sNamespacesDrawer.tsx` -34. `frontend-modern/src/components/Infrastructure/ResourceActionHistory.tsx` -35. `frontend-modern/src/components/Infrastructure/ResourceFacetSummary.tsx` -36. `frontend-modern/src/components/Infrastructure/ResourceChangeSummary.tsx` -37. `frontend-modern/src/components/Infrastructure/ResourceCorrelationSummary.tsx` -38. `frontend-modern/src/components/Infrastructure/ResourcePolicySummary.tsx` -39. `frontend-modern/src/components/Infrastructure/resourceBadges.ts` -40. `frontend-modern/src/components/Infrastructure/UnifiedResourceHostTableCard.tsx` -41. `frontend-modern/src/components/Infrastructure/UnifiedResourcePBSTableSection.tsx` -42. `frontend-modern/src/components/Infrastructure/UnifiedResourcePMGTableSection.tsx` -43. `frontend-modern/src/components/Infrastructure/UnifiedResourceServiceInfrastructureCard.tsx` -44. `frontend-modern/src/components/Infrastructure/unifiedResourceTableModel.ts` -45. `frontend-modern/src/components/Infrastructure/unifiedResourceTableStateModel.ts` -46. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerDerivedState.ts` -47. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerServiceModel.ts` -48. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerVmwareModel.ts` -49. `frontend-modern/src/components/Infrastructure/resourceDetailDiscoveryModel.ts` -50. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerOperationalModel.ts` -51. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerHistoryState.ts` -52. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerDockerActionsState.ts` -53. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerState.ts` -54. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableState.ts` -55. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableViewportSync.ts` -56. `frontend-modern/src/components/Discovery/DiscoveryTab.tsx` -57. `frontend-modern/src/components/Discovery/useDiscoveryTabState.ts` -58. `frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx` -59. `frontend-modern/src/features/infrastructure/useInfrastructurePageRouteState.ts` -60. `frontend-modern/src/features/infrastructure/useInfrastructurePageState.ts` -61. `frontend-modern/src/features/infrastructure/infrastructurePageModel.ts` -62. `frontend-modern/src/components/Infrastructure/InfrastructureSummary.tsx` -63. `frontend-modern/src/components/Infrastructure/useInfrastructureSummaryState.ts` -64. `frontend-modern/src/components/Infrastructure/infrastructureSummaryModel.ts` -65. `frontend-modern/src/utils/agentResources.ts` -66. `frontend-modern/src/utils/canonicalResourceTypes.ts` -67. `frontend-modern/src/utils/resourceBadgePresentation.ts` -68. `frontend-modern/src/utils/resourceChangePresentation.ts` -69. `frontend-modern/src/utils/actionAuditPresentation.ts` -70. `frontend-modern/src/utils/resourceCorrelationPresentation.ts` -71. `frontend-modern/src/utils/resourcePlatformData.ts` -72. `frontend-modern/src/utils/resourcePolicyPresentation.ts` -73. `frontend-modern/src/utils/resourceStateAdapters.ts` -74. `frontend-modern/src/utils/resourceTypeCompat.ts` -75. `frontend-modern/src/utils/resourceTypePresentation.ts` -76. `frontend-modern/src/utils/serviceHealthPresentation.ts` -77. `frontend-modern/src/utils/sourceTypePresentation.ts` -78. `frontend-modern/src/utils/workloadTypePresentation.ts` -79. `frontend-modern/src/components/PMG/ServiceHealthBadge.tsx` -80. `frontend-modern/src/utils/resourceIdentity.ts` -81. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerIdentityModel.ts` -82. `frontend-modern/src/hooks/useUnifiedResources.ts` -83. `frontend-modern/src/types/resource.ts` -84. `frontend-modern/src/utils/sourcePlatforms.ts` -85. `frontend-modern/src/utils/platformSupportManifest.generated.ts` -86. `internal/unifiedresources/kubernetes_metric_ids.go` -87. `internal/unifiedresources/policy_posture.go` +34. `frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx` +35. `frontend-modern/src/components/Infrastructure/ResourceActionHistory.tsx` +36. `frontend-modern/src/components/Infrastructure/ResourceFacetSummary.tsx` +37. `frontend-modern/src/components/Infrastructure/ResourceChangeSummary.tsx` +38. `frontend-modern/src/components/Infrastructure/ResourceCorrelationSummary.tsx` +39. `frontend-modern/src/components/Infrastructure/ResourcePolicySummary.tsx` +40. `frontend-modern/src/components/Infrastructure/resourceBadges.ts` +41. `frontend-modern/src/components/Infrastructure/UnifiedResourceHostTableCard.tsx` +42. `frontend-modern/src/components/Infrastructure/UnifiedResourcePBSTableSection.tsx` +43. `frontend-modern/src/components/Infrastructure/UnifiedResourcePMGTableSection.tsx` +44. `frontend-modern/src/components/Infrastructure/UnifiedResourceServiceInfrastructureCard.tsx` +45. `frontend-modern/src/components/Infrastructure/unifiedResourceTableModel.ts` +46. `frontend-modern/src/components/Infrastructure/unifiedResourceTableStateModel.ts` +47. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerDerivedState.ts` +48. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerServiceModel.ts` +49. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerVmwareModel.ts` +50. `frontend-modern/src/components/Infrastructure/resourceDetailDiscoveryModel.ts` +51. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerOperationalModel.ts` +52. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerHistoryState.ts` +53. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerDockerActionsState.ts` +54. `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerState.ts` +55. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableState.ts` +56. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableViewportSync.ts` +57. `frontend-modern/src/components/Discovery/DiscoveryTab.tsx` +58. `frontend-modern/src/components/Discovery/useDiscoveryTabState.ts` +59. `frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx` +60. `frontend-modern/src/features/infrastructure/useInfrastructurePageRouteState.ts` +61. `frontend-modern/src/features/infrastructure/useInfrastructurePageState.ts` +62. `frontend-modern/src/features/infrastructure/infrastructurePageModel.ts` +63. `frontend-modern/src/components/Infrastructure/InfrastructureSummary.tsx` +64. `frontend-modern/src/components/Infrastructure/useInfrastructureSummaryState.ts` +65. `frontend-modern/src/components/Infrastructure/infrastructureSummaryModel.ts` +66. `frontend-modern/src/utils/agentResources.ts` +67. `frontend-modern/src/utils/canonicalResourceTypes.ts` +68. `frontend-modern/src/utils/resourceBadgePresentation.ts` +69. `frontend-modern/src/utils/resourceChangePresentation.ts` +70. `frontend-modern/src/utils/actionAuditPresentation.ts` +71. `frontend-modern/src/utils/resourceCorrelationPresentation.ts` +72. `frontend-modern/src/utils/resourcePlatformData.ts` +73. `frontend-modern/src/utils/resourcePolicyPresentation.ts` +74. `frontend-modern/src/utils/resourceStateAdapters.ts` +75. `frontend-modern/src/utils/resourceTypeCompat.ts` +76. `frontend-modern/src/utils/resourceTypePresentation.ts` +77. `frontend-modern/src/utils/serviceHealthPresentation.ts` +78. `frontend-modern/src/utils/sourceTypePresentation.ts` +79. `frontend-modern/src/utils/workloadTypePresentation.ts` +80. `frontend-modern/src/components/PMG/ServiceHealthBadge.tsx` +81. `frontend-modern/src/utils/resourceIdentity.ts` +82. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerIdentityModel.ts` +83. `frontend-modern/src/hooks/useUnifiedResources.ts` +84. `frontend-modern/src/types/resource.ts` +85. `frontend-modern/src/utils/sourcePlatforms.ts` +86. `frontend-modern/src/utils/platformSupportManifest.generated.ts` +87. `internal/unifiedresources/kubernetes_metric_ids.go` +88. `internal/unifiedresources/policy_posture.go` ## Shared Boundaries @@ -165,10 +166,11 @@ cross-source deduplication. infrastructure tables must use the shared `Table` primitive's scroll frame directly instead of reintroducing page-local `overflow-x-auto` wrappers inside the canonical card shell. - Docker Swarm service and Kubernetes namespace/deployment resource-drawer - tables follow that same shell boundary: their platform-specific rows and - actions are unified-resource-owned, while horizontal overflow is owned by the - shared `Table` wrapper rather than drawer-local scroll divs. + Docker Swarm service, Kubernetes namespace/deployment, and PMG detail + resource-drawer tables follow that same shell boundary: their + platform-specific rows and actions are unified-resource-owned, while + horizontal overflow is owned by the shared `Table` wrapper rather than + drawer-local scroll divs. Resource detail mappers now reuse the shared `frontend-modern/src/utils/textPresentation.ts` title-case helper for sensor @@ -228,7 +230,7 @@ AI-only summary payloads, or page-local heuristics. generic disk-count aggregate, so resource drawers and incidents do not hide the actual protection boundary behind a broader count phrase. 6. Add canonical governed name-resolution or policy-aware resource lookup behavior through `internal/unifiedresources/resolve.go` and `internal/unifiedresources/resolve_context.go` -7. Add or change resource drawer timeline/facet/action-history presentation through `frontend-modern/src/components/Infrastructure/ResourceDetailDrawer.tsx`, `frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx`, `frontend-modern/src/components/Infrastructure/ResourceDetailDrawerDebugTab.tsx`, `frontend-modern/src/components/Docker/SwarmServicesDrawer.tsx`, `frontend-modern/src/components/Kubernetes/K8sDeploymentsDrawer.tsx`, `frontend-modern/src/components/Kubernetes/K8sNamespacesDrawer.tsx`, `frontend-modern/src/components/Infrastructure/ResourceActionHistory.tsx`, `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerState.ts`, `frontend-modern/src/components/Infrastructure/ResourceFacetSummary.tsx`, `frontend-modern/src/components/Infrastructure/resourceDetailMappers.ts`, and the governed `internal/api/resources.go` facet/timeline plus `internal/api/activity_audit_handlers.go` action-audit contracts together +7. Add or change resource drawer timeline/facet/action-history presentation through `frontend-modern/src/components/Infrastructure/ResourceDetailDrawer.tsx`, `frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx`, `frontend-modern/src/components/Infrastructure/ResourceDetailDrawerDebugTab.tsx`, `frontend-modern/src/components/Docker/SwarmServicesDrawer.tsx`, `frontend-modern/src/components/Kubernetes/K8sDeploymentsDrawer.tsx`, `frontend-modern/src/components/Kubernetes/K8sNamespacesDrawer.tsx`, `frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx`, `frontend-modern/src/components/Infrastructure/ResourceActionHistory.tsx`, `frontend-modern/src/components/Infrastructure/useResourceDetailDrawerState.ts`, `frontend-modern/src/components/Infrastructure/ResourceFacetSummary.tsx`, `frontend-modern/src/components/Infrastructure/resourceDetailMappers.ts`, and the governed `internal/api/resources.go` facet/timeline plus `internal/api/activity_audit_handlers.go` action-audit contracts together 8. Add or change discovery-support runtime under the resource drawer through `frontend-modern/src/components/Discovery/DiscoveryTab.tsx` for shell/presentation ownership and `frontend-modern/src/components/Discovery/useDiscoveryTabState.ts` for fetch, websocket-progress, and notes-mutation ownership 9. Keep dashboard and infrastructure freshness on the canonical unified-resource ownership path. `frontend-modern/src/stores/websocket.ts`, diff --git a/frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx b/frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx index 1ed7727a9..987bd7c4d 100644 --- a/frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx +++ b/frontend-modern/src/components/PMG/PMGInstanceDrawer.tsx @@ -319,44 +319,40 @@ export const PMGInstanceDrawer: Component = (props) => {
{drawerPresentation.nodesSectionTitle}
-
- - - - - {drawerPresentation.nodeColumnLabel} - - - {drawerPresentation.roleColumnLabel} - - - {drawerPresentation.statusColumnLabel} - - - {drawerPresentation.queueColumnLabel} - - - - - - {(node) => ( - - - {node.name} - - {node.role || '—'} - - {node.status || '—'} - - - {formatCompact(node.queueStatus?.total ?? 0)} - - - )} - - -
-
+ + + + + {drawerPresentation.nodeColumnLabel} + + + {drawerPresentation.roleColumnLabel} + + + {drawerPresentation.statusColumnLabel} + + + {drawerPresentation.queueColumnLabel} + + + + + + {(node) => ( + + + {node.name} + + {node.role || '—'} + {node.status || '—'} + + {formatCompact(node.queueStatus?.total ?? 0)} + + + )} + + +
@@ -374,34 +370,30 @@ export const PMGInstanceDrawer: Component = (props) => { inputClass="py-1 text-xs" /> -
- - - - - {drawerPresentation.domainColumnLabel} - - - {drawerPresentation.commentColumnLabel} - - - - - - {(row) => ( - - - {row.domain} - - - {row.comment || '—'} - - - )} - - -
-
+ + + + + {drawerPresentation.domainColumnLabel} + + + {drawerPresentation.commentColumnLabel} + + + + + + {(row) => ( + + + {row.domain} + + {row.comment || '—'} + + )} + + +
@@ -426,52 +418,50 @@ export const PMGInstanceDrawer: Component = (props) => { inputClass="py-1 text-xs" /> -
- - - - - {drawerPresentation.domainColumnLabel} - - - {drawerPresentation.mailColumnLabel} - - - {drawerPresentation.spamColumnLabel} - - - {drawerPresentation.virusColumnLabel} - - - {drawerPresentation.bytesColumnLabel} - - - - - - {(row) => ( - - - {row.domain} - - - {formatCompact(row.mailCount)} - - - {formatCompact(row.spamCount)} - - - {formatCompact(row.virusCount)} - - - {row.bytes ? formatBytes(row.bytes) : '—'} - - - )} - - -
-
+ + + + + {drawerPresentation.domainColumnLabel} + + + {drawerPresentation.mailColumnLabel} + + + {drawerPresentation.spamColumnLabel} + + + {drawerPresentation.virusColumnLabel} + + + {drawerPresentation.bytesColumnLabel} + + + + + + {(row) => ( + + + {row.domain} + + + {formatCompact(row.mailCount)} + + + {formatCompact(row.spamCount)} + + + {formatCompact(row.virusCount)} + + + {row.bytes ? formatBytes(row.bytes) : '—'} + + + )} + + +
diff --git a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts index 825a6f5e9..191225a36 100644 --- a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts +++ b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts @@ -131,6 +131,7 @@ import unifiedResourceHostTableCardSource from '@/components/Infrastructure/Unif import unifiedResourceServiceInfrastructureCardSource from '@/components/Infrastructure/UnifiedResourceServiceInfrastructureCard.tsx?raw'; import unifiedResourcePBSTableSectionSource from '@/components/Infrastructure/UnifiedResourcePBSTableSection.tsx?raw'; import unifiedResourcePMGTableSectionSource from '@/components/Infrastructure/UnifiedResourcePMGTableSection.tsx?raw'; +import pmgInstanceDrawerSource from '@/components/PMG/PMGInstanceDrawer.tsx?raw'; import swarmServicesDrawerSource from '@/components/Docker/SwarmServicesDrawer.tsx?raw'; import k8sDeploymentsDrawerSource from '@/components/Kubernetes/K8sDeploymentsDrawer.tsx?raw'; import k8sNamespacesDrawerSource from '@/components/Kubernetes/K8sNamespacesDrawer.tsx?raw'; @@ -531,6 +532,7 @@ describe('shared primitive guardrails', () => { diskListSource, infrastructureSourceManagerSource, configuredNodeTablesSource, + pmgInstanceDrawerSource, swarmServicesDrawerSource, k8sDeploymentsDrawerSource, k8sNamespacesDrawerSource, diff --git a/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts b/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts index 3cb7abea7..15c699e3f 100644 --- a/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts +++ b/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts @@ -3343,6 +3343,8 @@ describe('frontend resource type boundaries', () => { expect(pmgInstanceDrawerSource).toContain('PMG_DETAILS_LOADING_STATE_TITLE'); expect(pmgInstanceDrawerSource).toContain('PMG_DETAILS_LOADING_STATE_DESCRIPTION'); expect(pmgInstanceDrawerSource).toContain('PMG_DETAILS_FAILURE_STATE_TITLE'); + expect(pmgInstanceDrawerSource).toMatch(/)/); + expect(pmgInstanceDrawerSource).not.toContain('
'); expect(pmgInstanceDrawerSource).not.toContain('Search domains...'); expect(pmgInstanceDrawerSource).not.toContain('Unknown host'); expect(pmgInstanceDrawerSource).not.toContain('Spam Distribution');