From 196b4d85dcb32736615e523b8f9f7c52e5413074 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 16 Feb 2024 17:02:32 -0300 Subject: [PATCH 1/5] add build status on node --- .../src/CustomNodes/GenericNode/index.tsx | 69 +++++++++++-------- src/frontend/src/constants/enums.ts | 6 ++ src/frontend/src/modals/formModal/index.tsx | 1 - src/frontend/src/stores/flowStore.ts | 14 ++++ src/frontend/src/types/api/index.ts | 2 + src/frontend/src/types/components/index.ts | 2 +- src/frontend/src/types/flow/index.ts | 2 + src/frontend/src/types/zustand/flow/index.ts | 2 + src/frontend/src/utils/buildUtils.ts | 10 ++- 9 files changed, 75 insertions(+), 33 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 95ae9b1cf..e1206ecb7 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -7,6 +7,7 @@ import InputComponent from "../../components/inputComponent"; import { Button } from "../../components/ui/button"; import { Textarea } from "../../components/ui/textarea"; import { priorityFields } from "../../constants/constants"; +import { BuildStatus } from "../../constants/enums"; import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; import useFlowStore from "../../stores/flowStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore"; @@ -71,7 +72,6 @@ export default function GenericNode({ setHandles(count); } - useEffect(() => { countHandles(); }, [data, data.node]); @@ -164,8 +164,6 @@ export default function GenericNode({ numberOfHandles={handles} showNode={showNode} openAdvancedModal={false} - onCloseAdvancedModal={() => { - }} > @@ -410,33 +408,44 @@ export default function GenericNode({ } >
- - - + {data?.build_status === BuildStatus.TO_BUILD ? ( + <> + + + ) : ( + <> + + + + + )}
diff --git a/src/frontend/src/constants/enums.ts b/src/frontend/src/constants/enums.ts index a7bed8fde..57476239c 100644 --- a/src/frontend/src/constants/enums.ts +++ b/src/frontend/src/constants/enums.ts @@ -6,3 +6,9 @@ export enum TypeModal { TEXT = 1, PROMPT = 2, } + +export enum BuildStatus { + BUILDING = "BUILDING", + TO_BUILD = "TO_BUILD", + BUILDED = "BUILDED", +} diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index c85e77a0d..80ab8c06b 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -205,7 +205,6 @@ export default function FormModal({ if (Array.isArray(data) && data.length > 0) { //set chat history setChatHistory((_) => { - console.log(data); let newChatHistory: ChatMessageType[] = []; for (let i = 0; i < data.length; i++) { if (data[i].type === "prompt" && data[i].prompt) { diff --git a/src/frontend/src/stores/flowStore.ts b/src/frontend/src/stores/flowStore.ts index 473c615b1..cdb9955a3 100644 --- a/src/frontend/src/stores/flowStore.ts +++ b/src/frontend/src/stores/flowStore.ts @@ -11,6 +11,7 @@ import { } from "reactflow"; import { create } from "zustand"; import { INPUT_TYPES, OUTPUT_TYPES } from "../constants/constants"; +import { BuildStatus } from "../constants/enums"; import { getFlowPool, updateFlowInDatabase } from "../controllers/API"; import { NodeDataType, @@ -357,6 +358,7 @@ const useFlowStore = create((set, get) => ({ const setErrorData = useAlertStore.getState().setErrorData; function handleBuildUpdate(data: any) { get().addDataToFlowPool(data.data[data.id], data.id); + useFlowStore.getState().updateBuildStatus([data.id], BuildStatus.BUILDED); } await updateFlowInDatabase({ data: { @@ -382,6 +384,9 @@ const useFlowStore = create((set, get) => ({ onBuildError: (title, list) => { setErrorData({ list, title }); }, + onBuildStart: (idList) => { + useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILDING); + }, }); }, getFlow: () => { @@ -391,6 +396,15 @@ const useFlowStore = create((set, get) => ({ viewport: get().reactFlowInstance?.getViewport()!, }; }, + updateBuildStatus: (nodeIdList: string[], status: BuildStatus) => { + nodeIdList.forEach((id) => { + const nodeToUpdate = get().nodes.find((node) => node.id === id); + if (nodeToUpdate) { + nodeToUpdate.data.build_status = status; + get().setNodes(get().nodes); + } + }); + }, })); export default useFlowStore; diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 48db814cf..1286a90bc 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -1,4 +1,5 @@ import { Edge, Node, Viewport } from "reactflow"; +import { BuildStatus } from "../../constants/enums"; import { FlowType } from "../flow"; //kind and class are just representative names to represent the actual structure of the object received by the API export type APIDataType = { [key: string]: APIKindType }; @@ -36,6 +37,7 @@ export type APIClassType = { | CustomFieldsType | boolean | undefined; + build_status?: BuildStatus; }; export type TemplateVariableType = { diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index c3128b3f5..3a8563cf1 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -625,7 +625,7 @@ export type crashComponentPropsType = { export type validationStatusType = { id: string; - data: object; + data: object | any; params: string; progress: number; valid: boolean; diff --git a/src/frontend/src/types/flow/index.ts b/src/frontend/src/types/flow/index.ts index 544e78a45..5f2ed1dc4 100644 --- a/src/frontend/src/types/flow/index.ts +++ b/src/frontend/src/types/flow/index.ts @@ -1,4 +1,5 @@ import { ReactFlowJsonObject, XYPosition } from "reactflow"; +import { BuildStatus } from "../../constants/enums"; import { APIClassType } from "../api/index"; export type FlowType = { @@ -26,6 +27,7 @@ export type NodeDataType = { node?: APIClassType; id: string; output_types?: string[]; + build_status?: BuildStatus; }; // FlowStyleType is the type of the style object that is used to style the // Flow card with an emoji and a color. diff --git a/src/frontend/src/types/zustand/flow/index.ts b/src/frontend/src/types/zustand/flow/index.ts index 937197efd..3e56d49e2 100644 --- a/src/frontend/src/types/zustand/flow/index.ts +++ b/src/frontend/src/types/zustand/flow/index.ts @@ -7,6 +7,7 @@ import { ReactFlowInstance, Viewport, } from "reactflow"; +import { BuildStatus } from "../../../constants/enums"; import { FlowState } from "../../tabs"; export type chatInputType = { @@ -84,4 +85,5 @@ export type FlowStoreType = { unselectAll: () => void; buildFlow: (nodeId?: string) => Promise; getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport }; + updateBuildStatus: (nodeId: string[], status: BuildStatus) => void; }; diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts index d7cdf5538..1246caa8a 100644 --- a/src/frontend/src/utils/buildUtils.ts +++ b/src/frontend/src/utils/buildUtils.ts @@ -1,5 +1,7 @@ import { AxiosError } from "axios"; +import { BuildStatus } from "../constants/enums"; import { getVerticesOrder, postBuildVertex } from "../controllers/API"; +import useFlowStore from "../stores/flowStore"; import { VertexBuildTypeAPI } from "../types/api"; type BuildVerticesParams = { @@ -9,6 +11,7 @@ type BuildVerticesParams = { onBuildUpdate?: (data: any) => void; // Replace any with the actual type of data onBuildComplete?: (allNodesValid: boolean) => void; onBuildError?: (title, list) => void; + onBuildStart?: (idList: string[]) => void; }; export async function buildVertices({ @@ -18,10 +21,12 @@ export async function buildVertices({ onBuildUpdate, onBuildComplete, onBuildError, + onBuildStart, }: BuildVerticesParams) { let orderResponse = await getVerticesOrder(flowId); let verticesOrder: Array> = orderResponse.data.ids; let vertices: Array> = []; + if (nodeId) { for (let i = 0; i < verticesOrder.length; i += 1) { const innerArray = verticesOrder[i]; @@ -40,10 +45,13 @@ export async function buildVertices({ vertices = verticesOrder; } - // Set each vertex state to building + const verticesIds = vertices.flatMap((v) => v); + useFlowStore.getState().updateBuildStatus(verticesIds, BuildStatus.TO_BUILD); + // Set each vertex state to building const buildResults: Array = []; for (let i = 0; i < vertices.length; i += 1) { + if (onBuildStart) onBuildStart(vertices[i]); await Promise.all( vertices[i].map(async (id) => { try { From d153df478c64a8eb1f47977a6035141d57b8da7b Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 16 Feb 2024 17:15:18 -0300 Subject: [PATCH 2/5] add required function to generic nodfe --- src/frontend/src/CustomNodes/GenericNode/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index e1206ecb7..7c4e07f23 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -164,6 +164,7 @@ export default function GenericNode({ numberOfHandles={handles} showNode={showNode} openAdvancedModal={false} + onCloseAdvancedModal={() => {}} > From 09907ad943deb4432d3ffa7a3646003f80dadb9f Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Mon, 19 Feb 2024 18:35:24 -0300 Subject: [PATCH 3/5] add colors to borders when building --- .../src/CustomNodes/GenericNode/index.tsx | 15 +++++++++++--- src/frontend/src/stores/flowStore.ts | 4 +++- src/frontend/src/utils/buildUtils.ts | 20 +++++++++++++------ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 7c4e07f23..71d8de3b1 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -172,7 +172,15 @@ export default function GenericNode({ className={classNames( selected ? "border border-ring" : "border", showNode ? " w-96 rounded-lg" : " w-26 h-26 rounded-full", - "generic-node-div" + "generic-node-div", + data?.build_status === BuildStatus.BUILDED && + validationStatus && + !validationStatus.valid + ? "border-none ring ring-red-300" + : "", + data?.build_status === BuildStatus.BUILDING + ? " border-none ring" + : "" )} > {data.node?.beta && showNode && ( @@ -384,7 +392,8 @@ export default function GenericNode({
Building... ) : !validationStatus ? ( @@ -409,7 +418,7 @@ export default function GenericNode({ } >
- {data?.build_status === BuildStatus.TO_BUILD ? ( + {data?.build_status === BuildStatus.BUILDING ? ( <> ((set, get) => ({ } }, onBuildUpdate: handleBuildUpdate, - onBuildError: (title, list) => { + onBuildError: (title, list, idList) => { + useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILDED); + setErrorData({ list, title }); }, onBuildStart: (idList) => { diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts index 1246caa8a..26793b5fa 100644 --- a/src/frontend/src/utils/buildUtils.ts +++ b/src/frontend/src/utils/buildUtils.ts @@ -10,7 +10,7 @@ type BuildVerticesParams = { onProgressUpdate?: (progress: number) => void; // Replace number with the actual type if it's not a number onBuildUpdate?: (data: any) => void; // Replace any with the actual type of data onBuildComplete?: (allNodesValid: boolean) => void; - onBuildError?: (title, list) => void; + onBuildError?: (title, list, idList: string[]) => void; onBuildStart?: (idList: string[]) => void; }; @@ -62,7 +62,11 @@ export async function buildVertices({ let data = {}; if (!buildData.valid) { if (onBuildError) { - onBuildError("Error Building Component", [buildData.params]); + onBuildError( + "Error Building Component", + [buildData.params], + verticesIds + ); } } data[buildData.id] = buildData; @@ -72,10 +76,14 @@ export async function buildVertices({ } catch (error) { if (onBuildError) { console.log(error); - onBuildError("Error Building Component", [ - (error as AxiosError).response?.data?.detail ?? - "Unknown Error", - ]); + onBuildError( + "Error Building Component", + [ + (error as AxiosError).response?.data?.detail ?? + "Unknown Error", + ], + verticesIds + ); } } }) From a32c3a37300047c7d96c21408dbb65fc9aba66d0 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Tue, 20 Feb 2024 10:48:19 -0300 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=94=A8=20refactor(GenericNode/index.t?= =?UTF-8?q?sx):=20extract=20helper=20functions=20to=20improve=20code=20rea?= =?UTF-8?q?dability=20and=20maintainability=20=F0=9F=90=9B=20fix(GenericNo?= =?UTF-8?q?de/index.tsx):=20fix=20incorrect=20class=20name=20in=20getNodeC?= =?UTF-8?q?lassName=20function=20=E2=9C=A8=20feat(GenericNode/index.tsx):?= =?UTF-8?q?=20add=20renderIconComponents=20function=20to=20render=20differ?= =?UTF-8?q?ent=20icon=20components=20based=20on=20build=20and=20validation?= =?UTF-8?q?=20status=20=E2=9C=A8=20feat(GenericNode/index.tsx):=20add=20ge?= =?UTF-8?q?tSpecificClass=20function=20to=20determine=20specific=20class?= =?UTF-8?q?=20based=20on=20build=20and=20validation=20status=20=E2=9C=A8?= =?UTF-8?q?=20feat(GenericNode/index.tsx):=20add=20getStatusClassName=20fu?= =?UTF-8?q?nction=20to=20determine=20status=20class=20based=20on=20validat?= =?UTF-8?q?ion=20status=20and=20build=20status=20=E2=9C=A8=20feat(GenericN?= =?UTF-8?q?ode/index.tsx):=20add=20getIconComponent=20function=20to=20rend?= =?UTF-8?q?er=20icon=20component=20with=20name=20and=20class=20name=20?= =?UTF-8?q?=E2=9C=A8=20feat(GenericNode/index.tsx):=20add=20getNodeClassNa?= =?UTF-8?q?me=20function=20to=20determine=20node=20class=20name=20based=20?= =?UTF-8?q?on=20selected,=20showNode,=20build=20status,=20and=20validation?= =?UTF-8?q?=20status=20=E2=9C=A8=20feat(GenericNode/index.tsx):=20add=20ge?= =?UTF-8?q?tBaseBorderClass=20function=20to=20determine=20base=20border=20?= =?UTF-8?q?class=20based=20on=20selected=20state=20=E2=9C=A8=20feat(Generi?= =?UTF-8?q?cNode/index.tsx):=20add=20getNodeSizeClass=20function=20to=20de?= =?UTF-8?q?termine=20node=20size=20class=20based=20on=20showNode=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/CustomNodes/GenericNode/index.tsx | 130 +++++++++++------- 1 file changed, 81 insertions(+), 49 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 80b7ec88a..eb16542ef 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -157,6 +157,78 @@ export default function GenericNode({ ); }; + const getIconComponent = (name, className) => ( + + ); + + const getStatusClassName = ( + validationStatus: validationStatusType | null, + isBuilding: boolean + ) => { + if (validationStatus && validationStatus.valid) { + return "green-status"; + } else if (validationStatus && !validationStatus.valid) { + return "red-status"; + } else if (!validationStatus || isBuilding) { + return "yellow-status"; + } else { + return "status-build-animation"; + } + }; + + const renderIconComponents = ( + buildStatus: BuildStatus | undefined, + validationStatus: validationStatusType | null, + isBuilding: boolean + ) => { + if (buildStatus === BuildStatus.BUILDING) { + return getIconComponent("Square", "red-status"); + } else { + const className = getStatusClassName(validationStatus, isBuilding); + return <>{getIconComponent("Play", className)}; + } + }; + + const getSpecificClass = ( + buildStatus: BuildStatus | undefined, + validationStatus: validationStatusType | null + ) => { + if ( + buildStatus === BuildStatus.BUILDED && + validationStatus && + !validationStatus.valid + ) { + return "border-none ring ring-red-300"; + } else if (buildStatus === BuildStatus.BUILDING) { + return "border-none ring"; + } else { + return ""; + } + }; + + const getNodeClassName = ( + selected: boolean, + showNode: boolean, + buildStatus: BuildStatus | undefined, + validationStatus: validationStatusType | null + ) => { + return classNames( + getBaseBorderClass(selected), + getNodeSizeClass(showNode), + "generic-node-div", + getSpecificClass(buildStatus, validationStatus) + ); + }; + + const getBaseBorderClass = (selected) => + selected ? "border border-ring" : "border"; + + const getNodeSizeClass = (showNode) => + showNode ? "w-96 rounded-lg" : "w-26 h-26 rounded-full"; + return ( <> @@ -181,18 +253,11 @@ export default function GenericNode({
{data.node?.beta && showNode && ( @@ -430,43 +495,10 @@ export default function GenericNode({ } >
- {data?.build_status === BuildStatus.BUILDING ? ( - <> - - - ) : ( - <> - - - - + {renderIconComponents( + data?.build_status, + validationStatus, + isBuilding )}
From b3f82872b0f10a2b1332b5a649654004654f20a1 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Tue, 20 Feb 2024 10:48:32 -0300 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=90=9B=20fix(GenericNode/index.tsx):?= =?UTF-8?q?=20rename=20getIconComponent=20to=20getIconPlayOrPauseComponent?= =?UTF-8?q?=20for=20better=20clarity=20and=20semantics=20=F0=9F=90=9B=20fi?= =?UTF-8?q?x(GenericNode/index.tsx):=20rename=20renderIconComponents=20to?= =?UTF-8?q?=20renderIconPlayOrPauseComponents=20for=20better=20clarity=20a?= =?UTF-8?q?nd=20semantics=20=F0=9F=90=9B=20fix(GenericNode/index.tsx):=20r?= =?UTF-8?q?ename=20getSpecificClass=20to=20getSpecificClassFromBuildStatus?= =?UTF-8?q?=20for=20better=20clarity=20and=20semantics=20=F0=9F=90=9B=20fi?= =?UTF-8?q?x(GenericNode/index.tsx):=20rename=20getNodeClassName=20to=20ge?= =?UTF-8?q?tNodeBorderClassName=20for=20better=20clarity=20and=20semantics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/CustomNodes/GenericNode/index.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index eb16542ef..c7b85c57c 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -157,7 +157,7 @@ export default function GenericNode({ ); }; - const getIconComponent = (name, className) => ( + const getIconPlayOrPauseComponent = (name, className) => ( { if (buildStatus === BuildStatus.BUILDING) { - return getIconComponent("Square", "red-status"); + return getIconPlayOrPauseComponent("Square", "red-status"); } else { const className = getStatusClassName(validationStatus, isBuilding); - return <>{getIconComponent("Play", className)}; + return <>{getIconPlayOrPauseComponent("Play", className)}; } }; - const getSpecificClass = ( + const getSpecificClassFromBuildStatus = ( buildStatus: BuildStatus | undefined, validationStatus: validationStatusType | null ) => { @@ -209,7 +209,7 @@ export default function GenericNode({ } }; - const getNodeClassName = ( + const getNodeBorderClassName = ( selected: boolean, showNode: boolean, buildStatus: BuildStatus | undefined, @@ -219,7 +219,7 @@ export default function GenericNode({ getBaseBorderClass(selected), getNodeSizeClass(showNode), "generic-node-div", - getSpecificClass(buildStatus, validationStatus) + getSpecificClassFromBuildStatus(buildStatus, validationStatus) ); }; @@ -253,7 +253,7 @@ export default function GenericNode({
- {renderIconComponents( + {renderIconPlayOrPauseComponents( data?.build_status, validationStatus, isBuilding