2026-03-27 16:33:24 +01:00
|
|
|
import type { DiagramNode as DiagramNodeType, DiagramEdge as DiagramEdgeType } from '../../api/queries/diagrams';
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
import type { NodeConfig } from './types';
|
2026-03-27 18:52:32 +01:00
|
|
|
import type { NodeExecutionState, IterationInfo } from '../ExecutionDiagram/types';
|
2026-03-27 16:33:24 +01:00
|
|
|
import { colorForType, isCompoundType } from './node-colors';
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
import { DiagramNode } from './DiagramNode';
|
2026-03-27 16:33:24 +01:00
|
|
|
import { DiagramEdge } from './DiagramEdge';
|
2026-03-27 18:52:32 +01:00
|
|
|
import styles from './ProcessDiagram.module.css';
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
|
|
|
|
|
const HEADER_HEIGHT = 22;
|
|
|
|
|
const CORNER_RADIUS = 4;
|
|
|
|
|
|
|
|
|
|
interface CompoundNodeProps {
|
|
|
|
|
node: DiagramNodeType;
|
2026-03-27 16:33:24 +01:00
|
|
|
/** All edges for this section — compound filters to its own internal edges */
|
|
|
|
|
edges: DiagramEdgeType[];
|
|
|
|
|
/** Absolute offset of the nearest compound ancestor (for coordinate adjustment) */
|
|
|
|
|
parentX?: number;
|
|
|
|
|
parentY?: number;
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
selectedNodeId?: string;
|
|
|
|
|
hoveredNodeId: string | null;
|
|
|
|
|
nodeConfigs?: Map<string, NodeConfig>;
|
2026-03-27 18:47:59 +01:00
|
|
|
/** Execution overlay for edge traversal coloring */
|
|
|
|
|
executionOverlay?: Map<string, NodeExecutionState>;
|
2026-03-27 18:52:32 +01:00
|
|
|
/** Whether an execution overlay is active (enables dimming of skipped nodes) */
|
|
|
|
|
overlayActive?: boolean;
|
|
|
|
|
/** Per-compound iteration state */
|
|
|
|
|
iterationState?: Map<string, IterationInfo>;
|
|
|
|
|
/** Called when user changes iteration on a compound stepper */
|
|
|
|
|
onIterationChange?: (compoundNodeId: string, iterationIndex: number) => void;
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
onNodeClick: (nodeId: string) => void;
|
2026-03-27 16:58:35 +01:00
|
|
|
onNodeDoubleClick?: (nodeId: string) => void;
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
onNodeEnter: (nodeId: string) => void;
|
|
|
|
|
onNodeLeave: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function CompoundNode({
|
2026-03-27 16:33:24 +01:00
|
|
|
node, edges, parentX = 0, parentY = 0,
|
2026-03-27 18:47:59 +01:00
|
|
|
selectedNodeId, hoveredNodeId, nodeConfigs, executionOverlay,
|
2026-03-27 18:52:32 +01:00
|
|
|
overlayActive, iterationState, onIterationChange,
|
2026-03-27 16:58:35 +01:00
|
|
|
onNodeClick, onNodeDoubleClick, onNodeEnter, onNodeLeave,
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
}: CompoundNodeProps) {
|
2026-03-27 16:33:24 +01:00
|
|
|
const x = (node.x ?? 0) - parentX;
|
|
|
|
|
const y = (node.y ?? 0) - parentY;
|
|
|
|
|
const absX = node.x ?? 0;
|
|
|
|
|
const absY = node.y ?? 0;
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
const w = node.width ?? 200;
|
|
|
|
|
const h = node.height ?? 100;
|
|
|
|
|
const color = colorForType(node.type);
|
|
|
|
|
const typeName = node.type?.replace(/^EIP_/, '').replace(/_/g, ' ') ?? '';
|
|
|
|
|
const label = node.label ? `${typeName}: ${node.label}` : typeName;
|
2026-03-27 18:52:32 +01:00
|
|
|
const iterationInfo = node.id ? iterationState?.get(node.id) : undefined;
|
|
|
|
|
const headerWidth = w;
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
|
2026-03-27 16:33:24 +01:00
|
|
|
// Collect all descendant node IDs to filter edges that belong inside this compound
|
|
|
|
|
const descendantIds = new Set<string>();
|
|
|
|
|
collectIds(node.children ?? [], descendantIds);
|
|
|
|
|
|
|
|
|
|
const internalEdges = edges.filter(
|
|
|
|
|
e => descendantIds.has(e.sourceId) && descendantIds.has(e.targetId),
|
|
|
|
|
);
|
|
|
|
|
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
return (
|
|
|
|
|
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
|
|
|
|
|
{/* Container body */}
|
|
|
|
|
<rect
|
|
|
|
|
x={0}
|
|
|
|
|
y={0}
|
|
|
|
|
width={w}
|
|
|
|
|
height={h}
|
|
|
|
|
rx={CORNER_RADIUS}
|
|
|
|
|
fill="white"
|
|
|
|
|
stroke={color}
|
|
|
|
|
strokeWidth={1.5}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{/* Colored header bar */}
|
|
|
|
|
<rect x={0} y={0} width={w} height={HEADER_HEIGHT} rx={CORNER_RADIUS} fill={color} />
|
|
|
|
|
<rect x={CORNER_RADIUS} y={CORNER_RADIUS} width={w - CORNER_RADIUS * 2} height={HEADER_HEIGHT - CORNER_RADIUS} fill={color} />
|
|
|
|
|
|
|
|
|
|
{/* Header label */}
|
|
|
|
|
<text
|
|
|
|
|
x={w / 2}
|
|
|
|
|
y={HEADER_HEIGHT / 2 + 4}
|
|
|
|
|
fill="white"
|
|
|
|
|
fontSize={10}
|
|
|
|
|
fontWeight={600}
|
|
|
|
|
textAnchor="middle"
|
|
|
|
|
>
|
|
|
|
|
{label}
|
|
|
|
|
</text>
|
|
|
|
|
|
2026-03-27 18:52:32 +01:00
|
|
|
{/* Iteration stepper (for LOOP, SPLIT, MULTICAST with overlay data) */}
|
|
|
|
|
{iterationInfo && (
|
|
|
|
|
<foreignObject x={headerWidth - 80} y={1} width={75} height={20}>
|
|
|
|
|
<div className={styles.iterationStepper}>
|
|
|
|
|
<button
|
|
|
|
|
onClick={(e) => { e.stopPropagation(); onIterationChange?.(node.id!, iterationInfo.current - 1); }}
|
|
|
|
|
disabled={iterationInfo.current <= 0}
|
|
|
|
|
>
|
|
|
|
|
‹
|
|
|
|
|
</button>
|
|
|
|
|
<span>{iterationInfo.current + 1} / {iterationInfo.total}</span>
|
|
|
|
|
<button
|
|
|
|
|
onClick={(e) => { e.stopPropagation(); onIterationChange?.(node.id!, iterationInfo.current + 1); }}
|
|
|
|
|
disabled={iterationInfo.current >= iterationInfo.total - 1}
|
|
|
|
|
>
|
|
|
|
|
›
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</foreignObject>
|
|
|
|
|
)}
|
|
|
|
|
|
2026-03-27 16:33:24 +01:00
|
|
|
{/* Internal edges (rendered after background, before children) */}
|
|
|
|
|
<g className="edges">
|
2026-03-27 18:47:59 +01:00
|
|
|
{internalEdges.map((edge, i) => {
|
|
|
|
|
const isTraversed = executionOverlay
|
|
|
|
|
? (executionOverlay.has(edge.sourceId) && executionOverlay.has(edge.targetId))
|
|
|
|
|
: undefined;
|
|
|
|
|
return (
|
|
|
|
|
<DiagramEdge
|
|
|
|
|
key={`${edge.sourceId}-${edge.targetId}-${i}`}
|
|
|
|
|
edge={{
|
|
|
|
|
...edge,
|
|
|
|
|
points: edge.points.map(p => [p[0] - absX, p[1] - absY]),
|
|
|
|
|
}}
|
|
|
|
|
traversed={isTraversed}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
2026-03-27 16:33:24 +01:00
|
|
|
</g>
|
|
|
|
|
|
|
|
|
|
{/* Children — recurse into compound children, render leaves as DiagramNode */}
|
|
|
|
|
{node.children?.map(child => {
|
|
|
|
|
if (isCompoundType(child.type) && child.children && child.children.length > 0) {
|
|
|
|
|
return (
|
|
|
|
|
<CompoundNode
|
|
|
|
|
key={child.id}
|
|
|
|
|
node={child}
|
|
|
|
|
edges={edges}
|
|
|
|
|
parentX={absX}
|
|
|
|
|
parentY={absY}
|
|
|
|
|
selectedNodeId={selectedNodeId}
|
|
|
|
|
hoveredNodeId={hoveredNodeId}
|
|
|
|
|
nodeConfigs={nodeConfigs}
|
2026-03-27 18:47:59 +01:00
|
|
|
executionOverlay={executionOverlay}
|
2026-03-27 18:52:32 +01:00
|
|
|
overlayActive={overlayActive}
|
|
|
|
|
iterationState={iterationState}
|
|
|
|
|
onIterationChange={onIterationChange}
|
2026-03-27 16:33:24 +01:00
|
|
|
onNodeClick={onNodeClick}
|
2026-03-27 16:58:35 +01:00
|
|
|
onNodeDoubleClick={onNodeDoubleClick}
|
2026-03-27 16:33:24 +01:00
|
|
|
onNodeEnter={onNodeEnter}
|
|
|
|
|
onNodeLeave={onNodeLeave}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<DiagramNode
|
|
|
|
|
key={child.id}
|
|
|
|
|
node={{
|
|
|
|
|
...child,
|
|
|
|
|
x: (child.x ?? 0) - absX,
|
|
|
|
|
y: (child.y ?? 0) - absY,
|
|
|
|
|
}}
|
|
|
|
|
isHovered={hoveredNodeId === child.id}
|
|
|
|
|
isSelected={selectedNodeId === child.id}
|
|
|
|
|
config={child.id ? nodeConfigs?.get(child.id) : undefined}
|
2026-03-27 18:52:32 +01:00
|
|
|
executionState={executionOverlay?.get(child.id ?? '')}
|
|
|
|
|
overlayActive={overlayActive}
|
2026-03-27 16:33:24 +01:00
|
|
|
onClick={() => child.id && onNodeClick(child.id)}
|
2026-03-27 16:58:35 +01:00
|
|
|
onDoubleClick={() => child.id && onNodeDoubleClick?.(child.id)}
|
2026-03-27 16:33:24 +01:00
|
|
|
onMouseEnter={() => child.id && onNodeEnter(child.id)}
|
|
|
|
|
onMouseLeave={onNodeLeave}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:55:29 +01:00
|
|
|
</g>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-03-27 16:33:24 +01:00
|
|
|
|
|
|
|
|
function collectIds(nodes: DiagramNodeType[], set: Set<string>) {
|
|
|
|
|
for (const n of nodes) {
|
|
|
|
|
if (n.id) set.add(n.id);
|
|
|
|
|
if (n.children) collectIds(n.children, set);
|
|
|
|
|
}
|
|
|
|
|
}
|