From a7752de6a936296990eb7092b66af3b54ce8aac4 Mon Sep 17 00:00:00 2001 From: Shuchang Zheng Date: Fri, 24 Jan 2025 00:45:48 +0800 Subject: [PATCH] Update parameter hint (#1628) --- .../src/components/WorkflowBlockInput.tsx | 47 ++----------------- .../components/WorkflowBlockInputTextarea.tsx | 46 ++---------------- .../editor/hooks/useIsFirstNodeInWorkflow.tsx | 32 +++++++++++++ .../editor/nodes/ActionNode/ActionNode.tsx | 18 +++++-- .../nodes/ExtractionNode/ExtractionNode.tsx | 26 ++++++---- .../FileDownloadNode/FileDownloadNode.tsx | 17 +++++-- .../nodes/FileParserNode/FileParserNode.tsx | 28 +++++++---- .../editor/nodes/LoginNode/LoginNode.tsx | 17 +++++-- .../editor/nodes/LoopNode/LoopNode.tsx | 17 +++++-- .../nodes/NavigationNode/NavigationNode.tsx | 18 +++++-- .../nodes/PDFParserNode/PDFParserNode.tsx | 17 +++++-- .../nodes/SendEmailNode/SendEmailNode.tsx | 13 ++++- .../editor/nodes/TaskNode/TaskNode.tsx | 16 +++++-- .../nodes/TextPromptNode/TextPromptNode.tsx | 18 +++++-- .../nodes/ValidationNode/ValidationNode.tsx | 13 ++++- .../editor/nodes/WaitNode/WaitNode.tsx | 22 ++++++--- 16 files changed, 224 insertions(+), 141 deletions(-) create mode 100644 skyvern-frontend/src/routes/workflows/editor/hooks/useIsFirstNodeInWorkflow.tsx diff --git a/skyvern-frontend/src/components/WorkflowBlockInput.tsx b/skyvern-frontend/src/components/WorkflowBlockInput.tsx index 6fa6612c..655b4711 100644 --- a/skyvern-frontend/src/components/WorkflowBlockInput.tsx +++ b/skyvern-frontend/src/components/WorkflowBlockInput.tsx @@ -3,43 +3,14 @@ import { cn } from "@/util/utils"; import { Input } from "./ui/input"; import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; import { WorkflowBlockParameterSelect } from "@/routes/workflows/editor/nodes/WorkflowBlockParameterSelect"; -import { useEdges, useNodes } from "@xyflow/react"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "./ui/tooltip"; type Props = Omit, "onChange"> & { onChange: (value: string) => void; nodeId: string; - isFirstInputInNode?: boolean; }; function WorkflowBlockInput(props: Props) { const { nodeId, onChange, ...inputProps } = props; - const edges = useEdges(); - const nodes = useNodes(); - - function isInsideFirstNode() { - const node = nodes.find((node) => node.id === nodeId); - if (!node) { - return; - } - const incomingEdge = edges.find((edge) => edge.target === node.id); - if (!incomingEdge) { - return; - } - const source = incomingEdge.source; - const sourceNode = nodes.find((node) => node.id === source); - if (!sourceNode) { - return; - } - return !node.parentId && sourceNode.type === "start"; - } - - const showInputTooltip = isInsideFirstNode() && props.isFirstInputInNode; return (
@@ -52,19 +23,11 @@ function WorkflowBlockInput(props: Props) { />
- - - - -
- -
-
-
- Add parameters using the + button -
-
- + +
+ +
+
, @@ -17,32 +10,10 @@ type Props = Omit< > & { onChange: (value: string) => void; nodeId: string; - isFirstInputInNode?: boolean; }; function WorkflowBlockInputTextarea(props: Props) { const { nodeId, onChange, ...textAreaProps } = props; - const edges = useEdges(); - const nodes = useNodes(); - - function isInsideFirstNode() { - const node = nodes.find((node) => node.id === nodeId); - if (!node) { - return; - } - const incomingEdge = edges.find((edge) => edge.target === node.id); - if (!incomingEdge) { - return; - } - const source = incomingEdge.source; - const sourceNode = nodes.find((node) => node.id === source); - if (!sourceNode) { - return; - } - return !node.parentId && sourceNode.type === "start"; - } - - const showInputTooltip = isInsideFirstNode() && props.isFirstInputInNode; return (
@@ -55,18 +26,11 @@ function WorkflowBlockInputTextarea(props: Props) { />
- - - - -
- -
-
-
- Add parameters using the + button -
-
+ +
+ +
+
, edges: Array, id: string) { + const node = nodes.find((node) => node.id === id); + if (!node) { + return false; // doesn't make sense but for TS + } + const incomingEdge = edges.find((edge) => edge.target === node.id); + if (!incomingEdge) { + return false; + } + const source = incomingEdge.source; + const sourceNode = nodes.find((node) => node.id === source); + if (!sourceNode) { + return false; + } + return !node.parentId && sourceNode.type === "start"; +} + +type Props = { + id: string; +}; + +function useIsFirstBlockInWorkflow({ id }: Props): boolean { + const nodes = useNodes(); + const edges = useEdges(); + + return isFirstNode(nodes, edges, id); +} + +export { useIsFirstBlockInWorkflow }; diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx index 6e8569de..7d012a36 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/ActionNode/ActionNode.tsx @@ -34,6 +34,7 @@ import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes"; import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; const urlTooltip = "The URL Skyvern is navigating to. Leave this field blank to pick up from where the last block left off."; @@ -75,6 +76,8 @@ function ActionNode({ id, data }: NodeProps) { updateNodeData(id, { [key]: value }); } + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + return (
) {
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
+ { handleChange("url", value); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx index 16fbdd18..2b9e43ca 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/ExtractionNode/ExtractionNode.tsx @@ -32,6 +32,7 @@ import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; import { WorkflowDataSchemaInputGroup } from "@/components/DataSchemaInputGroup/WorkflowDataSchemaInputGroup"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function ExtractionNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -54,6 +55,8 @@ function ExtractionNode({ id, data }: NodeProps) { const edges = useEdges(); const outputParameterKeys = getAvailableOutputParameterKeys(nodes, edges, id); + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + function handleChange(key: string, value: unknown) { if (!editable) { return; @@ -100,16 +103,23 @@ function ExtractionNode({ id, data }: NodeProps) { />
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
+ { if (!editable) { diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/FileDownloadNode/FileDownloadNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/FileDownloadNode/FileDownloadNode.tsx index 6fa12e16..6c668462 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/FileDownloadNode/FileDownloadNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/FileDownloadNode/FileDownloadNode.tsx @@ -32,6 +32,7 @@ import type { FileDownloadNode } from "./types"; import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; const urlTooltip = "The URL Skyvern is navigating to. Leave this field blank to pick up from where the last block left off."; @@ -65,6 +66,8 @@ function FileDownloadNode({ id, data }: NodeProps) { const edges = useEdges(); const outputParameterKeys = getAvailableOutputParameterKeys(nodes, edges, id); + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + function handleChange(key: string, value: unknown) { if (!editable) { return; @@ -114,12 +117,18 @@ function FileDownloadNode({ id, data }: NodeProps) {
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
{ handleChange("url", value); 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 207cef61..79f26def 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/FileParserNode/FileParserNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/FileParserNode/FileParserNode.tsx @@ -1,5 +1,4 @@ import { HelpTooltip } from "@/components/HelpTooltip"; -import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback"; import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler"; @@ -11,6 +10,8 @@ import { EditableNodeTitle } from "../components/EditableNodeTitle"; import { NodeActionMenu } from "../NodeActionMenu"; import { WorkflowBlockIcon } from "../WorkflowBlockIcon"; import { type FileParserNode } from "./types"; +import { WorkflowBlockInput } from "@/components/WorkflowBlockInput"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function FileParserNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -23,6 +24,8 @@ function FileParserNode({ id, data }: NodeProps) { initialValue: data.label, }); + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + return (
) {
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
- { + onChange={(value) => { if (!data.editable) { return; } - setInputs({ ...inputs, fileUrl: event.target.value }); - updateNodeData(id, { fileUrl: event.target.value }); + setInputs({ ...inputs, fileUrl: value }); + updateNodeData(id, { fileUrl: value }); }} className="nopan text-xs" /> diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/LoginNode/LoginNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/LoginNode/LoginNode.tsx index a3280672..98f94f97 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/LoginNode/LoginNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/LoginNode/LoginNode.tsx @@ -34,6 +34,7 @@ import type { LoginNode } from "./types"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function LoginNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -60,6 +61,7 @@ function LoginNode({ id, data }: NodeProps) { const nodes = useNodes(); const edges = useEdges(); const outputParameterKeys = getAvailableOutputParameterKeys(nodes, edges, id); + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); function handleChange(key: string, value: unknown) { if (!editable) { @@ -111,12 +113,19 @@ function LoginNode({ id, data }: NodeProps) {
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
+ { handleChange("url", value); 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 a268e118..49777a6f 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/LoopNode/LoopNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/LoopNode/LoopNode.tsx @@ -19,6 +19,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import { WorkflowBlockIcon } from "../WorkflowBlockIcon"; import type { LoopNode } from "./types"; import { useState } from "react"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function LoopNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -32,6 +33,8 @@ function LoopNode({ id, data }: NodeProps) { }); const deleteNodeCallback = useDeleteNodeCallback(); + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + const children = nodes.filter((node) => node.parentId === id); const furthestDownChild: Node | null = children.reduce( (acc, child) => { @@ -99,12 +102,18 @@ function LoopNode({ id, data }: NodeProps) { />
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
{ diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/NavigationNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/NavigationNode.tsx index 4633ff5e..9ef7f2c3 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/NavigationNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/NavigationNode/NavigationNode.tsx @@ -34,6 +34,7 @@ import type { NavigationNode } from "./types"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function NavigationNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -63,6 +64,8 @@ function NavigationNode({ id, data }: NodeProps) { const edges = useEdges(); const outputParameterKeys = getAvailableOutputParameterKeys(nodes, edges, id); + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + function handleChange(key: string, value: unknown) { if (!editable) { return; @@ -113,12 +116,19 @@ function NavigationNode({ id, data }: NodeProps) {
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
+ { handleChange("url", value); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/PDFParserNode/PDFParserNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/PDFParserNode/PDFParserNode.tsx index eb3fbf8c..f243d17c 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/PDFParserNode/PDFParserNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/PDFParserNode/PDFParserNode.tsx @@ -13,6 +13,7 @@ import { dataSchemaExampleForFileExtraction } from "../types"; import { WorkflowBlockIcon } from "../WorkflowBlockIcon"; import { type PDFParserNode } from "./types"; import { WorkflowDataSchemaInputGroup } from "@/components/DataSchemaInputGroup/WorkflowDataSchemaInputGroup"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function PDFParserNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -34,6 +35,8 @@ function PDFParserNode({ id, data }: NodeProps) { updateNodeData(id, { [key]: value }); } + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + return (
) {
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
{ 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 a3afc26d..0e33bcd0 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx @@ -13,6 +13,7 @@ import { WorkflowBlockIcon } from "../WorkflowBlockIcon"; import { type SendEmailNode } from "./types"; import { WorkflowBlockInput } from "@/components/WorkflowBlockInput"; import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function SendEmailNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -36,6 +37,8 @@ function SendEmailNode({ id, data }: NodeProps) { updateNodeData(id, { [key]: value }); } + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + return (
) { />
- +
+ + {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null} +
{ handleChange("recipients", value); 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 b928d054..72b2bf4c 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx @@ -35,6 +35,7 @@ import { WorkflowBlockIcon } from "../WorkflowBlockIcon"; import { ParametersMultiSelect } from "./ParametersMultiSelect"; import type { TaskNode } from "./types"; import { WorkflowDataSchemaInputGroup } from "@/components/DataSchemaInputGroup/WorkflowDataSchemaInputGroup"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function TaskNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -43,6 +44,7 @@ function TaskNode({ id, data }: NodeProps) { const nodes = useNodes(); const edges = useEdges(); const outputParameterKeys = getAvailableOutputParameterKeys(nodes, edges, id); + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); const [label, setLabel] = useNodeLabelChangeHandler({ id, @@ -121,12 +123,18 @@ function TaskNode({ id, data }: NodeProps) {
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
{ handleChange("url", value); 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 e431d7f4..080c716d 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TextPromptNode/TextPromptNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/TextPromptNode/TextPromptNode.tsx @@ -24,6 +24,7 @@ import { type TextPromptNode } from "./types"; import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea"; import { WorkflowDataSchemaInputGroup } from "@/components/DataSchemaInputGroup/WorkflowDataSchemaInputGroup"; import { dataSchemaExampleValue } from "../types"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function TextPromptNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -51,6 +52,8 @@ function TextPromptNode({ id, data }: NodeProps) { updateNodeData(id, { [key]: value }); } + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + return (
) { />
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
+ { handleChange("prompt", value); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/ValidationNode/ValidationNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/ValidationNode/ValidationNode.tsx index a0551828..13a3147b 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/ValidationNode/ValidationNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/ValidationNode/ValidationNode.tsx @@ -32,6 +32,7 @@ import type { ValidationNode } from "./types"; import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function ValidationNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -58,6 +59,8 @@ function ValidationNode({ id, data }: NodeProps) { updateNodeData(id, { [key]: value }); } + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + return (
) { />
- +
+ + {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null} +
{ handleChange("completeCriterion", value); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/WaitNode/WaitNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/WaitNode/WaitNode.tsx index ebd40203..f1b89e81 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/WaitNode/WaitNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/WaitNode/WaitNode.tsx @@ -11,6 +11,7 @@ import { NodeActionMenu } from "../NodeActionMenu"; import { WorkflowBlockIcon } from "../WorkflowBlockIcon"; import type { WaitNode } from "./types"; import { WorkflowBlockInput } from "@/components/WorkflowBlockInput"; +import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; function WaitNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); @@ -32,6 +33,8 @@ function WaitNode({ id, data }: NodeProps) { updateNodeData(id, { [key]: value }); } + const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); + return (
) { />
-
- - +
+
+ + +
+ {isFirstWorkflowBlock ? ( +
+ Tip: Use the {"+"} button to add parameters! +
+ ) : null}
+