/* Deep pipeline flow explorer */ const FLOW_TABS = ['Uitleg', 'Code', 'Data', 'Artefacten', 'Runtime']; function nodeById(catalog, id) { return (catalog.nodes || []).find(n => n.id === id) || null; } function nodeVisibleInMode(node, flowMode) { const modes = node.modes || ['pand_scan']; return modes.includes(flowMode); } function groupNodes(catalog, groupId, flowMode) { return (catalog.nodes || []).filter(n => n.group === groupId && nodeVisibleInMode(n, flowMode)); } function FlowNode({ node, selected, traceRows, onClick }) { const trace = traceRows.find(r => r.node_id === node.id); const status = trace ? trace.status : null; const cls = [ 'bd-flow-node', selected ? 'is-selected' : '', status ? 'has-trace' : '', status ? `is-${status}` : '', ].filter(Boolean).join(' '); return ( ); } function FlowDetail({ node, activeTab, setActiveTab, traceRows }) { if (!node) return ; const rows = traceRows.filter(r => r.node_id === node.id); const latest = rows[rows.length - 1] || null; return ( ); } function SchermFlow() { const [catalog, setCatalog] = useState({groups: [], nodes: [], edges: []}); const [flowMode, setFlowMode] = useState('pand_scan'); const [selectedNodeId, setSelectedNodeId] = useState(null); const [activeGroup, setActiveGroup] = useState('foto'); const [activeTab, setActiveTab] = useState('Uitleg'); const [traceRows, setTraceRows] = useState([]); const [selectedTaakId, setSelectedTaakId] = useState(''); const [selectedPandId, setSelectedPandId] = useState(''); const [traceLaden, setTraceLaden] = useState(false); const [fout, setFout] = useState(null); useEffect(() => { fetch(`${API}/pipeline/flow-catalog`) .then(r => r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`))) .then(data => { setCatalog(data); const first = (data.nodes || []).find(n => n.id === 'foto.haal_luchtfoto') || (data.nodes || [])[0]; if (first) setSelectedNodeId(first.id); }) .catch(e => setFout(e.message || 'Flow-catalogus laden mislukt')); }, []); const selectedNode = nodeById(catalog, selectedNodeId); const visibleGroups = (catalog.groups || []).filter(g => groupNodes(catalog, g.id, flowMode).length > 0); const visibleNodes = groupNodes(catalog, activeGroup, flowMode); useEffect(() => { const firstGroup = visibleGroups[0]; if (firstGroup && !visibleGroups.some(g => g.id === activeGroup)) { setActiveGroup(firstGroup.id); return; } if (!selectedNode || !nodeVisibleInMode(selectedNode, flowMode)) { const firstNode = (catalog.nodes || []).find(n => nodeVisibleInMode(n, flowMode)); if (firstNode) setSelectedNodeId(firstNode.id); } }, [flowMode, catalog, activeGroup, selectedNodeId]); async function laadTrace() { if (!selectedTaakId) { setTraceRows([]); return; } setTraceLaden(true); setFout(null); try { const params = new URLSearchParams(); if (selectedPandId.trim()) params.set('pand_id', selectedPandId.trim()); const qs = params.toString(); const data = await fetch(`${API}/pipeline/${selectedTaakId}/trace${qs ? `?${qs}` : ''}`) .then(r => r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`))); setTraceRows(data || []); } catch (e) { setFout(e.message || 'Trace laden mislukt'); setTraceRows([]); } finally { setTraceLaden(false); } } return (

Flow

Bekijk wat de pipeline per stap doet, van BAG-pand tot AI-resultaat.

{[ ['pand_scan', 'Pand scan'], ['perceel_scan', 'Perceel scan'], ].map(([id, label]) => ( ))}
setSelectedTaakId(e.target.value)} /> setSelectedPandId(e.target.value)} /> Trace laden
{fout && {fout}}
{visibleNodes.map(node => ( ))}
); } window.SchermFlow = SchermFlow;