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'),