Tighten Agents platform table parity

Keep the Agents overview on shared platform table and detail-row primitives.
This commit is contained in:
rcourtman
2026-05-23 20:14:12 +01:00
parent 78d124a392
commit 3aa00e9bf6
4 changed files with 71 additions and 23 deletions
@@ -1,5 +1,4 @@
import { For, Show, type Component, type JSX } from 'solid-js';
import { ResourceDetailDrawer } from '@/components/Infrastructure/ResourceDetailDrawer';
import { StackedDiskBar } from '@/components/Workloads/StackedDiskBar';
import { StackedMemoryBar } from '@/components/Workloads/StackedMemoryBar';
import { ResponsiveMetricCell } from '@/components/shared/responsive';
@@ -15,6 +14,7 @@ import {
import { TableCard } from '@/components/shared/TableCard';
import { TableCardHeader } from '@/components/shared/TableCardHeader';
import {
PlatformResourceDetailTableRow,
createPlatformResourceDetailState,
getPlatformResourceDetailRowClass,
} from '@/features/platformPage/PlatformResourceDetailTableRow';
@@ -343,26 +343,13 @@ export const AgentsMachinesTable: Component<{
{formatLastSeen(machine.lastSeen)}
</TableCell>
</TableRow>
<Show when={isExpanded()}>
<TableRow data-inline-agent-machine-detail-for={machine.id}>
<TableCell
id={detailRowId()}
colspan={detailColspan}
class="border-b border-border bg-surface-alt p-0"
>
<div
class="px-2 py-3 sm:px-4 sm:py-4"
onClick={(event) => event.stopPropagation()}
>
<ResourceDetailDrawer
resource={machine}
presentation="table-row"
onClose={() => drawer.close(machine)}
/>
</div>
</TableCell>
</TableRow>
</Show>
<PlatformResourceDetailTableRow
resource={machine}
open={isExpanded()}
detailRowId={detailRowId()}
colSpan={detailColspan}
onClose={() => drawer.close(machine)}
/>
</>
);
}}
@@ -43,7 +43,7 @@ export function AgentsPageSurface() {
});
return (
<div data-testid="agents-page" class="space-y-3">
<div data-testid="agents-page" class="space-y-4">
<PlatformSectionTabs tabs={AGENTS_TAB_SPECS} active="overview" ariaLabel="Agents sections" />
<Show
@@ -1,4 +1,6 @@
import { describe, expect, it } from 'vitest';
import agentsMachinesTableSource from '@/features/agents/AgentsMachinesTable.tsx?raw';
import agentsPageSurfaceSource from '@/features/agents/AgentsPageSurface.tsx?raw';
import dockerHostsTableSource from '@/features/docker/DockerHostsTable.tsx?raw';
import dockerPageSurfaceSource from '@/features/docker/DockerPageSurface.tsx?raw';
import dockerServicesTableSource from '@/features/docker/DockerServicesTable.tsx?raw';
@@ -30,6 +32,7 @@ import vsphereDatastoresTableSource from '@/features/vmware/VsphereDatastoresTab
import vsphereHostsTableSource from '@/features/vmware/VsphereHostsTable.tsx?raw';
const platformTableSources = [
agentsMachinesTableSource,
proxmoxNodesTableSource,
dockerHostsTableSource,
dockerServicesTableSource,
@@ -50,6 +53,7 @@ const platformTableSources = [
];
const platformToolbarTableSources = [
agentsMachinesTableSource,
dockerHostsTableSource,
dockerServicesTableSource,
kubernetesClustersTableSource,
@@ -60,6 +64,7 @@ const platformToolbarTableSources = [
];
const overviewSurfaceSources = [
agentsPageSurfaceSource,
proxmoxPageSurfaceSource,
dockerPageSurfaceSource,
kubernetesPageSurfaceSource,
@@ -157,7 +162,7 @@ describe('platform overview layout guardrails', () => {
it('keeps provider overview pages in the parent-table plus child-inventory stack', () => {
for (const source of overviewSurfaceSources) {
expect(source).toContain('<div class="space-y-4">');
expect(source).toMatch(/<div[^>]*class="space-y-4"/);
expect(source).toContain('<PlatformSectionTabs');
expect(source).toContain('<PlatformTableLoadingState');
expect(source).toContain('PlatformTableEmptyState');
@@ -208,6 +213,14 @@ describe('platform overview layout guardrails', () => {
expect(vmwarePageSurfaceSource).not.toContain('<StorageSurface');
expect(vmwarePageSurfaceSource).not.toContain('forcedView="pools"');
expect(proxmoxPageSurfaceSource).toContain('suppressNodeFilter');
expect(agentsPageSurfaceSource).toContain('<AgentsMachinesTable');
expect(agentsPageSurfaceSource).not.toContain('InfrastructureSummary');
expect(agentsPageSurfaceSource).not.toContain('StickySummarySection');
expect(agentsPageSurfaceSource).not.toContain('ChartVisibilityToggleButton');
expect(agentsPageSurfaceSource).not.toContain('FilterBar');
expect(agentsPageSurfaceSource).not.toContain('UnifiedResourceTable');
expect(agentsMachinesTableSource).toContain('PlatformResourceDetailTableRow');
expect(agentsMachinesTableSource).not.toContain('ResourceDetailDrawer');
});
it('keeps TrueNAS overview inventory in tables instead of summary cards', () => {
@@ -270,5 +283,17 @@ describe('platform overview layout guardrails', () => {
/getPlatformTableHeadClassForKind\('numeric-value'\)[\s\S]{0,200}?VMs/,
);
expect(vsphereHostsTableSource).toContain('hidden md:table-cell');
expect(agentsMachinesTableSource).toMatch(
/getPlatformTableHeadClassForKind\('name'\)[\s\S]{0,200}?Machine/,
);
expect(agentsMachinesTableSource).toMatch(
/getPlatformTableHeadClassForKind\('metric-bar'\)[\s\S]{0,200}?CPU/,
);
expect(agentsMachinesTableSource).toMatch(
/getPlatformTableHeadClassForKind\('metric-bar'\)[\s\S]{0,200}?Memory/,
);
expect(agentsMachinesTableSource).toMatch(
/getPlatformTableHeadClassForKind\('metric-bar'\)[\s\S]{0,200}?Disk/,
);
});
});
@@ -2,6 +2,7 @@ import { cleanup, fireEvent, render, screen } from '@solidjs/testing-library';
import { afterEach, describe, expect, it, vi } from 'vitest';
import type { Resource } from '@/types/resource';
import { AgentsMachinesTable } from '@/features/agents/AgentsMachinesTable';
import { KubernetesClustersTable } from '@/features/kubernetes/KubernetesClustersTable';
import { KubernetesNodesTable } from '@/features/kubernetes/KubernetesNodesTable';
import { TrueNASStorageTopologyTable } from '@/features/truenas/TrueNASStorageTopologyTable';
@@ -34,6 +35,10 @@ vi.mock('@/components/Workloads/StackedMemoryBar', () => ({
StackedMemoryBar: () => <div data-testid="stacked-memory-bar" />,
}));
vi.mock('@/components/Workloads/StackedDiskBar', () => ({
StackedDiskBar: () => <div data-testid="stacked-disk-bar" />,
}));
const makeResource = ({
id,
type,
@@ -82,6 +87,37 @@ afterEach(() => {
});
describe('platform resource table drawers', () => {
it('opens canonical resource details from Agent machine rows', async () => {
const machine = makeResource({
id: 'agent:mac-mini',
type: 'agent',
name: 'mac-mini',
platformType: 'agent',
sourceType: 'agent',
agent: {
hostname: 'mac-mini.local',
osName: 'macOS',
osVersion: '15.2',
agentVersion: '6.0.0',
platform: 'darwin',
uptimeSeconds: 96_000,
},
});
render(() => (
<AgentsMachinesTable
resources={[machine]}
emptyIcon={<span />}
emptyTitle="No machines"
emptyDescription="No machines"
/>
));
const row = screen.getByText('mac-mini').closest('tr');
expect(row).toBeTruthy();
await expectRowOpensResourceDrawer(row!, machine.id);
});
it('opens canonical resource details from TrueNAS system rows', async () => {
const system = makeResource({
id: 'agent:truenas-main',