From 969393a06c8eb25471770d45598cf0ae76992ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20Szab=C3=B3?= Date: Thu, 20 Aug 2020 16:25:56 +0200 Subject: [PATCH] [Feature] Alert when trying to leave the Site Editor with unsaved changes (#24659) If we are trying to navigate away after making changes in the Site Editor, then we show an alert. Same way as we do in the Post Editor. Refactored `UnsavedChangesWarning` to accept a prop. This way we can decouple it from the Post Editor and use it for the Site Editor as well. --- .../edit-post/src/components/layout/index.js | 4 +++- .../edit-site/src/components/editor/index.js | 7 ++++++- packages/editor/CHANGELOG.md | 4 ++++ .../components/unsaved-changes-warning/index.js | 17 +++++++---------- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 9f5831b37de42e..edcd4d1a3b77ad 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -86,6 +86,7 @@ function Layout() { hasBlockSelected, showMostUsedBlocks, isInserterOpened, + isEditedPostDirty, } = useSelect( ( select ) => { return { hasFixedToolbar: select( 'core/edit-post' ).isFeatureActive( @@ -115,6 +116,7 @@ function Layout() { nextShortcut: select( 'core/keyboard-shortcuts' ).getAllShortcutRawKeyCombinations( 'core/edit-post/next-region' ), + isEditedPostDirty: select( 'core/editor' ).isEditedPostDirty, }; }, [] ); const className = classnames( 'edit-post-layout', 'is-mode-' + mode, { @@ -159,7 +161,7 @@ function Layout() { <> - + diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 041af86150bbad..8e2ff8f4d83d11 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -25,7 +25,7 @@ import { InterfaceSkeleton, ComplementaryArea, } from '@wordpress/interface'; -import { EntitiesSavedStates } from '@wordpress/editor'; +import { EntitiesSavedStates, UnsavedChangesWarning } from '@wordpress/editor'; import { __ } from '@wordpress/i18n'; import { PluginArea } from '@wordpress/plugins'; import { close } from '@wordpress/icons'; @@ -57,7 +57,9 @@ function Editor() { page, template, select, + hasDirtyEntityRecords, } = useSelect( ( _select ) => { + const { __experimentalGetDirtyEntityRecords } = _select( 'core' ); const { isFeatureActive, __experimentalGetPreviewDeviceType, @@ -96,6 +98,8 @@ function Editor() { : null, select: _select, entityId: _entityId, + hasDirtyEntityRecords: () => + __experimentalGetDirtyEntityRecords().length > 0, }; }, [] ); const { editEntityRecord } = useDispatch( 'core' ); @@ -159,6 +163,7 @@ function Editor() { <> + diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index db88795795497d..83b2801313d16e 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Change + +- The `UnsavedChangesWarning` component now accepts a required `isDirty` prop. Making it less tightly coupled so we can reuse it for site editing. + ## 9.4.0 (2019-06-12) ### Deprecations diff --git a/packages/editor/src/components/unsaved-changes-warning/index.js b/packages/editor/src/components/unsaved-changes-warning/index.js index 4a39c28e881719..03f30b6a151cbb 100644 --- a/packages/editor/src/components/unsaved-changes-warning/index.js +++ b/packages/editor/src/components/unsaved-changes-warning/index.js @@ -3,7 +3,6 @@ */ import { __ } from '@wordpress/i18n'; import { Component } from '@wordpress/element'; -import { withSelect } from '@wordpress/data'; class UnsavedChangesWarning extends Component { constructor() { @@ -27,9 +26,13 @@ class UnsavedChangesWarning extends Component { * @return {?string} Warning prompt message, if unsaved changes exist. */ warnIfUnsavedChanges( event ) { - const { isEditedPostDirty } = this.props; + const { isDirty } = this.props; - if ( isEditedPostDirty() ) { + // We need to call the selector directly in the listener to avoid race + // conditions with `BrowserURL` where `componentDidUpdate` gets the + // new value of `isEditedPostDirty` before this component does, + // causing this component to incorrectly think a trashed post is still dirty. + if ( isDirty() ) { event.returnValue = __( 'You have unsaved changes. If you proceed, they will be lost.' ); @@ -42,10 +45,4 @@ class UnsavedChangesWarning extends Component { } } -export default withSelect( ( select ) => ( { - // We need to call the selector directly in the listener to avoid race - // conditions with `BrowserURL` where `componentDidUpdate` gets the - // new value of `isEditedPostDirty` before this component does, - // causing this component to incorrectly think a trashed post is still dirty. - isEditedPostDirty: select( 'core/editor' ).isEditedPostDirty, -} ) )( UnsavedChangesWarning ); +export default UnsavedChangesWarning;