Workflow Run Timeline UI (#1433)
This commit is contained in:
@@ -19,10 +19,11 @@ import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { errorMappingExampleValue } from "../types";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { ClickIcon } from "@/components/icons/ClickIcon";
|
||||
import { placeholders, helpTooltips } from "../../helpContent";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { WorkflowBlockInput } from "@/components/WorkflowBlockInput";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
|
||||
const urlTooltip =
|
||||
"The URL Skyvern is navigating to. Leave this field blank to pick up from where the last block left off.";
|
||||
@@ -78,7 +79,10 @@ function ActionNode({ id, data }: NodeProps<ActionNode>) {
|
||||
<header className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<ClickIcon className="size-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Action}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -2,11 +2,12 @@ import { Label } from "@/components/ui/label";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { CodeIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import type { CodeBlockNode } from "./types";
|
||||
|
||||
function CodeBlockNode({ id, data }: NodeProps<CodeBlockNode>) {
|
||||
@@ -38,7 +39,10 @@ function CodeBlockNode({ id, data }: NodeProps<CodeBlockNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<CodeIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Code}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
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";
|
||||
import { DownloadIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position } from "@xyflow/react";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import type { DownloadNode } from "./types";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
|
||||
function DownloadNode({ id, data }: NodeProps<DownloadNode>) {
|
||||
const [label, setLabel] = useNodeLabelChangeHandler({
|
||||
@@ -35,7 +36,10 @@ function DownloadNode({ id, data }: NodeProps<DownloadNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<DownloadIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.DownloadToS3}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
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";
|
||||
import { CursorTextIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import { type FileParserNode } from "./types";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
|
||||
function FileParserNode({ id, data }: NodeProps<FileParserNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
@@ -40,7 +41,10 @@ function FileParserNode({ id, data }: NodeProps<FileParserNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<CursorTextIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.FileURLParser}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -14,13 +14,14 @@ import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTexta
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { LockOpen1Icon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { helpTooltips, placeholders } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { errorMappingExampleValue } from "../types";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import { CredentialParameterSelector } from "./CredentialParameterSelector";
|
||||
import type { LoginNode } from "./types";
|
||||
|
||||
@@ -72,7 +73,10 @@ function LoginNode({ id, data }: NodeProps<LoginNode>) {
|
||||
<header className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<LockOpen1Icon className="size-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Login}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
@@ -8,7 +9,7 @@ import {
|
||||
} from "@/components/ui/select";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { UpdateIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import type { Node } from "@xyflow/react";
|
||||
import {
|
||||
Handle,
|
||||
@@ -19,13 +20,13 @@ import {
|
||||
useReactFlow,
|
||||
} from "@xyflow/react";
|
||||
import { AppNode } from "..";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { useWorkflowParametersState } from "../../useWorkflowParametersState";
|
||||
import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import type { LoopNode } from "./types";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
|
||||
function LoopNode({ id, data }: NodeProps<LoopNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
@@ -88,7 +89,10 @@ function LoopNode({ id, data }: NodeProps<LoopNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<UpdateIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.ForLoop}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockInput } from "@/components/WorkflowBlockInput";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { helpTooltips, placeholders } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { errorMappingExampleValue } from "../types";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import type { NavigationNode } from "./types";
|
||||
import { RobotIcon } from "@/components/icons/RobotIcon";
|
||||
import { helpTooltips, placeholders } from "../../helpContent";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { WorkflowBlockInput } from "@/components/WorkflowBlockInput";
|
||||
|
||||
function NavigationNode({ id, data }: NodeProps<NavigationNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
@@ -74,7 +75,10 @@ function NavigationNode({ id, data }: NodeProps<NavigationNode>) {
|
||||
<header className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<RobotIcon className="size-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Navigation}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -4,12 +4,13 @@ import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { EnvelopeClosedIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import { type SendEmailNode } from "./types";
|
||||
|
||||
function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
@@ -52,7 +53,10 @@ function SendEmailNode({ id, data }: NodeProps<SendEmailNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<EnvelopeClosedIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.SendEmail}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -10,10 +10,12 @@ import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockInput } from "@/components/WorkflowBlockInput";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { ListBulletIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
@@ -29,10 +31,9 @@ import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { dataSchemaExampleValue, errorMappingExampleValue } from "../types";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import { ParametersMultiSelect } from "./ParametersMultiSelect";
|
||||
import type { TaskNode } from "./types";
|
||||
import { WorkflowBlockInput } from "@/components/WorkflowBlockInput";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
|
||||
function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
@@ -91,7 +92,10 @@ function TaskNode({ id, data }: NodeProps<TaskNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<ListBulletIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Task}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Separator } from "@/components/ui/separator";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { CursorTextIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import {
|
||||
Handle,
|
||||
NodeProps,
|
||||
@@ -22,6 +22,7 @@ import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import { type TextPromptNode } from "./types";
|
||||
|
||||
function TextPromptNode({ id, data }: NodeProps<TextPromptNode>) {
|
||||
@@ -60,7 +61,10 @@ function TextPromptNode({ id, data }: NodeProps<TextPromptNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<CursorTextIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.TextPrompt}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -3,11 +3,12 @@ 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";
|
||||
import { UploadIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position } from "@xyflow/react";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import { type UploadNode } from "./types";
|
||||
|
||||
function UploadNode({ id, data }: NodeProps<UploadNode>) {
|
||||
@@ -35,7 +36,10 @@ function UploadNode({ id, data }: NodeProps<UploadNode>) {
|
||||
<div className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<UploadIcon className="h-6 w-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.UploadToS3}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import type { ValidationNode } from "./types";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { useState } from "react";
|
||||
import { CheckCircledIcon } from "@radix-ui/react-icons";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { errorMappingExampleValue } from "../types";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { WorkflowBlockInputTextarea } from "@/components/WorkflowBlockInputTextarea";
|
||||
import { CodeEditor } from "@/routes/workflows/components/CodeEditor";
|
||||
import { useDeleteNodeCallback } from "@/routes/workflows/hooks/useDeleteNodeCallback";
|
||||
import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { errorMappingExampleValue } from "../types";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import type { ValidationNode } from "./types";
|
||||
|
||||
function ValidationNode({ id, data }: NodeProps<ValidationNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
@@ -62,7 +63,10 @@ function ValidationNode({ id, data }: NodeProps<ValidationNode>) {
|
||||
<header className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<CheckCircledIcon className="size-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Validation}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
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";
|
||||
import { StopwatchIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "@/routes/workflows/types/workflowTypes";
|
||||
import { Handle, NodeProps, Position, useReactFlow } from "@xyflow/react";
|
||||
import { useState } from "react";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
||||
import { NodeActionMenu } from "../NodeActionMenu";
|
||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||
import type { WaitNode } from "./types";
|
||||
import { HelpTooltip } from "@/components/HelpTooltip";
|
||||
import { helpTooltips } from "../../helpContent";
|
||||
|
||||
function WaitNode({ id, data }: NodeProps<WaitNode>) {
|
||||
const { updateNodeData } = useReactFlow();
|
||||
@@ -49,7 +50,10 @@ function WaitNode({ id, data }: NodeProps<WaitNode>) {
|
||||
<header className="flex h-[2.75rem] justify-between">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex h-[2.75rem] w-[2.75rem] items-center justify-center rounded border border-slate-600">
|
||||
<StopwatchIcon className="size-6" />
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Wait}
|
||||
className="size-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<EditableNodeTitle
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { ClickIcon } from "@/components/icons/ClickIcon";
|
||||
import { WorkflowBlockType } from "../../types/workflowTypes";
|
||||
import {
|
||||
CheckCircledIcon,
|
||||
CodeIcon,
|
||||
CursorTextIcon,
|
||||
DownloadIcon,
|
||||
EnvelopeClosedIcon,
|
||||
ListBulletIcon,
|
||||
LockOpen1Icon,
|
||||
StopwatchIcon,
|
||||
UpdateIcon,
|
||||
UploadIcon,
|
||||
} from "@radix-ui/react-icons";
|
||||
import { ExtractIcon } from "@/components/icons/ExtractIcon";
|
||||
import { RobotIcon } from "@/components/icons/RobotIcon";
|
||||
|
||||
type Props = {
|
||||
workflowBlockType: WorkflowBlockType;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
function WorkflowBlockIcon({ workflowBlockType, className }: Props) {
|
||||
switch (workflowBlockType) {
|
||||
case "action": {
|
||||
return <ClickIcon className={className} />;
|
||||
}
|
||||
case "code": {
|
||||
return <CodeIcon className={className} />;
|
||||
}
|
||||
case "download_to_s3": {
|
||||
return <DownloadIcon className={className} />;
|
||||
}
|
||||
case "extraction": {
|
||||
return <ExtractIcon className={className} />;
|
||||
}
|
||||
case "file_download": {
|
||||
return <DownloadIcon className={className} />;
|
||||
}
|
||||
case "file_url_parser": {
|
||||
return <CursorTextIcon className={className} />;
|
||||
}
|
||||
case "for_loop": {
|
||||
return <UpdateIcon className={className} />;
|
||||
}
|
||||
case "login": {
|
||||
return <LockOpen1Icon className={className} />;
|
||||
}
|
||||
case "navigation": {
|
||||
return <RobotIcon className={className} />;
|
||||
}
|
||||
case "send_email": {
|
||||
return <EnvelopeClosedIcon className={className} />;
|
||||
}
|
||||
case "task": {
|
||||
return <ListBulletIcon className={className} />;
|
||||
}
|
||||
case "text_prompt": {
|
||||
return <CursorTextIcon className={className} />;
|
||||
}
|
||||
case "upload_to_s3": {
|
||||
return <UploadIcon className={className} />;
|
||||
}
|
||||
case "validation": {
|
||||
return <CheckCircledIcon className={className} />;
|
||||
}
|
||||
case "wait": {
|
||||
return <StopwatchIcon className={className} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { WorkflowBlockIcon };
|
||||
@@ -1,3 +1,5 @@
|
||||
import { WorkflowBlockType } from "../../types/workflowTypes";
|
||||
|
||||
export type NodeBaseData = {
|
||||
label: string;
|
||||
continueOnFailure: boolean;
|
||||
@@ -14,3 +16,23 @@ export const dataSchemaExampleValue = {
|
||||
sample: { type: "string" },
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const workflowBlockTitle: {
|
||||
[blockType in WorkflowBlockType]: string;
|
||||
} = {
|
||||
action: "Action",
|
||||
code: "Code",
|
||||
download_to_s3: "Download",
|
||||
extraction: "Extraction",
|
||||
file_download: "File Download",
|
||||
file_url_parser: "File Parser",
|
||||
for_loop: "Loop",
|
||||
login: "Login",
|
||||
navigation: "Navigation",
|
||||
send_email: "Send Email",
|
||||
task: "Task",
|
||||
text_prompt: "Text Prompt",
|
||||
upload_to_s3: "Upload",
|
||||
validation: "Validation",
|
||||
wait: "Wait",
|
||||
};
|
||||
|
||||
@@ -1,24 +1,10 @@
|
||||
import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore";
|
||||
import {
|
||||
CheckCircledIcon,
|
||||
Cross2Icon,
|
||||
CursorTextIcon,
|
||||
DownloadIcon,
|
||||
EnvelopeClosedIcon,
|
||||
FileIcon,
|
||||
ListBulletIcon,
|
||||
LockOpen1Icon,
|
||||
PlusIcon,
|
||||
StopwatchIcon,
|
||||
UpdateIcon,
|
||||
UploadIcon,
|
||||
} from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockNode } from "../nodes";
|
||||
import { AddNodeProps } from "../FlowRenderer";
|
||||
import { ClickIcon } from "@/components/icons/ClickIcon";
|
||||
import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area";
|
||||
import { RobotIcon } from "@/components/icons/RobotIcon";
|
||||
import { ExtractIcon } from "@/components/icons/ExtractIcon";
|
||||
import { useWorkflowPanelStore } from "@/store/WorkflowPanelStore";
|
||||
import { Cross2Icon, PlusIcon } from "@radix-ui/react-icons";
|
||||
import { WorkflowBlockTypes } from "../../types/workflowTypes";
|
||||
import { AddNodeProps } from "../FlowRenderer";
|
||||
import { WorkflowBlockNode } from "../nodes";
|
||||
import { WorkflowBlockIcon } from "../nodes/WorkflowBlockIcon";
|
||||
|
||||
const nodeLibraryItems: Array<{
|
||||
nodeType: NonNullable<WorkflowBlockNode["type"]>;
|
||||
@@ -28,93 +14,166 @@ const nodeLibraryItems: Array<{
|
||||
}> = [
|
||||
{
|
||||
nodeType: "navigation",
|
||||
icon: <RobotIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Navigation}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Navigation Block",
|
||||
description: "Navigate on the page",
|
||||
},
|
||||
{
|
||||
nodeType: "action",
|
||||
icon: <ClickIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Action}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Action Block",
|
||||
description: "Take a single action",
|
||||
},
|
||||
{
|
||||
nodeType: "extraction",
|
||||
icon: <ExtractIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Extraction}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Extraction Block",
|
||||
description: "Extract data from the page",
|
||||
},
|
||||
{
|
||||
nodeType: "validation",
|
||||
icon: <CheckCircledIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Validation}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Validation Block",
|
||||
description: "Validate the state of the workflow or terminate",
|
||||
},
|
||||
{
|
||||
nodeType: "task",
|
||||
icon: <ListBulletIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Task}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Task Block",
|
||||
description: "Takes actions or extracts information",
|
||||
},
|
||||
{
|
||||
nodeType: "textPrompt",
|
||||
icon: <CursorTextIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.TextPrompt}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Text Prompt Block",
|
||||
description: "Generates AI response",
|
||||
},
|
||||
{
|
||||
nodeType: "sendEmail",
|
||||
icon: <EnvelopeClosedIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.SendEmail}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Send Email Block",
|
||||
description: "Sends an email",
|
||||
},
|
||||
{
|
||||
nodeType: "loop",
|
||||
icon: <UpdateIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.ForLoop}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "For Loop Block",
|
||||
description: "Repeats nested elements",
|
||||
},
|
||||
// temporarily removed
|
||||
// {
|
||||
// nodeType: "codeBlock",
|
||||
// icon: <CodeIcon className="size-6" />,
|
||||
// icon: <WorkflowBlockIcon
|
||||
// workflowBlockType={WorkflowBlockTypes.Code}
|
||||
// className="size-6"
|
||||
// />,
|
||||
// title: "Code Block",
|
||||
// description: "Executes Python code",
|
||||
// },
|
||||
{
|
||||
nodeType: "fileParser",
|
||||
icon: <FileIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.FileURLParser}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "File Parser Block",
|
||||
description: "Downloads and parses a file",
|
||||
},
|
||||
// disabled
|
||||
// {
|
||||
// nodeType: "download",
|
||||
// icon: <DownloadIcon className="size-6" />,
|
||||
// icon: (
|
||||
// <WorkflowBlockIcon
|
||||
// workflowBlockType={WorkflowBlockTypes.DownloadToS3}
|
||||
// className="size-6"
|
||||
// />
|
||||
// ),
|
||||
// title: "Download Block",
|
||||
// description: "Downloads a file from S3",
|
||||
// },
|
||||
{
|
||||
nodeType: "upload",
|
||||
icon: <UploadIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.UploadToS3}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Upload Block",
|
||||
description: "Uploads a file to S3",
|
||||
},
|
||||
{
|
||||
nodeType: "fileDownload",
|
||||
icon: <DownloadIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.FileDownload}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "File Download Block",
|
||||
description: "Download a file",
|
||||
},
|
||||
{
|
||||
nodeType: "login",
|
||||
icon: <LockOpen1Icon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Login}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Login Block",
|
||||
description: "Login to a website",
|
||||
},
|
||||
{
|
||||
nodeType: "wait",
|
||||
icon: <StopwatchIcon className="size-6" />,
|
||||
icon: (
|
||||
<WorkflowBlockIcon
|
||||
workflowBlockType={WorkflowBlockTypes.Wait}
|
||||
className="size-6"
|
||||
/>
|
||||
),
|
||||
title: "Wait Block",
|
||||
description: "Wait for some time",
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user