mitai-jinkendo/frontend/src/components/workflow/nodes/JoinNode.jsx
Lars c0525cf2d2
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 15s
feat: Extend JoinNode to support 8 input paths
- Increased from 3 to 8 input handles (path_1 through path_8)
- Evenly distributed across top edge (11%, 22%, 33%, ..., 89%)
- Backend already supports unlimited inputs dynamically
- Unused handles are ignored (no edges = no check)

Join strategies for missing inputs:
- wait_all: Fails if any connected path fails
- wait_any: Succeeds if at least 1 path succeeds
- best_effort: Always succeeds

User can still chain multiple Joins if >8 inputs needed.
Part 3: Inline Prompts - workflow flexibility
2026-04-11 10:25:28 +02:00

105 lines
2.7 KiB
JavaScript

import { Handle, Position } from 'reactflow'
/**
* JoinNode - Pfad-Konsolidierung
*
* Properties:
* - data.label: Node-Label
* - data.join_strategy: 'wait_all' | 'wait_any' | 'best_effort'
* - data.skip_handling: 'ignore_skipped' | 'use_placeholder' | 'require_minimum'
* - selected: Boolean
*/
export function JoinNode({ data, selected }) {
const strategy = data.join_strategy || 'wait_all'
const skipHandling = data.skip_handling || 'ignore_skipped'
// Strategy Display Names
const strategyLabels = {
'wait_all': 'Alle warten',
'wait_any': 'Beliebig',
'best_effort': 'Best Effort'
}
const skipLabels = {
'ignore_skipped': 'Ignorieren',
'use_placeholder': 'Platzhalter',
'require_minimum': 'Minimum'
}
return (
<div className={`workflow-node join-node ${selected ? 'selected' : ''}`}>
<div className="node-header">
<div className="node-icon">🔀</div>
<div className="node-label">{data.label || 'Join'}</div>
</div>
<div className="node-body">
<div className="strategy">
<strong>Strategie:</strong> {strategyLabels[strategy] || strategy}
</div>
<div className="skip-handling">
<strong>Skip:</strong> {skipLabels[skipHandling] || skipHandling}
</div>
</div>
{/* Mehrere Target Handles für eingehende Pfade (bis zu 8) */}
<Handle
type="target"
position={Position.Top}
id="path_1"
style={{ left: '11%', background: '#17A2B8' }}
/>
<Handle
type="target"
position={Position.Top}
id="path_2"
style={{ left: '22%', background: '#17A2B8' }}
/>
<Handle
type="target"
position={Position.Top}
id="path_3"
style={{ left: '33%', background: '#17A2B8' }}
/>
<Handle
type="target"
position={Position.Top}
id="path_4"
style={{ left: '44%', background: '#17A2B8' }}
/>
<Handle
type="target"
position={Position.Top}
id="path_5"
style={{ left: '56%', background: '#17A2B8' }}
/>
<Handle
type="target"
position={Position.Top}
id="path_6"
style={{ left: '67%', background: '#17A2B8' }}
/>
<Handle
type="target"
position={Position.Top}
id="path_7"
style={{ left: '78%', background: '#17A2B8' }}
/>
<Handle
type="target"
position={Position.Top}
id="path_8"
style={{ left: '89%', background: '#17A2B8' }}
/>
{/* Ein Source Handle für konsolidierten Ausgang */}
<Handle
type="source"
position={Position.Bottom}
id="out"
style={{ background: '#17A2B8' }}
/>
</div>
)
}