refactor: replace raw HTML tables in AgentHealth with DataTable composite

Replace hand-rolled <table>/<thead>/<tbody> markup in the AgentHealth page
with the existing DataTable composite, using column definitions with custom
render functions for StatusDot, Badge, and MonoText cells. Uses flush prop
for seamless GroupCard integration and pageSize=50 to avoid pagination.
Removes unused table-specific CSS classes (.instanceTable, .instanceRow,
.thStatus, .tdStatus, .instanceRowActive, .instanceCountBadge).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-24 12:29:45 +01:00
parent 8c1c953259
commit 08bac437f7
2 changed files with 76 additions and 125 deletions

View File

@@ -9,9 +9,11 @@ import { TopBar } from '../../design-system/layout/TopBar/TopBar'
// Composites
import { GroupCard } from '../../design-system/composites/GroupCard/GroupCard'
import { DataTable } from '../../design-system/composites/DataTable/DataTable'
import { LineChart } from '../../design-system/composites/LineChart/LineChart'
import { EventFeed } from '../../design-system/composites/EventFeed/EventFeed'
import { DetailPanel } from '../../design-system/composites/DetailPanel/DetailPanel'
import type { Column } from '../../design-system/composites/DataTable/types'
// Primitives
import { StatusDot } from '../../design-system/primitives/StatusDot/StatusDot'
@@ -143,6 +145,72 @@ export function AgentHealth() {
// Build trend data for selected instance
const trendData = selectedInstance ? buildTrendData(selectedInstance) : null
// Column definitions for the instance DataTable
const instanceColumns: Column<AgentHealthData>[] = useMemo(() => [
{
key: 'status',
header: '',
width: '12px',
render: (_val, row) => (
<StatusDot variant={row.status === 'live' ? 'live' : row.status === 'stale' ? 'stale' : 'dead'} />
),
},
{
key: 'name',
header: 'Instance',
render: (_val, row) => (
<MonoText size="sm" className={styles.instanceName}>{row.name}</MonoText>
),
},
{
key: 'state',
header: 'State',
render: (_val, row) => (
<Badge
label={row.status.toUpperCase()}
color={row.status === 'live' ? 'success' : row.status === 'stale' ? 'warning' : 'error'}
variant="filled"
/>
),
},
{
key: 'uptime',
header: 'Uptime',
render: (_val, row) => (
<MonoText size="xs" className={styles.instanceMeta}>{row.uptime}</MonoText>
),
},
{
key: 'tps',
header: 'TPS',
render: (_val, row) => (
<MonoText size="xs" className={styles.instanceMeta}>{row.tps.toFixed(1)}/s</MonoText>
),
},
{
key: 'errorRate',
header: 'Errors',
render: (_val, row) => (
<MonoText size="xs" className={row.errorRate ? styles.instanceError : styles.instanceMeta}>
{row.errorRate ?? '0 err/h'}
</MonoText>
),
},
{
key: 'lastSeen',
header: 'Heartbeat',
render: (_val, row) => (
<MonoText size="xs" className={
row.status === 'dead' ? styles.instanceHeartbeatDead :
row.status === 'stale' ? styles.instanceHeartbeatStale :
styles.instanceMeta
}>
{row.lastSeen}
</MonoText>
),
},
], [])
function handleInstanceClick(inst: AgentHealthData) {
setSelectedInstance(inst)
setPanelOpen(true)
@@ -362,65 +430,14 @@ export function AgentHealth() {
</div>
) : undefined}
>
<table className={styles.instanceTable}>
<thead>
<tr>
<th className={styles.thStatus} />
<th>Instance</th>
<th>State</th>
<th>Uptime</th>
<th>TPS</th>
<th>Errors</th>
<th>Heartbeat</th>
</tr>
</thead>
<tbody>
{group.instances.map((inst) => (
<tr
key={inst.id}
className={[
styles.instanceRow,
selectedInstance?.id === inst.id && panelOpen ? styles.instanceRowActive : '',
].filter(Boolean).join(' ')}
onClick={() => handleInstanceClick(inst)}
>
<td className={styles.tdStatus}>
<StatusDot variant={inst.status === 'live' ? 'live' : inst.status === 'stale' ? 'stale' : 'dead'} />
</td>
<td>
<MonoText size="sm" className={styles.instanceName}>{inst.name}</MonoText>
</td>
<td>
<Badge
label={inst.status.toUpperCase()}
color={inst.status === 'live' ? 'success' : inst.status === 'stale' ? 'warning' : 'error'}
variant="filled"
/>
</td>
<td>
<MonoText size="xs" className={styles.instanceMeta}>{inst.uptime}</MonoText>
</td>
<td>
<MonoText size="xs" className={styles.instanceMeta}>{inst.tps.toFixed(1)}/s</MonoText>
</td>
<td>
<MonoText size="xs" className={inst.errorRate ? styles.instanceError : styles.instanceMeta}>
{inst.errorRate ?? '0 err/h'}
</MonoText>
</td>
<td>
<MonoText size="xs" className={
inst.status === 'dead' ? styles.instanceHeartbeatDead :
inst.status === 'stale' ? styles.instanceHeartbeatStale :
styles.instanceMeta
}>
{inst.lastSeen}
</MonoText>
</td>
</tr>
))}
</tbody>
</table>
<DataTable<AgentHealthData>
columns={instanceColumns}
data={group.instances}
onRowClick={handleInstanceClick}
selectedId={panelOpen ? selectedInstance?.id : undefined}
pageSize={50}
flush
/>
</GroupCard>
))}
</div>