Reduce resource drawer service headings

This commit is contained in:
rcourtman 2026-03-19 23:23:30 +00:00
parent c17774b0a6
commit 025208e5e2
4 changed files with 47 additions and 15 deletions

View file

@ -304,6 +304,10 @@ compact labels (`Docker runtime`, `Updates`, `Checked`, `Show actions`,
`Check now`, `Update all`) and short queued/confirm feedback so action
surfaces stay readable without turning the card into a paragraph of control
copy.
The remaining PBS and PMG cards also stay neutral and resource-first now:
their headings read `PBS` and `PMG`, and the primary health row is `State`
instead of `Connection`, so service support blocks read like resource status
rather than branded sub-pages.
Unsupported secondary tabs now also use the same terse availability notices
(`PMG resources only.`, `Kubernetes clusters only.`, `Docker runtimes with
Swarm only.`) instead of explanatory sentences, so mismatch fallback state

View file

@ -1145,6 +1145,7 @@ const DrawerContent: Component<ResourceDetailDrawerProps> = (props) => {
showLabel="Show service details"
hideLabel="Hide service details"
contentClass="mt-3 grid gap-3 md:grid-cols-2 lg:grid-cols-3"
dataTestId="resource-service-details-section"
>
<Show when={props.resource.type === 'docker-host'}>
<div class="rounded border border-sky-200 bg-sky-50 p-3 dark:border-sky-700 dark:bg-sky-900">
@ -1339,7 +1340,7 @@ const DrawerContent: Component<ResourceDetailDrawerProps> = (props) => {
<div class="rounded border border-indigo-200 bg-indigo-50 p-3 dark:border-indigo-700 dark:bg-indigo-900">
<div class="mb-2 flex items-center justify-between gap-2">
<div class="text-[11px] font-medium uppercase tracking-wide text-indigo-700 dark:text-indigo-300">
PBS Service
PBS
</div>
<Show when={pbs().hostname}>
<span
@ -1352,7 +1353,7 @@ const DrawerContent: Component<ResourceDetailDrawerProps> = (props) => {
</div>
<div class="space-y-1.5 text-[11px]">
<div class="flex items-center justify-between gap-2">
<span class="text-muted">Connection</span>
<span class="text-muted">State</span>
<span class={`font-medium ${connection.text}`}>{connection.label}</span>
</div>
<Show when={pbs().version}>
@ -1428,7 +1429,7 @@ const DrawerContent: Component<ResourceDetailDrawerProps> = (props) => {
<div class="rounded border border-rose-200 bg-rose-50 p-3 dark:border-rose-700 dark:bg-rose-900">
<div class="mb-2 flex items-center justify-between gap-2">
<div class="text-[11px] font-medium uppercase tracking-wide text-rose-700 dark:text-rose-300">
Mail Gateway
PMG
</div>
<Show when={pmg().hostname}>
<span
@ -1441,7 +1442,7 @@ const DrawerContent: Component<ResourceDetailDrawerProps> = (props) => {
</div>
<div class="space-y-1.5 text-[11px]">
<div class="flex items-center justify-between gap-2">
<span class="text-muted">Connection</span>
<span class="text-muted">State</span>
<span class={`font-medium ${connection.text}`}>{connection.label}</span>
</div>
<Show when={pmg().version}>

View file

@ -372,7 +372,10 @@ describe('ResourceDetailDrawer change history section', () => {
expect(screen.getByText('Service details')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: 'Show service details' }));
expect(screen.getByText('PBS Service')).toBeInTheDocument();
const serviceDetails = within(screen.getByTestId('resource-service-details-section'));
expect(serviceDetails.getByText('PBS')).toBeInTheDocument();
expect(serviceDetails.queryByText('PBS Service')).toBeNull();
expect(serviceDetails.queryByText('Connection')).toBeNull();
expect(screen.queryByText('Backup summary')).toBeNull();
expect(screen.queryByText('Job breakdown')).toBeNull();
expect(screen.queryByText('Show job detail')).toBeNull();

View file

@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest';
import { fireEvent, render, waitFor } from '@solidjs/testing-library';
import { fireEvent, render, within } from '@solidjs/testing-library';
import type { Resource } from '@/types/resource';
import { ResourceDetailDrawer } from '@/components/Infrastructure/ResourceDetailDrawer';
@ -32,6 +32,26 @@ vi.mock('@/api/resources', () => ({
},
}));
vi.mock('@/api/ai', () => ({
AIAPI: {
getResourceIntelligence: vi.fn().mockResolvedValue({
resource_id: 'resource-1',
health: {
score: 92,
grade: 'A',
trend: 'stable',
factors: [],
prediction: 'Stable',
},
recent_changes: [],
dependencies: [],
dependents: [],
correlations: [],
note_count: 0,
}),
},
}));
const baseResource = (overrides: Partial<Resource>): Resource => ({
id: 'resource-1',
type: 'agent',
@ -66,7 +86,7 @@ describe('ResourceDetailDrawer service cards', () => {
},
});
const { getByText, getAllByText, getByRole, queryByText } = render(() => (
const { getByText, getByRole, getByTestId, queryByText } = render(() => (
<ResourceDetailDrawer resource={resource} />
));
@ -74,8 +94,11 @@ describe('ResourceDetailDrawer service cards', () => {
expect(getByText('2 datastores · 3 jobs')).toBeInTheDocument();
expect(queryByText('PBS Service')).toBeNull();
fireEvent.click(getByRole('button', { name: 'Show service details' }));
expect(getByText('PBS Service')).toBeInTheDocument();
expect(getAllByText('pbs-main.local').length).toBeGreaterThan(0);
const serviceDetails = within(getByTestId('resource-service-details-section'));
expect(serviceDetails.getByText('PBS')).toBeInTheDocument();
expect(serviceDetails.queryByText('Connection')).toBeNull();
expect(serviceDetails.getAllByText('State').length).toBeGreaterThan(0);
expect(serviceDetails.getAllByText('pbs-main.local').length).toBeGreaterThan(0);
expect(queryByText('Backup summary')).toBeNull();
expect(queryByText('Job breakdown')).toBeNull();
expect(queryByText('Show job detail')).toBeNull();
@ -89,7 +112,7 @@ describe('ResourceDetailDrawer service cards', () => {
);
});
it('renders PMG card with compact summary and queue/mail breakdown sections', async () => {
it('renders PMG card with compact summary and queue/mail breakdown sections', () => {
const resource = baseResource({
id: 'pmg-1',
type: 'pmg',
@ -113,7 +136,7 @@ describe('ResourceDetailDrawer service cards', () => {
},
});
const { getByText, getAllByText, getByRole, queryByText } = render(() => (
const { getByText, getByRole, getByTestId, queryByText } = render(() => (
<ResourceDetailDrawer resource={resource} />
));
@ -121,10 +144,11 @@ describe('ResourceDetailDrawer service cards', () => {
expect(getByText('519 queue total · 16 backlog')).toBeInTheDocument();
expect(queryByText('Mail Gateway')).toBeNull();
fireEvent.click(getByRole('button', { name: 'Show service details' }));
await waitFor(() => {
expect(getByText('Mail Gateway')).toBeInTheDocument();
});
expect(getAllByText('pmg-main.local').length).toBeGreaterThan(0);
const serviceDetails = within(getByTestId('resource-service-details-section'));
expect(serviceDetails.getByText('PMG')).toBeInTheDocument();
expect(serviceDetails.queryByText('Connection')).toBeNull();
expect(serviceDetails.getAllByText('State').length).toBeGreaterThan(0);
expect(serviceDetails.getAllByText('pmg-main.local').length).toBeGreaterThan(0);
expect(queryByText('Mail flow summary')).toBeNull();
expect(queryByText('Queue breakdown')).toBeNull();
expect(queryByText('Mail processing')).toBeNull();