export const NODE_TYPES = [ { type: 'start', label: 'Start' }, { type: 'condition', label: 'Condition' }, { type: 'approval', label: 'Approval' }, { type: 'notify', label: 'Notify' }, { type: 'action', label: 'Action' }, { type: 'end', label: 'End' }, ]; export function labelFor(node) { const type = node.type || node.data?.nodeType; const config = node.config || node.data?.config || {}; if (type === 'approval') return `Approval (${config.mode || 'single'})`; if (type === 'end') return `End (${config.outcome || 'completed'})`; if (type === 'notify') return 'Notify'; if (type === 'action') return config.name || 'Action'; if (type === 'condition') return 'Condition'; return 'Start'; } export function edgeLabel(when) { if (!when || !when.field) return ''; return `${when.field} ${when.op || 'eq'} ${when.value ?? ''}`; } export function toFlow(definition) { const layout = definition.layout || {}; return { nodes: (definition.nodes || []).map((node, index) => ({ id: node.id, position: layout[node.id] || { x: 80 + (index % 3) * 220, y: 80 + Math.floor(index / 3) * 140 }, data: { label: labelFor(node), nodeType: node.type, config: node.config || {}, }, })), edges: (definition.edges || []).map((edge) => ({ id: edge.id, source: edge.source, target: edge.target, label: edgeLabel(edge.when), data: { when: edge.when || null }, })), }; } export function fromFlow(nodes, edges) { return { nodes: nodes.map((node) => ({ id: node.id, type: node.data.nodeType, config: node.data.config || {}, })), edges: edges.map((edge) => { const when = edge.data && edge.data.when && edge.data.when.field ? edge.data.when : null; return { id: edge.id, source: edge.source, target: edge.target, ...(when ? { when } : {}), }; }), layout: Object.fromEntries(nodes.map((node) => [node.id, node.position])), }; } export function defaultConfig(type) { if (type === 'approval') return { mode: 'sequential', approvers: ['l1manager'], escalate_vacant: true }; if (type === 'notify') return { recipients: ['l1manager'], subject: '', body: '' }; if (type === 'action') return { name: 'set_status', status: 'approved' }; if (type === 'end') return { outcome: 'completed' }; return {}; }