From a23903083068bedce6f9012d4507f6dc58fd54c3 Mon Sep 17 00:00:00 2001 From: Shuchang Zheng Date: Wed, 16 Oct 2024 12:45:06 -0700 Subject: [PATCH] Task block changes (#989) --- .../editor/nodes/TaskNode/TaskNode.tsx | 763 ++++++++---------- .../TaskNode/TaskNodeDisplayModeSwitch.tsx | 36 - .../workflows/editor/nodes/TaskNode/types.ts | 3 + 3 files changed, 354 insertions(+), 448 deletions(-) delete mode 100644 skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNodeDisplayModeSwitch.tsx 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 69cf1826..0dd28213 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNode.tsx @@ -27,7 +27,6 @@ import { AppNode } from ".."; import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils"; import { EditableNodeTitle } from "../components/EditableNodeTitle"; import { NodeActionMenu } from "../NodeActionMenu"; -import { TaskNodeDisplayModeSwitch } from "./TaskNodeDisplayModeSwitch"; import { TaskNodeParametersPanel } from "./TaskNodeParametersPanel"; import { dataSchemaExampleValue, @@ -35,17 +34,11 @@ import { fieldPlaceholders, helpTooltipContent, type TaskNode, - type TaskNodeDisplayMode, } from "./types"; -import { useParams } from "react-router-dom"; - -function getLocalStorageKey(workflowPermanentId: string, label: string) { - return `skyvern-task-block-${workflowPermanentId}-${label}`; -} +import { Separator } from "@/components/ui/separator"; function TaskNode({ id, data }: NodeProps) { const { updateNodeData } = useReactFlow(); - const { workflowPermanentId } = useParams(); const { editable } = data; const deleteNodeCallback = useDeleteNodeCallback(); const nodes = useNodes(); @@ -56,15 +49,6 @@ function TaskNode({ id, data }: NodeProps) { initialValue: data.label, }); - const [displayMode, setDisplayMode] = useState( - workflowPermanentId && - localStorage.getItem(getLocalStorageKey(workflowPermanentId, label)) - ? (localStorage.getItem( - getLocalStorageKey(workflowPermanentId, label), - ) as TaskNodeDisplayMode) - : "basic", - ); - const [inputs, setInputs] = useState({ url: data.url, navigationGoal: data.navigationGoal, @@ -74,6 +58,7 @@ function TaskNode({ id, data }: NodeProps) { maxStepsOverride: data.maxStepsOverride, allowDownloads: data.allowDownloads, continueOnFailure: data.continueOnFailure, + cacheActions: data.cacheActions, downloadSuffix: data.downloadSuffix, errorCodeMapping: data.errorCodeMapping, totpVerificationUrl: data.totpVerificationUrl, @@ -88,386 +73,6 @@ function TaskNode({ id, data }: NodeProps) { updateNodeData(id, { [key]: value }); } - const basicContent = ( - <> -
-
- - -
- { - if (!editable) { - return; - } - handleChange("url", event.target.value); - }} - placeholder={fieldPlaceholders["url"]} - /> -
-
-
- - -
- { - if (!editable) { - return; - } - handleChange("navigationGoal", event.target.value); - }} - value={inputs.navigationGoal} - placeholder={fieldPlaceholders["navigationGoal"]} - className="nopan text-xs" - /> -
-
- { - updateNodeData(id, { parameterKeys }); - }} - /> -
- - ); - - const advancedContent = ( - <> - - - Content - -
-
-
- - -
- { - if (!editable) { - return; - } - handleChange("url", event.target.value); - }} - value={inputs.url} - placeholder={fieldPlaceholders["url"]} - className="nopan text-xs" - /> -
-
-
- - -
- { - if (!editable) { - return; - } - handleChange("navigationGoal", event.target.value); - }} - value={inputs.navigationGoal} - placeholder={fieldPlaceholders["navigationGoal"]} - className="nopan text-xs" - /> -
-
- { - updateNodeData(id, { parameterKeys }); - }} - /> -
-
-
-
- - Extraction - -
-
-
- - -
- { - if (!editable) { - return; - } - handleChange("dataExtractionGoal", event.target.value); - }} - value={inputs.dataExtractionGoal} - placeholder={fieldPlaceholders["dataExtractionGoal"]} - className="nopan text-xs" - /> -
-
-
-
- - -
- { - if (!editable) { - return; - } - handleChange( - "dataSchema", - checked - ? JSON.stringify(dataSchemaExampleValue, null, 2) - : "null", - ); - }} - /> -
- {inputs.dataSchema !== "null" && ( -
- { - if (!editable) { - return; - } - handleChange("dataSchema", value); - }} - className="nowheel nopan" - /> -
- )} -
-
-
-
- - Limits - -
-
-
- - -
- { - if (!editable) { - return; - } - const value = - event.target.value === "" - ? null - : Number(event.target.value); - handleChange("maxRetries", value); - }} - /> -
-
-
- - -
- { - if (!editable) { - return; - } - const value = - event.target.value === "" - ? null - : Number(event.target.value); - handleChange("maxStepsOverride", value); - }} - /> -
-
-
- - -
-
- { - if (!editable) { - return; - } - handleChange("allowDownloads", checked); - }} - /> -
-
-
-
- -
-
- { - if (!editable) { - return; - } - handleChange("continueOnFailure", checked); - }} - /> -
-
-
-
- - -
- { - if (!editable) { - return; - } - handleChange("downloadSuffix", event.target.value); - }} - /> -
-
-
-
- - -
- { - if (!editable) { - return; - } - handleChange( - "errorCodeMapping", - checked - ? JSON.stringify(errorMappingExampleValue, null, 2) - : "null", - ); - }} - /> -
- {inputs.errorCodeMapping !== "null" && ( -
- { - if (!editable) { - return; - } - handleChange("errorCodeMapping", value); - }} - className="nowheel nopan" - /> -
- )} -
-
-
-
- - Two-Factor Authentication - -
-
-
- - -
- { - if (!editable) { - return; - } - handleChange("totpVerificationUrl", event.target.value); - }} - value={inputs.totpVerificationUrl ?? ""} - placeholder={fieldPlaceholders["totpVerificationUrl"]} - className="nopan text-xs" - /> -
-
-
- - -
- { - if (!editable) { - return; - } - handleChange("totpIdentifier", event.target.value); - }} - value={inputs.totpIdentifier ?? ""} - placeholder={fieldPlaceholders["totpIdentifier"]} - className="nopan text-xs" - /> -
-
-
-
-
- - ); - return (
) { id="b" className="opacity-0" /> -
+
@@ -505,20 +110,354 @@ function TaskNode({ id, data }: NodeProps) { }} />
- { - setDisplayMode(mode); - if (workflowPermanentId) { - localStorage.setItem( - getLocalStorageKey(workflowPermanentId, label), - mode, - ); - } - }} - /> - {displayMode === "basic" && basicContent} - {displayMode === "advanced" && advancedContent} + + + Content + +
+
+
+ + +
+ { + if (!editable) { + return; + } + handleChange("url", event.target.value); + }} + value={inputs.url} + placeholder={fieldPlaceholders["url"]} + className="nopan text-xs" + /> +
+
+
+ + +
+ { + if (!editable) { + return; + } + handleChange("navigationGoal", event.target.value); + }} + value={inputs.navigationGoal} + placeholder={fieldPlaceholders["navigationGoal"]} + className="nopan text-xs" + /> +
+
+ { + updateNodeData(id, { parameterKeys }); + }} + /> +
+
+
+
+ + Extraction + +
+
+
+ + +
+ { + if (!editable) { + return; + } + handleChange("dataExtractionGoal", event.target.value); + }} + value={inputs.dataExtractionGoal} + placeholder={fieldPlaceholders["dataExtractionGoal"]} + className="nopan text-xs" + /> +
+
+
+
+ + +
+ { + if (!editable) { + return; + } + handleChange( + "dataSchema", + checked + ? JSON.stringify(dataSchemaExampleValue, null, 2) + : "null", + ); + }} + /> +
+ {inputs.dataSchema !== "null" && ( +
+ { + if (!editable) { + return; + } + handleChange("dataSchema", value); + }} + className="nowheel nopan" + /> +
+ )} +
+
+
+
+ + Advanced Settings + +
+
+
+ + +
+ { + if (!editable) { + return; + } + const value = + event.target.value === "" + ? null + : Number(event.target.value); + handleChange("maxRetries", value); + }} + /> +
+
+
+ + +
+ { + if (!editable) { + return; + } + const value = + event.target.value === "" + ? null + : Number(event.target.value); + handleChange("maxStepsOverride", value); + }} + /> +
+
+
+
+ + +
+ { + if (!editable) { + return; + } + handleChange( + "errorCodeMapping", + checked + ? JSON.stringify(errorMappingExampleValue, null, 2) + : "null", + ); + }} + /> +
+ {inputs.errorCodeMapping !== "null" && ( +
+ { + if (!editable) { + return; + } + handleChange("errorCodeMapping", value); + }} + className="nowheel nopan" + /> +
+ )} +
+ +
+
+ + +
+
+ { + if (!editable) { + return; + } + handleChange("continueOnFailure", checked); + }} + /> +
+
+
+
+ + +
+
+ { + if (!editable) { + return; + } + handleChange("cacheActions", checked); + }} + /> +
+
+ +
+
+ + +
+
+ { + if (!editable) { + return; + } + handleChange("allowDownloads", checked); + }} + /> +
+
+
+
+ + +
+ { + if (!editable) { + return; + } + handleChange("downloadSuffix", event.target.value); + }} + /> +
+ +
+
+ + +
+ { + if (!editable) { + return; + } + handleChange("totpVerificationUrl", event.target.value); + }} + value={inputs.totpVerificationUrl ?? ""} + placeholder={fieldPlaceholders["totpVerificationUrl"]} + className="nopan text-xs" + /> +
+
+
+ + +
+ { + if (!editable) { + return; + } + handleChange("totpIdentifier", event.target.value); + }} + value={inputs.totpIdentifier ?? ""} + placeholder={fieldPlaceholders["totpIdentifier"]} + className="nopan text-xs" + /> +
+
+
+
+
); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNodeDisplayModeSwitch.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNodeDisplayModeSwitch.tsx deleted file mode 100644 index c11e205a..00000000 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/TaskNodeDisplayModeSwitch.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { cn } from "@/util/utils"; -import { TaskNodeDisplayMode } from "./types"; - -type Props = { - value: TaskNodeDisplayMode; - onChange: (mode: TaskNodeDisplayMode) => void; -}; - -function TaskNodeDisplayModeSwitch({ value, onChange }: Props) { - return ( -
-
{ - onChange("basic"); - }} - > - Basic -
-
{ - onChange("advanced"); - }} - > - Advanced -
-
- ); -} - -export { TaskNodeDisplayModeSwitch }; diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/types.ts b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/types.ts index d277885a..352694ff 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/TaskNode/types.ts @@ -74,6 +74,9 @@ export const helpTooltipContent = { "If you have an internal system for storing TOTP codes, link the endpoint here.", totpIdentifier: "If you are running multiple tasks or workflows at once, you will need to give the task an identifier to know that this TOTP goes with this task.", + continueOnFailure: + "Allow the workflow to continue if it encounters a failure.", + cacheActions: "Cache the actions of this task.", } as const; export const fieldPlaceholders = {