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 { useMemo } from 'react';
|
|
|
|
|
import { useDiagramByRoute } from '../../api/queries/diagrams';
|
2026-03-27 18:40:57 +01:00
|
|
|
import type { DiagramNode, DiagramEdge, DiagramLayout } 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 { DiagramSection } from './types';
|
2026-03-27 16:45:10 +01:00
|
|
|
import { isErrorCompoundType, isCompletionCompoundType } 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
|
|
|
|
2026-03-27 17:10:01 +01:00
|
|
|
const SECTION_GAP = 80;
|
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
|
|
|
|
|
|
|
|
export function useDiagramData(
|
|
|
|
|
application: string,
|
|
|
|
|
routeId: string,
|
|
|
|
|
direction: 'LR' | 'TB' = 'LR',
|
2026-03-27 18:40:57 +01:00
|
|
|
preloadedLayout?: DiagramLayout,
|
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 18:40:57 +01:00
|
|
|
// 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;
|
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 result = useMemo(() => {
|
|
|
|
|
if (!layout?.nodes) {
|
|
|
|
|
return { sections: [], totalWidth: 0, totalHeight: 0 };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const allEdges = layout.edges ?? [];
|
|
|
|
|
|
2026-03-27 16:45:10 +01:00
|
|
|
// Separate main nodes from completion and error handler compound sections
|
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 mainNodes: DiagramNode[] = [];
|
2026-03-27 16:45:10 +01:00
|
|
|
const completionSections: { label: string; nodes: DiagramNode[] }[] = [];
|
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 errorSections: { label: string; nodes: DiagramNode[] }[] = [];
|
|
|
|
|
|
|
|
|
|
for (const node of layout.nodes) {
|
2026-03-27 16:45:10 +01:00
|
|
|
if (isCompletionCompoundType(node.type) && node.children && node.children.length > 0) {
|
|
|
|
|
completionSections.push({
|
|
|
|
|
label: node.label || 'onCompletion',
|
|
|
|
|
nodes: node.children,
|
|
|
|
|
});
|
|
|
|
|
} else if (isErrorCompoundType(node.type) && node.children && node.children.length > 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
|
|
|
errorSections.push({
|
|
|
|
|
label: node.label || 'Error Handler',
|
|
|
|
|
nodes: node.children,
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
mainNodes.push(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collect node IDs for edge filtering
|
|
|
|
|
const mainNodeIds = new Set<string>();
|
|
|
|
|
collectNodeIds(mainNodes, mainNodeIds);
|
|
|
|
|
|
|
|
|
|
const mainEdges = allEdges.filter(
|
|
|
|
|
e => mainNodeIds.has(e.sourceId) && mainNodeIds.has(e.targetId),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Compute main section bounding box
|
|
|
|
|
const mainBounds = computeBounds(mainNodes);
|
|
|
|
|
|
|
|
|
|
const sections: DiagramSection[] = [
|
|
|
|
|
{
|
|
|
|
|
label: 'Main Route',
|
|
|
|
|
nodes: mainNodes,
|
|
|
|
|
edges: mainEdges,
|
|
|
|
|
offsetY: 0,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let currentY = mainBounds.maxY + SECTION_GAP;
|
2026-03-27 16:33:24 +01:00
|
|
|
let maxWidth = mainBounds.maxX;
|
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:45:10 +01:00
|
|
|
const addHandlerSections = (
|
|
|
|
|
handlers: { label: string; nodes: DiagramNode[] }[],
|
|
|
|
|
variant: 'completion' | 'error',
|
|
|
|
|
) => {
|
|
|
|
|
for (const hs of handlers) {
|
|
|
|
|
const bounds = computeBounds(hs.nodes);
|
|
|
|
|
const offX = bounds.minX;
|
|
|
|
|
const offY = bounds.minY;
|
|
|
|
|
const shiftedNodes = shiftNodes(hs.nodes, offX, offY);
|
|
|
|
|
const nodeIds = new Set<string>();
|
|
|
|
|
collectNodeIds(hs.nodes, nodeIds);
|
|
|
|
|
const edges = allEdges
|
|
|
|
|
.filter(e => nodeIds.has(e.sourceId) && nodeIds.has(e.targetId))
|
|
|
|
|
.map(e => ({
|
|
|
|
|
...e,
|
|
|
|
|
points: e.points.map(p => [p[0] - offX, p[1] - offY]),
|
|
|
|
|
}));
|
|
|
|
|
const sectionHeight = bounds.maxY - bounds.minY;
|
|
|
|
|
const sectionWidth = bounds.maxX - bounds.minX;
|
|
|
|
|
sections.push({
|
|
|
|
|
label: hs.label,
|
|
|
|
|
nodes: shiftedNodes,
|
|
|
|
|
edges,
|
|
|
|
|
offsetY: currentY,
|
|
|
|
|
variant,
|
|
|
|
|
});
|
|
|
|
|
currentY += sectionHeight + SECTION_GAP;
|
|
|
|
|
if (sectionWidth > maxWidth) maxWidth = sectionWidth;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Completion handlers first (above error handlers)
|
|
|
|
|
addHandlerSections(completionSections, 'completion');
|
|
|
|
|
// Then error handlers
|
|
|
|
|
addHandlerSections(errorSections, 'error');
|
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
|
|
|
const totalWidth = Math.max(layout.width ?? 0, mainBounds.maxX, maxWidth);
|
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 totalHeight = currentY;
|
|
|
|
|
|
|
|
|
|
return { sections, totalWidth, totalHeight };
|
|
|
|
|
}, [layout]);
|
|
|
|
|
|
2026-03-27 18:40:57 +01:00
|
|
|
return {
|
|
|
|
|
...result,
|
|
|
|
|
isLoading: preloadedLayout ? false : isLoading,
|
|
|
|
|
error: preloadedLayout ? null : error,
|
|
|
|
|
};
|
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
|
|
|
/** Shift all node coordinates by subtracting an offset, recursively. */
|
|
|
|
|
function shiftNodes(nodes: DiagramNode[], offX: number, offY: number): DiagramNode[] {
|
|
|
|
|
return nodes.map(n => ({
|
|
|
|
|
...n,
|
|
|
|
|
x: (n.x ?? 0) - offX,
|
|
|
|
|
y: (n.y ?? 0) - offY,
|
|
|
|
|
children: n.children ? shiftNodes(n.children, offX, offY) : undefined,
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
function collectNodeIds(nodes: DiagramNode[], set: Set<string>) {
|
|
|
|
|
for (const n of nodes) {
|
|
|
|
|
if (n.id) set.add(n.id);
|
|
|
|
|
if (n.children) collectNodeIds(n.children, set);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function computeBounds(nodes: DiagramNode[]): {
|
|
|
|
|
minX: number; minY: number; maxX: number; maxY: number;
|
|
|
|
|
} {
|
|
|
|
|
let minX = Infinity, minY = Infinity, maxX = 0, maxY = 0;
|
|
|
|
|
for (const n of nodes) {
|
|
|
|
|
const x = n.x ?? 0;
|
|
|
|
|
const y = n.y ?? 0;
|
|
|
|
|
const w = n.width ?? 80;
|
|
|
|
|
const h = n.height ?? 40;
|
|
|
|
|
if (x < minX) minX = x;
|
|
|
|
|
if (y < minY) minY = y;
|
|
|
|
|
if (x + w > maxX) maxX = x + w;
|
|
|
|
|
if (y + h > maxY) maxY = y + h;
|
|
|
|
|
if (n.children) {
|
|
|
|
|
const childBounds = computeBounds(n.children);
|
|
|
|
|
if (childBounds.maxX > maxX) maxX = childBounds.maxX;
|
|
|
|
|
if (childBounds.maxY > maxY) maxY = childBounds.maxY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { minX: minX === Infinity ? 0 : minX, minY: minY === Infinity ? 0 : minY, maxX, maxY };
|
|
|
|
|
}
|