diff --git a/src/frontend/src/components/chatComponent/index.tsx b/src/frontend/src/components/chatComponent/index.tsx index 59cc54b4c..0d598b300 100644 --- a/src/frontend/src/components/chatComponent/index.tsx +++ b/src/frontend/src/components/chatComponent/index.tsx @@ -14,10 +14,11 @@ import { } from "react"; import { sendAll } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; -import { classNames, nodeColors } from "../../utils"; +import { classNames, nodeColors, snakeToNormalCase } from "../../utils"; import { TabsContext } from "../../contexts/tabsContext"; import { ChatType } from "../../types/chat"; import ChatMessage from "./chatMessage"; +import { NodeType } from "../../types/flow"; const _ = require("lodash"); @@ -28,7 +29,7 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) { const [open, setOpen] = useState(true); const [chatValue, setChatValue] = useState(""); const [chatHistory, setChatHistory] = useState(flow.chat); - const { setErrorData } = useContext(alertContext); + const { setErrorData, setNoticeData } = useContext(alertContext); const addChatHistory = ( message: string, isSend: boolean, @@ -73,36 +74,58 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) { useEffect(() => { if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" }); }, [chatHistory]); - function validateNodes() { - if ( - reactFlowInstance.getNodes().some( - (n) => - n.data.node && - Object.keys(n.data.node.template).some((t: any) => { - return ( - n.data.node.template[t].required && - (!n.data.node.template[t].value || - n.data.node.template[t].value === "") && - !reactFlowInstance - .getEdges() - .some( - (e) => - e.targetHandle.split("|")[1] === t && - e.targetHandle.split("|")[2] === n.id - ) - ); - }) - ) - ) { - return false; + + function validateNode(n: NodeType): Array { + if (!n.data?.node?.template || !Object.keys(n.data.node.template)) { + setNoticeData({ + title: + "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!", + }); + return []; } - return true; + + const { + type, + node: { template }, + } = n.data; + + return Object.keys(template).reduce( + (errors: Array, t) => + errors.concat( + template[t].required && + (!template[t].value || template[t].value === "") && + !reactFlowInstance + .getEdges() + .some( + (e) => + e.targetHandle.split("|")[1] === t && + e.targetHandle.split("|")[2] === n.id + ) + ? [ + `${type} is missing ${ + template.display_name + ? template.display_name + : snakeToNormalCase(template[t].name) + }.`, + ] + : [] + ), + [] as string[] + ); } + + function validateNodes() { + return reactFlowInstance + .getNodes() + .flatMap((n: NodeType) => validateNode(n)); + } + const ref = useRef(null); function sendMessage() { if (chatValue !== "") { - if (validateNodes()) { + let nodeValidationErrors = validateNodes(); + if (nodeValidationErrors.length === 0) { setLockChat(true); let message = chatValue; setChatValue(""); @@ -136,10 +159,8 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) { }); } else { setErrorData({ - title: "Error sending message", - list: [ - "Oops! Looks like you missed some required information. Please fill in all the required fields before continuing.", - ], + title: "Oops! Looks like you missed some required information:", + list: nodeValidationErrors, }); } } else {