fix: disable execution overlay when drilled into sub-route

The execution overlay data maps to the root route's processor IDs. When
drilled into a sub-route, those IDs don't match, causing all nodes to
appear dimmed. Now clears the overlay and shows pure topology when
viewing a sub-route via drill-down.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-27 19:43:51 +01:00
parent 0b8efa1998
commit bfd76261ef

View File

@@ -57,8 +57,6 @@ export function ProcessDiagram({
iterationState,
onIterationChange,
}: ProcessDiagramProps) {
const overlayActive = !!executionOverlay;
// Route stack for drill-down navigation
const [routeStack, setRouteStack] = useState<string[]>([routeId]);
@@ -68,10 +66,15 @@ export function ProcessDiagram({
}, [routeId]);
const currentRouteId = routeStack[routeStack.length - 1];
const isDrilledDown = currentRouteId !== routeId;
// Disable overlay when drilled down — the execution data is for the root route
// and doesn't map to sub-route node IDs. Sub-route shows topology only.
const overlayActive = !!executionOverlay && !isDrilledDown;
const effectiveOverlay = isDrilledDown ? undefined : executionOverlay;
// Only use the pre-fetched diagramLayout for the root route.
// When drilled down into a sub-route, fetch the sub-route's diagram by route ID.
const effectiveLayout = currentRouteId === routeId ? diagramLayout : undefined;
const effectiveLayout = isDrilledDown ? undefined : diagramLayout;
const { sections, totalWidth, totalHeight, isLoading, error } = useDiagramData(
application, currentRouteId, direction, effectiveLayout,
@@ -108,16 +111,16 @@ export function ProcessDiagram({
// COMPLETED when the route executed (i.e., overlay has any entries).
const getNodeExecutionState = useCallback(
(nodeId: string | undefined, nodeType: string | undefined) => {
if (!nodeId || !executionOverlay) return undefined;
const state = executionOverlay.get(nodeId);
if (!nodeId || !effectiveOverlay) return undefined;
const state = effectiveOverlay.get(nodeId);
if (state) return state;
// Synthesize COMPLETED for ENDPOINT nodes when overlay is active
if (nodeType === 'ENDPOINT' && executionOverlay.size > 0) {
if (nodeType === 'ENDPOINT' && effectiveOverlay.size > 0) {
return { status: 'COMPLETED' as const, durationMs: 0, hasTraceData: false };
}
return undefined;
},
[executionOverlay],
[effectiveOverlay],
);
const handleNodeClick = useCallback(
@@ -264,9 +267,9 @@ export function ProcessDiagram({
{/* Main section top-level edges (not inside compounds) */}
<g className="edges">
{mainSection.edges.filter(e => topLevelEdge(e, mainSection.nodes)).map((edge, i) => {
const sourceHasState = executionOverlay?.has(edge.sourceId) || endpointNodeIds.has(edge.sourceId);
const targetHasState = executionOverlay?.has(edge.targetId) || endpointNodeIds.has(edge.targetId);
const isTraversed = executionOverlay
const sourceHasState = effectiveOverlay?.has(edge.sourceId) || endpointNodeIds.has(edge.sourceId);
const targetHasState = effectiveOverlay?.has(edge.targetId) || endpointNodeIds.has(edge.targetId);
const isTraversed = effectiveOverlay
? (!!sourceHasState && !!targetHasState)
: undefined;
return (
@@ -287,7 +290,7 @@ export function ProcessDiagram({
selectedNodeId={selectedNodeId}
hoveredNodeId={toolbar.hoveredNodeId}
nodeConfigs={nodeConfigs}
executionOverlay={executionOverlay}
executionOverlay={effectiveOverlay}
overlayActive={overlayActive}
iterationState={iterationState}
onIterationChange={onIterationChange}