/** * NodeConfigPanel - Configures parameters for input/human nodes. * Form fields: draggable, required toggle, layout ohne clipping. */ import React, { useState, useEffect } from 'react'; import { FaGripVertical } from 'react-icons/fa'; import type { CanvasNode } from './FlowCanvas'; import type { NodeType } from '../../api/automation2Api'; import styles from './Automation2FlowEditor.module.css'; type FormField = { name?: string; type?: string; label?: string; required?: boolean }; interface NodeConfigPanelProps { node: CanvasNode | null; nodeType: NodeType | undefined; language: string; onParametersChange: (nodeId: string, parameters: Record) => void; } export const NodeConfigPanel: React.FC = ({ node, nodeType, language, onParametersChange, }) => { const [params, setParams] = useState>({}); useEffect(() => { setParams(node?.parameters ?? {}); }, [node?.id, node?.parameters]); const updateParam = (key: string, value: unknown) => { const next = { ...params, [key]: value }; setParams(next); if (node) onParametersChange(node.id, next); }; if (!node || !node.type.startsWith('input.')) return null; const nt = nodeType; const getLabel = (text: string | Record | undefined) => { if (!text) return ''; if (typeof text === 'string') return text; return (text as Record)[language] ?? (text as Record).en ?? ''; }; const renderConfig = () => { switch (node.type) { case 'input.form': { const fields = (params.fields as FormField[]) ?? []; const moveField = (fromIndex: number, toIndex: number) => { if (fromIndex < 0 || toIndex < 0 || fromIndex >= fields.length || toIndex >= fields.length) return; const next = [...fields]; const [removed] = next.splice(fromIndex, 1); next.splice(toIndex, 0, removed); updateParam('fields', next); }; return (
{fields.map((f, i) => (
{ e.preventDefault(); e.dataTransfer.dropEffect = 'move'; }} onDrop={(e) => { e.preventDefault(); const from = parseInt(e.dataTransfer.getData('text/plain'), 10); if (!Number.isNaN(from) && from !== i) moveField(from, i); }} >
{ e.dataTransfer.setData('text/plain', String(i)); e.dataTransfer.effectAllowed = 'move'; }} >
{ const next = [...fields]; next[i] = { ...next[i], name: e.target.value }; updateParam('fields', next); }} /> { const next = [...fields]; next[i] = { ...next[i], label: e.target.value }; updateParam('fields', next); }} />
))}
); } case 'input.approval': return ( <>
updateParam('title', e.target.value)} placeholder="Genehmigungstitel" />