make other script enabled blocks flip-to-script; add type-checked lis… (#3179)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { Flippable } from "@/components/Flippable";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
@@ -23,6 +25,7 @@ import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { placeholders, helpTooltips } from "../../helpContent";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
|
||||
import { WorkflowBlockInput } from "@/components/WorkflowBlockInput";
|
||||
import { AppNode } from "..";
|
||||
import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils";
|
||||
@@ -31,6 +34,7 @@ import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"
|
||||
import { RunEngineSelector } from "@/components/EngineSelector";
|
||||
import { ModelSelector } from "@/components/ModelSelector";
|
||||
import { useDebugStore } from "@/store/useDebugStore";
|
||||
import { useBlockScriptStore } from "@/store/BlockScriptStore";
|
||||
import { cn } from "@/util/utils";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { NodeHeader } from "../components/NodeHeader";
|
||||
@@ -44,7 +48,10 @@ const navigationGoalPlaceholder = 'Input {{ name }} into "Name" field.';
|
||||
|
||||
function ActionNode({ id, data, type }: NodeProps<ActionNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const [facing, setFacing] = useState<"front" | "back">("front");
|
||||
const blockScriptStore = useBlockScriptStore();
|
||||
const { editable, debuggable, label } = data;
|
||||
const script = blockScriptStore.scripts[label];
|
||||
const [inputs, setInputs] = useState({
|
||||
url: data.url,
|
||||
navigationGoal: data.navigationGoal,
|
||||
@@ -78,7 +85,12 @@ function ActionNode({ id, data, type }: NodeProps<ActionNode>) {
|
||||
|
||||
const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id });
|
||||
|
||||
useEffect(() => {
|
||||
setFacing(data.showCode ? "back" : "front");
|
||||
}, [data.showCode]);
|
||||
|
||||
return (
|
||||
<Flippable facing={facing} preserveFrontsideHeight={true}>
|
||||
<div>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -158,8 +170,8 @@ function ActionNode({ id, data, type }: NodeProps<ActionNode>) {
|
||||
</div>
|
||||
<div className="rounded-md bg-slate-800 p-2">
|
||||
<div className="space-y-1 text-xs text-slate-400">
|
||||
Tip: While executing the action block, Skyvern will only take one
|
||||
action.
|
||||
Tip: While executing the action block, Skyvern will only take
|
||||
one action.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -227,7 +239,11 @@ function ActionNode({ id, data, type }: NodeProps<ActionNode>) {
|
||||
handleChange(
|
||||
"errorCodeMapping",
|
||||
checked
|
||||
? JSON.stringify(errorMappingExampleValue, null, 2)
|
||||
? JSON.stringify(
|
||||
errorMappingExampleValue,
|
||||
null,
|
||||
2,
|
||||
)
|
||||
: "null",
|
||||
);
|
||||
}}
|
||||
@@ -380,6 +396,8 @@ function ActionNode({ id, data, type }: NodeProps<ActionNode>) {
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
<BlockCodeEditor blockLabel={label} blockType={type} script={script} />
|
||||
</Flippable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { Flippable } from "@/components/Flippable";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import {
|
||||
Accordion,
|
||||
@@ -22,6 +24,7 @@ import { dataSchemaExampleValue } from "../types";
|
||||
import type { ExtractionNode } from "./types";
|
||||
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
|
||||
import { helpTooltips, placeholders } from "../../helpContent";
|
||||
import { AppNode } from "..";
|
||||
import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils";
|
||||
@@ -31,13 +34,17 @@ import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"
|
||||
import { RunEngineSelector } from "@/components/EngineSelector";
|
||||
import { ModelSelector } from "@/components/ModelSelector";
|
||||
import { useDebugStore } from "@/store/useDebugStore";
|
||||
import { useBlockScriptStore } from "@/store/BlockScriptStore";
|
||||
import { cn } from "@/util/utils";
|
||||
import { NodeHeader } from "../components/NodeHeader";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
function ExtractionNode({ id, data, type }: NodeProps<ExtractionNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const [facing, setFacing] = useState<"front" | "back">("front");
|
||||
const blockScriptStore = useBlockScriptStore();
|
||||
const { debuggable, editable, label } = data;
|
||||
const script = blockScriptStore.scripts[label];
|
||||
const debugStore = useDebugStore();
|
||||
const elideFromDebugging = debugStore.isDebugMode && !debuggable;
|
||||
const { blockLabel: urlBlockLabel } = useParams();
|
||||
@@ -67,7 +74,12 @@ function ExtractionNode({ id, data, type }: NodeProps<ExtractionNode>) {
|
||||
updateNodeData(id, { [key]: value });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setFacing(data.showCode ? "back" : "front");
|
||||
}, [data.showCode]);
|
||||
|
||||
return (
|
||||
<Flippable facing={facing} preserveFrontsideHeight={true}>
|
||||
<div>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -189,7 +201,9 @@ function ExtractionNode({ id, data, type }: NodeProps<ExtractionNode>) {
|
||||
</div>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder={placeholders["extraction"]["maxStepsOverride"]}
|
||||
placeholder={
|
||||
placeholders["extraction"]["maxStepsOverride"]
|
||||
}
|
||||
className="nopan w-52 text-xs"
|
||||
min="0"
|
||||
value={inputs.maxStepsOverride ?? ""}
|
||||
@@ -212,7 +226,9 @@ function ExtractionNode({ id, data, type }: NodeProps<ExtractionNode>) {
|
||||
Continue on Failure
|
||||
</Label>
|
||||
<HelpTooltip
|
||||
content={helpTooltips["extraction"]["continueOnFailure"]}
|
||||
content={
|
||||
helpTooltips["extraction"]["continueOnFailure"]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-52">
|
||||
@@ -254,6 +270,8 @@ function ExtractionNode({ id, data, type }: NodeProps<ExtractionNode>) {
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
<BlockCodeEditor blockLabel={label} blockType={type} script={script} />
|
||||
</Flippable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { Flippable } from "@/components/Flippable";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import {
|
||||
Accordion,
|
||||
@@ -11,7 +13,9 @@ import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useBlockScriptStore } from "@/store/BlockScriptStore";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
@@ -44,7 +48,10 @@ const navigationGoalPlaceholder = "Tell Skyvern which file to download.";
|
||||
|
||||
function FileDownloadNode({ id, data }: NodeProps<FileDownloadNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const [facing, setFacing] = useState<"front" | "back">("front");
|
||||
const blockScriptStore = useBlockScriptStore();
|
||||
const { debuggable, editable, label } = data;
|
||||
const script = blockScriptStore.scripts[label];
|
||||
const debugStore = useDebugStore();
|
||||
const { blockLabel: urlBlockLabel } = useParams();
|
||||
const thisBlockIsPlaying =
|
||||
@@ -75,7 +82,12 @@ function FileDownloadNode({ id, data }: NodeProps<FileDownloadNode>) {
|
||||
updateNodeData(id, { [key]: value });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setFacing(data.showCode ? "back" : "front");
|
||||
}, [data.showCode]);
|
||||
|
||||
return (
|
||||
<Flippable facing={facing} preserveFrontsideHeight={true}>
|
||||
<div>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -229,7 +241,11 @@ function FileDownloadNode({ id, data }: NodeProps<FileDownloadNode>) {
|
||||
handleChange(
|
||||
"errorCodeMapping",
|
||||
checked
|
||||
? JSON.stringify(errorMappingExampleValue, null, 2)
|
||||
? JSON.stringify(
|
||||
errorMappingExampleValue,
|
||||
null,
|
||||
2,
|
||||
)
|
||||
: "null",
|
||||
);
|
||||
}}
|
||||
@@ -351,6 +367,12 @@ function FileDownloadNode({ id, data }: NodeProps<FileDownloadNode>) {
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
<BlockCodeEditor
|
||||
blockLabel={label}
|
||||
blockType="file_download" // sic: naming is not consistent
|
||||
script={script}
|
||||
/>
|
||||
</Flippable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { Flippable } from "@/components/Flippable";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import {
|
||||
Accordion,
|
||||
@@ -11,7 +13,9 @@ import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useBlockScriptStore } from "@/store/BlockScriptStore";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
@@ -38,7 +42,10 @@ import { useParams } from "react-router-dom";
|
||||
|
||||
function LoginNode({ id, data, type }: NodeProps<LoginNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const [facing, setFacing] = useState<"front" | "back">("front");
|
||||
const blockScriptStore = useBlockScriptStore();
|
||||
const { debuggable, editable, label } = data;
|
||||
const script = blockScriptStore.scripts[label];
|
||||
const debugStore = useDebugStore();
|
||||
const elideFromDebugging = debugStore.isDebugMode && !debuggable;
|
||||
const { blockLabel: urlBlockLabel } = useParams();
|
||||
@@ -72,7 +79,12 @@ function LoginNode({ id, data, type }: NodeProps<LoginNode>) {
|
||||
updateNodeData(id, { [key]: value });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setFacing(data.showCode ? "back" : "front");
|
||||
}, [data.showCode]);
|
||||
|
||||
return (
|
||||
<Flippable facing={facing} preserveFrontsideHeight={true}>
|
||||
<div>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -132,7 +144,9 @@ function LoginNode({ id, data, type }: NodeProps<LoginNode>) {
|
||||
<div className="space-y-2">
|
||||
<div className="flex gap-2">
|
||||
<Label className="text-xs text-slate-300">Login Goal</Label>
|
||||
<HelpTooltip content={helpTooltips["login"]["navigationGoal"]} />
|
||||
<HelpTooltip
|
||||
content={helpTooltips["login"]["navigationGoal"]}
|
||||
/>
|
||||
</div>
|
||||
<WorkflowBlockInputTextarea
|
||||
nodeId={id}
|
||||
@@ -255,7 +269,11 @@ function LoginNode({ id, data, type }: NodeProps<LoginNode>) {
|
||||
handleChange(
|
||||
"errorCodeMapping",
|
||||
checked
|
||||
? JSON.stringify(errorMappingExampleValue, null, 2)
|
||||
? JSON.stringify(
|
||||
errorMappingExampleValue,
|
||||
null,
|
||||
2,
|
||||
)
|
||||
: "null",
|
||||
);
|
||||
}}
|
||||
@@ -357,6 +375,8 @@ function LoginNode({ id, data, type }: NodeProps<LoginNode>) {
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
<BlockCodeEditor blockLabel={label} blockType={type} script={script} />
|
||||
</Flippable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,16 @@ import { DotsHorizontalIcon } from "@radix-ui/react-icons";
|
||||
import { OrgWalled } from "@/components/Orgwalled";
|
||||
|
||||
type Props = {
|
||||
isScriptable?: boolean;
|
||||
onDelete: () => void;
|
||||
onShowScript?: () => void;
|
||||
};
|
||||
|
||||
function NodeActionMenu({ onDelete, onShowScript }: Props) {
|
||||
function NodeActionMenu({
|
||||
isScriptable = false,
|
||||
onDelete,
|
||||
onShowScript,
|
||||
}: Props) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -30,6 +35,7 @@ function NodeActionMenu({ onDelete, onShowScript }: Props) {
|
||||
>
|
||||
Delete Block
|
||||
</DropdownMenuItem>
|
||||
{isScriptable && (
|
||||
<OrgWalled className="p-0">
|
||||
{onShowScript && (
|
||||
<DropdownMenuItem
|
||||
@@ -41,6 +47,7 @@ function NodeActionMenu({ onDelete, onShowScript }: Props) {
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</OrgWalled>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { Flippable } from "@/components/Flippable";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import {
|
||||
Accordion,
|
||||
@@ -12,7 +14,9 @@ import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockInput } from "@/components/WorkflowBlockInput";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useBlockScriptStore } from "@/store/BlockScriptStore";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
@@ -39,7 +43,10 @@ import { useParams } from "react-router-dom";
|
||||
|
||||
function TaskNode({ id, data, type }: NodeProps<TaskNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const [facing, setFacing] = useState<"front" | "back">("front");
|
||||
const blockScriptStore = useBlockScriptStore();
|
||||
const { debuggable, editable, label } = data;
|
||||
const script = blockScriptStore.scripts[label];
|
||||
const debugStore = useDebugStore();
|
||||
const elideFromDebugging = debugStore.isDebugMode && !debuggable;
|
||||
const { blockLabel: urlBlockLabel } = useParams();
|
||||
@@ -78,7 +85,12 @@ function TaskNode({ id, data, type }: NodeProps<TaskNode>) {
|
||||
updateNodeData(id, { [key]: value });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setFacing(data.showCode ? "back" : "front");
|
||||
}, [data.showCode]);
|
||||
|
||||
return (
|
||||
<Flippable facing={facing} preserveFrontsideHeight={true}>
|
||||
<div>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -285,7 +297,11 @@ function TaskNode({ id, data, type }: NodeProps<TaskNode>) {
|
||||
handleChange(
|
||||
"errorCodeMapping",
|
||||
checked
|
||||
? JSON.stringify(errorMappingExampleValue, null, 2)
|
||||
? JSON.stringify(
|
||||
errorMappingExampleValue,
|
||||
null,
|
||||
2,
|
||||
)
|
||||
: "null",
|
||||
);
|
||||
}}
|
||||
@@ -391,7 +407,9 @@ function TaskNode({ id, data, type }: NodeProps<TaskNode>) {
|
||||
<Label className="text-xs font-normal text-slate-300">
|
||||
File Suffix
|
||||
</Label>
|
||||
<HelpTooltip content={helpTooltips["task"]["fileSuffix"]} />
|
||||
<HelpTooltip
|
||||
content={helpTooltips["task"]["fileSuffix"]}
|
||||
/>
|
||||
</div>
|
||||
<WorkflowBlockInput
|
||||
nodeId={id}
|
||||
@@ -449,6 +467,8 @@ function TaskNode({ id, data, type }: NodeProps<TaskNode>) {
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
<BlockCodeEditor blockLabel={label} blockType={type} script={script} />
|
||||
</Flippable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { useEffect } from "react";
|
||||
import { Flippable } from "@/components/Flippable";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import type { URLNode } from "./types";
|
||||
import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow";
|
||||
import { useState } from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
|
||||
import { placeholders } from "../../helpContent";
|
||||
import { useBlockScriptStore } from "@/store/BlockScriptStore";
|
||||
import { useDebugStore } from "@/store/useDebugStore";
|
||||
import { cn } from "@/util/utils";
|
||||
import { NodeHeader } from "../components/NodeHeader";
|
||||
@@ -12,7 +16,10 @@ import { useParams } from "react-router-dom";
|
||||
|
||||
function URLNode({ id, data, type }: NodeProps<URLNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const [facing, setFacing] = useState<"front" | "back">("front");
|
||||
const blockScriptStore = useBlockScriptStore();
|
||||
const { debuggable, editable, label } = data;
|
||||
const script = blockScriptStore.scripts[label];
|
||||
const debugStore = useDebugStore();
|
||||
const elideFromDebugging = debugStore.isDebugMode && !debuggable;
|
||||
const { blockLabel: urlBlockLabel } = useParams();
|
||||
@@ -32,7 +39,12 @@ function URLNode({ id, data, type }: NodeProps<URLNode>) {
|
||||
updateNodeData(id, { [key]: value });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setFacing(data.showCode ? "back" : "front");
|
||||
}, [data.showCode]);
|
||||
|
||||
return (
|
||||
<Flippable facing={facing} preserveFrontsideHeight={true}>
|
||||
<div>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -88,6 +100,12 @@ function URLNode({ id, data, type }: NodeProps<URLNode>) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BlockCodeEditor
|
||||
blockLabel={label}
|
||||
blockType="goto_url" // sic: the naming is inconsistent
|
||||
script={script}
|
||||
/>
|
||||
</Flippable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { Flippable } from "@/components/Flippable";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import {
|
||||
Accordion,
|
||||
@@ -10,7 +12,9 @@ import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useBlockScriptStore } from "@/store/BlockScriptStore";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
@@ -35,7 +39,10 @@ import { useParams } from "react-router-dom";
|
||||
|
||||
function ValidationNode({ id, data, type }: NodeProps<ValidationNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
const [facing, setFacing] = useState<"front" | "back">("front");
|
||||
const blockScriptStore = useBlockScriptStore();
|
||||
const { debuggable, editable, label } = data;
|
||||
const script = blockScriptStore.scripts[label];
|
||||
const debugStore = useDebugStore();
|
||||
const elideFromDebugging = debugStore.isDebugMode && !debuggable;
|
||||
const { blockLabel: urlBlockLabel } = useParams();
|
||||
@@ -61,7 +68,12 @@ function ValidationNode({ id, data, type }: NodeProps<ValidationNode>) {
|
||||
|
||||
const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id });
|
||||
|
||||
useEffect(() => {
|
||||
setFacing(data.showCode ? "back" : "front");
|
||||
}, [data.showCode]);
|
||||
|
||||
return (
|
||||
<Flippable facing={facing} preserveFrontsideHeight={true}>
|
||||
<div>
|
||||
<Handle
|
||||
type="source"
|
||||
@@ -153,7 +165,9 @@ function ValidationNode({ id, data, type }: NodeProps<ValidationNode>) {
|
||||
Error Messages
|
||||
</Label>
|
||||
<HelpTooltip
|
||||
content={helpTooltips["validation"]["errorCodeMapping"]}
|
||||
content={
|
||||
helpTooltips["validation"]["errorCodeMapping"]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Checkbox
|
||||
@@ -166,7 +180,11 @@ function ValidationNode({ id, data, type }: NodeProps<ValidationNode>) {
|
||||
handleChange(
|
||||
"errorCodeMapping",
|
||||
checked
|
||||
? JSON.stringify(errorMappingExampleValue, null, 2)
|
||||
? JSON.stringify(
|
||||
errorMappingExampleValue,
|
||||
null,
|
||||
2,
|
||||
)
|
||||
: "null",
|
||||
);
|
||||
}}
|
||||
@@ -196,7 +214,9 @@ function ValidationNode({ id, data, type }: NodeProps<ValidationNode>) {
|
||||
Continue on Failure
|
||||
</Label>
|
||||
<HelpTooltip
|
||||
content={helpTooltips["validation"]["continueOnFailure"]}
|
||||
content={
|
||||
helpTooltips["validation"]["continueOnFailure"]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-52">
|
||||
@@ -217,6 +237,8 @@ function ValidationNode({ id, data, type }: NodeProps<ValidationNode>) {
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
<BlockCodeEditor blockLabel={label} blockType={type} script={script} />
|
||||
</Flippable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import { useDebugSessionQuery } from "@/routes/workflows/hooks/useDebugSessionQu
|
||||
import { useWorkflowRunQuery } from "@/routes/workflows/hooks/useWorkflowRunQuery";
|
||||
import {
|
||||
debuggableWorkflowBlockTypes,
|
||||
scriptableWorkflowBlockTypes,
|
||||
type WorkflowBlockType,
|
||||
type WorkflowApiResponse,
|
||||
} from "@/routes/workflows/types/workflowTypes";
|
||||
@@ -154,6 +155,7 @@ function NodeHeader({
|
||||
const queryClient = useQueryClient();
|
||||
const location = useLocation();
|
||||
const isDebuggable = debuggableWorkflowBlockTypes.has(type);
|
||||
const isScriptable = scriptableWorkflowBlockTypes.has(type);
|
||||
const { data: workflowRun } = useWorkflowRunQuery();
|
||||
const workflowRunIsRunningOrQueued =
|
||||
workflowRun && statusIsRunningOrQueued(workflowRun);
|
||||
@@ -414,6 +416,7 @@ function NodeHeader({
|
||||
})}
|
||||
>
|
||||
<NodeActionMenu
|
||||
isScriptable={isScriptable}
|
||||
onDelete={() => {
|
||||
deleteNodeCallback(nodeId);
|
||||
}}
|
||||
|
||||
@@ -228,6 +228,17 @@ export const debuggableWorkflowBlockTypes: Set<WorkflowBlockType> = new Set([
|
||||
"validation",
|
||||
]);
|
||||
|
||||
export const scriptableWorkflowBlockTypes: Set<WorkflowBlockType> = new Set([
|
||||
"action",
|
||||
"extraction",
|
||||
"file_download",
|
||||
"goto_url",
|
||||
"login",
|
||||
"navigation",
|
||||
"task",
|
||||
"validation",
|
||||
]);
|
||||
|
||||
export function isTaskVariantBlock(item: {
|
||||
block_type: WorkflowBlockType;
|
||||
}): boolean {
|
||||
|
||||
Reference in New Issue
Block a user