diff --git a/src/frontend/src/components/chatComponent/buildTrigger/index.tsx b/src/frontend/src/components/chatComponent/buildTrigger/index.tsx index 09ab90ff7..f551d6d06 100644 --- a/src/frontend/src/components/chatComponent/buildTrigger/index.tsx +++ b/src/frontend/src/components/chatComponent/buildTrigger/index.tsx @@ -7,9 +7,9 @@ import { alertContext } from "../../../contexts/alertContext"; import { typesContext } from "../../../contexts/typesContext"; import { postBuildInit } from "../../../controllers/API"; import { FlowType } from "../../../types/flow"; -import { validateNodes } from "../../../utils"; import { TabsContext } from "../../../contexts/tabsContext"; +import { validateNodes } from "../../../utils/reactflowUtils"; import RadialProgressComponent from "../../RadialProgress"; export default function BuildTrigger({ diff --git a/src/frontend/src/modals/formModal/index.tsx b/src/frontend/src/modals/formModal/index.tsx index 12f7683b3..6bcd1a331 100644 --- a/src/frontend/src/modals/formModal/index.tsx +++ b/src/frontend/src/modals/formModal/index.tsx @@ -5,7 +5,7 @@ import { typesContext } from "../../contexts/typesContext"; import { sendAllProps } from "../../types/api"; import { ChatMessageType } from "../../types/chat"; import { FlowType } from "../../types/flow"; -import { classNames, validateNodes } from "../../utils"; +import { classNames } from "../../utils"; import ChatInput from "./chatInput"; import ChatMessage from "./chatMessage"; @@ -29,6 +29,7 @@ import { import { Textarea } from "../../components/ui/textarea"; import { CHAT_FORM_DIALOG_SUBTITLE, THOUGHTS_ICON } from "../../constants"; import { TabsContext } from "../../contexts/tabsContext"; +import { validateNodes } from "../../utils/reactflowUtils"; export default function FormModal({ flow, diff --git a/src/frontend/src/utils.ts b/src/frontend/src/utils.ts index 6aed03239..beec2239e 100644 --- a/src/frontend/src/utils.ts +++ b/src/frontend/src/utils.ts @@ -1,9 +1,7 @@ import clsx, { ClassValue } from "clsx"; -import { ReactFlowInstance } from "reactflow"; import { twMerge } from "tailwind-merge"; import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "./flow_constants"; import { IVarHighlightType } from "./types/components"; -import { NodeType } from "./types/flow"; export function classNames(...classes: Array) { return classes.filter(Boolean).join(" "); @@ -209,58 +207,6 @@ export function buildInputs(tabsState, id) { : '{"input": "message"}'; } -export function validateNode( - n: NodeType, - reactFlowInstance: ReactFlowInstance -): Array { - if (!n.data?.node?.template || !Object.keys(n.data.node.template)) { - return [ - "We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", - ]; - } - - const { - type, - node: { template }, - } = n.data; - - return Object.keys(template).reduce( - (errors: Array, t) => - errors.concat( - template[t].required && - template[t].show && - (template[t].value === undefined || - template[t].value === null || - template[t].value === "") && - !reactFlowInstance - .getEdges() - .some( - (e) => - e.targetHandle.split("|")[1] === t && - e.targetHandle.split("|")[2] === n.id - ) - ? [ - `${type} is missing ${ - template.display_name || toNormalCase(template[t].name) - }.`, - ] - : [] - ), - [] as string[] - ); -} - -export function validateNodes(reactFlowInstance: ReactFlowInstance) { - if (reactFlowInstance.getNodes().length === 0) { - return [ - "No nodes found in the flow. Please add at least one node to the flow.", - ]; - } - return reactFlowInstance - .getNodes() - .flatMap((n: NodeType) => validateNode(n, reactFlowInstance)); -} - export function getRandomElement(array: T[]): T { return array[Math.floor(Math.random() * array.length)]; } diff --git a/src/frontend/src/utils/reactflowUtils.ts b/src/frontend/src/utils/reactflowUtils.ts index 515199574..b14a24c70 100644 --- a/src/frontend/src/utils/reactflowUtils.ts +++ b/src/frontend/src/utils/reactflowUtils.ts @@ -3,6 +3,7 @@ import { Connection, ReactFlowInstance } from "reactflow"; import { APITemplateType } from "../types/api"; import { FlowType, NodeType } from "../types/flow"; import { cleanEdgesType } from "../types/utils/reactflowUtils"; +import { toNormalCase } from "../utils"; export function cleanEdges({ flow: { edges, nodes }, @@ -166,3 +167,55 @@ export function buildTweaks(flow) { return acc; }, {}); } + +export function validateNode( + n: NodeType, + reactFlowInstance: ReactFlowInstance +): Array { + if (!n.data?.node?.template || !Object.keys(n.data.node.template)) { + return [ + "We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", + ]; + } + + const { + type, + node: { template }, + } = n.data; + + return Object.keys(template).reduce( + (errors: Array, t) => + errors.concat( + template[t].required && + template[t].show && + (template[t].value === undefined || + template[t].value === null || + template[t].value === "") && + !reactFlowInstance + .getEdges() + .some( + (e) => + e.targetHandle.split("|")[1] === t && + e.targetHandle.split("|")[2] === n.id + ) + ? [ + `${type} is missing ${ + template.display_name || toNormalCase(template[t].name) + }.`, + ] + : [] + ), + [] as string[] + ); +} + +export function validateNodes(reactFlowInstance: ReactFlowInstance) { + if (reactFlowInstance.getNodes().length === 0) { + return [ + "No nodes found in the flow. Please add at least one node to the flow.", + ]; + } + return reactFlowInstance + .getNodes() + .flatMap((n: NodeType) => validateNode(n, reactFlowInstance)); +}