diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index e1e212e1019d1..b1d767284611f 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -968,10 +968,6 @@ _Returns_ Returns whether the pre-publish panel should be shown or skipped when the user clicks the "publish" button. -_Parameters_ - -- _state_ `Object`: Global application state. - _Returns_ - `boolean`: Whether the pre-publish panel should be shown or not. @@ -1049,11 +1045,7 @@ Action that creates an undo history record. ### disablePublishSidebar -Action that disables the publish sidebar. - -_Returns_ - -- `Object`: Action object +Disables the publish sidebar. ### editPost @@ -1067,11 +1059,7 @@ _Parameters_ ### enablePublishSidebar -Action that enables the publish sidebar. - -_Returns_ - -- `Object`: Action object +Enable the publish sidebar. ### enterFormattedText diff --git a/package-lock.json b/package-lock.json index 245a22583d7a8..a7039a2d554ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17688,6 +17688,7 @@ "@wordpress/keycodes": "file:packages/keycodes", "@wordpress/media-utils": "file:packages/media-utils", "@wordpress/notices": "file:packages/notices", + "@wordpress/preferences": "file:packages/preferences", "@wordpress/reusable-blocks": "file:packages/reusable-blocks", "@wordpress/rich-text": "file:packages/rich-text", "@wordpress/server-side-render": "file:packages/server-side-render", diff --git a/packages/data/src/plugins/persistence/index.js b/packages/data/src/plugins/persistence/index.js index 89f73737cc59a..f00f8a8fc2b18 100644 --- a/packages/data/src/plugins/persistence/index.js +++ b/packages/data/src/plugins/persistence/index.js @@ -300,9 +300,19 @@ export function migrateFeaturePreferencesToPreferencesStore( } } +/** + * Migrates an individual item inside the `preferences` object for a store. + * + * @param {Object} persistence The persistence interface. + * @param {Object} migrate An options object that contains details of the migration. + * @param {string} migrate.from The name of the store to migrate from. + * @param {string} migrate.scope The scope in the preferences store to migrate to. + * @param {string} key The key in the preferences object to migrate. + * @param {?Function} convert A function that converts preferences from one format to another. + */ export function migrateIndividualPreferenceToPreferencesStore( persistence, - sourceStoreName, + { from: sourceStoreName, scope }, key, convert = identity ) { @@ -311,14 +321,12 @@ export function migrateIndividualPreferenceToPreferencesStore( const sourcePreference = state[ sourceStoreName ]?.preferences?.[ key ]; // There's nothing to migrate, exit early. - if ( ! sourcePreference ) { + if ( sourcePreference === undefined ) { return; } const targetPreference = - state[ preferencesStoreName ]?.preferences?.[ sourceStoreName ]?.[ - key - ]; + state[ preferencesStoreName ]?.preferences?.[ scope ]?.[ key ]; // There's existing data at the target, so don't overwrite it, exit early. if ( targetPreference ) { @@ -327,7 +335,7 @@ export function migrateIndividualPreferenceToPreferencesStore( const otherScopes = state[ preferencesStoreName ]?.preferences; const otherPreferences = - state[ preferencesStoreName ]?.preferences?.[ sourceStoreName ]; + state[ preferencesStoreName ]?.preferences?.[ scope ]; // Pass an object with the key and value as this allows the convert // function to convert to a data structure that has different keys. @@ -336,7 +344,7 @@ export function migrateIndividualPreferenceToPreferencesStore( persistence.set( preferencesStoreName, { preferences: { ...otherScopes, - [ sourceStoreName ]: { + [ scope ]: { ...otherPreferences, ...convertedPreferences, }, @@ -602,28 +610,33 @@ persistencePlugin.__unstableMigrate = ( pluginOptions ) => { // Other ad-hoc preferences. migrateIndividualPreferenceToPreferencesStore( persistence, - 'core/edit-post', + { from: 'core/edit-post', scope: 'core/edit-post' }, 'hiddenBlockTypes' ); migrateIndividualPreferenceToPreferencesStore( persistence, - 'core/edit-post', + { from: 'core/edit-post', scope: 'core/edit-post' }, 'editorMode' ); migrateIndividualPreferenceToPreferencesStore( persistence, - 'core/edit-post', + { from: 'core/edit-post', scope: 'core/edit-post' }, 'preferredStyleVariations' ); migrateIndividualPreferenceToPreferencesStore( persistence, - 'core/edit-post', + { from: 'core/edit-post', scope: 'core/edit-post' }, 'panels', convertEditPostPanels ); migrateIndividualPreferenceToPreferencesStore( persistence, - 'core/edit-site', + { from: 'core/editor', scope: 'core/edit-post' }, + 'isPublishSidebarEnabled' + ); + migrateIndividualPreferenceToPreferencesStore( + persistence, + { from: 'core/edit-site', scope: 'core/edit-site' }, 'editorMode' ); migrateInterfaceEnableItemsToPreferencesStore( persistence ); diff --git a/packages/data/src/plugins/persistence/test/index.js b/packages/data/src/plugins/persistence/test/index.js index 0b2c7e9e3643d..9e442a63daa7e 100644 --- a/packages/data/src/plugins/persistence/test/index.js +++ b/packages/data/src/plugins/persistence/test/index.js @@ -694,7 +694,7 @@ describe( 'migrateIndividualPreferenceToPreferencesStore', () => { migrateIndividualPreferenceToPreferencesStore( persistenceInterface, - 'core/test', + { from: 'core/test', scope: 'core/test' }, 'myPreference' ); @@ -743,7 +743,7 @@ describe( 'migrateIndividualPreferenceToPreferencesStore', () => { migrateIndividualPreferenceToPreferencesStore( persistenceInterface, - 'core/test', + { from: 'core/test', scope: 'core/test' }, 'myPreference' ); @@ -771,6 +771,41 @@ describe( 'migrateIndividualPreferenceToPreferencesStore', () => { } ); } ); + it( 'supports moving data to a scope that is differently named to the source store', () => { + const persistenceInterface = createPersistenceInterface( { + storageKey: 'test-username', + } ); + + const initialState = { + preferences: { + myPreference: '123', + }, + }; + + persistenceInterface.set( 'core/source', initialState ); + + migrateIndividualPreferenceToPreferencesStore( + persistenceInterface, + { from: 'core/source', scope: 'core/destination' }, + 'myPreference' + ); + + expect( persistenceInterface.get() ).toEqual( { + 'core/preferences': { + preferences: { + 'core/destination': { + myPreference: '123', + }, + }, + }, + 'core/source': { + preferences: { + myPreference: undefined, + }, + }, + } ); + } ); + it( 'does not migrate data if there is already a matching preference key at the target', () => { const persistenceInterface = createPersistenceInterface( { storageKey: 'test-username', @@ -792,7 +827,7 @@ describe( 'migrateIndividualPreferenceToPreferencesStore', () => { migrateIndividualPreferenceToPreferencesStore( persistenceInterface, - 'core/test', + { from: 'core/test', scope: 'core/test' }, 'myPreference' ); @@ -811,6 +846,37 @@ describe( 'migrateIndividualPreferenceToPreferencesStore', () => { }, } ); } ); + + it( 'migrates preferences that have a `false` value', () => { + const persistenceInterface = createPersistenceInterface( { + storageKey: 'test-username', + } ); + + persistenceInterface.set( 'core/test', { + preferences: { + myFalsePreference: false, + }, + } ); + + migrateIndividualPreferenceToPreferencesStore( + persistenceInterface, + { from: 'core/test', scope: 'core/test' }, + 'myFalsePreference' + ); + + expect( persistenceInterface.get() ).toEqual( { + 'core/preferences': { + preferences: { + 'core/test': { + myFalsePreference: false, + }, + }, + }, + 'core/test': { + preferences: {}, + }, + } ); + } ); } ); describe( 'migrateThirdPartyFeaturePreferencesToPreferencesStore', () => { diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 3d3901f10a731..6ff6a7603d89f 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -112,6 +112,7 @@ export function initializeEditor( fullscreenMode: true, hiddenBlockTypes: [], inactivePanels: [], + isPublishSidebarEnabled: true, openPanels: [ 'post-status' ], preferredStyleVariations: {}, showBlockBreadcrumbs: true, diff --git a/packages/edit-post/src/index.native.js b/packages/edit-post/src/index.native.js index 48738bd68d8a7..b825d50ace0c0 100644 --- a/packages/edit-post/src/index.native.js +++ b/packages/edit-post/src/index.native.js @@ -27,6 +27,7 @@ export function initializeEditor( id, postType, postId ) { fullscreenMode: true, hiddenBlockTypes: [], inactivePanels: [], + isPublishSidebarEnabled: true, openPanels: [ 'post-status' ], preferredStyleVariations: {}, welcomeGuide: true, diff --git a/packages/editor/package.json b/packages/editor/package.json index 14dcdc1f2c0fa..a2f0798fcba20 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -50,6 +50,7 @@ "@wordpress/keycodes": "file:../keycodes", "@wordpress/media-utils": "file:../media-utils", "@wordpress/notices": "file:../notices", + "@wordpress/preferences": "file:../preferences", "@wordpress/reusable-blocks": "file:../reusable-blocks", "@wordpress/rich-text": "file:../rich-text", "@wordpress/server-side-render": "file:../server-side-render", diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index 02aceef3eaf9a..03e0a51186d9b 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -16,6 +16,7 @@ import { import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -320,26 +321,22 @@ export function updatePostLock( lock ) { } /** - * Action that enables the publish sidebar. - * - * @return {Object} Action object + * Enable the publish sidebar. */ -export function enablePublishSidebar() { - return { - type: 'ENABLE_PUBLISH_SIDEBAR', - }; -} +export const enablePublishSidebar = () => ( { registry } ) => { + registry + .dispatch( preferencesStore ) + .set( 'core/edit-post', 'isPublishSidebarEnabled', true ); +}; /** - * Action that disables the publish sidebar. - * - * @return {Object} Action object + * Disables the publish sidebar. */ -export function disablePublishSidebar() { - return { - type: 'DISABLE_PUBLISH_SIDEBAR', - }; -} +export const disablePublishSidebar = () => ( { registry } ) => { + registry + .dispatch( preferencesStore ) + .set( 'core/edit-post', 'isPublishSidebarEnabled', false ); +}; /** * Action that locks post saving. diff --git a/packages/editor/src/store/defaults.js b/packages/editor/src/store/defaults.js index a626bd7345693..66bcdc72dd8be 100644 --- a/packages/editor/src/store/defaults.js +++ b/packages/editor/src/store/defaults.js @@ -3,11 +3,6 @@ */ import { SETTINGS_DEFAULTS } from '@wordpress/block-editor'; -export const PREFERENCES_DEFAULTS = { - insertUsage: {}, // Should be kept for backward compatibility, see: https://github.com/WordPress/gutenberg/issues/14580. - isPublishSidebarEnabled: true, -}; - /** * The default post editor settings. * diff --git a/packages/editor/src/store/index.js b/packages/editor/src/store/index.js index a9a3ec8cfdada..baee4d9197d0c 100644 --- a/packages/editor/src/store/index.js +++ b/packages/editor/src/store/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { createReduxStore, registerStore } from '@wordpress/data'; +import { createReduxStore, register } from '@wordpress/data'; /** * Internal dependencies @@ -33,12 +33,6 @@ export const storeConfig = { */ export const store = createReduxStore( STORE_NAME, { ...storeConfig, - persist: [ 'preferences' ], } ); -// Once we build a more generic persistence plugin that works across types of stores -// we'd be able to replace this with a register call. -registerStore( STORE_NAME, { - ...storeConfig, - persist: [ 'preferences' ], -} ); +register( store ); diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index fc5be10508bd4..7567c4189254a 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -11,7 +11,7 @@ import { combineReducers } from '@wordpress/data'; /** * Internal dependencies */ -import { PREFERENCES_DEFAULTS, EDITOR_SETTINGS_DEFAULTS } from './defaults'; +import { EDITOR_SETTINGS_DEFAULTS } from './defaults'; /** * Returns a post attribute value, flattening nested rendered content using its @@ -119,32 +119,6 @@ export function template( state = { isValid: true }, action ) { return state; } -/** - * Reducer returning the user preferences. - * - * @param {Object} state Current state. - * @param {Object} action Dispatched action. - * - * @return {string} Updated state. - */ -export function preferences( state = PREFERENCES_DEFAULTS, action ) { - switch ( action.type ) { - case 'ENABLE_PUBLISH_SIDEBAR': - return { - ...state, - isPublishSidebarEnabled: true, - }; - - case 'DISABLE_PUBLISH_SIDEBAR': - return { - ...state, - isPublishSidebarEnabled: false, - }; - } - - return state; -} - /** * Reducer returning current network request state (whether a request to * the WP REST API is in progress, successful, or failed). @@ -282,7 +256,6 @@ export function editorSettings( state = EDITOR_SETTINGS_DEFAULTS, action ) { export default combineReducers( { postId, postType, - preferences, saving, postLock, template, diff --git a/packages/editor/src/store/reducer.native.js b/packages/editor/src/store/reducer.native.js index b3d7e8e435b5a..991addd88620b 100644 --- a/packages/editor/src/store/reducer.native.js +++ b/packages/editor/src/store/reducer.native.js @@ -9,7 +9,6 @@ import { combineReducers } from '@wordpress/data'; import { postId, postType, - preferences, saving, postLock, postSavingLock, @@ -84,7 +83,6 @@ export default combineReducers( { postId, postType, postTitle, - preferences, saving, postLock, postSavingLock, diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index db452ecf23130..8915197dc2932 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -20,11 +20,11 @@ import { Platform } from '@wordpress/element'; import { layout } from '@wordpress/icons'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies */ -import { PREFERENCES_DEFAULTS } from './defaults'; import { EDIT_MERGE_PROPERTIES, PERMALINK_POSTNAME_REGEX, @@ -1093,16 +1093,15 @@ export function canUserUseUnfilteredHTML( state ) { * Returns whether the pre-publish panel should be shown * or skipped when the user clicks the "publish" button. * - * @param {Object} state Global application state. - * * @return {boolean} Whether the pre-publish panel should be shown or not. */ -export function isPublishSidebarEnabled( state ) { - if ( state.preferences.hasOwnProperty( 'isPublishSidebarEnabled' ) ) { - return state.preferences.isPublishSidebarEnabled; - } - return PREFERENCES_DEFAULTS.isPublishSidebarEnabled; -} +export const isPublishSidebarEnabled = createRegistrySelector( + ( select ) => () => + !! select( preferencesStore ).get( + 'core/edit-post', + 'isPublishSidebarEnabled' + ) +); /** * Return the current block list. diff --git a/packages/editor/src/store/test/actions.js b/packages/editor/src/store/test/actions.js index 7f2357964404f..ee223c09f3965 100644 --- a/packages/editor/src/store/test/actions.js +++ b/packages/editor/src/store/test/actions.js @@ -6,6 +6,7 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; import { createRegistry } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; +import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -46,6 +47,7 @@ function createRegistryWithStores() { registry.register( coreStore ); registry.register( editorStore ); registry.register( noticesStore ); + registry.register( preferencesStore ); // Register post type entity. registry.dispatch( coreStore ).addEntities( [ postTypeConfig ] ); @@ -349,4 +351,39 @@ describe( 'Editor actions', () => { } ); } ); } ); + + describe( 'enablePublishSidebar', () => { + it( 'enables the publish sidebar', () => { + const registry = createRegistryWithStores(); + + // Starts off as `undefined` as a default hasn't been set. + expect( + registry.select( editorStore ).isPublishSidebarEnabled() + ).toBe( false ); + + registry.dispatch( editorStore ).enablePublishSidebar(); + + expect( + registry.select( editorStore ).isPublishSidebarEnabled() + ).toBe( true ); + } ); + } ); + + describe( 'disablePublishSidebar', () => { + it( 'disables the publish sidebar', () => { + const registry = createRegistryWithStores(); + + // Enable it to start with so that can test it flipping from `true` to `false`. + registry.dispatch( editorStore ).enablePublishSidebar(); + expect( + registry.select( editorStore ).isPublishSidebarEnabled() + ).toBe( true ); + + registry.dispatch( editorStore ).disablePublishSidebar(); + + expect( + registry.select( editorStore ).isPublishSidebarEnabled() + ).toBe( false ); + } ); + } ); } ); diff --git a/packages/editor/src/store/test/reducer.js b/packages/editor/src/store/test/reducer.js index d06b90dd672fe..3b0ea9d3340a1 100644 --- a/packages/editor/src/store/test/reducer.js +++ b/packages/editor/src/store/test/reducer.js @@ -11,7 +11,6 @@ import { isUpdatingSamePostProperty, shouldOverwriteState, getPostRawValue, - preferences, saving, postSavingLock, postAutosavingLock, @@ -163,36 +162,6 @@ describe( 'state', () => { } ); } ); - describe( 'preferences()', () => { - it( 'should apply all defaults', () => { - const state = preferences( undefined, {} ); - expect( state ).toEqual( { - insertUsage: {}, - isPublishSidebarEnabled: true, - } ); - } ); - - it( 'should disable the publish sidebar', () => { - const original = deepFreeze( preferences( undefined, {} ) ); - const state = preferences( original, { - type: 'DISABLE_PUBLISH_SIDEBAR', - } ); - - expect( state.isPublishSidebarEnabled ).toBe( false ); - } ); - - it( 'should enable the publish sidebar', () => { - const original = deepFreeze( - preferences( { isPublishSidebarEnabled: false }, {} ) - ); - const state = preferences( original, { - type: 'ENABLE_PUBLISH_SIDEBAR', - } ); - - expect( state.isPublishSidebarEnabled ).toBe( true ); - } ); - } ); - describe( 'saving()', () => { it( 'should update when a request is started', () => { const state = saving( null, { diff --git a/packages/editor/src/store/test/selectors.js b/packages/editor/src/store/test/selectors.js index 3bbdc27e6e352..ef0ba07e720c6 100644 --- a/packages/editor/src/store/test/selectors.js +++ b/packages/editor/src/store/test/selectors.js @@ -22,7 +22,6 @@ import { layout, footer, header } from '@wordpress/icons'; * Internal dependencies */ import * as _selectors from '../selectors'; -import { PREFERENCES_DEFAULTS } from '../defaults'; const selectors = { ..._selectors }; const selectorNames = Object.keys( selectors ); @@ -182,7 +181,6 @@ const { didPostSaveRequestFail, getSuggestedPostFormat, getEditedPostContent, - isPublishSidebarEnabled, isPermalinkEditable, getPermalink, getPermalinkParts, @@ -2570,39 +2568,6 @@ describe( 'selectors', () => { } ); } ); - describe( 'isPublishSidebarEnabled', () => { - it( 'should return the value on state if it is thruthy', () => { - const state = { - preferences: { - isPublishSidebarEnabled: true, - }, - }; - expect( isPublishSidebarEnabled( state ) ).toBe( - state.preferences.isPublishSidebarEnabled - ); - } ); - - it( 'should return the value on state if it is falsy', () => { - const state = { - preferences: { - isPublishSidebarEnabled: false, - }, - }; - expect( isPublishSidebarEnabled( state ) ).toBe( - state.preferences.isPublishSidebarEnabled - ); - } ); - - it( 'should return the default value if there is no isPublishSidebarEnabled key on state', () => { - const state = { - preferences: {}, - }; - expect( isPublishSidebarEnabled( state ) ).toBe( - PREFERENCES_DEFAULTS.isPublishSidebarEnabled - ); - } ); - } ); - describe( 'isPermalinkEditable', () => { it( 'should be false if there is no permalink', () => { const state = {