diff --git a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx
index 98bb4a29a..de3c6af0e 100644
--- a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx
+++ b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx
@@ -28,6 +28,10 @@ vi.mock('@/components/Discovery/DiscoveryTab', () => ({
DiscoveryTab: () =>
,
}));
+vi.mock('@/components/Workloads/StackedDiskBar', () => ({
+ StackedDiskBar: () => ,
+}));
+
vi.mock('@/api/resources', () => ({
ResourceAPI: {
getFacetBundle: vi.fn().mockResolvedValue({
@@ -40,6 +44,7 @@ vi.mock('@/api/resources', () => ({
vi.mock('@/api/ai', () => ({
AIAPI: {
+ getSettings: vi.fn().mockResolvedValue({ discovery_enabled: false }),
getResourceIntelligence: vi.fn().mockResolvedValue({
resource_id: 'resource-1',
health: {
@@ -206,6 +211,55 @@ describe('ResourceDetailDrawer service cards', () => {
expect(activeTasks.getByText('Queued')).toBeInTheDocument();
});
+ it('renders merged agent hardware for a standalone PBS host', () => {
+ const resource = baseResource({
+ id: 'pbs-agent-1',
+ type: 'pbs',
+ name: 'pbs-bare-metal',
+ displayName: 'PBS Bare Metal',
+ platformId: 'pbs-bare-metal',
+ platformType: 'proxmox-pbs',
+ sourceType: 'hybrid',
+ memory: { current: 50, total: 16_000, used: 8_000, free: 8_000 },
+ platformData: {
+ sources: ['pbs', 'agent'],
+ pbs: {
+ hostname: 'pbs-bare-metal',
+ connectionHealth: 'online',
+ datastoreCount: 1,
+ },
+ agent: {
+ agentId: 'agent-pbs-1',
+ agentVersion: '6.4.0',
+ hostname: 'pbs-bare-metal',
+ osName: 'Debian GNU/Linux',
+ osVersion: '13',
+ kernelVersion: '6.12.0-pve',
+ architecture: 'amd64',
+ cpuCount: 8,
+ networkInterfaces: [{ name: 'eno1', addresses: ['192.0.2.10'] }],
+ disks: [{ mountpoint: '/', total: 10_000, used: 4_000, free: 6_000 }],
+ sensors: { temperatureCelsius: { cpu_package: 61 } },
+ },
+ },
+ });
+
+ const { getByTestId } = render(() => (
+
+ ));
+
+ expandPlatformDetails(getByTestId);
+ const hostDetails = within(getByTestId('resource-host-details-section'));
+ expect(hostDetails.getByText('System')).toBeInTheDocument();
+ expect(hostDetails.getByText('Hardware')).toBeInTheDocument();
+ expect(hostDetails.getByText('Network')).toBeInTheDocument();
+ expect(hostDetails.getByText('Disks')).toBeInTheDocument();
+ expect(hostDetails.getByText('Thermals')).toBeInTheDocument();
+ expect(hostDetails.getByText('Debian GNU/Linux 13')).toBeInTheDocument();
+ expect(hostDetails.getByText('eno1')).toBeInTheDocument();
+ expect(hostDetails.getByText('192.0.2.10')).toBeInTheDocument();
+ });
+
it('renders PMG card with compact summary and queue/mail breakdown sections', () => {
const resource = baseResource({
id: 'pmg-1',
diff --git a/frontend-modern/src/features/proxmox/ProxmoxBackupServersTable.tsx b/frontend-modern/src/features/proxmox/ProxmoxBackupServersTable.tsx
index 394200647..b74b1a467 100644
--- a/frontend-modern/src/features/proxmox/ProxmoxBackupServersTable.tsx
+++ b/frontend-modern/src/features/proxmox/ProxmoxBackupServersTable.tsx
@@ -1,6 +1,5 @@
import { For, Show, createMemo, type Accessor, type JSX } from 'solid-js';
-import { InlineDetailTableRow } from '@/components/shared/InlineDetailTableRow';
import { StatusDot } from '@/components/shared/StatusDot';
import { TableCell, TableHead, TableRow } from '@/components/shared/Table';
import {
@@ -19,6 +18,7 @@ import {
import {
createPlatformResourceDetailState,
getPlatformResourceDetailRowInteractionProps,
+ PlatformResourceDetailTableRow,
PlatformResourceDetailToggleButton,
} from '@/features/platformPage/PlatformResourceDetailTableRow';
import type { PBSBackup } from '@/types/api';
@@ -44,6 +44,7 @@ import {
interface BackupServerRow {
key: string;
+ resource: Resource;
serverName: string;
online: boolean;
connectionLabel: string;
@@ -124,6 +125,7 @@ export function buildBackupServerRows(
const datastores = server.pbs?.datastores ?? [];
const memoryTotal = server.memory?.total ?? 0;
const host = {
+ resource: server,
serverName: server.name,
online: serverIsOnline(server),
connectionLabel: connectionLabel(server),
@@ -413,39 +415,14 @@ export function ProxmoxBackupServersTable(props: {
-
-
-
-
- Server:{' '}
- {row.serverName}
-
-
- Datastore:{' '}
- {row.datastore?.name || '—'}
-
-
- Version:{' '}
- {row.version || '—'}
-
-
- Memory:{' '}
-
- {row.memoryTotal
- ? `${formatPlatformTableBytesValue(row.memoryUsed, '0 B')} / ${formatPlatformTableBytesValue(row.memoryTotal)}`
- : '—'}
-
-
-
-
-
+ detail.close(rowIdentity)}
+ />
>
);
}}
diff --git a/frontend-modern/src/features/proxmox/__tests__/ProxmoxBackupServersTable.drawer.test.tsx b/frontend-modern/src/features/proxmox/__tests__/ProxmoxBackupServersTable.drawer.test.tsx
new file mode 100644
index 000000000..8061513bf
--- /dev/null
+++ b/frontend-modern/src/features/proxmox/__tests__/ProxmoxBackupServersTable.drawer.test.tsx
@@ -0,0 +1,69 @@
+import { fireEvent, render, screen } from '@solidjs/testing-library';
+import { describe, expect, it, vi } from 'vitest';
+
+import type { Resource } from '@/types/resource';
+import { ProxmoxBackupServersTable } from '../ProxmoxBackupServersTable';
+
+vi.mock('@/components/Infrastructure/ResourceDetailDrawer', () => ({
+ ResourceDetailDrawer: (props: {
+ resource: Resource;
+ initialShowHostDetails?: boolean;
+ onClose?: () => void;
+ }) => (
+
+
+
+ ),
+}));
+
+const makePbsResource = (): Resource =>
+ ({
+ id: 'pbs-1',
+ type: 'pbs',
+ name: 'pbs-main',
+ displayName: 'PBS Main',
+ platformId: 'pbs-main',
+ platformType: 'proxmox-pbs',
+ sourceType: 'hybrid',
+ status: 'online',
+ lastSeen: 1_700_000_000_000,
+ cpu: { current: 12.4 },
+ memory: { current: 40, total: 8_000, used: 3_200, free: 4_800 },
+ pbs: {
+ instanceId: 'pbs-main',
+ version: '3.2.1',
+ connectionHealth: 'healthy',
+ datastores: [{ name: 'tank', total: 1_000, used: 400, available: 600, usagePercent: 40 }],
+ },
+ platformData: {
+ sources: ['pbs', 'agent'],
+ agent: {
+ agentId: 'agent-pbs-1',
+ hostname: 'pbs-main',
+ osName: 'Debian GNU/Linux',
+ disks: [{ mountpoint: '/', total: 10_000, used: 4_000 }],
+ },
+ pbs: { instanceId: 'pbs-main', hostname: 'pbs-main', datastoreCount: 1 },
+ },
+ }) as Resource;
+
+describe('ProxmoxBackupServersTable details', () => {
+ it('opens the canonical resource drawer with merged host details expanded', () => {
+ render(() => );
+
+ fireEvent.click(screen.getByRole('button', { name: 'Expand details for pbs-main' }));
+
+ const detail = screen.getByTestId('pbs-resource-detail');
+ expect(detail).toHaveAttribute('data-resource-id', 'pbs-1');
+ expect(detail).toHaveAttribute('data-host-details-open', 'true');
+
+ fireEvent.click(screen.getByRole('button', { name: 'Close details' }));
+ expect(screen.queryByTestId('pbs-resource-detail')).not.toBeInTheDocument();
+ });
+});