Auto update output parameter names after renaming a block (#828)

This commit is contained in:
Kerem Yilmaz
2024-09-13 12:00:16 -07:00
committed by GitHub
parent d435f1bffa
commit 5feee8f594
9 changed files with 182 additions and 20 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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,
};