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 { DiagramNode as DiagramNodeType } from '../../api/queries/diagrams';
|
|
|
|
|
import type { NodeConfig } from './types';
|
|
|
|
|
import { colorForType, iconForType } from './node-colors';
|
|
|
|
|
import { ConfigBadge } from './ConfigBadge';
|
|
|
|
|
|
|
|
|
|
const TOP_BAR_HEIGHT = 6;
|
|
|
|
|
const CORNER_RADIUS = 4;
|
|
|
|
|
|
|
|
|
|
interface DiagramNodeProps {
|
|
|
|
|
node: DiagramNodeType;
|
|
|
|
|
isHovered: boolean;
|
|
|
|
|
isSelected: boolean;
|
|
|
|
|
config?: NodeConfig;
|
|
|
|
|
onClick: () => void;
|
2026-03-27 16:58:35 +01:00
|
|
|
onDoubleClick?: () => 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
|
|
|
onMouseEnter: () => void;
|
|
|
|
|
onMouseLeave: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function DiagramNode({
|
2026-03-27 16:58:35 +01:00
|
|
|
node, isHovered, isSelected, config, onClick, onDoubleClick, onMouseEnter, onMouseLeave,
|
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
|
|
|
}: DiagramNodeProps) {
|
|
|
|
|
const x = node.x ?? 0;
|
|
|
|
|
const y = node.y ?? 0;
|
|
|
|
|
const w = node.width ?? 120;
|
|
|
|
|
const h = node.height ?? 40;
|
|
|
|
|
const color = colorForType(node.type);
|
|
|
|
|
const icon = iconForType(node.type);
|
|
|
|
|
|
|
|
|
|
// Extract label parts: type name and detail
|
|
|
|
|
const typeName = node.type?.replace(/^EIP_/, '').replace(/_/g, ' ') ?? '';
|
|
|
|
|
const detail = node.label || '';
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<g
|
|
|
|
|
data-node-id={node.id}
|
|
|
|
|
transform={`translate(${x}, ${y})`}
|
|
|
|
|
onClick={(e) => { e.stopPropagation(); onClick(); }}
|
2026-03-27 16:58:35 +01:00
|
|
|
onDoubleClick={(e) => { e.stopPropagation(); onDoubleClick?.(); }}
|
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
|
|
|
onMouseEnter={onMouseEnter}
|
|
|
|
|
onMouseLeave={onMouseLeave}
|
|
|
|
|
style={{ cursor: 'pointer' }}
|
|
|
|
|
>
|
|
|
|
|
{/* Selection ring */}
|
|
|
|
|
{isSelected && (
|
|
|
|
|
<rect
|
|
|
|
|
x={-2}
|
|
|
|
|
y={-2}
|
|
|
|
|
width={w + 4}
|
|
|
|
|
height={h + 4}
|
|
|
|
|
rx={CORNER_RADIUS + 2}
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="#C6820E"
|
|
|
|
|
strokeWidth={2.5}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* Card background */}
|
|
|
|
|
<rect
|
|
|
|
|
x={0}
|
|
|
|
|
y={0}
|
|
|
|
|
width={w}
|
|
|
|
|
height={h}
|
|
|
|
|
rx={CORNER_RADIUS}
|
|
|
|
|
fill={isHovered ? '#F5F0EA' : 'white'}
|
|
|
|
|
stroke={isHovered || isSelected ? color : '#E4DFD8'}
|
|
|
|
|
strokeWidth={isHovered || isSelected ? 1.5 : 1}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{/* Colored top bar */}
|
|
|
|
|
<rect x={0} y={0} width={w} height={TOP_BAR_HEIGHT} rx={CORNER_RADIUS} fill={color} />
|
|
|
|
|
<rect x={CORNER_RADIUS} y={0} width={w - CORNER_RADIUS * 2} height={TOP_BAR_HEIGHT} fill={color} />
|
|
|
|
|
|
|
|
|
|
{/* Icon */}
|
|
|
|
|
<text x={14} y={h / 2 + 6} fill={color} fontSize={14}>
|
|
|
|
|
{icon}
|
|
|
|
|
</text>
|
|
|
|
|
|
|
|
|
|
{/* Type name */}
|
|
|
|
|
<text x={32} y={h / 2 + 1} fill="#1A1612" fontSize={11} fontWeight={600}>
|
|
|
|
|
{typeName}
|
|
|
|
|
</text>
|
|
|
|
|
|
|
|
|
|
{/* Detail label (truncated) */}
|
|
|
|
|
{detail && detail !== typeName && (
|
|
|
|
|
<text x={32} y={h / 2 + 14} fill="#5C5347" fontSize={10}>
|
|
|
|
|
{detail.length > 22 ? detail.slice(0, 20) + '...' : detail}
|
|
|
|
|
</text>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* Config badges */}
|
|
|
|
|
{config && <ConfigBadge nodeWidth={w} config={config} />}
|
|
|
|
|
</g>
|
|
|
|
|
);
|
|
|
|
|
}
|