feat: improve workflow builder UX (#41)

* chore: improve ux of workflow editor

* Improve workflow UX

* Add option to edit workflow name

* Fix undo/ redo for node editing
This commit is contained in:
Abhishek 2025-11-06 18:26:15 +05:30 committed by Sabiha Khan
parent 6ab23d4066
commit 1a0a18a435
27 changed files with 1749 additions and 879 deletions

View file

@ -8,6 +8,8 @@ import { NodeHeader, NodeHeaderIcon, NodeHeaderTitle } from "@/components/flow/n
interface NodeContentProps {
selected: boolean;
invalid?: boolean;
selected_through_edge?: boolean;
hovered_through_edge?: boolean;
title: string;
icon: ReactNode;
bgColor: string;
@ -15,11 +17,15 @@ interface NodeContentProps {
hasTargetHandle?: boolean;
children?: ReactNode;
className?: string;
onDoubleClick?: () => void;
nodeId?: string;
}
export const NodeContent = ({
selected,
invalid,
selected_through_edge,
hovered_through_edge,
title,
icon,
bgColor,
@ -27,13 +33,22 @@ export const NodeContent = ({
hasTargetHandle = false,
children,
className = "",
onDoubleClick,
nodeId,
}: NodeContentProps) => {
return (
<BaseNode selected={selected} invalid={invalid} className={`p-0 overflow-hidden ${className}`}>
<BaseNode
selected={selected}
invalid={invalid}
selected_through_edge={selected_through_edge}
hovered_through_edge={hovered_through_edge}
className={`p-0 overflow-hidden ${className}`}
onDoubleClick={onDoubleClick}
>
{hasTargetHandle && <BaseHandle type="target" position={Position.Top} />}
<NodeHeader className={`px-3 py-2 border-b ${bgColor}`}>
<NodeHeaderIcon>{icon}</NodeHeaderIcon>
<NodeHeaderTitle>{title}</NodeHeaderTitle>
<NodeHeaderTitle>{title} - NodeID: {nodeId}</NodeHeaderTitle>
</NodeHeader>
<div className="p-3">
{children}

View file

@ -1,7 +1,7 @@
import { useReactFlow } from "@xyflow/react";
import { useCallback, useState } from "react";
import { FlowEdge, FlowNode, FlowNodeData } from "@/components/flow/types";
import { useWorkflowStore } from "@/app/workflow/[workflowId]/stores/workflowStore";
import { FlowNodeData } from "@/components/flow/types";
interface UseNodeHandlersProps {
id: string;
@ -10,25 +10,26 @@ interface UseNodeHandlersProps {
export const useNodeHandlers = ({ id, additionalData = {} }: UseNodeHandlersProps) => {
const [open, setOpen] = useState(false);
const { setNodes } = useReactFlow<FlowNode, FlowEdge>();
const updateNode = useWorkflowStore((state) => state.updateNode);
const deleteNode = useWorkflowStore((state) => state.deleteNode);
const nodes = useWorkflowStore((state) => state.nodes);
const handleSaveNodeData = useCallback(
(updatedData: FlowNodeData) => {
setNodes((nodes) => {
const updatedNodes = nodes.map((node) =>
node.id === id
? { ...node, data: { ...node.data, ...updatedData, ...additionalData } }
: node
);
return updatedNodes;
});
// Find the current node to merge data properly
const currentNode = nodes.find(node => node.id === id);
if (currentNode) {
updateNode(id, {
data: { ...currentNode.data, ...updatedData, ...additionalData }
});
}
},
[id, setNodes, additionalData]
[id, updateNode, additionalData, nodes]
);
const handleDeleteNode = useCallback(() => {
setNodes((nodes) => nodes.filter((node) => node.id !== id));
}, [id, setNodes]);
deleteNode(id);
}, [id, deleteNode]);
return {
open,