Skip to content

Commit

Permalink
feat: add build in progress modal when trying to exit (#3695)
Browse files Browse the repository at this point in the history
* Changed store to stop the isBuilding state as well

* Create Build In Progress modal

* Use blocker to stop if its building as well
  • Loading branch information
lucaseduoli authored Sep 5, 2024
1 parent 46a66a5 commit a4dc538
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 23 deletions.
26 changes: 26 additions & 0 deletions src/frontend/src/modals/buildInProgressModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ConfirmationModal from "../confirmationModal";

export function BuildInProgressModal({
onStopBuild,
onCancel,
}: {
onStopBuild: () => void;
onCancel: () => void;
}): JSX.Element {
return (
<ConfirmationModal
open={true}
onClose={onCancel}
title="Build in Progress"
cancelText="Cancel"
confirmationText="Stop Build"
onConfirm={onStopBuild}
onCancel={onCancel}
size="x-small"
>
<ConfirmationModal.Content>
The flow is currently building. Do you want to stop the build and exit?
</ConfirmationModal.Content>
</ConfirmationModal>
);
}
76 changes: 53 additions & 23 deletions src/frontend/src/pages/FlowPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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();
Expand All @@ -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
}
Expand All @@ -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(() => {
Expand Down Expand Up @@ -118,26 +138,36 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
</a>
)}
</div>
{blocker.state === "blocked" && currentSavedFlow && (
<SaveChangesModal
onSave={handleSave}
onCancel={() => (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 && (
<BuildInProgressModal
onStopBuild={handleStopBuild}
onCancel={() => blocker.reset?.()}
/>
)}
{!isBuilding && currentSavedFlow && (
<SaveChangesModal
onSave={handleSave}
onCancel={() => 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}
/>
)}
</>
)}
</>
);
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/stores/flowStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
isBuilding: false,
stopBuilding: () => {
get().buildController.abort();
set({ isBuilding: false });
},
isPending: true,
setHasIO: (hasIO) => {
Expand Down

0 comments on commit a4dc538

Please sign in to comment.