diff --git a/assets/js/src/form_editor/components/editor.jsx b/assets/js/src/form_editor/components/editor.jsx
index 6f23ca095a..16925266a9 100644
--- a/assets/js/src/form_editor/components/editor.jsx
+++ b/assets/js/src/form_editor/components/editor.jsx
@@ -14,6 +14,7 @@ import Header from './header.jsx';
import Sidebar from './sidebar.jsx';
import FormTitle from './form_title.jsx';
import Notices from './notices.jsx';
+import UnsavedChangesNotice from './unsaved_changes_notice.jsx';
import FormStyles from './form_styles.jsx';
// Editor settings - see @wordpress/block-editor/src/store/defaults.js
@@ -56,6 +57,7 @@ export default () => {
>
+
diff --git a/assets/js/src/form_editor/components/unsaved_changes_notice.jsx b/assets/js/src/form_editor/components/unsaved_changes_notice.jsx
new file mode 100644
index 0000000000..d43f4082f8
--- /dev/null
+++ b/assets/js/src/form_editor/components/unsaved_changes_notice.jsx
@@ -0,0 +1,28 @@
+import React, { useEffect } from 'react';
+import MailPoet from 'mailpoet';
+import { useSelect } from '@wordpress/data';
+
+function UnsavedChangesNotice() {
+ const hasUnsavedChanges = useSelect(
+ (sel) => sel('mailpoet-form-editor').hasUnsavedChanges(),
+ []
+ );
+
+ function onUnload(event) {
+ if (hasUnsavedChanges) {
+ event.returnValue = MailPoet.I18n.t('changesNotSaved'); // eslint-disable-line no-param-reassign
+ return event.returnValue;
+ }
+ return '';
+ }
+
+ useEffect(() => {
+ window.addEventListener('beforeunload', onUnload);
+
+ return () => window.removeEventListener('beforeunload', onUnload);
+ });
+
+ return (<>>);
+}
+
+export default UnsavedChangesNotice;
diff --git a/assets/js/src/form_editor/store/reducers/change_form_blocks.jsx b/assets/js/src/form_editor/store/reducers/change_form_blocks.jsx
index fcf4698041..0b1b474a40 100644
--- a/assets/js/src/form_editor/store/reducers/change_form_blocks.jsx
+++ b/assets/js/src/form_editor/store/reducers/change_form_blocks.jsx
@@ -7,6 +7,7 @@ export default (state, action) => {
};
return {
...newState,
+ hasUnsavedChanges: true,
formErrors: validateForm(newState.formData, newState.formBlocks),
};
};
diff --git a/assets/js/src/form_editor/store/reducers/change_form_name.jsx b/assets/js/src/form_editor/store/reducers/change_form_name.jsx
index 55637a413c..8ede578462 100644
--- a/assets/js/src/form_editor/store/reducers/change_form_name.jsx
+++ b/assets/js/src/form_editor/store/reducers/change_form_name.jsx
@@ -2,6 +2,7 @@ export default (state, action) => ({
...state,
formData: {
...state.formData,
+ hasUnsavedChanges: true,
name: action.name,
},
});
diff --git a/assets/js/src/form_editor/store/reducers/change_form_settings.jsx b/assets/js/src/form_editor/store/reducers/change_form_settings.jsx
index 81b50679e1..224d3b540c 100644
--- a/assets/js/src/form_editor/store/reducers/change_form_settings.jsx
+++ b/assets/js/src/form_editor/store/reducers/change_form_settings.jsx
@@ -10,6 +10,7 @@ export default (state, action) => {
};
return {
...newState,
+ hasUnsavedChanges: true,
formErrors: validateForm(newState.formData, newState.formBlocks),
};
};
diff --git a/assets/js/src/form_editor/store/reducers/change_form_styles.jsx b/assets/js/src/form_editor/store/reducers/change_form_styles.jsx
index e41fc7c001..47c779ddc5 100644
--- a/assets/js/src/form_editor/store/reducers/change_form_styles.jsx
+++ b/assets/js/src/form_editor/store/reducers/change_form_styles.jsx
@@ -3,5 +3,6 @@ export default (state, action) => ({
formData: {
...state.formData,
styles: action.styles,
+ hasUnsavedChanges: true,
},
});
diff --git a/assets/js/src/form_editor/store/reducers/save_form_done.jsx b/assets/js/src/form_editor/store/reducers/save_form_done.jsx
index 4eb48f5e21..a11233d8ba 100644
--- a/assets/js/src/form_editor/store/reducers/save_form_done.jsx
+++ b/assets/js/src/form_editor/store/reducers/save_form_done.jsx
@@ -11,6 +11,7 @@ export default (state) => {
return {
...state,
isFormSaving: false,
+ hasUnsavedChanges: false,
notices,
};
};
diff --git a/assets/js/src/form_editor/store/selectors.jsx b/assets/js/src/form_editor/store/selectors.jsx
index 29a54249de..edd7f739c0 100644
--- a/assets/js/src/form_editor/store/selectors.jsx
+++ b/assets/js/src/form_editor/store/selectors.jsx
@@ -62,4 +62,7 @@ export default {
getIsCustomFieldCreating(state) {
return state.isCustomFieldCreating;
},
+ hasUnsavedChanges(state) {
+ return state.hasUnsavedChanges;
+ },
};
diff --git a/assets/js/src/form_editor/store/store.jsx b/assets/js/src/form_editor/store/store.jsx
index 20daf4346b..f46229eee0 100644
--- a/assets/js/src/form_editor/store/store.jsx
+++ b/assets/js/src/form_editor/store/store.jsx
@@ -34,6 +34,7 @@ export default () => {
isCustomFieldSaving: false,
isCustomFieldCreating: false,
notices: [],
+ hasUnsavedChanges: false,
sidebar: {
activeTab: 'form',
openedPanels: ['basic-settings'],
diff --git a/views/form/editor.html b/views/form/editor.html
index 12e4e976d8..a5d75d13dc 100644
--- a/views/form/editor.html
+++ b/views/form/editor.html
@@ -31,6 +31,7 @@
<% block translations %>
<%= localize({
'addFormName': _x('Add form name', 'A placeholder for form name input'),
+ 'changesNotSaved': __('Your changes you made may not be saved'),
'form': __('Form'),
'formSettings': _x('Settings', 'A settings section heading'),
'customFieldSettings': _x('Custom field settings', 'A settings section heading'),