From ff59dc5d573ba49568d12b0bb3d2c6f56ff63957 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Fri, 27 Mar 2026 18:40:57 +0100 Subject: [PATCH] feat: add execution overlay types and extend ProcessDiagram with diagramLayout prop Define the execution overlay type system (NodeExecutionState, IterationInfo, DetailTab) and extend ProcessDiagramProps with optional overlay props. Add diagramLayout prop so ExecutionDiagram can pass a pre-fetched layout by content hash, bypassing the internal route-based fetch in useDiagramData. Co-Authored-By: Claude Opus 4.6 (1M context) --- ui/src/components/ExecutionDiagram/types.ts | 24 +++++++++++++++++++ .../ProcessDiagram/ProcessDiagram.tsx | 3 ++- ui/src/components/ProcessDiagram/types.ts | 11 ++++++++- .../ProcessDiagram/useDiagramData.ts | 16 ++++++++++--- 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 ui/src/components/ExecutionDiagram/types.ts diff --git a/ui/src/components/ExecutionDiagram/types.ts b/ui/src/components/ExecutionDiagram/types.ts new file mode 100644 index 00000000..5837fbd3 --- /dev/null +++ b/ui/src/components/ExecutionDiagram/types.ts @@ -0,0 +1,24 @@ +import type { components } from '../../api/schema'; + +export type ExecutionDetail = components['schemas']['ExecutionDetail']; +export type ProcessorNode = components['schemas']['ProcessorNode']; + +export interface NodeExecutionState { + status: 'COMPLETED' | 'FAILED'; + durationMs: number; + /** True if this node's target sub-route failed (DIRECT/SEDA) */ + subRouteFailed?: boolean; + /** True if trace data is available for this processor */ + hasTraceData?: boolean; +} + +export interface IterationInfo { + /** Current iteration index (0-based) */ + current: number; + /** Total number of iterations */ + total: number; + /** Type of iteration (determines label) */ + type: 'loop' | 'split' | 'multicast'; +} + +export type DetailTab = 'info' | 'headers' | 'input' | 'output' | 'error' | 'config' | 'timeline'; diff --git a/ui/src/components/ProcessDiagram/ProcessDiagram.tsx b/ui/src/components/ProcessDiagram/ProcessDiagram.tsx index 7269c262..d9c6bdbc 100644 --- a/ui/src/components/ProcessDiagram/ProcessDiagram.tsx +++ b/ui/src/components/ProcessDiagram/ProcessDiagram.tsx @@ -52,6 +52,7 @@ export function ProcessDiagram({ nodeConfigs, knownRouteIds, className, + diagramLayout, }: ProcessDiagramProps) { // Route stack for drill-down navigation const [routeStack, setRouteStack] = useState([routeId]); @@ -64,7 +65,7 @@ export function ProcessDiagram({ const currentRouteId = routeStack[routeStack.length - 1]; const { sections, totalWidth, totalHeight, isLoading, error } = useDiagramData( - application, currentRouteId, direction, + application, currentRouteId, direction, diagramLayout, ); const zoom = useZoomPan(); diff --git a/ui/src/components/ProcessDiagram/types.ts b/ui/src/components/ProcessDiagram/types.ts index 41e153e0..01d3776d 100644 --- a/ui/src/components/ProcessDiagram/types.ts +++ b/ui/src/components/ProcessDiagram/types.ts @@ -1,4 +1,5 @@ -import type { DiagramNode, DiagramEdge } from '../../api/queries/diagrams'; +import type { DiagramNode, DiagramEdge, DiagramLayout } from '../../api/queries/diagrams'; +import type { NodeExecutionState, IterationInfo } from '../ExecutionDiagram/types'; export type NodeAction = 'inspect' | 'toggle-trace' | 'configure-tap' | 'copy-id'; @@ -26,4 +27,12 @@ export interface ProcessDiagramProps { /** Known route IDs for this application (enables drill-down resolution) */ knownRouteIds?: Set; className?: string; + /** Pre-fetched diagram layout (bypasses internal fetch by application/routeId) */ + diagramLayout?: DiagramLayout; + /** Execution overlay: maps diagram node ID → execution state */ + executionOverlay?: Map; + /** Per-compound iteration info: maps compound node ID → iteration info */ + iterationState?: Map; + /** Called when user changes iteration on a compound stepper */ + onIterationChange?: (compoundNodeId: string, iterationIndex: number) => void; } diff --git a/ui/src/components/ProcessDiagram/useDiagramData.ts b/ui/src/components/ProcessDiagram/useDiagramData.ts index c23fa56b..fbf6a3f9 100644 --- a/ui/src/components/ProcessDiagram/useDiagramData.ts +++ b/ui/src/components/ProcessDiagram/useDiagramData.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react'; import { useDiagramByRoute } from '../../api/queries/diagrams'; -import type { DiagramNode, DiagramEdge } from '../../api/queries/diagrams'; +import type { DiagramNode, DiagramEdge, DiagramLayout } from '../../api/queries/diagrams'; import type { DiagramSection } from './types'; import { isErrorCompoundType, isCompletionCompoundType } from './node-colors'; @@ -10,8 +10,14 @@ export function useDiagramData( application: string, routeId: string, direction: 'LR' | 'TB' = 'LR', + preloadedLayout?: DiagramLayout, ) { - const { data: layout, isLoading, error } = useDiagramByRoute(application, routeId, direction); + // When a preloaded layout is provided, disable the internal fetch + const fetchApp = preloadedLayout ? undefined : application; + const fetchRoute = preloadedLayout ? undefined : routeId; + const { data: fetchedLayout, isLoading, error } = useDiagramByRoute(fetchApp, fetchRoute, direction); + + const layout = preloadedLayout ?? fetchedLayout; const result = useMemo(() => { if (!layout?.nodes) { @@ -106,7 +112,11 @@ export function useDiagramData( return { sections, totalWidth, totalHeight }; }, [layout]); - return { ...result, isLoading, error }; + return { + ...result, + isLoading: preloadedLayout ? false : isLoading, + error: preloadedLayout ? null : error, + }; } /** Shift all node coordinates by subtracting an offset, recursively. */