diff --git a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx index 73331fb27..5d60f9fac 100644 --- a/src/frontend/src/components/headerComponent/components/menuBar/index.tsx +++ b/src/frontend/src/components/headerComponent/components/menuBar/index.tsx @@ -33,6 +33,7 @@ export const MenuBar = ({ const n = useFlowStore((state) => state.nodes); const navigate = useNavigate(); + const isBuilding = useFlowStore((state) => state.isBuilding); function handleAddFlow() { try { @@ -45,6 +46,15 @@ export const MenuBar = ({ } } + function printByBuildStatus() { + if (isBuilding) { + return "Building..."; + } else if (saveLoading) { + return "Saving..."; + } + return "Saved"; + } + return currentFlow ? (
diff --git a/src/frontend/src/components/newChatView/chatMessage/index.tsx b/src/frontend/src/components/newChatView/chatMessage/index.tsx index 9e40ee7a2..a3570c9aa 100644 --- a/src/frontend/src/components/newChatView/chatMessage/index.tsx +++ b/src/frontend/src/components/newChatView/chatMessage/index.tsx @@ -1,5 +1,5 @@ import Convert from "ansi-to-html"; -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import Markdown from "react-markdown"; import rehypeMathjax from "rehype-mathjax"; import remarkGfm from "remark-gfm"; @@ -23,208 +23,228 @@ export default function ChatMessage({ const template = chat.template; const [promptOpen, setPromptOpen] = useState(false); const chat_message = chat.message.toString(); + + useEffect(() => { + const element = document.getElementById("last-chat-message"); + if (element) { + setTimeout(() => { + element.scrollIntoView({ behavior: "smooth" }); + }, 200); + } + }, [lastMessage]); + return ( -
-
- {!chat.isSend ? ( -
-
- robot_image -
- {chat.sender_name} -
- ) : ( -
-
- male_technology -
- {chat.sender_name} -
+ <> +
- {!chat.isSend ? ( -
-
- {hidden && chat.thought && chat.thought !== "" && ( -
setHidden((prev) => !prev)} - className="form-modal-chat-icon-div" - > - +
+ {!chat.isSend ? ( +
+
+ robot_image
- )} - {chat.thought && chat.thought !== "" && !hidden && ( - setHidden((prev) => !prev)} - /> - )} - {chat.thought && chat.thought !== "" && !hidden &&

} -
-
-
- {useMemo( - () => - chat.message.toString() === "" && lockChat ? ( - - ) : ( - {chat.sender_name} +
+ ) : ( +
+
+ male_technology +
+ {chat.sender_name} +
+ )} +
+ {!chat.isSend ? ( +
+
+ {hidden && chat.thought && chat.thought !== "" && ( +
setHidden((prev) => !prev)} + className="form-modal-chat-icon-div" + > + +
+ )} + {chat.thought && chat.thought !== "" && !hidden && ( + setHidden((prev) => !prev)} + /> + )} + {chat.thought && chat.thought !== "" && !hidden &&

} +
+
+
+ {useMemo( + () => + chat.message.toString() === "" && lockChat ? ( + + ) : ( + {props.children}; - }, - code: ({ - node, - inline, - className, - children, - ...props - }) => { - if (children.length) { - if (children[0] === "▍") { - return ( - - ▍ - + components={{ + pre({ node, ...props }) { + return <>{props.children}; + }, + code: ({ + node, + inline, + className, + children, + ...props + }) => { + if (children.length) { + if (children[0] === "▍") { + return ( + + ▍ + + ); + } + + children[0] = (children[0] as string).replace( + "`▍`", + "▍" ); } - children[0] = (children[0] as string).replace( - "`▍`", - "▍" + const match = /language-(\w+)/.exec( + className || "" ); - } - const match = /language-(\w+)/.exec( - className || "" - ); - - return !inline ? ( - {}} - /> - ) : ( - - {children} - - ); - }, - }} - > - {chat_message} - - ), - [chat.message, chat_message] + return !inline ? ( + {}} + /> + ) : ( + + {children} + + ); + }, + }} + > + {chat_message} + + ), + [chat.message, chat_message] + )} +
+ {chat.files && ( +
+ {chat.files.map((file, index) => { + return ( +
+ +
+ ); + })} +
)}
- {chat.files && ( -
- {chat.files.map((file, index) => { - return ( -
- -
- ); - })} -
- )}
-
- ) : ( -
- {template ? ( - <> - - - {promptOpen - ? template?.split("\n")?.map((line, index) => { - const regex = /{([^}]+)}/g; - let match; - let parts: Array = []; - let lastIndex = 0; - while ((match = regex.exec(line)) !== null) { - // Push text up to the match - if (match.index !== lastIndex) { - parts.push(line.substring(lastIndex, match.index)); - } - // Push div with matched text - if (chat.message[match[1]]) { - parts.push( - - {chat.message[match[1]]} - - ); - } + ) : ( +
+ {template ? ( + <> + + + {promptOpen + ? template?.split("\n")?.map((line, index) => { + const regex = /{([^}]+)}/g; + let match; + let parts: Array = []; + let lastIndex = 0; + while ((match = regex.exec(line)) !== null) { + // Push text up to the match + if (match.index !== lastIndex) { + parts.push(line.substring(lastIndex, match.index)); + } + // Push div with matched text + if (chat.message[match[1]]) { + parts.push( + + {chat.message[match[1]]} + + ); + } - // Update last index - lastIndex = regex.lastIndex; - } - // Push text after the last match - if (lastIndex !== line.length) { - parts.push(line.substring(lastIndex)); - } - return

{parts}

; - }) - : chat.message.toString()} -
- - ) : ( - {chat.message.toString()} - )} -
- )} -
+ // Update last index + lastIndex = regex.lastIndex; + } + // Push text after the last match + if (lastIndex !== line.length) { + parts.push(line.substring(lastIndex)); + } + return

{parts}

; + }) + : chat.message.toString()} + + + ) : ( + {chat.message.toString()} + )} +
+ )} +
+
+ ); } diff --git a/src/frontend/src/controllers/API/api.tsx b/src/frontend/src/controllers/API/api.tsx index b659333a1..0942374e5 100644 --- a/src/frontend/src/controllers/API/api.tsx +++ b/src/frontend/src/controllers/API/api.tsx @@ -124,6 +124,7 @@ function ApiInterceptor() { if (error?.response?.status === 500) { const vertices = useFlowStore.getState().verticesBuild; useFlowStore.getState().updateBuildStatus(vertices, BuildStatus.BUILT); + useFlowStore.getState().setIsBuilding(false); } } diff --git a/src/frontend/src/stores/flowsManagerStore.ts b/src/frontend/src/stores/flowsManagerStore.ts index 3b4640b21..a65c686b4 100644 --- a/src/frontend/src/stores/flowsManagerStore.ts +++ b/src/frontend/src/stores/flowsManagerStore.ts @@ -83,7 +83,6 @@ const useFlowsManagerStore = create((set, get) => ({ if (saveTimeoutId) { clearTimeout(saveTimeoutId); } - set({ saveLoading: true }); // Set up a new timeout. saveTimeoutId = setTimeout(() => { if (get().currentFlow) { @@ -92,10 +91,11 @@ const useFlowsManagerStore = create((set, get) => ({ true ); } - }, 300); // Delay of 300ms. + set({ saveLoading: true }); + }, 1000); // Delay of 1000ms. }, saveFlow: (flow: FlowType, silent?: boolean) => { - set({ saveLoading: true }) + set({ saveLoading: true }); return new Promise((resolve, reject) => { updateFlowInDatabase(flow) .then((updatedFlow) => { @@ -117,7 +117,7 @@ const useFlowsManagerStore = create((set, get) => ({ //update tabs state resolve(); - set({ saveLoading: false }) + set({ saveLoading: false }); } }) .catch((err) => { diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts index 9d5c63387..f7e621b25 100644 --- a/src/frontend/src/utils/buildUtils.ts +++ b/src/frontend/src/utils/buildUtils.ts @@ -49,6 +49,7 @@ export async function buildVertices({ const verticesIds = vertices_layers.flat(); useFlowStore.getState().updateBuildStatus(verticesIds, BuildStatus.TO_BUILD); useFlowStore.getState().updateVerticesBuild(verticesIds); + useFlowStore.getState().setIsBuilding(true); // Set each vertex state to building const buildResults: Array = []; @@ -76,6 +77,7 @@ export async function buildVertices({ if (onBuildComplete) { const allNodesValid = buildResults.every((result) => result); onBuildComplete(allNodesValid); + useFlowStore.getState().setIsBuilding(false); } }