diff --git a/web/src/views/Workflow/components/CanvasToolbar.tsx b/web/src/views/Workflow/components/CanvasToolbar.tsx index 1bbb51f2..8225b65f 100644 --- a/web/src/views/Workflow/components/CanvasToolbar.tsx +++ b/web/src/views/Workflow/components/CanvasToolbar.tsx @@ -57,7 +57,6 @@ const CanvasToolbar: FC = ({ } }} labelRender={(props) => { - console.log('props', props) return `${props.value}%` }} className="rb:w-20 rb:h-4!" diff --git a/web/src/views/Workflow/components/Chat/Chat.tsx b/web/src/views/Workflow/components/Chat/Chat.tsx index 863825ba..025c2e0b 100644 --- a/web/src/views/Workflow/components/Chat/Chat.tsx +++ b/web/src/views/Workflow/components/Chat/Chat.tsx @@ -66,8 +66,6 @@ const Chat = forwardRef([]) const [message, setMessage] = useState(undefined) - console.log('abortRef', abortRef, chatList) - /** * Opens the chat drawer and loads workflow variables from the start node */ diff --git a/web/src/views/Workflow/components/Nodes/AddNode.tsx b/web/src/views/Workflow/components/Nodes/AddNode.tsx index 3bdb96c0..15f4aa1e 100644 --- a/web/src/views/Workflow/components/Nodes/AddNode.tsx +++ b/web/src/views/Workflow/components/Nodes/AddNode.tsx @@ -18,6 +18,7 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => { // Handle node selection from popover and create new node replacing the add-node placeholder const handleNodeSelect = (selectedNodeType: any) => { + graph.startBatch('add-node'); const parentBBox = node.getBBox(); const cycleId = data.cycle; const horizontalSpacing = 0; @@ -76,6 +77,8 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => { } }); + graph.stopBatch('add-node'); + setTimeout(() => { addedEdges.forEach(e => { const src = graph.getCellById(e.getSourceCellId()); diff --git a/web/src/views/Workflow/components/Nodes/ConditionNode.tsx b/web/src/views/Workflow/components/Nodes/ConditionNode.tsx index b431ddd4..74a15c78 100644 --- a/web/src/views/Workflow/components/Nodes/ConditionNode.tsx +++ b/web/src/views/Workflow/components/Nodes/ConditionNode.tsx @@ -99,7 +99,7 @@ const ConditionNode: ReactShapeConfig['component'] = ({ node }) => { {data.type === 'if-else' && {data.config?.cases?.defaultValue.map((item: any, index: number) => ( -
0 ? '' : 'rb:mb-1'}> +
0 ? "space-between" : 'end'} className="rb:mb-1! rb:leading-4"> {item.expressions.length > 0 && CASE{index + 1}} {index === 0 ? 'IF' : `ELIF`} diff --git a/web/src/views/Workflow/components/PortClickHandler.tsx b/web/src/views/Workflow/components/PortClickHandler.tsx index cb3e16c4..68aef867 100644 --- a/web/src/views/Workflow/components/PortClickHandler.tsx +++ b/web/src/views/Workflow/components/PortClickHandler.tsx @@ -46,6 +46,7 @@ const PortClickHandler: React.FC = ({ graph }) => { // Handle node selection from popover menu and create new node with edge connection const handleNodeSelect = (selectedNodeType: any) => { if (!sourceNode || !graph) return; + graph.startBatch('add-node'); const sourceNodeData = sourceNode.getData(); const sourceNodeType = sourceNodeData?.type; @@ -308,6 +309,7 @@ const PortClickHandler: React.FC = ({ graph }) => { if (tgt?.isNode()) tgt.toFront(); }); } + graph.stopBatch('add-node'); }, 50); // Clean up temporary element diff --git a/web/src/views/Workflow/hooks/useWorkflowGraph.ts b/web/src/views/Workflow/hooks/useWorkflowGraph.ts index a22ee6c0..060bc75c 100644 --- a/web/src/views/Workflow/hooks/useWorkflowGraph.ts +++ b/web/src/views/Workflow/hooks/useWorkflowGraph.ts @@ -488,6 +488,9 @@ export const useWorkflowGraph = ({ graphRef.current.cleanHistory() } }, 200) + } else { + graphRef.current.enableHistory() + graphRef.current.cleanHistory() } } /** @@ -526,14 +529,12 @@ export const useWorkflowGraph = ({ enabled: false, beforeAddCommand(_event, args: any) { const event = args?.key ? `cell:change:${args.key}` : _event; - if (event.startsWith('cell:change:') && - event !== 'cell:change:position' && - event !== 'cell:change:source' && - event !== 'cell:change:target') return false; + const allowed = ['cell:added', 'cell:removed', 'cell:change:position', 'cell:change:source', 'cell:change:target']; + if (!allowed.includes(event)) return false; }, }), ); - graphRef.current.on('history:change', ({ cmds }: { cmds: Command[] }) => { + graphRef.current.on('history:change', () => { setCanUndo(graphRef.current?.canUndo() ?? false) setCanRedo(graphRef.current?.canRedo() ?? false) }) @@ -753,8 +754,6 @@ export const useWorkflowGraph = ({ // Find corresponding parent node const parentNode = nodes?.find(n => n.id === nodeData.cycle); if (parentNode) { - // Use removeChild method to delete child node - parentNode.removeChild(nodeToDelete); parentNodesToUpdate.push(parentNode); } // Add child node to deletion list @@ -782,6 +781,12 @@ export const useWorkflowGraph = ({ // Delete all collected nodes and edges if (cells.length > 0) { + graphRef.current?.startBatch('delete'); + // Remove parent-child relationships before removeCells + parentNodesToUpdate.forEach(parentNode => { + cells.filter(c => c.isNode() && (c as Node).getData()?.cycle === parentNode.getData()?.id) + .forEach(child => parentNode.removeChild(child)); + }); graphRef.current?.removeCells(cells); // If parent is iteration/loop and only cycle-start remains, add add-node connected to it @@ -818,6 +823,7 @@ export const useWorkflowGraph = ({ }); } }); + graphRef.current?.stopBatch('delete'); } return false; }; diff --git a/web/src/views/Workflow/utils.ts b/web/src/views/Workflow/utils.ts index 74dfca2c..a4035517 100644 --- a/web/src/views/Workflow/utils.ts +++ b/web/src/views/Workflow/utils.ts @@ -17,6 +17,7 @@ export const isSubExprSet = (sub: any) => { * Uses the same per-expression height logic as getConditionNodeCasePortY. */ export const calcConditionNodeTotalHeight = (cases: any[]) => { + if (!cases?.length) return conditionNodeHeight; const casesHeight = cases.reduce((acc: number, c: any) => { const exprs = c?.expressions ?? []; const n = exprs.length;