diff --git a/frontend/src/lib/components/graph/FlowGraphV2.svelte b/frontend/src/lib/components/graph/FlowGraphV2.svelte index c91e3e2dfd..04c2abaa84 100644 --- a/frontend/src/lib/components/graph/FlowGraphV2.svelte +++ b/frontend/src/lib/components/graph/FlowGraphV2.svelte @@ -1336,8 +1336,9 @@ {maxHeight} {selectedId} onSelect={(id) => { + if (notSelectable) return selectionManager.selectId(id) - if (!notSelectable) onSelect?.(id) + onSelect?.(id) }} > {#snippet topLeftControls()} diff --git a/frontend/src/lib/components/graph/simplified/SimplifiedFlowGraph.svelte b/frontend/src/lib/components/graph/simplified/SimplifiedFlowGraph.svelte index ab7cea850f..a7cd7ed095 100644 --- a/frontend/src/lib/components/graph/simplified/SimplifiedFlowGraph.svelte +++ b/frontend/src/lib/components/graph/simplified/SimplifiedFlowGraph.svelte @@ -37,7 +37,16 @@ let layout = $derived( layoutSimplifiedFlow({ modules: modules ?? [], failureModule, preprocessorModule }) ) - let nodes = $derived(layout.nodes.map((n) => ({ ...n, selected: n.id === selectedId }))) + // The full graph selects a branch lane as `-branch-`; here the lane + // belongs to its group, which is keyed by the module id. + let nodes = $derived( + layout.nodes.map((n) => ({ + ...n, + selected: + n.id === selectedId || + (n.type === 'simplifiedBox' && !!selectedId?.startsWith(`${n.id}-branch-`)) + })) + ) const PAD = 72 const MIN_READABLE_ZOOM = 0.7 diff --git a/frontend/src/lib/components/graph/simplified/simplifiedLayout.test.ts b/frontend/src/lib/components/graph/simplified/simplifiedLayout.test.ts index b62dede548..c1b8ce01c5 100644 --- a/frontend/src/lib/components/graph/simplified/simplifiedLayout.test.ts +++ b/frontend/src/lib/components/graph/simplified/simplifiedLayout.test.ts @@ -85,4 +85,26 @@ describe('layoutSimplifiedFlow', () => { 'one:empty-1->Result' ]) }) + + it('joins two branch groups in a row through one junction instead of every exit-entry pair', () => { + const group = (id: string, steps: string[]): FlowModule => ({ + id, + value: { type: 'branchall', branches: steps.map((s) => ({ modules: [step(s, s)] })) } + }) + const { nodes, edges } = layoutSimplifiedFlow( + { modules: [group('g1', ['a', 'b']), group('g2', ['c', 'd', 'e'])] }, + measure + ) + const junction = nodes.find((n) => (n.data as { kind?: string }).kind === 'junction')! + const pairs = edges.map((e) => `${e.source}->${e.target}`) + expect(pairs).toEqual(expect.arrayContaining(['a', 'b'].map((s) => `${s}->${junction.id}`))) + expect(pairs).toEqual( + expect.arrayContaining(['c', 'd', 'e'].map((t) => `${junction.id}->${t}`)) + ) + expect(pairs.filter((p) => /^[ab]->[cde]$/.test(p))).toEqual([]) + // It sits in the gap between the two groups + const byId = Object.fromEntries(nodes.map((n) => [n.id, n])) + expect(junction.position.x).toBeGreaterThan(byId.a.position.x + byId.a.width!) + expect(junction.position.x + junction.width!).toBeLessThan(byId.c.position.x) + }) }) diff --git a/frontend/src/lib/components/graph/simplified/simplifiedLayout.ts b/frontend/src/lib/components/graph/simplified/simplifiedLayout.ts index 121ce8e38b..a97feef8df 100644 --- a/frontend/src/lib/components/graph/simplified/simplifiedLayout.ts +++ b/frontend/src/lib/components/graph/simplified/simplifiedLayout.ts @@ -189,9 +189,11 @@ function sized( measure: TextMeasurer ): SimplifiedNodeData { const meta = [data.stepId, data.typeLabel].filter(Boolean).join(' ยท ') + // The error handler and the preprocessor prefix their meta row with an 11px icon and its gap + const metaIcon = data.kind === 'failure' || data.kind === 'preprocessor' ? 18 : 0 const content = Math.max( measure(data.title, 'title'), - meta ? measure(meta, 'meta') : 0, + meta ? measure(meta, 'meta') + metaIcon : 0, data.detail ? measure(data.detail, 'meta') : 0 ) const width = Math.round( @@ -216,7 +218,8 @@ export function moduleNodeData( module: mod, title, stepId: mod.id, - typeLabel: typeLabel(mod) === title ? undefined : typeLabel(mod), + typeLabel: + typeLabel(mod).toLowerCase() === title.toLowerCase() ? undefined : typeLabel(mod), detail: moduleDetail(mod, title) }, measure