feat(web): make instance detail the operations workbench

This commit is contained in:
chick
2026-07-19 14:05:06 +08:00
parent f7d69a0fa7
commit 75682b8134
8 changed files with 663 additions and 140 deletions
+45
View File
@@ -0,0 +1,45 @@
// @vitest-environment jsdom
import { cleanup, render, screen, within } from '@testing-library/react';
import { afterEach, describe, expect, it } from 'vitest';
import { FleetPage, type FleetSnapshot } from './fleet-page.js';
const snapshot: FleetSnapshot = {
instances: [
{
id: 'alpha',
name: 'Alpha modem',
url: 'http://192.168.1.2',
tags: [],
},
],
statuses: new Map([
[
'alpha',
{
instanceId: 'alpha',
connectivity: 'online',
authentication: 'authenticated',
freshness: 'fresh',
capabilities: ['overview', 'messages'],
anomalies: [],
},
],
]),
};
afterEach(cleanup);
describe('FleetPage card navigation', () => {
it('makes the whole instance card open its dashboard while admin controls stay separately interactive', () => {
render(<FleetPage initialData={snapshot} />);
const card = screen.getByRole('article', { name: 'Alpha modem 实例概览' });
const entry = within(card).getByRole('link', { name: '打开 Alpha modem 实例仪表盘' });
expect(entry.getAttribute('href')).toBe('/instances/alpha/overview');
expect(entry.classList.contains('fleet-card-entry')).toBe(true);
expect(within(card).getByRole('link', { name: '编辑 Alpha modem' })).toBeTruthy();
expect(within(card).getByRole('button', { name: '删除 Alpha modem' })).toBeTruthy();
expect(within(card).queryByRole('link', { name: /查看.*短信/ })).toBeNull();
});
});
+7 -10
View File
@@ -458,10 +458,14 @@ export function FleetPage({
key={row.id}
>
<header>
<div>
<a
className="fleet-card-entry"
href={`/instances/${encodeURIComponent(row.id)}/overview`}
aria-label={`打开 ${row.displayName} 实例仪表盘`}
>
<h2>{row.displayName}</h2>
<code>{row.id}</code>
</div>
</a>
<span className={`status status-${row.statusKind}`}>
{STATUS_LABELS[row.statusKind]}
</span>
@@ -520,14 +524,7 @@ export function FleetPage({
<p className="fleet-card-sms-empty"></p>
)}
</section>
<div className="fleet-card-actions">
<a
className="primary-action"
href={`/instances/${encodeURIComponent(row.id)}/messages`}
aria-label={`查看 ${row.displayName} 的短信`}
>
</a>
<div className="fleet-card-actions fleet-card-admin-actions">
<a
href={`/settings/instances/${encodeURIComponent(row.id)}`}
aria-label={`编辑 ${row.displayName}`}