Compare commits
2 Commits
26de222884
...
30e9b55379
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30e9b55379 | ||
|
|
3091754b0f |
@@ -90,7 +90,7 @@ export function DetailPanel({
|
||||
<div className={styles.detailPanel}>
|
||||
{/* Header bar */}
|
||||
<div className={styles.processorHeader}>
|
||||
<span className={styles.processorName}>Details</span>
|
||||
<span className={styles.processorName}>{selectedProcessor ? 'Processor Details' : 'Exchange Details'}</span>
|
||||
</div>
|
||||
|
||||
{/* Tab bar */}
|
||||
|
||||
@@ -20,15 +20,46 @@ interface ExecutionDiagramProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ITERATION_WRAPPER_TYPES = new Set([
|
||||
'loopIteration', 'splitIteration', 'multicastBranch',
|
||||
]);
|
||||
|
||||
function wrapperIndex(proc: ProcessorNode): number | undefined {
|
||||
return proc.loopIndex ?? proc.splitIndex ?? proc.multicastIndex ?? undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a processor in the tree, respecting iteration filtering.
|
||||
* Only recurses into the selected iteration wrapper so the returned
|
||||
* ProcessorNode has data from the correct iteration.
|
||||
*/
|
||||
function findProcessorInTree(
|
||||
nodes: ProcessorNode[] | undefined,
|
||||
processorId: string | null,
|
||||
iterationState?: Map<string, import('./types').IterationInfo>,
|
||||
parentId?: string,
|
||||
): ProcessorNode | null {
|
||||
if (!nodes || !processorId) return null;
|
||||
for (const n of nodes) {
|
||||
if (!n.processorId) continue;
|
||||
|
||||
// Iteration wrapper: only recurse into the selected iteration
|
||||
if (ITERATION_WRAPPER_TYPES.has(n.processorType)) {
|
||||
if (parentId && iterationState?.has(parentId)) {
|
||||
const info = iterationState.get(parentId)!;
|
||||
const idx = wrapperIndex(n);
|
||||
if (idx != null && idx !== info.current) continue;
|
||||
}
|
||||
if (n.children) {
|
||||
const found = findProcessorInTree(n.children, processorId, iterationState, n.processorId);
|
||||
if (found) return found;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.processorId === processorId) return n;
|
||||
if (n.children) {
|
||||
const found = findProcessorInTree(n.children, processorId);
|
||||
const found = findProcessorInTree(n.children, processorId, iterationState, n.processorId);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
@@ -204,7 +235,11 @@ export function ExecutionDiagram({
|
||||
{/* Detail panel */}
|
||||
<div className={styles.detailArea} style={{ height: `${100 - splitPercent}%` }}>
|
||||
<DetailPanel
|
||||
selectedProcessor={findProcessorInTree(detail.processors, selectedProcessorId || null)}
|
||||
selectedProcessor={
|
||||
selectedProcessorId && overlay.has(selectedProcessorId)
|
||||
? findProcessorInTree(detail.processors, selectedProcessorId, iterationState)
|
||||
: null
|
||||
}
|
||||
executionDetail={detail}
|
||||
executionId={executionId}
|
||||
onSelectProcessor={setSelectedProcessorId}
|
||||
|
||||
@@ -71,6 +71,10 @@ export function CompoundNode({
|
||||
const isGated = ownState?.filterMatched === false || ownState?.duplicateMessage === true;
|
||||
const effectiveColor = isGated ? 'var(--amber)' : color;
|
||||
|
||||
// Dim compound when overlay is active but neither the compound nor any
|
||||
// descendant was executed in the current iteration.
|
||||
const isSkipped = overlayActive && !ownState && !hasExecutedDescendant(node, executionOverlay);
|
||||
|
||||
// _TRY_BODY / _CB_MAIN: transparent wrapper — no header, no border, just layout
|
||||
if (node.type === '_TRY_BODY' || node.type === '_CB_MAIN') {
|
||||
return (
|
||||
@@ -85,7 +89,7 @@ export function CompoundNode({
|
||||
if (node.type === '_CB_FALLBACK') {
|
||||
const fallbackColor = '#7C3AED'; // EIP purple
|
||||
return (
|
||||
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
|
||||
<g data-node-id={node.id} transform={`translate(${x}, ${y})`} opacity={isSkipped ? 0.35 : undefined}>
|
||||
<rect x={0} y={0} width={w} height={h} rx={CORNER_RADIUS}
|
||||
fill={fallbackColor} fillOpacity={0.06} />
|
||||
<rect x={0} y={0} width={w} height={h} rx={CORNER_RADIUS}
|
||||
@@ -106,7 +110,7 @@ export function CompoundNode({
|
||||
: (node.label ? `finally: ${node.label}` : 'finally');
|
||||
|
||||
return (
|
||||
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
|
||||
<g data-node-id={node.id} transform={`translate(${x}, ${y})`} opacity={isSkipped ? 0.35 : undefined}>
|
||||
{/* Tinted background */}
|
||||
<rect x={0} y={0} width={w} height={h} rx={CORNER_RADIUS}
|
||||
fill={color} fillOpacity={0.06} />
|
||||
@@ -126,7 +130,7 @@ export function CompoundNode({
|
||||
// Default compound rendering (DO_TRY, EIP_CHOICE, EIP_FILTER, EIP_IDEMPOTENT_CONSUMER, etc.)
|
||||
const containerFill = isGated ? 'var(--amber-bg)' : 'white';
|
||||
return (
|
||||
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
|
||||
<g data-node-id={node.id} transform={`translate(${x}, ${y})`} opacity={isSkipped ? 0.35 : undefined}>
|
||||
{/* Container body */}
|
||||
<rect
|
||||
x={0}
|
||||
@@ -268,3 +272,15 @@ function collectIds(nodes: DiagramNodeType[], set: Set<string>) {
|
||||
if (n.children) collectIds(n.children, set);
|
||||
}
|
||||
}
|
||||
|
||||
function hasExecutedDescendant(
|
||||
node: DiagramNodeType,
|
||||
overlay?: Map<string, NodeExecutionState>,
|
||||
): boolean {
|
||||
if (!overlay || !node.children) return false;
|
||||
for (const child of node.children) {
|
||||
if (child.id && overlay.has(child.id)) return true;
|
||||
if (child.children && hasExecutedDescendant(child, overlay)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user