diff --git a/web/src/components/tree.tsx b/web/src/components/tree.tsx
index c154d76..1e3f4b0 100644
--- a/web/src/components/tree.tsx
+++ b/web/src/components/tree.tsx
@@ -33,7 +33,7 @@ const TreeView = ({
diff --git a/web/src/containers/Studio/editor.tsx b/web/src/containers/Studio/editor.tsx
index f206f69..6a8b819 100644
--- a/web/src/containers/Studio/editor.tsx
+++ b/web/src/containers/Studio/editor.tsx
@@ -39,6 +39,8 @@ import FilePathInputModal from '../../components/filePathInputModal'
import BootstrapSnackbar, { AlertSeverityType } from '../../components/snackbar'
import Modal from '../../components/modal'
+import usePrompt from '../../utils/usePrompt'
+
const StyledTabPanel = styled(TabPanel)(() => ({
padding: '10px'
}))
@@ -98,6 +100,11 @@ const SASjsEditor = ({
diffEditorRef.current = diffEditor
}
+ usePrompt(
+ 'Changes you made may not be saved.',
+ prevFileContent !== fileContent
+ )
+
useEffect(() => {
setRunTimes(Object.values(appContext.runTimes))
}, [appContext.runTimes])
diff --git a/web/src/utils/usePrompt.ts b/web/src/utils/usePrompt.ts
new file mode 100644
index 0000000..8c2676c
--- /dev/null
+++ b/web/src/utils/usePrompt.ts
@@ -0,0 +1,36 @@
+import { useEffect, useCallback, useContext } from 'react'
+import { UNSAFE_NavigationContext as NavigationContext } from 'react-router-dom'
+import { History, Blocker, Transition } from 'history'
+
+function useBlocker(blocker: Blocker, when = true) {
+ const navigator = useContext(NavigationContext).navigator as History
+
+ useEffect(() => {
+ if (!when) return
+
+ const unblock = navigator.block((tx: Transition) => {
+ const autoUnblockingTx = {
+ ...tx,
+ retry() {
+ unblock()
+ tx.retry()
+ }
+ }
+
+ blocker(autoUnblockingTx)
+ })
+
+ return unblock
+ }, [navigator, blocker, when])
+}
+
+export default function usePrompt(message: string, when = true) {
+ const blocker = useCallback(
+ (tx) => {
+ if (window.confirm(message)) tx.retry()
+ },
+ [message]
+ )
+
+ useBlocker(blocker, when)
+}