feat: route control buttons reflect current route state
Some checks failed
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m8s
CI / deploy (push) Has been cancelled
CI / deploy-feature (push) Has been cancelled
CI / docker (push) Has been cancelled

Buttons are disabled based on route state: Started disables
Start/Resume, Stopped disables Stop/Suspend/Resume, Suspended
disables Start/Suspend. State looked up from catalog API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-02 22:56:49 +02:00
parent 2265ebf801
commit 38b76513c7
2 changed files with 29 additions and 3 deletions

View File

@@ -1,9 +1,10 @@
import { useMemo } from 'react';
import { useNavigate } from 'react-router';
import { GitBranch, Server, RotateCcw, FileText } from 'lucide-react';
import { StatusDot, MonoText, Badge } from '@cameleer/design-system';
import { StatusDot, MonoText, Badge, useGlobalFilters } from '@cameleer/design-system';
import { useCorrelationChain } from '../../api/queries/correlation';
import { useAgents } from '../../api/queries/agents';
import { useRouteCatalog } from '../../api/queries/catalog';
import { useAuthStore } from '../../auth/auth-store';
import type { ExecutionDetail } from '../../components/ExecutionDiagram/types';
import { attributeBadgeColor } from '../../utils/attribute-color';
@@ -44,11 +45,27 @@ function formatDuration(ms: number): string {
export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }: ExchangeHeaderProps) {
const navigate = useNavigate();
const { timeRange } = useGlobalFilters();
const { data: chainResult } = useCorrelationChain(detail.correlationId ?? null);
const chain = chainResult?.data;
const showChain = chain && chain.length > 1;
const attrs = Object.entries(detail.attributes ?? {});
// Look up route state from catalog
const { data: catalog } = useRouteCatalog(timeRange.start.toISOString(), timeRange.end.toISOString());
const routeState = useMemo(() => {
if (!catalog) return undefined;
for (const app of catalog as any[]) {
if (app.appId !== detail.applicationId) continue;
for (const route of app.routes || []) {
if (route.routeId === detail.routeId) {
return (route.routeState ?? 'started') as 'started' | 'stopped' | 'suspended';
}
}
}
return undefined;
}, [catalog, detail.applicationId, detail.routeId]);
// Look up agent state for icon coloring + route control capability
const { data: agents } = useAgents(undefined, detail.applicationId);
const { agentState, hasRouteControl, hasReplay } = useMemo(() => {
@@ -114,6 +131,7 @@ export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }:
<RouteControlBar
application={detail.applicationId}
routeId={detail.routeId}
routeState={routeState}
hasRouteControl={hasRouteControl}
hasReplay={hasReplay}
agentId={detail.instanceId}