From 55f6a40341426ac8d836ed72ae526161cc8f9520 Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Fri, 12 May 2023 15:35:06 +1000 Subject: [PATCH 1/5] Directly save if only changing current context --- .../src/components/save-button/index.js | 5 +- .../src/components/save-hub/index.js | 138 +++++++++++++++--- .../src/components/save-hub/style.scss | 6 + .../edit-site/src/components/sidebar/index.js | 4 +- .../src/components/sidebar/style.scss | 7 - 5 files changed, 127 insertions(+), 33 deletions(-) diff --git a/packages/edit-site/src/components/save-button/index.js b/packages/edit-site/src/components/save-button/index.js index 0d78e32307797a..2b22713261755e 100644 --- a/packages/edit-site/src/components/save-button/index.js +++ b/packages/edit-site/src/components/save-button/index.js @@ -17,6 +17,7 @@ export default function SaveButton( { className = 'edit-site-save-button__button', variant = 'primary', showTooltip = true, + defaultLabel, icon, } ) { const { isDirty, isSaving, isSaveViewOpen } = useSelect( ( select ) => { @@ -39,9 +40,11 @@ export default function SaveButton( { const getLabel = () => { if ( disabled ) { - return __( 'Saved' ); + return __( 'No changes to save' ); } + if ( defaultLabel ) return defaultLabel; + if ( isPreviewingTheme() && isDirty ) { return __( 'Activate & Save' ); } else if ( isPreviewingTheme() ) { diff --git a/packages/edit-site/src/components/save-hub/index.js b/packages/edit-site/src/components/save-hub/index.js index 0c99cfd9d4d44c..7617ca475bf8d1 100644 --- a/packages/edit-site/src/components/save-hub/index.js +++ b/packages/edit-site/src/components/save-hub/index.js @@ -1,27 +1,50 @@ /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; -import { __experimentalHStack as HStack } from '@wordpress/components'; -import { sprintf, _n } from '@wordpress/i18n'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { Button, __experimentalHStack as HStack } from '@wordpress/components'; +import { __, sprintf, _n } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; import { check } from '@wordpress/icons'; +import { privateApis as routerPrivateApis } from '@wordpress/router'; +import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ import SaveButton from '../save-button'; import { isPreviewingTheme } from '../../utils/is-previewing-theme'; +import { unlock } from '../../private-apis'; + +const { useLocation } = unlock( routerPrivateApis ); + +const PUBLISH_ON_SAVE_ENTITIES = [ + { + kind: 'postType', + name: 'wp_navigation', + }, +]; export default function SaveHub() { - const { countUnsavedChanges, isDirty, isSaving } = useSelect( + const { params } = useLocation(); + + const { __unstableMarkLastChangeAsPersistent } = + useDispatch( blockEditorStore ); + + const { createSuccessNotice, createErrorNotice } = + useDispatch( noticesStore ); + + const { dirtyRecords, countUnsavedChanges, isDirty, isSaving } = useSelect( ( select ) => { const { __experimentalGetDirtyEntityRecords, isSavingEntityRecord, } = select( coreStore ); const dirtyEntityRecords = __experimentalGetDirtyEntityRecords(); + return { + dirtyRecords: dirtyEntityRecords, isDirty: dirtyEntityRecords.length > 0, isSaving: dirtyEntityRecords.some( ( record ) => isSavingEntityRecord( record.kind, record.name, record.key ) @@ -32,29 +55,100 @@ export default function SaveHub() { [] ); + const { + editEntityRecord, + saveEditedEntityRecord, + __experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits, + } = useDispatch( coreStore ); + const disabled = isSaving || ( ! isDirty && ! isPreviewingTheme() ); + // if we have only one unsaved change and it matches current context, we can show a more specific label + let dirtyLocal = null; + + if ( countUnsavedChanges === 1 ) { + // if we are on global styles + if ( params.path?.includes( 'wp_global_styles' ) ) { + dirtyLocal = dirtyRecords.find( + ( record ) => record.name === 'globalStyles' + ); + } + // if we are on pages + else if ( !! params.postType ) { + dirtyLocal = dirtyRecords.find( + ( record ) => + record.name === params.postType && + String( record.key ) === params.postId + ); + } + } + + const label = dirtyLocal + ? __( 'Save' ) + : sprintf( + // translators: %d: number of unsaved changes (number). + _n( + 'Review %d changeā€¦', + 'Review %d changesā€¦', + countUnsavedChanges + ), + countUnsavedChanges + ); + + const saveCurrentEntity = async () => { + if ( ! dirtyLocal ) return; + + const { kind, name, key, property } = dirtyLocal; + + try { + if ( 'root' === dirtyLocal.kind && 'site' === name ) { + await saveSpecifiedEntityEdits( 'root', 'site', undefined, [ + property, + ] ); + } else { + if ( + PUBLISH_ON_SAVE_ENTITIES.some( + ( typeToPublish ) => + typeToPublish.kind === kind && + typeToPublish.name === name + ) + ) { + editEntityRecord( kind, name, key, { status: 'publish' } ); + } + + await saveEditedEntityRecord( kind, name, key ); + } + + __unstableMarkLastChangeAsPersistent(); + + createSuccessNotice( __( 'Site updated.' ), { + type: 'snackbar', + } ); + } catch ( error ) { + createErrorNotice( `${ __( 'Saving failed.' ) } ${ error }` ); + } + }; + return ( - { isDirty && ( - - { sprintf( - // translators: %d: number of unsaved changes (number). - _n( - '%d unsaved change', - '%d unsaved changes', - countUnsavedChanges - ), - countUnsavedChanges - ) } - + { dirtyLocal ? ( + + ) : ( + ) } - ); } diff --git a/packages/edit-site/src/components/save-hub/style.scss b/packages/edit-site/src/components/save-hub/style.scss index 0b8fb9c510f7a9..5daefd70d896ff 100644 --- a/packages/edit-site/src/components/save-hub/style.scss +++ b/packages/edit-site/src/components/save-hub/style.scss @@ -1,9 +1,15 @@ .edit-site-save-hub { color: $gray-600; + border-top: 1px solid $gray-800; + flex-shrink: 0; + margin: 0; + padding: $canvas-padding; } .edit-site-save-hub__button { color: inherit; + width: 100%; + justify-content: center; &[aria-disabled="true"] { opacity: 1; diff --git a/packages/edit-site/src/components/sidebar/index.js b/packages/edit-site/src/components/sidebar/index.js index 9571d6b54b4039..88c633571df000 100644 --- a/packages/edit-site/src/components/sidebar/index.js +++ b/packages/edit-site/src/components/sidebar/index.js @@ -76,9 +76,7 @@ function Sidebar() { > -
- -
+ ); } diff --git a/packages/edit-site/src/components/sidebar/style.scss b/packages/edit-site/src/components/sidebar/style.scss index 08f6da48da6667..7f3188f5e3468b 100644 --- a/packages/edit-site/src/components/sidebar/style.scss +++ b/packages/edit-site/src/components/sidebar/style.scss @@ -8,13 +8,6 @@ } } -.edit-site-sidebar__footer { - border-top: 1px solid $gray-800; - flex-shrink: 0; - margin: 0 $canvas-padding; - padding: $canvas-padding 0; -} - .edit-site-sidebar__content.edit-site-sidebar__content { overflow-x: unset; } From 476b4e3628567bf37de36c3c78455c723bac20b7 Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Mon, 15 May 2023 07:49:07 +1000 Subject: [PATCH 2/5] change save button label --- packages/edit-site/src/components/save-button/index.js | 5 ++++- packages/edit-site/src/components/save-hub/index.js | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/save-button/index.js b/packages/edit-site/src/components/save-button/index.js index 2b22713261755e..d3ce3a3b37d083 100644 --- a/packages/edit-site/src/components/save-button/index.js +++ b/packages/edit-site/src/components/save-button/index.js @@ -40,7 +40,10 @@ export default function SaveButton( { const getLabel = () => { if ( disabled ) { - return __( 'No changes to save' ); + return __( 'Saved' ); + } + if ( isSaving ) { + return __( 'Saving' ); } if ( defaultLabel ) return defaultLabel; diff --git a/packages/edit-site/src/components/save-hub/index.js b/packages/edit-site/src/components/save-hub/index.js index 7617ca475bf8d1..af977de34c30dc 100644 --- a/packages/edit-site/src/components/save-hub/index.js +++ b/packages/edit-site/src/components/save-hub/index.js @@ -83,7 +83,7 @@ export default function SaveHub() { } } - const label = dirtyLocal + let label = dirtyLocal ? __( 'Save' ) : sprintf( // translators: %d: number of unsaved changes (number). @@ -95,6 +95,10 @@ export default function SaveHub() { countUnsavedChanges ); + if ( isSaving ) { + label = __( 'Saving' ); + } + const saveCurrentEntity = async () => { if ( ! dirtyLocal ) return; @@ -136,6 +140,7 @@ export default function SaveHub() { variant="primary" onClick={ saveCurrentEntity } isBusy={ isSaving } + aria-disabled={ isSaving } className="edit-site-save-hub__button" > { label } From 2db3dcf51ccd50cba6662a57a9f96e06fd9846b0 Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Mon, 15 May 2023 10:59:53 +1000 Subject: [PATCH 3/5] save button label updating --- packages/edit-site/src/components/save-button/index.js | 6 +++--- packages/edit-site/src/components/save-hub/index.js | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/edit-site/src/components/save-button/index.js b/packages/edit-site/src/components/save-button/index.js index d3ce3a3b37d083..01a8972fc23315 100644 --- a/packages/edit-site/src/components/save-button/index.js +++ b/packages/edit-site/src/components/save-button/index.js @@ -39,12 +39,12 @@ export default function SaveButton( { const disabled = isSaving || ! activateSaveEnabled; const getLabel = () => { - if ( disabled ) { - return __( 'Saved' ); - } if ( isSaving ) { return __( 'Saving' ); } + if ( disabled ) { + return __( 'Saved' ); + } if ( defaultLabel ) return defaultLabel; diff --git a/packages/edit-site/src/components/save-hub/index.js b/packages/edit-site/src/components/save-hub/index.js index af977de34c30dc..3e8163588497ec 100644 --- a/packages/edit-site/src/components/save-hub/index.js +++ b/packages/edit-site/src/components/save-hub/index.js @@ -140,6 +140,7 @@ export default function SaveHub() { variant="primary" onClick={ saveCurrentEntity } isBusy={ isSaving } + disabled={ isSaving } aria-disabled={ isSaving } className="edit-site-save-hub__button" > @@ -150,7 +151,7 @@ export default function SaveHub() { className="edit-site-save-hub__button" variant={ disabled ? null : 'primary' } showTooltip={ false } - icon={ disabled ? check : null } + icon={ disabled && ! isSaving ? check : null } defaultLabel={ label } /> ) } From 0c25a0d0a0ccef436531dd80c29388115a6b5beb Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Wed, 24 May 2023 16:01:39 +1000 Subject: [PATCH 4/5] update to check postId for save hub --- packages/edit-site/src/components/save-hub/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/save-hub/index.js b/packages/edit-site/src/components/save-hub/index.js index 3e8163588497ec..8d06585cf38595 100644 --- a/packages/edit-site/src/components/save-hub/index.js +++ b/packages/edit-site/src/components/save-hub/index.js @@ -74,7 +74,7 @@ export default function SaveHub() { ); } // if we are on pages - else if ( !! params.postType ) { + else if ( !! params.postId ) { dirtyLocal = dirtyRecords.find( ( record ) => record.name === params.postType && From c052b14d8ef51f7eb705f0f8f5af7a4442dbe79b Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Tue, 6 Jun 2023 14:29:45 +1000 Subject: [PATCH 5/5] refactored save hub logic --- .../src/components/save-hub/index.js | 91 ++++++++++--------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/packages/edit-site/src/components/save-hub/index.js b/packages/edit-site/src/components/save-hub/index.js index 8d06585cf38595..4b4d1c92442a16 100644 --- a/packages/edit-site/src/components/save-hub/index.js +++ b/packages/edit-site/src/components/save-hub/index.js @@ -35,25 +35,49 @@ export default function SaveHub() { const { createSuccessNotice, createErrorNotice } = useDispatch( noticesStore ); - const { dirtyRecords, countUnsavedChanges, isDirty, isSaving } = useSelect( - ( select ) => { - const { - __experimentalGetDirtyEntityRecords, - isSavingEntityRecord, - } = select( coreStore ); - const dirtyEntityRecords = __experimentalGetDirtyEntityRecords(); - - return { - dirtyRecords: dirtyEntityRecords, - isDirty: dirtyEntityRecords.length > 0, - isSaving: dirtyEntityRecords.some( ( record ) => - isSavingEntityRecord( record.kind, record.name, record.key ) - ), - countUnsavedChanges: dirtyEntityRecords.length, - }; - }, - [] - ); + const { dirtyCurrentEntity, countUnsavedChanges, isDirty, isSaving } = + useSelect( + ( select ) => { + const { + __experimentalGetDirtyEntityRecords, + isSavingEntityRecord, + } = select( coreStore ); + const dirtyEntityRecords = + __experimentalGetDirtyEntityRecords(); + let calcDirtyCurrentEntity = null; + + if ( dirtyEntityRecords.length === 1 ) { + // if we are on global styles + if ( params.path?.includes( 'wp_global_styles' ) ) { + calcDirtyCurrentEntity = dirtyEntityRecords.find( + ( record ) => record.name === 'globalStyles' + ); + } + // if we are on pages + else if ( params.postId ) { + calcDirtyCurrentEntity = dirtyEntityRecords.find( + ( record ) => + record.name === params.postType && + String( record.key ) === params.postId + ); + } + } + + return { + dirtyCurrentEntity: calcDirtyCurrentEntity, + isDirty: dirtyEntityRecords.length > 0, + isSaving: dirtyEntityRecords.some( ( record ) => + isSavingEntityRecord( + record.kind, + record.name, + record.key + ) + ), + countUnsavedChanges: dirtyEntityRecords.length, + }; + }, + [ params.path, params.postType, params.postId ] + ); const { editEntityRecord, @@ -64,26 +88,7 @@ export default function SaveHub() { const disabled = isSaving || ( ! isDirty && ! isPreviewingTheme() ); // if we have only one unsaved change and it matches current context, we can show a more specific label - let dirtyLocal = null; - - if ( countUnsavedChanges === 1 ) { - // if we are on global styles - if ( params.path?.includes( 'wp_global_styles' ) ) { - dirtyLocal = dirtyRecords.find( - ( record ) => record.name === 'globalStyles' - ); - } - // if we are on pages - else if ( !! params.postId ) { - dirtyLocal = dirtyRecords.find( - ( record ) => - record.name === params.postType && - String( record.key ) === params.postId - ); - } - } - - let label = dirtyLocal + let label = dirtyCurrentEntity ? __( 'Save' ) : sprintf( // translators: %d: number of unsaved changes (number). @@ -100,12 +105,12 @@ export default function SaveHub() { } const saveCurrentEntity = async () => { - if ( ! dirtyLocal ) return; + if ( ! dirtyCurrentEntity ) return; - const { kind, name, key, property } = dirtyLocal; + const { kind, name, key, property } = dirtyCurrentEntity; try { - if ( 'root' === dirtyLocal.kind && 'site' === name ) { + if ( 'root' === dirtyCurrentEntity.kind && 'site' === name ) { await saveSpecifiedEntityEdits( 'root', 'site', undefined, [ property, ] ); @@ -135,7 +140,7 @@ export default function SaveHub() { return ( - { dirtyLocal ? ( + { dirtyCurrentEntity ? (