feat: add interactive ProcessDiagram SVG component (sub-project 1/3)
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m0s
CI / docker (push) Successful in 56s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 38s

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>
This commit is contained in:
hsiegeln
2026-03-27 13:55:29 +01:00
parent 78e12f5cf9
commit ac32396a57
24 changed files with 7264 additions and 18 deletions

View File

@@ -112,7 +112,7 @@ public class ElkDiagramRenderer implements DiagramRenderer {
@Override
public String renderSvg(RouteGraph graph) {
LayoutResult result = computeLayout(graph);
LayoutResult result = computeLayout(graph, Direction.DOWN);
DiagramLayout layout = result.layout;
int svgWidth = (int) Math.ceil(layout.width()) + 2 * PADDING;
@@ -153,21 +153,27 @@ public class ElkDiagramRenderer implements DiagramRenderer {
@Override
public DiagramLayout layoutJson(RouteGraph graph) {
return computeLayout(graph).layout;
return computeLayout(graph, Direction.RIGHT).layout;
}
@Override
public DiagramLayout layoutJson(RouteGraph graph, String direction) {
Direction dir = "TB".equalsIgnoreCase(direction) ? Direction.DOWN : Direction.RIGHT;
return computeLayout(graph, dir).layout;
}
// ----------------------------------------------------------------
// Layout computation
// ----------------------------------------------------------------
private LayoutResult computeLayout(RouteGraph graph) {
private LayoutResult computeLayout(RouteGraph graph, Direction rootDirection) {
ElkGraphFactory factory = ElkGraphFactory.eINSTANCE;
// Create root node
ElkNode rootNode = factory.createElkNode();
rootNode.setIdentifier("root");
rootNode.setProperty(CoreOptions.ALGORITHM, "org.eclipse.elk.layered");
rootNode.setProperty(CoreOptions.DIRECTION, Direction.DOWN);
rootNode.setProperty(CoreOptions.DIRECTION, rootDirection);
rootNode.setProperty(CoreOptions.SPACING_NODE_NODE, NODE_SPACING);
rootNode.setProperty(CoreOptions.SPACING_EDGE_NODE, EDGE_SPACING);
rootNode.setProperty(CoreOptions.HIERARCHY_HANDLING, HierarchyHandling.INCLUDE_CHILDREN);