Workflow Run Timeline UI (#1433)

This commit is contained in:
Shuchang Zheng
2024-12-23 23:44:47 -08:00
committed by GitHub
parent 682bc717f9
commit 517de67811
42 changed files with 1517 additions and 301 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 };

View File

@@ -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",
};

View File

@@ -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",
},