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) => {