From caa75e565d80d17e63cb1945166f1c61e2055e81 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Wed, 15 Dec 2021 03:09:52 +1100 Subject: [PATCH] Show notice on save in site editor (#36897) * Show notice on save in site editor Co-authored-by: Kai Hao --- .../site-editor/multi-entity-saving.test.js | 18 +++++++-- .../components/entities-saved-states/index.js | 38 ++++++++++++++++--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js b/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js index 26ba4976a506b..0f965a15dbff4 100644 --- a/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js +++ b/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js @@ -27,7 +27,7 @@ describe( 'Multi-entity save flow', () => { const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`; const savePanelSelector = '.entities-saved-states__panel'; const closePanelButtonSelector = - '.editor-post-publish-panel__header-cancel-button button'; + '.editor-post-publish-panel__header-cancel-button button:not(:disabled)'; const createNewButtonSelector = '//button[contains(text(), "New template part")]'; @@ -158,7 +158,10 @@ describe( 'Multi-entity save flow', () => { await assertExistance( savePanelSelector, false ); // Close publish panel. - await page.click( closePanelButtonSelector ); + const closePanelButton = await page.waitForSelector( + closePanelButtonSelector + ); + await closePanelButton.click(); // Verify saving is disabled. const draftSaved = await page.waitForSelector( draftSavedSelector ); @@ -167,13 +170,22 @@ describe( 'Multi-entity save flow', () => { await assertExistance( saveA11ySelector, false ); await publishPost(); + // Wait for the success notice specifically for the published post. + // `publishPost()` has a similar check but it only checks for the + // existence of any snackbars. In this case, there's another "Site updated" + // notice which will be sufficient for that and thus creating a false-positive. + await page.waitForXPath( + '//*[@id="a11y-speak-polite"][contains(text(), "Post published")]' + ); // Update the post. await page.click( '.editor-post-title' ); await page.keyboard.type( '...more title!' ); // Verify update button is enabled. - const enabledSaveButton = await page.$( enabledSavePostSelector ); + const enabledSaveButton = await page.waitForSelector( + enabledSavePostSelector + ); expect( enabledSaveButton ).not.toBeNull(); // Verify multi-entity saving not enabled. await assertMultiSaveDisabled(); diff --git a/packages/editor/src/components/entities-saved-states/index.js b/packages/editor/src/components/entities-saved-states/index.js index ea5e4e5fa25ec..becb092165dda 100644 --- a/packages/editor/src/components/entities-saved-states/index.js +++ b/packages/editor/src/components/entities-saved-states/index.js @@ -14,6 +14,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { __experimentalUseDialog as useDialog } from '@wordpress/compose'; import { close as closeIcon } from '@wordpress/icons'; +import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies @@ -80,6 +81,10 @@ export default function EntitiesSavedStates( { close } ) { blockEditorStore ); + const { createSuccessNotice, createErrorNotice } = useDispatch( + noticesStore + ); + // To group entities by type. const partitionedSavables = groupBy( dirtyEntityRecords, 'name' ); @@ -139,6 +144,7 @@ export default function EntitiesSavedStates( { close } ) { close( entitiesToSave ); const siteItemsToSave = []; + const pendingSavedRecords = []; entitiesToSave.forEach( ( { kind, name, key, property } ) => { if ( 'root' === kind && 'site' === name ) { siteItemsToSave.push( property ); @@ -153,19 +159,39 @@ export default function EntitiesSavedStates( { close } ) { editEntityRecord( kind, name, key, { status: 'publish' } ); } - saveEditedEntityRecord( kind, name, key ); + pendingSavedRecords.push( + saveEditedEntityRecord( kind, name, key ) + ); } } ); if ( siteItemsToSave.length ) { - saveSpecifiedEntityEdits( - 'root', - 'site', - undefined, - siteItemsToSave + pendingSavedRecords.push( + saveSpecifiedEntityEdits( + 'root', + 'site', + undefined, + siteItemsToSave + ) ); } __unstableMarkLastChangeAsPersistent(); + + Promise.all( pendingSavedRecords ) + .then( ( values ) => { + if ( + values.some( ( value ) => typeof value === 'undefined' ) + ) { + createErrorNotice( __( 'Saving failed.' ) ); + } else { + createSuccessNotice( __( 'Site updated.' ), { + type: 'snackbar', + } ); + } + } ) + .catch( ( error ) => + createErrorNotice( `${ __( 'Saving failed.' ) } ${ error }` ) + ); }; // Explicitly define this with no argument passed. Using `close` on