From a4dc5381b2cf31c507cc32f9027f76bf00d61ccc Mon Sep 17 00:00:00 2001 From: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:50:12 -0300 Subject: [PATCH] feat: add build in progress modal when trying to exit (#3695) * Changed store to stop the isBuilding state as well * Create Build In Progress modal * Use blocker to stop if its building as well --- .../src/modals/buildInProgressModal/index.tsx | 26 +++++++ src/frontend/src/pages/FlowPage/index.tsx | 76 +++++++++++++------ src/frontend/src/stores/flowStore.ts | 1 + 3 files changed, 80 insertions(+), 23 deletions(-) create mode 100644 src/frontend/src/modals/buildInProgressModal/index.tsx diff --git a/src/frontend/src/modals/buildInProgressModal/index.tsx b/src/frontend/src/modals/buildInProgressModal/index.tsx new file mode 100644 index 000000000..359a6bfa5 --- /dev/null +++ b/src/frontend/src/modals/buildInProgressModal/index.tsx @@ -0,0 +1,26 @@ +import ConfirmationModal from "../confirmationModal"; + +export function BuildInProgressModal({ + onStopBuild, + onCancel, +}: { + onStopBuild: () => void; + onCancel: () => void; +}): JSX.Element { + return ( + + + The flow is currently building. Do you want to stop the build and exit? + + + ); +} diff --git a/src/frontend/src/pages/FlowPage/index.tsx b/src/frontend/src/pages/FlowPage/index.tsx index 6485692f0..3502ccebe 100644 --- a/src/frontend/src/pages/FlowPage/index.tsx +++ b/src/frontend/src/pages/FlowPage/index.tsx @@ -8,6 +8,7 @@ import { customStringify } from "@/utils/reactflowUtils"; import { useEffect } from "react"; import { useBlocker, useParams } from "react-router-dom"; import FlowToolbar from "../../components/chatComponent"; +import { BuildInProgressModal } from "../../modals/buildInProgressModal"; import { useDarkStore } from "../../stores/darkStore"; import useFlowStore from "../../stores/flowStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore"; @@ -23,7 +24,9 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element { customStringify(currentFlow) !== customStringify(currentSavedFlow) && (currentFlow?.data?.nodes?.length ?? 0) > 0; - const blocker = useBlocker(changesNotSaved); + const isBuilding = useFlowStore((state) => state.isBuilding); + const blocker = useBlocker(changesNotSaved || isBuilding); + const version = useDarkStore((state) => state.version); const setOnFlowPage = useFlowStore((state) => state.setOnFlowPage); const { id } = useParams(); @@ -41,13 +44,30 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element { const autoSaving = useFlowsManagerStore((state) => state.autoSaving); + const stopBuilding = useFlowStore((state) => state.stopBuilding); + const handleSave = () => { saveFlow().then(() => (blocker.proceed ? blocker.proceed() : null)); }; + const handleStopBuild = () => { + stopBuilding(); + if (blocker.proceed) blocker.proceed(); + }; + + const handleExit = () => { + if (isBuilding) { + // Do nothing, let the blocker handle it + } else if (changesNotSaved) { + if (blocker.proceed) blocker.proceed(); + } else { + navigate("/all"); + } + }; + useEffect(() => { const handleBeforeUnload = (event: BeforeUnloadEvent) => { - if (changesNotSaved) { + if (changesNotSaved || isBuilding) { event.preventDefault(); event.returnValue = ""; // Required for Chrome } @@ -58,7 +78,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element { return () => { window.removeEventListener("beforeunload", handleBeforeUnload); }; - }, [changesNotSaved, navigate]); + }, [changesNotSaved, isBuilding]); // Set flow tab id useEffect(() => { @@ -118,26 +138,36 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element { )} - {blocker.state === "blocked" && currentSavedFlow && ( - (blocker.reset ? blocker.reset() : null)} - onProceed={() => (blocker.proceed ? blocker.proceed() : null)} - flowName={currentSavedFlow.name} - unsavedChanges={changesNotSaved} - lastSaved={ - updatedAt - ? new Date(updatedAt).toLocaleString("en-US", { - hour: "numeric", - minute: "numeric", - second: "numeric", - month: "numeric", - day: "numeric", - }) - : undefined - } - autoSave={autoSaving} - /> + {blocker.state === "blocked" && ( + <> + {isBuilding && ( + blocker.reset?.()} + /> + )} + {!isBuilding && currentSavedFlow && ( + blocker.reset?.()} + onProceed={handleExit} + flowName={currentSavedFlow.name} + unsavedChanges={changesNotSaved} + lastSaved={ + updatedAt + ? new Date(updatedAt).toLocaleString("en-US", { + hour: "numeric", + minute: "numeric", + second: "numeric", + month: "numeric", + day: "numeric", + }) + : undefined + } + autoSave={autoSaving} + /> + )} + )} ); diff --git a/src/frontend/src/stores/flowStore.ts b/src/frontend/src/stores/flowStore.ts index ef9a637a4..184217d77 100644 --- a/src/frontend/src/stores/flowStore.ts +++ b/src/frontend/src/stores/flowStore.ts @@ -81,6 +81,7 @@ const useFlowStore = create((set, get) => ({ isBuilding: false, stopBuilding: () => { get().buildController.abort(); + set({ isBuilding: false }); }, isPending: true, setHasIO: (hasIO) => {