Auto update output parameter names after renaming a block (#828)
This commit is contained in:
@@ -2,14 +2,23 @@ import { Label } from "@/components/ui/label";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { CodeIcon } from "@radix-ui/react-icons";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
Position,
|
||||
useNodes,
|
||||
useReactFlow,
|
||||
} from "@xyflow/react";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import type { CodeBlockNode } from "./types";
|
||||
import { useState } from "react";
|
||||
import { getUpdatedNodesAfterLabelUpdateForParameterKeys } from "../../workflowEditorUtils";
|
||||
import { AppNode } from "..";
|
||||
|
||||
function CodeBlockNode({ id, data }: NodeProps<CodeBlockNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const nodes = useNodes();
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
const [label, setLabel] = useState(data.label);
|
||||
const [inputs, setInputs] = useState({
|
||||
@@ -43,6 +52,13 @@ function CodeBlockNode({ id, data }: NodeProps<CodeBlockNode>) {
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">Code Block</span>
|
||||
|
||||
@@ -2,14 +2,25 @@ import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { DownloadIcon } from "@radix-ui/react-icons";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
Position,
|
||||
useNodes,
|
||||
useReactFlow,
|
||||
} from "@xyflow/react";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import type { DownloadNode } from "./types";
|
||||
import { useState } from "react";
|
||||
import { getUpdatedNodesAfterLabelUpdateForParameterKeys } from "../../workflowEditorUtils";
|
||||
import { AppNode } from "..";
|
||||
|
||||
function DownloadNode({ id, data }: NodeProps<DownloadNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const nodes = useNodes();
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
const [label, setLabel] = useState(data.label);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -33,9 +44,19 @@ function DownloadNode({ id, data }: NodeProps<DownloadNode>) {
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
value={data.label}
|
||||
value={label}
|
||||
editable={data.editable}
|
||||
onChange={(value) => updateNodeData(id, { label: value })}
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">Download Block</span>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { CursorTextIcon } from "@radix-ui/react-icons";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
Position,
|
||||
useNodes,
|
||||
useReactFlow,
|
||||
} from "@xyflow/react";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import type { FileParserNode } from "./types";
|
||||
import { useState } from "react";
|
||||
import { getUpdatedNodesAfterLabelUpdateForParameterKeys } from "../../workflowEditorUtils";
|
||||
import { AppNode } from "..";
|
||||
|
||||
function FileParserNode({ id, data }: NodeProps<FileParserNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
const nodes = useNodes();
|
||||
const [label, setLabel] = useState(data.label);
|
||||
const [inputs, setInputs] = useState({
|
||||
fileUrl: data.fileUrl,
|
||||
@@ -42,6 +51,13 @@ function FileParserNode({ id, data }: NodeProps<FileParserNode>) {
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">File Parser Block</span>
|
||||
|
||||
@@ -14,9 +14,11 @@ import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import type { LoopNode } from "./types";
|
||||
import { useState } from "react";
|
||||
import { getUpdatedNodesAfterLabelUpdateForParameterKeys } from "../../workflowEditorUtils";
|
||||
import { AppNode } from "..";
|
||||
|
||||
function LoopNode({ id, data }: NodeProps<LoopNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const nodes = useNodes();
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
const [label, setLabel] = useState(data.label);
|
||||
@@ -77,6 +79,13 @@ function LoopNode({ id, data }: NodeProps<LoopNode>) {
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">Loop Block</span>
|
||||
|
||||
@@ -3,14 +3,23 @@ import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { EnvelopeClosedIcon } from "@radix-ui/react-icons";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
Position,
|
||||
useNodes,
|
||||
useReactFlow,
|
||||
} from "@xyflow/react";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import type { SendEmailNode } from "./types";
|
||||
import { useState } from "react";
|
||||
import { getUpdatedNodesAfterLabelUpdateForParameterKeys } from "../../workflowEditorUtils";
|
||||
import { AppNode } from "..";
|
||||
|
||||
function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const nodes = useNodes();
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
const [label, setLabel] = useState(data.label);
|
||||
const [inputs, setInputs] = useState({
|
||||
@@ -56,6 +65,13 @@ function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">Send Email Block</span>
|
||||
|
||||
@@ -23,7 +23,10 @@ import {
|
||||
} from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { AppNode } from "..";
|
||||
import { getOutputParameterKey } from "../../workflowEditorUtils";
|
||||
import {
|
||||
getOutputParameterKey,
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys,
|
||||
} from "../../workflowEditorUtils";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { TaskNodeDisplayModeSwitch } from "./TaskNodeDisplayModeSwitch";
|
||||
@@ -54,7 +57,7 @@ function getPreviousNodeIds(
|
||||
}
|
||||
|
||||
function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const [displayMode, setDisplayMode] = useState<TaskNodeDisplayMode>("basic");
|
||||
const { editable } = data;
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
@@ -419,7 +422,13 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
editable={editable}
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">Task Block</span>
|
||||
|
||||
@@ -5,14 +5,23 @@ import { Separator } from "@/components/ui/separator";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { CursorTextIcon } from "@radix-ui/react-icons";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
Position,
|
||||
useNodes,
|
||||
useReactFlow,
|
||||
} from "@xyflow/react";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import type { TextPromptNode } from "./types";
|
||||
import { useState } from "react";
|
||||
import { getUpdatedNodesAfterLabelUpdateForParameterKeys } from "../../workflowEditorUtils";
|
||||
import { AppNode } from "..";
|
||||
|
||||
function TextPromptNode({ id, data }: NodeProps<TextPromptNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const nodes = useNodes();
|
||||
const { editable } = data;
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
const [label, setLabel] = useState(data.label);
|
||||
@@ -48,6 +57,13 @@ function TextPromptNode({ id, data }: NodeProps<TextPromptNode>) {
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">Text Prompt Block</span>
|
||||
|
||||
@@ -2,14 +2,25 @@ import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { UploadIcon } from "@radix-ui/react-icons";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
Position,
|
||||
useNodes,
|
||||
useReactFlow,
|
||||
} from "@xyflow/react";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import type { UploadNode } from "./types";
|
||||
import { useState } from "react";
|
||||
import { getUpdatedNodesAfterLabelUpdateForParameterKeys } from "../../workflowEditorUtils";
|
||||
import { AppNode } from "..";
|
||||
|
||||
function UploadNode({ id, data }: NodeProps<UploadNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const { updateNodeData, setNodes } = useReactFlow();
|
||||
const nodes = useNodes();
|
||||
const deleteNodeCallback = useDeleteNodeCallback();
|
||||
const [label, setLabel] = useState(data.label);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -33,9 +44,19 @@ function UploadNode({ id, data }: NodeProps<UploadNode>) {
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
value={data.label}
|
||||
value={label}
|
||||
editable={data.editable}
|
||||
onChange={(value) => updateNodeData(id, { label: value })}
|
||||
onChange={(value) => {
|
||||
setLabel(value);
|
||||
updateNodeData(id, { label: value });
|
||||
setNodes(
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id,
|
||||
value,
|
||||
nodes as Array<AppNode>,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-slate-400">Upload Block</span>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { sendEmailNodeDefaultData } from "./nodes/SendEmailNode/types";
|
||||
import { taskNodeDefaultData } from "./nodes/TaskNode/types";
|
||||
import { textPromptNodeDefaultData } from "./nodes/TextPromptNode/types";
|
||||
import { uploadNodeDefaultData } from "./nodes/UploadNode/types";
|
||||
import type { Node } from "@xyflow/react";
|
||||
|
||||
export const NEW_NODE_LABEL_PREFIX = "Block ";
|
||||
|
||||
@@ -620,6 +621,42 @@ function getOutputParameterKey(label: string) {
|
||||
return label + "_output";
|
||||
}
|
||||
|
||||
function getUpdatedNodesAfterLabelUpdateForParameterKeys(
|
||||
id: string,
|
||||
newLabel: string,
|
||||
nodes: Array<Node>,
|
||||
): Array<Node> {
|
||||
const labelUpdatedNode = nodes.find((node) => node.id === id);
|
||||
if (!labelUpdatedNode) {
|
||||
return nodes;
|
||||
}
|
||||
const oldLabel = labelUpdatedNode.data.label as string;
|
||||
return nodes.map((node) => {
|
||||
if (node.type === "task") {
|
||||
return {
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
parameterKeys: (node.data.parameterKeys as Array<string>).map(
|
||||
(key) =>
|
||||
key === getOutputParameterKey(oldLabel)
|
||||
? getOutputParameterKey(newLabel)
|
||||
: key,
|
||||
),
|
||||
label: node.id === id ? newLabel : node.data.label,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
label: node.id === id ? newLabel : node.data.label,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
createNode,
|
||||
generateNodeData,
|
||||
@@ -629,4 +666,5 @@ export {
|
||||
generateNodeLabel,
|
||||
convertEchoParameters,
|
||||
getOutputParameterKey,
|
||||
getUpdatedNodesAfterLabelUpdateForParameterKeys,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user