feat: support ON_COMPLETION handler sections in diagram
Add ON_COMPLETION to backend COMPOUND_TYPES and frontend rendering. Completion handlers render as teal-tinted sections between the main flow and error handlers, structurally parallel to onException. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
|
||||
import { useDiagramByRoute } from '../../api/queries/diagrams';
|
||||
import type { DiagramNode, DiagramEdge } from '../../api/queries/diagrams';
|
||||
import type { DiagramSection } from './types';
|
||||
import { isErrorCompoundType } from './node-colors';
|
||||
import { isErrorCompoundType, isCompletionCompoundType } from './node-colors';
|
||||
|
||||
const SECTION_GAP = 40;
|
||||
|
||||
@@ -20,12 +20,18 @@ export function useDiagramData(
|
||||
|
||||
const allEdges = layout.edges ?? [];
|
||||
|
||||
// Separate main nodes from error handler compound sections
|
||||
// Separate main nodes from completion and error handler compound sections
|
||||
const mainNodes: DiagramNode[] = [];
|
||||
const completionSections: { label: string; nodes: DiagramNode[] }[] = [];
|
||||
const errorSections: { label: string; nodes: DiagramNode[] }[] = [];
|
||||
|
||||
for (const node of layout.nodes) {
|
||||
if (isErrorCompoundType(node.type) && node.children && node.children.length > 0) {
|
||||
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) {
|
||||
errorSections.push({
|
||||
label: node.label || 'Error Handler',
|
||||
nodes: node.children,
|
||||
@@ -58,39 +64,41 @@ export function useDiagramData(
|
||||
let currentY = mainBounds.maxY + SECTION_GAP;
|
||||
let maxWidth = mainBounds.maxX;
|
||||
|
||||
for (const es of errorSections) {
|
||||
const errorBounds = computeBounds(es.nodes);
|
||||
const offX = errorBounds.minX;
|
||||
const offY = errorBounds.minY;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
// Normalize node coordinates relative to the section's own origin
|
||||
const shiftedNodes = shiftNodes(es.nodes, offX, offY);
|
||||
|
||||
const errorNodeIds = new Set<string>();
|
||||
collectNodeIds(es.nodes, errorNodeIds);
|
||||
|
||||
// Shift edge points too
|
||||
const errorEdges = allEdges
|
||||
.filter(e => errorNodeIds.has(e.sourceId) && errorNodeIds.has(e.targetId))
|
||||
.map(e => ({
|
||||
...e,
|
||||
points: e.points.map(p => [p[0] - offX, p[1] - offY]),
|
||||
}));
|
||||
|
||||
const sectionHeight = errorBounds.maxY - errorBounds.minY;
|
||||
const sectionWidth = errorBounds.maxX - errorBounds.minX;
|
||||
|
||||
sections.push({
|
||||
label: es.label,
|
||||
nodes: shiftedNodes,
|
||||
edges: errorEdges,
|
||||
offsetY: currentY,
|
||||
variant: 'error',
|
||||
});
|
||||
|
||||
currentY += sectionHeight + SECTION_GAP;
|
||||
if (sectionWidth > maxWidth) maxWidth = sectionWidth;
|
||||
}
|
||||
// Completion handlers first (above error handlers)
|
||||
addHandlerSections(completionSections, 'completion');
|
||||
// Then error handlers
|
||||
addHandlerSections(errorSections, 'error');
|
||||
|
||||
const totalWidth = Math.max(layout.width ?? 0, mainBounds.maxX, maxWidth);
|
||||
const totalHeight = currentY;
|
||||
|
||||
Reference in New Issue
Block a user