diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx
index dfa505f91..c7b85c57c 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]);
@@ -157,6 +157,78 @@ export default function GenericNode({
);
};
+ const getIconPlayOrPauseComponent = (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 renderIconPlayOrPauseComponents = (
+ buildStatus: BuildStatus | undefined,
+ validationStatus: validationStatusType | null,
+ isBuilding: boolean
+ ) => {
+ if (buildStatus === BuildStatus.BUILDING) {
+ return getIconPlayOrPauseComponent("Square", "red-status");
+ } else {
+ const className = getStatusClassName(validationStatus, isBuilding);
+ return <>{getIconPlayOrPauseComponent("Play", className)}>;
+ }
+ };
+
+ const getSpecificClassFromBuildStatus = (
+ 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 getNodeBorderClassName = (
+ selected: boolean,
+ showNode: boolean,
+ buildStatus: BuildStatus | undefined,
+ validationStatus: validationStatusType | null
+ ) => {
+ return classNames(
+ getBaseBorderClass(selected),
+ getNodeSizeClass(showNode),
+ "generic-node-div",
+ getSpecificClassFromBuildStatus(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,10 +253,11 @@ export default function GenericNode({
{data.node?.beta && showNode && (
@@ -396,7 +469,8 @@ export default function GenericNode({
Building...
) : !validationStatus ? (
@@ -421,33 +495,11 @@ export default function GenericNode({
}
>
-
-
-
+ {renderIconPlayOrPauseComponents(
+ data?.build_status,
+ validationStatus,
+ isBuilding
+ )}
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 f14b9558e..92dc11ee8 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,
@@ -380,6 +381,7 @@ const useFlowStore = create
((set, get) => ({
const setNoticeData = useAlertStore.getState().setNoticeData;
function handleBuildUpdate(data: any) {
get().addDataToFlowPool(data.data[data.id], data.id);
+ useFlowStore.getState().updateBuildStatus([data.id], BuildStatus.BUILDED);
}
await updateFlowInDatabase({
data: {
@@ -403,9 +405,14 @@ const useFlowStore = create((set, get) => ({
}
},
onBuildUpdate: handleBuildUpdate,
- onBuildError: (title, list) => {
+ onBuildError: (title, list, idList) => {
+ useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILDED);
+
setErrorData({ list, title });
},
+ onBuildStart: (idList) => {
+ useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILDING);
+ },
});
},
getFlow: () => {
@@ -415,6 +422,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 a85965f16..429379155 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 = {
@@ -85,4 +86,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 5b217b6d5..854a86f24 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 = {
@@ -8,7 +10,8 @@ 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;
};
export async function buildVertices({
@@ -18,10 +21,12 @@ export async function buildVertices({
onBuildUpdate,
onBuildComplete,
onBuildError,
+ onBuildStart,
}: BuildVerticesParams) {
let orderResponse = await getVerticesOrder(flowId, nodeId);
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 {
@@ -54,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;
@@ -64,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
+ );
}
}
})