enable code view for taskv2 block (#3443)

This commit is contained in:
Jonathan Dobson
2025-09-16 09:03:30 -04:00
committed by GitHub
parent 085902a228
commit ca84e57665
2 changed files with 157 additions and 140 deletions

View File

@@ -1,3 +1,5 @@
import { useEffect, useState } from "react";
import { Flippable } from "@/components/Flippable";
import { HelpTooltip } from "@/components/HelpTooltip"; import { HelpTooltip } from "@/components/HelpTooltip";
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea"; import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
import { import {
@@ -10,7 +12,6 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react"; import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
import { useState } from "react";
import { helpTooltips, placeholders } from "../../helpContent"; import { helpTooltips, placeholders } from "../../helpContent";
import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow"; import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow";
import { MAX_STEPS_DEFAULT, type Taskv2Node } from "./types"; import { MAX_STEPS_DEFAULT, type Taskv2Node } from "./types";
@@ -22,6 +23,8 @@ import { useParams } from "react-router-dom";
import { statusIsRunningOrQueued } from "@/routes/tasks/types"; import { statusIsRunningOrQueued } from "@/routes/tasks/types";
import { useWorkflowRunQuery } from "@/routes/workflows/hooks/useWorkflowRunQuery"; import { useWorkflowRunQuery } from "@/routes/workflows/hooks/useWorkflowRunQuery";
import { useRerender } from "@/hooks/useRerender"; import { useRerender } from "@/hooks/useRerender";
import { BlockCodeEditor } from "@/routes/workflows/components/BlockCodeEditor";
import { useBlockScriptStore } from "@/store/BlockScriptStore";
function Taskv2Node({ id, data, type }: NodeProps<Taskv2Node>) { function Taskv2Node({ id, data, type }: NodeProps<Taskv2Node>) {
const { editable, label } = data; const { editable, label } = data;
@@ -34,6 +37,9 @@ function Taskv2Node({ id, data, type }: NodeProps<Taskv2Node>) {
const thisBlockIsPlaying = const thisBlockIsPlaying =
workflowRunIsRunningOrQueued && thisBlockIsTargetted; workflowRunIsRunningOrQueued && thisBlockIsTargetted;
const { updateNodeData } = useReactFlow(); const { updateNodeData } = useReactFlow();
const [facing, setFacing] = useState<"front" | "back">("front");
const blockScriptStore = useBlockScriptStore();
const script = blockScriptStore.scripts[label];
const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id }); const isFirstWorkflowBlock = useIsFirstBlockInWorkflow({ id });
const rerender = useRerender({ prefix: "accordian" }); const rerender = useRerender({ prefix: "accordian" });
@@ -54,151 +60,161 @@ function Taskv2Node({ id, data, type }: NodeProps<Taskv2Node>) {
updateNodeData(id, { [key]: value }); updateNodeData(id, { [key]: value });
} }
useEffect(() => {
setFacing(data.showCode ? "back" : "front");
}, [data.showCode]);
return ( return (
<div> <Flippable facing={facing} preserveFrontsideHeight={true}>
<Handle <div>
type="source" <Handle
position={Position.Bottom} type="source"
id="a" position={Position.Bottom}
className="opacity-0" id="a"
/> className="opacity-0"
<Handle
type="target"
position={Position.Top}
id="b"
className="opacity-0"
/>
<div
className={cn(
"transform-origin-center w-[30rem] space-y-4 rounded-lg bg-slate-elevation3 px-6 py-4 transition-all",
{
"pointer-events-none": thisBlockIsPlaying,
"bg-slate-950 outline outline-2 outline-slate-300":
thisBlockIsTargetted,
},
)}
>
<NodeHeader
blockLabel={label}
editable={editable}
nodeId={id}
totpIdentifier={inputs.totpIdentifier}
totpUrl={inputs.totpVerificationUrl}
type="task_v2" // sic: the naming is not consistent
/> />
<div className="space-y-4"> <Handle
<div className="space-y-2"> type="target"
<div className="flex justify-between"> position={Position.Top}
<Label className="text-xs text-slate-300">Prompt</Label> id="b"
{isFirstWorkflowBlock ? ( className="opacity-0"
<div className="flex justify-end text-xs text-slate-400"> />
Tip: Use the {"+"} button to add parameters! <div
</div> className={cn(
) : null} "transform-origin-center w-[30rem] space-y-4 rounded-lg bg-slate-elevation3 px-6 py-4 transition-all",
</div> {
<WorkflowBlockInputTextarea "pointer-events-none": thisBlockIsPlaying,
nodeId={id} "bg-slate-950 outline outline-2 outline-slate-300":
onChange={(value) => { thisBlockIsTargetted,
handleChange("prompt", value); },
}} )}
value={inputs.prompt}
placeholder={placeholders[type]["prompt"]}
className="nopan text-xs"
/>
</div>
<div className="space-y-2">
<Label className="text-xs text-slate-300">URL</Label>
<WorkflowBlockInputTextarea
canWriteTitle={true}
nodeId={id}
onChange={(value) => {
handleChange("url", value);
}}
value={inputs.url}
placeholder={placeholders[type]["url"]}
className="nopan text-xs"
/>
</div>
</div>
<Separator />
<Accordion
type="single"
collapsible
onValueChange={() => rerender.bump()}
> >
<AccordionItem value="advanced" className="border-b-0"> <NodeHeader
<AccordionTrigger className="py-0"> blockLabel={label}
Advanced Settings editable={editable}
</AccordionTrigger> nodeId={id}
<AccordionContent key={rerender.key} className="pl-6 pr-1 pt-4"> totpIdentifier={inputs.totpIdentifier}
<div className="space-y-4"> totpUrl={inputs.totpVerificationUrl}
<ModelSelector type="task_v2" // sic: the naming is not consistent
className="nopan w-52 text-xs" />
value={inputs.model} <div className="space-y-4">
onChange={(value) => { <div className="space-y-2">
handleChange("model", value); <div className="flex justify-between">
}} <Label className="text-xs text-slate-300">Prompt</Label>
/> {isFirstWorkflowBlock ? (
<div className="space-y-2"> <div className="flex justify-end text-xs text-slate-400">
<div className="flex gap-2"> Tip: Use the {"+"} button to add parameters!
<Label className="text-xs text-slate-300">Max Steps</Label>
<HelpTooltip content={helpTooltips[type]["maxSteps"]} />
</div> </div>
<Input ) : null}
type="number"
placeholder="10"
className="nopan text-xs"
value={data.maxSteps ?? MAX_STEPS_DEFAULT}
onChange={(event) => {
handleChange("maxSteps", Number(event.target.value));
}}
/>
</div>
<div className="space-y-2">
<div className="flex gap-2">
<Label className="text-xs text-slate-300">
2FA Identifier
</Label>
<HelpTooltip
content={helpTooltips[type]["totpIdentifier"]}
/>
</div>
<WorkflowBlockInputTextarea
nodeId={id}
onChange={(value) => {
handleChange("totpIdentifier", value);
}}
value={inputs.totpIdentifier ?? ""}
placeholder={placeholders["navigation"]["totpIdentifier"]}
className="nopan text-xs"
/>
</div>
<div className="space-y-2">
<div className="flex gap-2">
<Label className="text-xs text-slate-300">
2FA Verification URL
</Label>
<HelpTooltip
content={helpTooltips["task"]["totpVerificationUrl"]}
/>
</div>
<WorkflowBlockInputTextarea
nodeId={id}
onChange={(value) => {
handleChange("totpVerificationUrl", value);
}}
value={inputs.totpVerificationUrl ?? ""}
placeholder={placeholders["task"]["totpVerificationUrl"]}
className="nopan text-xs"
/>
</div>
</div> </div>
</AccordionContent> <WorkflowBlockInputTextarea
</AccordionItem> nodeId={id}
</Accordion> onChange={(value) => {
<NodeTabs blockLabel={label} /> handleChange("prompt", value);
}}
value={inputs.prompt}
placeholder={placeholders[type]["prompt"]}
className="nopan text-xs"
/>
</div>
<div className="space-y-2">
<Label className="text-xs text-slate-300">URL</Label>
<WorkflowBlockInputTextarea
canWriteTitle={true}
nodeId={id}
onChange={(value) => {
handleChange("url", value);
}}
value={inputs.url}
placeholder={placeholders[type]["url"]}
className="nopan text-xs"
/>
</div>
</div>
<Separator />
<Accordion
type="single"
collapsible
onValueChange={() => rerender.bump()}
>
<AccordionItem value="advanced" className="border-b-0">
<AccordionTrigger className="py-0">
Advanced Settings
</AccordionTrigger>
<AccordionContent key={rerender.key} className="pl-6 pr-1 pt-4">
<div className="space-y-4">
<ModelSelector
className="nopan w-52 text-xs"
value={inputs.model}
onChange={(value) => {
handleChange("model", value);
}}
/>
<div className="space-y-2">
<div className="flex gap-2">
<Label className="text-xs text-slate-300">
Max Steps
</Label>
<HelpTooltip content={helpTooltips[type]["maxSteps"]} />
</div>
<Input
type="number"
placeholder="10"
className="nopan text-xs"
value={data.maxSteps ?? MAX_STEPS_DEFAULT}
onChange={(event) => {
handleChange("maxSteps", Number(event.target.value));
}}
/>
</div>
<div className="space-y-2">
<div className="flex gap-2">
<Label className="text-xs text-slate-300">
2FA Identifier
</Label>
<HelpTooltip
content={helpTooltips[type]["totpIdentifier"]}
/>
</div>
<WorkflowBlockInputTextarea
nodeId={id}
onChange={(value) => {
handleChange("totpIdentifier", value);
}}
value={inputs.totpIdentifier ?? ""}
placeholder={placeholders["navigation"]["totpIdentifier"]}
className="nopan text-xs"
/>
</div>
<div className="space-y-2">
<div className="flex gap-2">
<Label className="text-xs text-slate-300">
2FA Verification URL
</Label>
<HelpTooltip
content={helpTooltips["task"]["totpVerificationUrl"]}
/>
</div>
<WorkflowBlockInputTextarea
nodeId={id}
onChange={(value) => {
handleChange("totpVerificationUrl", value);
}}
value={inputs.totpVerificationUrl ?? ""}
placeholder={placeholders["task"]["totpVerificationUrl"]}
className="nopan text-xs"
/>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
<NodeTabs blockLabel={label} />
</div>
</div> </div>
</div>
<BlockCodeEditor blockLabel={label} blockType="task_v2" script={script} />
</Flippable>
); );
} }

View File

@@ -247,6 +247,7 @@ export const scriptableWorkflowBlockTypes: Set<WorkflowBlockType> = new Set([
"login", "login",
"navigation", "navigation",
"task", "task",
"task_v2",
"validation", "validation",
]); ]);