2026-03-26 12:51:07 +01:00
|
|
|
import { useState, useMemo, useCallback } from 'react';
|
2026-03-26 12:01:57 +01:00
|
|
|
import { useParams, useNavigate } from 'react-router';
|
2026-04-09 08:28:31 +02:00
|
|
|
import { ExternalLink, RefreshCw, Pencil } from 'lucide-react';
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
import {
|
2026-03-30 16:28:12 +02:00
|
|
|
StatCard, StatusDot, Badge, MonoText,
|
|
|
|
|
GroupCard, DataTable, EventFeed,
|
2026-04-09 15:22:14 +02:00
|
|
|
LogViewer, ButtonGroup, SectionHeader, Toggle, Select, Button, useToast,
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
} from '@cameleer/design-system';
|
2026-03-25 22:54:07 +01:00
|
|
|
import type { Column, FeedEvent, LogEntry, ButtonGroupItem } from '@cameleer/design-system';
|
2026-03-19 18:16:16 +01:00
|
|
|
import styles from './AgentHealth.module.css';
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
import logStyles from '../../styles/log-panel.module.css';
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
import { useAgents, useAgentEvents } from '../../api/queries/agents';
|
2026-03-25 22:54:07 +01:00
|
|
|
import { useApplicationLogs } from '../../api/queries/logs';
|
2026-03-26 12:51:07 +01:00
|
|
|
import { useApplicationConfig, useUpdateApplicationConfig } from '../../api/queries/commands';
|
2026-04-02 19:08:00 +02:00
|
|
|
import type { ConfigUpdateResponse } from '../../api/queries/commands';
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
import type { AgentInstance } from '../../api/types';
|
2026-04-09 08:28:31 +02:00
|
|
|
import { timeAgo } from '../../utils/format-utils';
|
|
|
|
|
import { formatUptime, mapLogLevel, eventSeverity, eventIcon } from '../../utils/agent-utils';
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
|
|
|
|
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
function formatErrorRate(rate?: number): string {
|
|
|
|
|
if (rate == null) return '\u2014';
|
|
|
|
|
return `${(rate * 100).toFixed(1)}%`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type NormStatus = 'live' | 'stale' | 'dead';
|
|
|
|
|
|
|
|
|
|
function normalizeStatus(status: string): NormStatus {
|
|
|
|
|
return status.toLowerCase() as NormStatus;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function statusColor(s: NormStatus): 'success' | 'warning' | 'error' {
|
|
|
|
|
if (s === 'live') return 'success';
|
|
|
|
|
if (s === 'stale') return 'warning';
|
|
|
|
|
return 'error';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Data grouping ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
interface AppGroup {
|
|
|
|
|
appId: string;
|
|
|
|
|
instances: AgentInstance[];
|
|
|
|
|
liveCount: number;
|
|
|
|
|
staleCount: number;
|
|
|
|
|
deadCount: number;
|
|
|
|
|
totalTps: number;
|
|
|
|
|
totalActiveRoutes: number;
|
|
|
|
|
totalRoutes: number;
|
2026-03-23 18:25:14 +01:00
|
|
|
}
|
|
|
|
|
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
function groupByApp(agentList: AgentInstance[]): AppGroup[] {
|
|
|
|
|
const map = new Map<string, AgentInstance[]>();
|
|
|
|
|
for (const a of agentList) {
|
fix: update agent field names in frontend to match backend DTO
The AgentInstanceResponse backend DTO uses instanceId, displayName,
applicationId, status — but the stale schema.d.ts still had id, name,
application, state. This caused the runtime table to show no data.
- Update schema.d.ts AgentInstanceResponse fields
- Fix AgentHealth: row.id→instanceId, row.name→displayName,
row.application→applicationId, inst.id→instanceId
- Fix AgentInstance: agent.id→instanceId, agent.name→displayName
- Fix ExchangeHeader: agent.id→instanceId, agent.state→status
- Fix LayoutShell search: agent.state→status, agentTps→tps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:36:31 +02:00
|
|
|
const app = a.applicationId;
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
const list = map.get(app) ?? [];
|
|
|
|
|
list.push(a);
|
|
|
|
|
map.set(app, list);
|
|
|
|
|
}
|
|
|
|
|
return Array.from(map.entries()).map(([appId, instances]) => ({
|
|
|
|
|
appId,
|
|
|
|
|
instances,
|
|
|
|
|
liveCount: instances.filter((i) => normalizeStatus(i.status) === 'live').length,
|
|
|
|
|
staleCount: instances.filter((i) => normalizeStatus(i.status) === 'stale').length,
|
|
|
|
|
deadCount: instances.filter((i) => normalizeStatus(i.status) === 'dead').length,
|
|
|
|
|
totalTps: instances.reduce((s, i) => s + (i.tps ?? 0), 0),
|
|
|
|
|
totalActiveRoutes: instances.reduce((s, i) => s + (i.activeRoutes ?? 0), 0),
|
|
|
|
|
totalRoutes: instances.reduce((s, i) => s + (i.totalRoutes ?? 0), 0),
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function appHealth(group: AppGroup): 'success' | 'warning' | 'error' {
|
|
|
|
|
if (group.deadCount > 0) return 'error';
|
|
|
|
|
if (group.staleCount > 0) return 'warning';
|
|
|
|
|
return 'success';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Detail sub-components ────────────────────────────────────────────────────
|
|
|
|
|
|
2026-03-25 22:54:07 +01:00
|
|
|
const LOG_LEVEL_ITEMS: ButtonGroupItem[] = [
|
|
|
|
|
{ value: 'error', label: 'Error', color: 'var(--error)' },
|
|
|
|
|
{ value: 'warn', label: 'Warn', color: 'var(--warning)' },
|
|
|
|
|
{ value: 'info', label: 'Info', color: 'var(--success)' },
|
|
|
|
|
{ value: 'debug', label: 'Debug', color: 'var(--running)' },
|
2026-03-26 23:03:15 +01:00
|
|
|
{ value: 'trace', label: 'Trace', color: 'var(--text-muted)' },
|
2026-03-25 22:54:07 +01:00
|
|
|
];
|
|
|
|
|
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
// ── AgentHealth page ─────────────────────────────────────────────────────────
|
|
|
|
|
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
export default function AgentHealth() {
|
|
|
|
|
const { appId } = useParams();
|
2026-03-26 12:01:57 +01:00
|
|
|
const navigate = useNavigate();
|
2026-03-26 12:51:07 +01:00
|
|
|
const { toast } = useToast();
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
const { data: agents } = useAgents(undefined, appId);
|
2026-03-26 12:51:07 +01:00
|
|
|
const { data: appConfig } = useApplicationConfig(appId);
|
|
|
|
|
const updateConfig = useUpdateApplicationConfig();
|
|
|
|
|
|
2026-03-26 13:12:56 +01:00
|
|
|
const [configEditing, setConfigEditing] = useState(false);
|
|
|
|
|
const [configDraft, setConfigDraft] = useState<Record<string, string | boolean>>({});
|
|
|
|
|
|
|
|
|
|
const startConfigEdit = useCallback(() => {
|
|
|
|
|
if (!appConfig) return;
|
|
|
|
|
setConfigDraft({
|
2026-03-26 23:36:31 +01:00
|
|
|
applicationLogLevel: appConfig.applicationLogLevel ?? 'INFO',
|
|
|
|
|
agentLogLevel: appConfig.agentLogLevel ?? 'INFO',
|
2026-03-26 13:12:56 +01:00
|
|
|
engineLevel: appConfig.engineLevel ?? 'REGULAR',
|
|
|
|
|
payloadCaptureMode: appConfig.payloadCaptureMode ?? 'NONE',
|
|
|
|
|
metricsEnabled: appConfig.metricsEnabled,
|
|
|
|
|
});
|
|
|
|
|
setConfigEditing(true);
|
|
|
|
|
}, [appConfig]);
|
|
|
|
|
|
|
|
|
|
const saveConfigEdit = useCallback(() => {
|
2026-03-26 12:51:07 +01:00
|
|
|
if (!appConfig) return;
|
2026-03-26 13:12:56 +01:00
|
|
|
const updated = { ...appConfig, ...configDraft };
|
2026-03-26 12:51:07 +01:00
|
|
|
updateConfig.mutate(updated, {
|
2026-04-02 19:08:00 +02:00
|
|
|
onSuccess: (saved: ConfigUpdateResponse) => {
|
2026-03-26 13:12:56 +01:00
|
|
|
setConfigEditing(false);
|
|
|
|
|
setConfigDraft({});
|
2026-04-02 19:08:00 +02:00
|
|
|
if (saved.pushResult.success) {
|
|
|
|
|
toast({ title: 'Config updated', description: `${appId} (v${saved.config.version}) — pushed to ${saved.pushResult.total}/${saved.pushResult.total} agents`, variant: 'success' });
|
|
|
|
|
} else {
|
|
|
|
|
const failed = [...saved.pushResult.responses.filter(r => r.status !== 'SUCCESS').map(r => r.agentId), ...saved.pushResult.timedOut];
|
|
|
|
|
toast({ title: 'Config updated — partial push failure', description: `${saved.pushResult.responded}/${saved.pushResult.total} responded. Failed: ${failed.join(', ')}`, variant: 'warning', duration: 86_400_000 });
|
|
|
|
|
}
|
2026-03-26 12:51:07 +01:00
|
|
|
},
|
|
|
|
|
onError: () => {
|
2026-04-02 19:08:00 +02:00
|
|
|
toast({ title: 'Config update failed', variant: 'error', duration: 86_400_000 });
|
2026-03-26 12:51:07 +01:00
|
|
|
},
|
|
|
|
|
});
|
2026-03-26 13:12:56 +01:00
|
|
|
}, [appConfig, configDraft, updateConfig, toast, appId]);
|
2026-03-25 19:53:33 +01:00
|
|
|
const [eventSortAsc, setEventSortAsc] = useState(false);
|
2026-03-25 22:41:00 +01:00
|
|
|
const [eventRefreshTo, setEventRefreshTo] = useState<string | undefined>();
|
|
|
|
|
const { data: events } = useAgentEvents(appId, undefined, 50, eventRefreshTo);
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
|
2026-03-25 22:54:07 +01:00
|
|
|
const [logSearch, setLogSearch] = useState('');
|
|
|
|
|
const [logLevels, setLogLevels] = useState<Set<string>>(new Set());
|
|
|
|
|
const [logSortAsc, setLogSortAsc] = useState(false);
|
|
|
|
|
const [logRefreshTo, setLogRefreshTo] = useState<string | undefined>();
|
|
|
|
|
const { data: rawLogs } = useApplicationLogs(appId, undefined, { toOverride: logRefreshTo });
|
|
|
|
|
const logEntries = useMemo<LogEntry[]>(() => {
|
|
|
|
|
const mapped = (rawLogs || []).map((l) => ({
|
|
|
|
|
timestamp: l.timestamp ?? '',
|
|
|
|
|
level: mapLogLevel(l.level),
|
|
|
|
|
message: l.message ?? '',
|
|
|
|
|
}));
|
|
|
|
|
return logSortAsc ? mapped.toReversed() : mapped;
|
|
|
|
|
}, [rawLogs, logSortAsc]);
|
|
|
|
|
const logSearchLower = logSearch.toLowerCase();
|
|
|
|
|
const filteredLogs = logEntries
|
|
|
|
|
.filter((l) => logLevels.size === 0 || logLevels.has(l.level))
|
|
|
|
|
.filter((l) => !logSearchLower || l.message.toLowerCase().includes(logSearchLower));
|
|
|
|
|
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
const agentList = agents ?? [];
|
|
|
|
|
|
|
|
|
|
const groups = useMemo(() => groupByApp(agentList), [agentList]);
|
|
|
|
|
|
|
|
|
|
// Aggregate stats
|
|
|
|
|
const totalInstances = agentList.length;
|
|
|
|
|
const liveCount = agentList.filter((a) => normalizeStatus(a.status) === 'live').length;
|
|
|
|
|
const staleCount = agentList.filter((a) => normalizeStatus(a.status) === 'stale').length;
|
|
|
|
|
const deadCount = agentList.filter((a) => normalizeStatus(a.status) === 'dead').length;
|
|
|
|
|
const totalTps = agentList.reduce((s, a) => s + (a.tps ?? 0), 0);
|
|
|
|
|
const totalActiveRoutes = agentList.reduce((s, a) => s + (a.activeRoutes ?? 0), 0);
|
|
|
|
|
const totalRoutes = agentList.reduce((s, a) => s + (a.totalRoutes ?? 0), 0);
|
|
|
|
|
|
|
|
|
|
// Map events to FeedEvent
|
2026-03-25 19:53:33 +01:00
|
|
|
const feedEvents: FeedEvent[] = useMemo(() => {
|
2026-04-01 20:18:06 +02:00
|
|
|
const mapped = (events ?? []).map((e: { id: number; instanceId: string; eventType: string; detail: string; timestamp: string }) => ({
|
2026-03-25 19:53:33 +01:00
|
|
|
id: String(e.id),
|
2026-04-02 23:06:01 +02:00
|
|
|
severity: eventSeverity(e.eventType),
|
|
|
|
|
icon: eventIcon(e.eventType),
|
fix: update frontend field names for identity rename (applicationId, instanceId)
The backend identity rename (applicationName → applicationId,
agentId → instanceId) was not reflected in the frontend. This caused
drilldown to fail (detail.applicationName was undefined, disabling
the diagram fetch) and various display issues.
Updated schema.d.ts, ExchangeHeader, ExecutionDiagram, Dashboard,
AgentHealth, AgentInstance, LayoutShell, LogTab, InfoTab, DetailPanel,
ExchangesPage, and tracing-store.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
|
|
|
message: `${e.instanceId}: ${e.eventType}${e.detail ? ' \u2014 ' + e.detail : ''}`,
|
2026-03-25 19:53:33 +01:00
|
|
|
timestamp: new Date(e.timestamp),
|
|
|
|
|
}));
|
|
|
|
|
return eventSortAsc ? mapped.toReversed() : mapped;
|
2026-04-02 23:06:01 +02:00
|
|
|
}, [events, eventSortAsc]);
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
// Column definitions for the instance DataTable
|
|
|
|
|
const instanceColumns: Column<AgentInstance>[] = useMemo(
|
|
|
|
|
() => [
|
|
|
|
|
{
|
|
|
|
|
key: 'status',
|
|
|
|
|
header: '',
|
|
|
|
|
width: '12px',
|
|
|
|
|
render: (_val, row) => <StatusDot variant={normalizeStatus(row.status)} />,
|
|
|
|
|
},
|
2026-03-26 12:01:57 +01:00
|
|
|
{
|
|
|
|
|
key: '_inspect',
|
|
|
|
|
header: '',
|
|
|
|
|
width: '36px',
|
|
|
|
|
render: (_val, row) => (
|
|
|
|
|
<button
|
|
|
|
|
className={styles.inspectLink}
|
|
|
|
|
title="Open instance page"
|
|
|
|
|
onClick={(e) => {
|
|
|
|
|
e.stopPropagation();
|
fix: update agent field names in frontend to match backend DTO
The AgentInstanceResponse backend DTO uses instanceId, displayName,
applicationId, status — but the stale schema.d.ts still had id, name,
application, state. This caused the runtime table to show no data.
- Update schema.d.ts AgentInstanceResponse fields
- Fix AgentHealth: row.id→instanceId, row.name→displayName,
row.application→applicationId, inst.id→instanceId
- Fix AgentInstance: agent.id→instanceId, agent.name→displayName
- Fix ExchangeHeader: agent.id→instanceId, agent.state→status
- Fix LayoutShell search: agent.state→status, agentTps→tps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:36:31 +02:00
|
|
|
navigate(`/agents/${row.applicationId}/${row.instanceId}`);
|
2026-03-26 12:01:57 +01:00
|
|
|
}}
|
|
|
|
|
>
|
2026-03-27 23:16:39 +01:00
|
|
|
<ExternalLink size={14} />
|
2026-03-26 12:01:57 +01:00
|
|
|
</button>
|
|
|
|
|
),
|
|
|
|
|
},
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
{
|
|
|
|
|
key: 'name',
|
|
|
|
|
header: 'Instance',
|
|
|
|
|
render: (_val, row) => (
|
fix: update agent field names in frontend to match backend DTO
The AgentInstanceResponse backend DTO uses instanceId, displayName,
applicationId, status — but the stale schema.d.ts still had id, name,
application, state. This caused the runtime table to show no data.
- Update schema.d.ts AgentInstanceResponse fields
- Fix AgentHealth: row.id→instanceId, row.name→displayName,
row.application→applicationId, inst.id→instanceId
- Fix AgentInstance: agent.id→instanceId, agent.name→displayName
- Fix ExchangeHeader: agent.id→instanceId, agent.state→status
- Fix LayoutShell search: agent.state→status, agentTps→tps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:36:31 +02:00
|
|
|
<MonoText size="sm" className={styles.instanceName}>{row.displayName ?? row.instanceId}</MonoText>
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'state',
|
|
|
|
|
header: 'State',
|
|
|
|
|
render: (_val, row) => {
|
|
|
|
|
const ns = normalizeStatus(row.status);
|
|
|
|
|
return <Badge label={row.status} color={statusColor(ns)} variant="filled" />;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'uptime',
|
|
|
|
|
header: 'Uptime',
|
|
|
|
|
render: (_val, row) => (
|
|
|
|
|
<MonoText size="xs" className={styles.instanceMeta}>{formatUptime(row.uptimeSeconds)}</MonoText>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'tps',
|
|
|
|
|
header: 'TPS',
|
|
|
|
|
render: (_val, row) => (
|
|
|
|
|
<MonoText size="xs" className={styles.instanceMeta}>
|
|
|
|
|
{row.tps != null ? `${row.tps.toFixed(1)}/s` : '\u2014'}
|
|
|
|
|
</MonoText>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'errorRate',
|
|
|
|
|
header: 'Errors',
|
|
|
|
|
render: (_val, row) => (
|
|
|
|
|
<MonoText size="xs" className={row.errorRate ? styles.instanceError : styles.instanceMeta}>
|
|
|
|
|
{formatErrorRate(row.errorRate)}
|
|
|
|
|
</MonoText>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'lastHeartbeat',
|
|
|
|
|
header: 'Heartbeat',
|
|
|
|
|
render: (_val, row) => {
|
|
|
|
|
const ns = normalizeStatus(row.status);
|
|
|
|
|
return (
|
|
|
|
|
<MonoText
|
|
|
|
|
size="xs"
|
|
|
|
|
className={
|
|
|
|
|
ns === 'dead'
|
|
|
|
|
? styles.instanceHeartbeatDead
|
|
|
|
|
: ns === 'stale'
|
|
|
|
|
? styles.instanceHeartbeatStale
|
|
|
|
|
: styles.instanceMeta
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{timeAgo(row.lastHeartbeat)}
|
|
|
|
|
</MonoText>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
[],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
function handleInstanceClick(inst: AgentInstance) {
|
fix: update agent field names in frontend to match backend DTO
The AgentInstanceResponse backend DTO uses instanceId, displayName,
applicationId, status — but the stale schema.d.ts still had id, name,
application, state. This caused the runtime table to show no data.
- Update schema.d.ts AgentInstanceResponse fields
- Fix AgentHealth: row.id→instanceId, row.name→displayName,
row.application→applicationId, inst.id→instanceId
- Fix AgentInstance: agent.id→instanceId, agent.name→displayName
- Fix ExchangeHeader: agent.id→instanceId, agent.state→status
- Fix LayoutShell search: agent.state→status, agentTps→tps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:36:31 +02:00
|
|
|
navigate(`/runtime/${inst.applicationId}/${inst.instanceId}`);
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isFullWidth = !!appId;
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
|
|
|
|
|
return (
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
<div className={styles.content}>
|
|
|
|
|
{/* Stat strip */}
|
2026-03-19 18:16:16 +01:00
|
|
|
<div className={styles.statStrip}>
|
2026-03-23 21:50:16 +01:00
|
|
|
<StatCard
|
|
|
|
|
label="Total Agents"
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
value={String(totalInstances)}
|
|
|
|
|
accent={deadCount > 0 ? 'warning' : 'amber'}
|
|
|
|
|
detail={
|
|
|
|
|
<span className={styles.breakdown}>
|
|
|
|
|
<span className={styles.bpLive}><StatusDot variant="live" /> {liveCount} live</span>
|
|
|
|
|
<span className={styles.bpStale}><StatusDot variant="stale" /> {staleCount} stale</span>
|
|
|
|
|
<span className={styles.bpDead}><StatusDot variant="dead" /> {deadCount} dead</span>
|
|
|
|
|
</span>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<StatCard
|
|
|
|
|
label="Applications"
|
|
|
|
|
value={String(groups.length)}
|
|
|
|
|
accent="running"
|
2026-03-23 21:50:16 +01:00
|
|
|
detail={
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
<span className={styles.breakdown}>
|
|
|
|
|
<span className={styles.bpLive}>
|
|
|
|
|
<StatusDot variant="live" /> {groups.filter((g) => g.deadCount === 0 && g.staleCount === 0).length} healthy
|
|
|
|
|
</span>
|
|
|
|
|
<span className={styles.bpStale}>
|
|
|
|
|
<StatusDot variant="stale" /> {groups.filter((g) => g.staleCount > 0 && g.deadCount === 0).length} degraded
|
|
|
|
|
</span>
|
|
|
|
|
<span className={styles.bpDead}>
|
|
|
|
|
<StatusDot variant="dead" /> {groups.filter((g) => g.deadCount > 0).length} critical
|
|
|
|
|
</span>
|
2026-03-23 21:50:16 +01:00
|
|
|
</span>
|
|
|
|
|
}
|
|
|
|
|
/>
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
<StatCard
|
|
|
|
|
label="Active Routes"
|
|
|
|
|
value={
|
|
|
|
|
<span
|
|
|
|
|
className={
|
|
|
|
|
styles[
|
|
|
|
|
totalActiveRoutes === 0
|
|
|
|
|
? 'routesError'
|
|
|
|
|
: totalActiveRoutes < totalRoutes
|
|
|
|
|
? 'routesWarning'
|
|
|
|
|
: 'routesSuccess'
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{totalActiveRoutes}/{totalRoutes}
|
|
|
|
|
</span>
|
|
|
|
|
}
|
|
|
|
|
accent={totalActiveRoutes === 0 ? 'error' : totalActiveRoutes < totalRoutes ? 'warning' : 'success'}
|
|
|
|
|
detail={totalActiveRoutes < totalRoutes ? `${totalRoutes - totalActiveRoutes} suspended` : 'all routes active'}
|
|
|
|
|
/>
|
|
|
|
|
<StatCard
|
|
|
|
|
label="Total TPS"
|
|
|
|
|
value={totalTps.toFixed(1)}
|
|
|
|
|
accent="amber"
|
|
|
|
|
detail="msg/s"
|
|
|
|
|
/>
|
|
|
|
|
<StatCard
|
|
|
|
|
label="Dead"
|
|
|
|
|
value={String(deadCount)}
|
|
|
|
|
accent={deadCount > 0 ? 'error' : 'success'}
|
|
|
|
|
detail={deadCount > 0 ? 'requires attention' : 'all healthy'}
|
|
|
|
|
/>
|
2026-03-23 18:25:14 +01:00
|
|
|
</div>
|
|
|
|
|
|
2026-03-26 11:40:37 +01:00
|
|
|
<div style={{ marginBottom: 12 }}>
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
<Badge
|
|
|
|
|
label={`${liveCount}/${totalInstances} live`}
|
|
|
|
|
color={deadCount > 0 ? 'error' : staleCount > 0 ? 'warning' : 'success'}
|
|
|
|
|
variant="filled"
|
|
|
|
|
/>
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
</div>
|
|
|
|
|
|
2026-03-26 12:51:07 +01:00
|
|
|
{/* Application config bar */}
|
|
|
|
|
{appId && appConfig && (
|
|
|
|
|
<div className={styles.configBar}>
|
2026-03-26 13:12:56 +01:00
|
|
|
{configEditing ? (
|
|
|
|
|
<>
|
|
|
|
|
<div className={styles.configField}>
|
2026-03-26 23:36:31 +01:00
|
|
|
<span className={styles.configLabel}>App Log Level</span>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Select value={String(configDraft.applicationLogLevel ?? 'INFO')}
|
|
|
|
|
onChange={(e) => setConfigDraft(d => ({ ...d, applicationLogLevel: e.target.value }))}
|
|
|
|
|
options={[
|
|
|
|
|
{ value: 'ERROR', label: 'ERROR' },
|
|
|
|
|
{ value: 'WARN', label: 'WARN' },
|
|
|
|
|
{ value: 'INFO', label: 'INFO' },
|
|
|
|
|
{ value: 'DEBUG', label: 'DEBUG' },
|
|
|
|
|
{ value: 'TRACE', label: 'TRACE' },
|
|
|
|
|
]}
|
|
|
|
|
/>
|
2026-03-26 23:36:31 +01:00
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Agent Log Level</span>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Select value={String(configDraft.agentLogLevel ?? 'INFO')}
|
|
|
|
|
onChange={(e) => setConfigDraft(d => ({ ...d, agentLogLevel: e.target.value }))}
|
|
|
|
|
options={[
|
|
|
|
|
{ value: 'ERROR', label: 'ERROR' },
|
|
|
|
|
{ value: 'WARN', label: 'WARN' },
|
|
|
|
|
{ value: 'INFO', label: 'INFO' },
|
|
|
|
|
{ value: 'DEBUG', label: 'DEBUG' },
|
|
|
|
|
{ value: 'TRACE', label: 'TRACE' },
|
|
|
|
|
]}
|
|
|
|
|
/>
|
2026-03-26 13:12:56 +01:00
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Engine Level</span>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Select value={String(configDraft.engineLevel ?? 'REGULAR')}
|
|
|
|
|
onChange={(e) => setConfigDraft(d => ({ ...d, engineLevel: e.target.value }))}
|
|
|
|
|
options={[
|
|
|
|
|
{ value: 'NONE', label: 'None' },
|
|
|
|
|
{ value: 'MINIMAL', label: 'Minimal' },
|
|
|
|
|
{ value: 'REGULAR', label: 'Regular' },
|
|
|
|
|
{ value: 'COMPLETE', label: 'Complete' },
|
|
|
|
|
]}
|
|
|
|
|
/>
|
2026-03-26 13:12:56 +01:00
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Payload Capture</span>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Select value={String(configDraft.payloadCaptureMode ?? 'NONE')}
|
|
|
|
|
onChange={(e) => setConfigDraft(d => ({ ...d, payloadCaptureMode: e.target.value }))}
|
|
|
|
|
options={[
|
|
|
|
|
{ value: 'NONE', label: 'None' },
|
|
|
|
|
{ value: 'INPUT', label: 'Input' },
|
|
|
|
|
{ value: 'OUTPUT', label: 'Output' },
|
|
|
|
|
{ value: 'BOTH', label: 'Both' },
|
|
|
|
|
]}
|
|
|
|
|
/>
|
2026-03-26 13:12:56 +01:00
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Metrics</span>
|
2026-03-26 21:30:35 +01:00
|
|
|
<Toggle checked={Boolean(configDraft.metricsEnabled)}
|
|
|
|
|
onChange={(e) => setConfigDraft(d => ({ ...d, metricsEnabled: (e.target as HTMLInputElement).checked }))} />
|
2026-03-26 13:12:56 +01:00
|
|
|
</div>
|
2026-03-26 21:28:30 +01:00
|
|
|
<div className={styles.configActions}>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Button variant="primary" size="sm" onClick={saveConfigEdit} disabled={updateConfig.isPending}>Save</Button>
|
|
|
|
|
<Button variant="secondary" size="sm" onClick={() => { setConfigEditing(false); setConfigDraft({}); }}>Cancel</Button>
|
2026-03-26 21:28:30 +01:00
|
|
|
</div>
|
2026-03-26 13:12:56 +01:00
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<>
|
|
|
|
|
<div className={styles.configField}>
|
2026-03-26 23:36:31 +01:00
|
|
|
<span className={styles.configLabel}>App Log Level</span>
|
|
|
|
|
<Badge label={appConfig.applicationLogLevel ?? 'INFO'} color={
|
|
|
|
|
(appConfig.applicationLogLevel ?? 'INFO') === 'ERROR' ? 'error'
|
|
|
|
|
: (appConfig.applicationLogLevel ?? 'INFO') === 'WARN' ? 'warning'
|
|
|
|
|
: (appConfig.applicationLogLevel ?? 'INFO') === 'DEBUG' ? 'running'
|
|
|
|
|
: (appConfig.applicationLogLevel ?? 'INFO') === 'TRACE' ? 'auto' : 'success'
|
|
|
|
|
} variant="filled" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Agent Log Level</span>
|
|
|
|
|
<Badge label={appConfig.agentLogLevel ?? 'INFO'} color={
|
|
|
|
|
(appConfig.agentLogLevel ?? 'INFO') === 'ERROR' ? 'error'
|
|
|
|
|
: (appConfig.agentLogLevel ?? 'INFO') === 'WARN' ? 'warning'
|
|
|
|
|
: (appConfig.agentLogLevel ?? 'INFO') === 'DEBUG' ? 'running'
|
|
|
|
|
: (appConfig.agentLogLevel ?? 'INFO') === 'TRACE' ? 'auto' : 'success'
|
2026-03-26 13:12:56 +01:00
|
|
|
} variant="filled" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Engine Level</span>
|
|
|
|
|
<Badge label={appConfig.engineLevel ?? 'REGULAR'} color={
|
|
|
|
|
(appConfig.engineLevel ?? 'REGULAR') === 'NONE' ? 'error'
|
|
|
|
|
: (appConfig.engineLevel ?? 'REGULAR') === 'MINIMAL' ? 'warning'
|
|
|
|
|
: (appConfig.engineLevel ?? 'REGULAR') === 'COMPLETE' ? 'running' : 'success'
|
|
|
|
|
} variant="filled" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Payload Capture</span>
|
|
|
|
|
<Badge label={appConfig.payloadCaptureMode ?? 'NONE'} color={
|
|
|
|
|
(appConfig.payloadCaptureMode ?? 'NONE') === 'BOTH' ? 'running'
|
|
|
|
|
: (appConfig.payloadCaptureMode ?? 'NONE') === 'NONE' ? 'auto' : 'warning'
|
|
|
|
|
} variant="filled" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.configField}>
|
|
|
|
|
<span className={styles.configLabel}>Metrics</span>
|
|
|
|
|
<Badge label={appConfig.metricsEnabled ? 'On' : 'Off'} color={appConfig.metricsEnabled ? 'success' : 'error'} variant="filled" />
|
|
|
|
|
</div>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Button variant="ghost" size="sm" title="Edit config" onClick={startConfigEdit}><Pencil size={14} /></Button>
|
2026-03-26 13:12:56 +01:00
|
|
|
</>
|
|
|
|
|
)}
|
2026-03-26 12:51:07 +01:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
{/* Group cards grid */}
|
|
|
|
|
<div className={isFullWidth ? styles.groupGridSingle : styles.groupGrid}>
|
|
|
|
|
{groups.map((group) => (
|
|
|
|
|
<GroupCard
|
|
|
|
|
key={group.appId}
|
|
|
|
|
title={group.appId}
|
|
|
|
|
accent={appHealth(group)}
|
|
|
|
|
headerRight={
|
|
|
|
|
<Badge
|
|
|
|
|
label={`${group.liveCount}/${group.instances.length} LIVE`}
|
|
|
|
|
color={appHealth(group)}
|
|
|
|
|
variant="filled"
|
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
meta={
|
|
|
|
|
<div className={styles.groupMeta}>
|
|
|
|
|
<span><strong>{group.totalTps.toFixed(1)}</strong> msg/s</span>
|
|
|
|
|
<span><strong>{group.totalActiveRoutes}</strong>/{group.totalRoutes} routes</span>
|
|
|
|
|
<span>
|
|
|
|
|
<StatusDot
|
|
|
|
|
variant={
|
|
|
|
|
appHealth(group) === 'success'
|
|
|
|
|
? 'live'
|
|
|
|
|
: appHealth(group) === 'warning'
|
|
|
|
|
? 'stale'
|
|
|
|
|
: 'dead'
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
footer={
|
|
|
|
|
group.deadCount > 0 ? (
|
|
|
|
|
<div className={styles.alertBanner}>
|
|
|
|
|
<span className={styles.alertIcon}>⚠</span>
|
|
|
|
|
<span>
|
|
|
|
|
Single point of failure —{' '}
|
|
|
|
|
{group.deadCount === group.instances.length
|
|
|
|
|
? 'no redundancy'
|
|
|
|
|
: `${group.deadCount} dead instance${group.deadCount > 1 ? 's' : ''}`}
|
|
|
|
|
</span>
|
fix: align all pages with design system mocks — stat cards, tables, detail panels
Dashboard: correct stat card labels (Exchanges/Success Rate/Errors/Throughput/Latency p99),
add detail text, trends, sparklines on all cards, Agent column, LIVE badge,
expanded detail panel with Agent/Correlation/Timestamp, "Open full details" link.
Agent Health: per-group meta (TPS/routes) in GroupCard header, proper HTML table
with column headers for instance list.
Agent Instance: stat card detail props (heap info, start date), scope trail with
inline status/version/routes badges.
Routes: 5th In-Flight stat card, enriched stat card props (detail/trend/sparkline),
SLA threshold line on latency chart.
Exchange Detail: Agent stat box in header.
Also: vite proxy CORS fix, cross-env dev scripts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:28:56 +01:00
|
|
|
</div>
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
) : undefined
|
|
|
|
|
}
|
|
|
|
|
>
|
fix: update agent field names in frontend to match backend DTO
The AgentInstanceResponse backend DTO uses instanceId, displayName,
applicationId, status — but the stale schema.d.ts still had id, name,
application, state. This caused the runtime table to show no data.
- Update schema.d.ts AgentInstanceResponse fields
- Fix AgentHealth: row.id→instanceId, row.name→displayName,
row.application→applicationId, inst.id→instanceId
- Fix AgentInstance: agent.id→instanceId, agent.name→displayName
- Fix ExchangeHeader: agent.id→instanceId, agent.state→status
- Fix LayoutShell search: agent.state→status, agentTps→tps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:36:31 +02:00
|
|
|
<DataTable<AgentInstance & { id: string }>
|
|
|
|
|
columns={instanceColumns as Column<AgentInstance & { id: string }>[]}
|
|
|
|
|
data={group.instances.map(i => ({ ...i, id: i.instanceId }))}
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
onRowClick={handleInstanceClick}
|
|
|
|
|
pageSize={50}
|
|
|
|
|
flush
|
|
|
|
|
/>
|
|
|
|
|
</GroupCard>
|
|
|
|
|
))}
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
</div>
|
|
|
|
|
|
2026-03-25 22:54:07 +01:00
|
|
|
{/* Log + Timeline side by side */}
|
|
|
|
|
<div className={styles.bottomRow}>
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
<div className={logStyles.logCard}>
|
|
|
|
|
<div className={logStyles.logHeader}>
|
2026-03-25 22:54:07 +01:00
|
|
|
<SectionHeader>Application Log</SectionHeader>
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
<div className={logStyles.headerActions}>
|
2026-03-25 22:54:07 +01:00
|
|
|
<span className={styles.sectionMeta}>{logEntries.length} entries</span>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Button variant="ghost" size="sm" onClick={() => setLogSortAsc((v) => !v)} title={logSortAsc ? 'Oldest first' : 'Newest first'}>
|
2026-03-25 22:54:07 +01:00
|
|
|
{logSortAsc ? '\u2191' : '\u2193'}
|
2026-04-09 15:22:14 +02:00
|
|
|
</Button>
|
|
|
|
|
<Button variant="ghost" size="sm" onClick={() => setLogRefreshTo(new Date().toISOString())} title="Refresh">
|
2026-03-27 23:16:39 +01:00
|
|
|
<RefreshCw size={14} />
|
2026-04-09 15:22:14 +02:00
|
|
|
</Button>
|
2026-03-25 22:54:07 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
<div className={logStyles.logToolbar}>
|
|
|
|
|
<div className={logStyles.logSearchWrap}>
|
2026-03-25 22:54:07 +01:00
|
|
|
<input
|
|
|
|
|
type="text"
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
className={logStyles.logSearchInput}
|
2026-03-25 22:54:07 +01:00
|
|
|
placeholder="Search logs\u2026"
|
|
|
|
|
value={logSearch}
|
|
|
|
|
onChange={(e) => setLogSearch(e.target.value)}
|
|
|
|
|
aria-label="Search logs"
|
|
|
|
|
/>
|
|
|
|
|
{logSearch && (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
className={logStyles.logSearchClear}
|
2026-03-25 22:54:07 +01:00
|
|
|
onClick={() => setLogSearch('')}
|
|
|
|
|
aria-label="Clear search"
|
|
|
|
|
>
|
|
|
|
|
×
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<ButtonGroup items={LOG_LEVEL_ITEMS} value={logLevels} onChange={setLogLevels} />
|
|
|
|
|
{logLevels.size > 0 && (
|
2026-04-09 15:22:14 +02:00
|
|
|
<Button variant="ghost" size="sm" onClick={() => setLogLevels(new Set())}>
|
2026-03-25 22:54:07 +01:00
|
|
|
Clear
|
2026-04-09 15:22:14 +02:00
|
|
|
</Button>
|
2026-03-25 22:54:07 +01:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
{filteredLogs.length > 0 ? (
|
|
|
|
|
<LogViewer entries={filteredLogs} maxHeight={360} />
|
|
|
|
|
) : (
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
<div className={logStyles.logEmpty}>
|
2026-03-25 22:54:07 +01:00
|
|
|
{logSearch || logLevels.size > 0 ? 'No matching log entries' : 'No log entries available'}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-03-25 19:53:33 +01:00
|
|
|
<div className={styles.eventCard}>
|
2026-03-23 21:50:16 +01:00
|
|
|
<div className={styles.eventCardHeader}>
|
feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3
example UI, replacing mock data with real backend API hooks. This brings
richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline,
DateRangePicker, expandable rows) while preserving all existing API
integration, auth, and routing infrastructure.
Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail,
AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles).
Also enhanced LayoutShell CommandPalette with real search data from catalog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:42:16 +01:00
|
|
|
<span className={styles.sectionTitle}>Timeline</span>
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
<div className={logStyles.headerActions}>
|
2026-03-25 19:53:33 +01:00
|
|
|
<span className={styles.sectionMeta}>{feedEvents.length} events</span>
|
2026-04-09 15:22:14 +02:00
|
|
|
<Button variant="ghost" size="sm" onClick={() => setEventSortAsc((v) => !v)} title={eventSortAsc ? 'Oldest first' : 'Newest first'}>
|
2026-03-25 19:53:33 +01:00
|
|
|
{eventSortAsc ? '\u2191' : '\u2193'}
|
2026-04-09 15:22:14 +02:00
|
|
|
</Button>
|
|
|
|
|
<Button variant="ghost" size="sm" onClick={() => setEventRefreshTo(new Date().toISOString())} title="Refresh">
|
2026-03-27 23:16:39 +01:00
|
|
|
<RefreshCw size={14} />
|
2026-04-09 15:22:14 +02:00
|
|
|
</Button>
|
2026-03-25 19:53:33 +01:00
|
|
|
</div>
|
2026-03-23 21:50:16 +01:00
|
|
|
</div>
|
2026-03-25 22:54:07 +01:00
|
|
|
{feedEvents.length > 0 ? (
|
|
|
|
|
<EventFeed events={feedEvents} maxItems={100} />
|
|
|
|
|
) : (
|
refactor: UI consistency — shared CSS, design system colors, no inline styles
Phase 1: Extract 6 shared CSS modules (table-section, log-panel,
rate-colors, refresh-indicator, chart-card, section-card) eliminating
~135 duplicate class definitions across 11 files.
Phase 2: Replace all hardcoded hex colors in CSS modules with design
system variables. Strip ~55 hex fallbacks from var() patterns. Fix 4
undefined variable names (--accent, --bg-base, --surface, --bg-surface-raised).
Phase 3: Replace ~45 hardcoded hex values in ProcessDiagram SVG
components with var() CSS custom properties. Fix Dashboard.tsx color prop.
Phase 4: Create CSS modules for AdminLayout, DatabaseAdminPage,
OidcCallback (previously 100% inline). Extract shared PageLoader
component (replaces 3 copy-pasted spinner patterns). Move AppsTab
static inline styles to CSS classes. Extract LayoutShell StarredList styles.
58 files changed, net -219 lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:55:54 +02:00
|
|
|
<div className={logStyles.logEmpty}>No events in the selected time range.</div>
|
2026-03-25 22:54:07 +01:00
|
|
|
)}
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
</div>
|
2026-03-25 22:54:07 +01:00
|
|
|
</div>
|
2026-03-23 18:28:52 +01:00
|
|
|
|
feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend:
- Add agent_events table (V5) and lifecycle event recording
- Add route catalog endpoint (GET /routes/catalog)
- Add route metrics endpoint (GET /routes/metrics)
- Add agent events endpoint (GET /agents/events-log)
- Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds
- Add TimescaleDB retention/compression policies (V6)
Frontend:
- Replace custom Mission Control UI with @cameleer/design-system components
- Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth,
AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger
- New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette
- Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1)
- Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg
CI:
- Pass REGISTRY_TOKEN build-arg to UI Docker build step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 17:38:39 +01:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|