Skip to content

Commit

Permalink
Merge pull request #177 from flatironinstitute/are-you-sure
Browse files Browse the repository at this point in the history
Confirm before unload if unsaved changes
  • Loading branch information
WardBrian authored Jul 30, 2024
2 parents c78aa2c + 17c3113 commit b76447b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
12 changes: 10 additions & 2 deletions gui/src/app/Project/ProjectContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { initialDataModel, ProjectDataModel } from "@SpCore/ProjectDataModel";
import {
initialDataModel,
modelHasUnsavedChanges,
ProjectDataModel,
} from "@SpCore/ProjectDataModel";
import {
fetchRemoteProject,
fromQueryParams,
Expand Down Expand Up @@ -47,9 +51,13 @@ const ProjectContextProvider: FunctionComponent<

useEffect(() => {
// as user reloads the page or closes the tab, save state to local storage
const handleBeforeUnload = () => {
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
const state = serializeProjectToLocalStorage(data);
localStorage.setItem("stan-playground-saved-state", state);
if (modelHasUnsavedChanges(data)) {
e.preventDefault();
e.returnValue = true; // legacy
}
};
window.addEventListener("beforeunload", handleBeforeUnload);

Expand Down
30 changes: 25 additions & 5 deletions gui/src/app/pages/HomePage/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { ProjectContext } from "@SpCore/ProjectContextProvider";
import { modelHasUnsavedChanges } from "@SpCore/ProjectDataModel";
import LoadProjectWindow from "@SpPages/LoadProjectWindow";
import SaveProjectWindow from "@SpPages/SaveProjectWindow";
import ModalWindow, { useModalWindow } from "@fi-sci/modal-window";
import { List, ListItem } from "@mui/material";
import Button from "@mui/material/Button";
import Divider from "@mui/material/Divider";
import Drawer from "@mui/material/Drawer";
import Link from "@mui/material/Link";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import Toolbar from "@mui/material/Toolbar";
import { FunctionComponent, useContext } from "react";
import { Link } from "react-router-dom";
import { FunctionComponent, useContext, useMemo } from "react";
import { useNavigate } from "react-router-dom";

type Sidebar = {
hasUnsavedChanges: boolean;
Expand All @@ -33,7 +36,12 @@ const Sidebar: FunctionComponent<Sidebar> = ({
collapsed,
}) => {
// note: this is close enough to pass in directly if we wish
const { update } = useContext(ProjectContext);
const { data, update } = useContext(ProjectContext);

const navigate = useNavigate();

const dataModified = useMemo(() => modelHasUnsavedChanges(data), [data]);

const {
visible: saveProjectVisible,
handleOpen: saveProjectOpen,
Expand Down Expand Up @@ -67,7 +75,19 @@ const Sidebar: FunctionComponent<Sidebar> = ({
<List>
{exampleLinks.map((example, i) => (
<ListItem key={i}>
<Link replace to={`?project=${example.link}`}>
<Link
component="button"
onClick={() => {
if (
!dataModified ||
window.confirm(
"Are you sure you want to load this example? This will overwrite your current project.",
)
) {
navigate(`?project=${example.link}`, { replace: true });
}
}}
>
{example.name}
</Link>
</ListItem>
Expand Down

0 comments on commit b76447b

Please sign in to comment.