diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/CodeBlockNode/CodeBlockNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/CodeBlockNode/CodeBlockNode.tsx index afae032e..4fccbaec 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/CodeBlockNode/CodeBlockNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/CodeBlockNode/CodeBlockNode.tsx @@ -14,7 +14,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import type { CodeBlockNode } from "./types"; import { useState } from "react"; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; import { AppNode } from ".."; @@ -54,8 +54,9 @@ function CodeBlockNode({ id, data }: NodeProps) { editable={data.editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/DownloadNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/DownloadNode.tsx index d0b0ee6b..c67feda6 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/DownloadNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/DownloadNode.tsx @@ -14,7 +14,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import type { DownloadNode } from "./types"; import { useState } from "react"; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; import { AppNode } from ".."; @@ -51,8 +51,9 @@ function DownloadNode({ id, data }: NodeProps) { editable={data.editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/FileParserNode/FileParserNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/FileParserNode/FileParserNode.tsx index 267b222d..bc5bcf57 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/FileParserNode/FileParserNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/FileParserNode/FileParserNode.tsx @@ -13,7 +13,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import type { FileParserNode } from "./types"; import { useState } from "react"; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; import { AppNode } from ".."; @@ -53,8 +53,9 @@ function FileParserNode({ id, data }: NodeProps) { editable={data.editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/LoopNode/LoopNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/LoopNode/LoopNode.tsx index e92da0cd..ec67066b 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/LoopNode/LoopNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/LoopNode/LoopNode.tsx @@ -15,7 +15,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import type { LoopNode } from "./types"; import { useState } from "react"; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; import { AppNode } from ".."; @@ -81,8 +81,9 @@ function LoopNode({ id, data }: NodeProps) { editable={data.editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx index 8fb280fa..99255769 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx @@ -15,7 +15,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import type { SendEmailNode } from "./types"; import { useState } from "react"; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; import { AppNode } from ".."; @@ -66,8 +66,9 @@ function SendEmailNode({ id, data }: NodeProps) { editable={data.editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx index 96fc6854..6fe75d08 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx @@ -24,7 +24,7 @@ import { import { useState } from "react"; import { AppNode } from ".."; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getOutputParameterKey, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; @@ -423,8 +423,9 @@ function TaskNode({ id, data }: NodeProps) { editable={editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/TextPromptNode/TextPromptNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/TextPromptNode/TextPromptNode.tsx index e85f4d23..9a07d606 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TextPromptNode/TextPromptNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/TextPromptNode/TextPromptNode.tsx @@ -17,7 +17,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import type { TextPromptNode } from "./types"; import { useState } from "react"; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; import { AppNode } from ".."; @@ -59,8 +59,9 @@ function TextPromptNode({ id, data }: NodeProps) { editable={data.editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/UploadNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/UploadNode.tsx index 2d978c88..e0fd0b43 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/UploadNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/UploadNode.tsx @@ -14,7 +14,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import type { UploadNode } from "./types"; import { useState } from "react"; import { - getLabelForExistingNode, + getUniqueLabelForExistingNode, getUpdatedNodesAfterLabelUpdateForParameterKeys, } from "../../workflowEditorUtils"; import { AppNode } from ".."; @@ -51,8 +51,9 @@ function UploadNode({ id, data }: NodeProps) { editable={data.editable} onChange={(value) => { const existingLabels = nodes.map((n) => n.data.label); - const newLabel = getLabelForExistingNode( - value, + const labelWithoutWhitespace = value.replace(/\s+/g, "_"); + const newLabel = getUniqueLabelForExistingNode( + labelWithoutWhitespace, existingLabels, ); setLabel(newLabel); diff --git a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts index b40f09cf..995ea106 100644 --- a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts +++ b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts @@ -30,7 +30,7 @@ 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 "; +export const NEW_NODE_LABEL_PREFIX = "block_"; function layoutUtil( nodes: Array, @@ -754,12 +754,15 @@ function getAdditionalParametersForEmailBlock( return sendEmailParameters; } -function getLabelForExistingNode(label: string, existingLabels: Array) { +function getUniqueLabelForExistingNode( + label: string, + existingLabels: Array, +) { if (!existingLabels.includes(label)) { return label; } for (let i = 2; i < existingLabels.length + 1; i++) { - const candidate = `${label} (${i})`; + const candidate = `${label}_${i}`; if (!existingLabels.includes(candidate)) { return candidate; } @@ -801,7 +804,7 @@ export { getOutputParameterKey, getUpdatedNodesAfterLabelUpdateForParameterKeys, getAdditionalParametersForEmailBlock, - getLabelForExistingNode, + getUniqueLabelForExistingNode, isOutputParameterKey, getBlockNameOfOutputParameterKey, getDefaultValueForParameterType,