From e435910bd5b811a98bba56471828cdc2d18fb227 Mon Sep 17 00:00:00 2001 From: asim-shrestha Date: Wed, 19 Jul 2023 12:12:04 -0700 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20Update=20node=20abstraction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next/src/components/workflow/AbstractNode.tsx | 25 ++++++++++++++----- next/src/components/workflow/BasicNode.tsx | 4 +-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/next/src/components/workflow/AbstractNode.tsx b/next/src/components/workflow/AbstractNode.tsx index 88c443b0bf..18f4cd12fd 100644 --- a/next/src/components/workflow/AbstractNode.tsx +++ b/next/src/components/workflow/AbstractNode.tsx @@ -4,8 +4,16 @@ import type { HandleType, Position } from "reactflow"; import { Handle } from "reactflow"; import clsx from "clsx"; +interface Handle { + position: Position; + type: HandleType; + className?: string; + id?: string; + text?: string; +} + interface NodeProps extends PropsWithChildren { - handles: [Position, HandleType][]; + handles: Handle[]; selected: boolean; status?: string; } @@ -24,14 +32,19 @@ function AbstractNode(props: NodeProps) { )} > {props.children} - {props.handles.map(([position, type]) => ( + {props.handles.map(({ position, type, text, className, id }, i) => ( + className={clsx( + "border-gradient !hover:border-white grid !h-fit !w-fit place-items-center !rounded-md !bg-black p-1 text-xs font-light", + className + )} + > + {text} + ))} ); diff --git a/next/src/components/workflow/BasicNode.tsx b/next/src/components/workflow/BasicNode.tsx index ac7dc7352b..7ba65e29cd 100644 --- a/next/src/components/workflow/BasicNode.tsx +++ b/next/src/components/workflow/BasicNode.tsx @@ -12,8 +12,8 @@ function BasicNode({ data, selected }: NodeProps) { selected={selected} status={data.status} handles={[ - [Position.Top, "target"], - [Position.Bottom, "source"], + { position: Position.Top, type: "target" }, + { position: Position.Bottom, type: "source" }, ]} >
From 9bd333ad8e6698cb9cbc106743190ce36e3164c2 Mon Sep 17 00:00:00 2001 From: asim-shrestha Date: Wed, 19 Jul 2023 12:16:02 -0700 Subject: [PATCH 2/6] =?UTF-8?q?=E2=9C=A8=20Fix=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next/src/components/workflow/Flowchart.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/next/src/components/workflow/Flowchart.tsx b/next/src/components/workflow/Flowchart.tsx index 15cceb56a6..dd6f0bc39a 100644 --- a/next/src/components/workflow/Flowchart.tsx +++ b/next/src/components/workflow/Flowchart.tsx @@ -1,3 +1,4 @@ +import type { ComponentProps, MouseEvent} from "react"; import { type FC, useCallback } from "react"; import type { Connection, EdgeChange, FitViewOptions, NodeChange } from "reactflow"; import ReactFlow, { @@ -11,12 +12,14 @@ import ReactFlow, { } from "reactflow"; import "reactflow/dist/style.css"; -import CustomNode from "./BasicNode"; +import BasicNode from "./BasicNode"; import CustomEdge from "./BasicEdge"; import type { EdgesModel, NodesModel } from "../../types/workflow"; +import IfNode from "./IfNode"; const nodeTypes = { - custom: CustomNode, + if: IfNode, + custom: BasicNode, }; const edgeTypes = { @@ -27,8 +30,8 @@ const fitViewOptions: FitViewOptions = { padding: 0.2, }; -interface FlowChartProps extends React.ComponentProps { - onSave?: (e: React.MouseEvent) => Promise; +interface FlowChartProps extends ComponentProps { + onSave?: (e: MouseEvent) => Promise; controls?: boolean; minimap?: boolean; From a74909b783dcc35450f088ef3da1fc39619987df Mon Sep 17 00:00:00 2001 From: asim-shrestha Date: Wed, 19 Jul 2023 12:16:17 -0700 Subject: [PATCH 3/6] =?UTF-8?q?=E2=9C=A8=20Update=20styling=20for=20border?= =?UTF-8?q?-gradient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next/src/styles/globals.css | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/next/src/styles/globals.css b/next/src/styles/globals.css index 029f615259..c2f78a8ffb 100644 --- a/next/src/styles/globals.css +++ b/next/src/styles/globals.css @@ -13,9 +13,10 @@ body { } .border-gradient { + /* Mark as important to override react flow styling */ background: linear-gradient(black, black) padding-box, - linear-gradient(to bottom, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.15)) border-box; - border: 1px solid transparent; + linear-gradient(to bottom, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.15)) border-box !important; + border: 1px solid transparent !important; } .radial-background-1 { @@ -314,16 +315,17 @@ Not supports in Firefox and IE */ .animate-border-pulse { animation: border-pulse-animation 2s infinite; } + @keyframes moveBackground { from { - background-position: 0 0; + background-position: 0 0; } to { - background-position: 100% 0; + background-position: 100% 0; } - } +} - .bg-stars { +.bg-stars { animation: moveBackground 30s linear infinite; background: url("/stars.svg"); background-size: cover; @@ -333,4 +335,4 @@ Not supports in Firefox and IE */ left: 0; right: 0; z-index: -1; - } \ No newline at end of file +} \ No newline at end of file From ab4841e5bff5ad4acab720e318d0e3b4e7dfa1d4 Mon Sep 17 00:00:00 2001 From: asim-shrestha Date: Wed, 19 Jul 2023 12:16:26 -0700 Subject: [PATCH 4/6] =?UTF-8?q?=E2=9C=A8=20Create=20IfNode=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next/src/services/workflow/node-block-definitions.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/next/src/services/workflow/node-block-definitions.ts b/next/src/services/workflow/node-block-definitions.ts index 71addb315d..96adc779bb 100644 --- a/next/src/services/workflow/node-block-definitions.ts +++ b/next/src/services/workflow/node-block-definitions.ts @@ -68,8 +68,17 @@ const SlackWebhookBlockDefinition: NodeBlockDefinition = { ], }; +const IfBlockDefinition: NodeBlockDefinition = { + name: "If Block", + type: "IfBlock", + description: "Conditionally take a path", + image_url: "/tools/web.png", + input_fields: [], + output_fields: [], +}; + export const getNodeBlockDefinitions = () => { - return [UrlStatusCheckBlockDefinition, SlackWebhookBlockDefinition]; + return [UrlStatusCheckBlockDefinition, SlackWebhookBlockDefinition, IfBlockDefinition]; }; export const getNodeBlockDefinitionFromNode = (node: Node) => { From 0a2b26610a651a8470388a23b7ddd197cb752051 Mon Sep 17 00:00:00 2001 From: asim-shrestha Date: Wed, 19 Jul 2023 12:19:15 -0700 Subject: [PATCH 5/6] =?UTF-8?q?=E2=9C=A8=20Create=20IfNode=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next/src/components/workflow/IfNode.tsx | 44 +++++++++++++++++++++++++ next/src/hooks/useWorkflow.ts | 7 ++-- next/src/types/workflow.ts | 11 ++++++- 3 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 next/src/components/workflow/IfNode.tsx diff --git a/next/src/components/workflow/IfNode.tsx b/next/src/components/workflow/IfNode.tsx new file mode 100644 index 0000000000..2ce4c3bf9c --- /dev/null +++ b/next/src/components/workflow/IfNode.tsx @@ -0,0 +1,44 @@ +import React, { memo } from "react"; +import { type NodeProps, Position } from "reactflow"; +import type { WorkflowNode } from "../../types/workflow"; +import { getNodeBlockDefinitions } from "../../services/workflow/node-block-definitions"; +import AbstractNode from "./AbstractNode"; + +function IfNode(props: NodeProps) { + const { data, selected } = props; + const definition = getNodeBlockDefinitions().find((d) => d.type === data.block.type); + console.log(props); + return ( + +
+
+
{definition?.name}
+
{definition?.description}
+
+
+
+ ); +} + +export default memo(IfNode); diff --git a/next/src/hooks/useWorkflow.ts b/next/src/hooks/useWorkflow.ts index 1f5ed6dbd1..64430b648a 100644 --- a/next/src/hooks/useWorkflow.ts +++ b/next/src/hooks/useWorkflow.ts @@ -1,9 +1,10 @@ import type { Edge, Node } from "reactflow"; -import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import type { Dispatch, SetStateAction} from "react"; +import { useEffect, useState } from "react"; import { nanoid } from "nanoid"; import { useMutation, useQuery } from "@tanstack/react-query"; import type { NodeBlock, Workflow, WorkflowEdge, WorkflowNode } from "../types/workflow"; -import { toReactFlowEdge, toReactFlowNode } from "../types/workflow"; +import { getNodeType, toReactFlowEdge, toReactFlowNode } from "../types/workflow"; import WorkflowApi from "../services/workflow/workflowApi"; import useSocket from "./useSocket"; import { z } from "zod"; @@ -91,7 +92,7 @@ export const useWorkflow = (workflowId: string, session: Session | null) => { ...(nodes ?? []), { id: ref, - type: "custom", + type: getNodeType(block), position: { x: 0, y: 0 }, data: { id: undefined, diff --git a/next/src/types/workflow.ts b/next/src/types/workflow.ts index eca87d63a4..66435522da 100644 --- a/next/src/types/workflow.ts +++ b/next/src/types/workflow.ts @@ -43,7 +43,7 @@ export const toReactFlowNode = (node: WorkflowNode) => id: node.id ?? node.ref, data: node, position: { x: node.pos_x, y: node.pos_y }, - type: "custom", + type: getNodeType(node.block), } as Node); export const toReactFlowEdge = (edge: WorkflowEdge) => @@ -54,3 +54,12 @@ export const toReactFlowEdge = (edge: WorkflowEdge) => ...edge, }, } as Edge); + +export const getNodeType = (block: NodeBlock) => { + switch (block.type) { + case "IfBlock": + return "if"; + default: + return "custom"; + } +}; From a6dd5eb6b2406d5ac6fd6b024c9457069a1a8f61 Mon Sep 17 00:00:00 2001 From: asim-shrestha Date: Wed, 19 Jul 2023 12:25:55 -0700 Subject: [PATCH 6/6] =?UTF-8?q?=E2=9C=A8=20Remove=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next/src/components/workflow/IfNode.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next/src/components/workflow/IfNode.tsx b/next/src/components/workflow/IfNode.tsx index 2ce4c3bf9c..edd6df76aa 100644 --- a/next/src/components/workflow/IfNode.tsx +++ b/next/src/components/workflow/IfNode.tsx @@ -7,7 +7,7 @@ import AbstractNode from "./AbstractNode"; function IfNode(props: NodeProps) { const { data, selected } = props; const definition = getNodeBlockDefinitions().find((d) => d.type === data.block.type); - console.log(props); + return (