From cbec06145257224771cb56ee9c98a432d8f07c05 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 12 Dec 2022 10:27:20 +0100 Subject: [PATCH] Synchronize the sidebar state in the url (#46433) --- .../data/data-core-edit-site.md | 41 ++++++++---- .../src/components/block-editor/index.js | 14 ++-- .../edit-site/src/components/editor/index.js | 30 ++++----- .../src/components/navigate-to-link/index.js | 10 +-- .../edit-site/src/components/sidebar/index.js | 17 ++++- .../use-init-edited-entity-from-url.js} | 2 + .../use-sync-sidebar-path-with-url.js | 36 +++++++++++ packages/edit-site/src/store/actions.js | 64 +++++++++++-------- packages/edit-site/src/store/reducer.js | 33 ++-------- packages/edit-site/src/store/selectors.js | 36 +++++++---- packages/edit-site/src/store/test/actions.js | 18 +----- packages/edit-site/src/store/test/reducer.js | 49 +++----------- .../edit-site/src/store/test/selectors.js | 23 +------ 13 files changed, 183 insertions(+), 190 deletions(-) rename packages/edit-site/src/components/{use-init-edited-entity-from-url/index.js => sync-state-with-url/use-init-edited-entity-from-url.js} (82%) create mode 100644 packages/edit-site/src/components/sync-state-with-url/use-sync-sidebar-path-with-url.js diff --git a/docs/reference-guides/data/data-core-edit-site.md b/docs/reference-guides/data/data-core-edit-site.md index 6577ae72575ffe..53fd4d138383ae 100644 --- a/docs/reference-guides/data/data-core-edit-site.md +++ b/docs/reference-guides/data/data-core-edit-site.md @@ -34,6 +34,20 @@ _Returns_ - `Array`: Template parts and their blocks in an array. +### getEditedPostContext + +> **Deprecated** + +Returns the edited post's context object. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `Object`: Page. + ### getEditedPostId Returns the ID of the currently edited template or template part. @@ -72,15 +86,7 @@ _Returns_ ### getHomeTemplateId -Returns the current home template ID. - -_Parameters_ - -- _state_ `Object`: Global application state. - -_Returns_ - -- `number?`: Home template ID. +> **Deprecated** ### getNavigationPanelActiveMenu @@ -88,6 +94,8 @@ _Returns_ ### getPage +> **Deprecated** + Returns the current page object. _Parameters_ @@ -230,14 +238,21 @@ _Parameters_ - _options_ `[Object]`: - _options.allowUndo_ `[boolean]`: Whether to allow the user to undo reverting the template. Default true. -### setHomeTemplateId +### setEditedPostContext -Action that sets the home template ID to the template ID of the page resolved -from a given path. +Set's the current block editor context. _Parameters_ -- _homeTemplateId_ `number`: The template ID for the homepage. +- _context_ `Object`: The context object. + +_Returns_ + +- `number`: The resolved template ID for the page route. + +### setHomeTemplateId + +> **Deprecated** ### setIsInserterOpened diff --git a/packages/edit-site/src/components/block-editor/index.js b/packages/edit-site/src/components/block-editor/index.js index 4dbebdf1ea8bb7..0f39f771a5d360 100644 --- a/packages/edit-site/src/components/block-editor/index.js +++ b/packages/edit-site/src/components/block-editor/index.js @@ -56,19 +56,14 @@ const LAYOUT = { }; export default function BlockEditor( { setIsInserterOpen } ) { - const { storedSettings, templateType, page, canvasMode } = useSelect( + const { storedSettings, templateType, canvasMode } = useSelect( ( select ) => { - const { - getSettings, - getEditedPostType, - getPage, - __unstableGetCanvasMode, - } = select( editSiteStore ); + const { getSettings, getEditedPostType, __unstableGetCanvasMode } = + select( editSiteStore ); return { storedSettings: getSettings( setIsInserterOpen ), templateType: getEditedPostType(), - page: getPage(), canvasMode: __unstableGetCanvasMode(), }; }, @@ -200,11 +195,10 @@ export default function BlockEditor( { setIsInserterOpen } ) { ( fillProps ) => ( ), - [ page ] + [] ) } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 8ed10e81f626c7..2bb06063bc75aa 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -31,7 +31,7 @@ import { SidebarComplementaryAreaFills } from '../sidebar-edit-mode'; import BlockEditor from '../block-editor'; import CodeEditor from '../code-editor'; import KeyboardShortcuts from '../keyboard-shortcuts'; -import useInitEditedEntityFromURL from '../use-init-edited-entity-from-url'; +import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url'; import InserterSidebar from '../secondary-sidebar/inserter-sidebar'; import ListViewSidebar from '../secondary-sidebar/list-view-sidebar'; import WelcomeGuide from '../welcome-guide'; @@ -59,7 +59,7 @@ export default function Editor() { editedPostId, editedPostType, editedPost, - page, + context, hasLoadedPost, editorMode, canvasMode, @@ -75,7 +75,7 @@ export default function Editor() { const { getEditedPostType, getEditedPostId, - getPage, + getEditedPostContext, getEditorMode, __unstableGetCanvasMode, isInserterOpened, @@ -99,7 +99,7 @@ export default function Editor() { editedPost: postId ? getEntityRecord( 'postType', postType, postId ) : null, - page: getPage(), + context: getEditedPostContext(), hasLoadedPost: postId ? hasFinishedResolution( 'getEntityRecord', [ 'postType', @@ -128,7 +128,8 @@ export default function Editor() { ), }; }, [] ); - const { setIsSaveViewOpened, setPage } = useDispatch( editSiteStore ); + const { setIsSaveViewOpened, setEditedPostContext } = + useDispatch( editSiteStore ); const isViewMode = canvasMode === 'view'; const isEditMode = canvasMode === 'edit'; @@ -142,23 +143,20 @@ export default function Editor() { : __( 'Block Library' ); const blockContext = useMemo( () => ( { - ...page?.context, + ...context, queryContext: [ - page?.context.queryContext || { page: 1 }, + context?.queryContext || { page: 1 }, ( newQueryContext ) => - setPage( { - ...page, - context: { - ...page?.context, - queryContext: { - ...page?.context.queryContext, - ...newQueryContext, - }, + setEditedPostContext( { + ...context, + queryContext: { + ...context?.queryContext, + ...newQueryContext, }, } ), ], } ), - [ page?.context ] + [ context ] ); const isReady = editedPostType !== undefined && editedPostId !== undefined; diff --git a/packages/edit-site/src/components/navigate-to-link/index.js b/packages/edit-site/src/components/navigate-to-link/index.js index 77f440abfc78f0..26347f153eaad4 100644 --- a/packages/edit-site/src/components/navigate-to-link/index.js +++ b/packages/edit-site/src/components/navigate-to-link/index.js @@ -9,12 +9,7 @@ import { edit } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; -export default function NavigateToLink( { - type, - id, - activePage, - onActivePageChange, -} ) { +export default function NavigateToLink( { type, id, onActivePageChange } ) { const post = useSelect( ( select ) => type && @@ -27,7 +22,6 @@ export default function NavigateToLink( { const onClick = useMemo( () => { if ( ! post?.link ) return null; const path = getPathAndQueryString( post.link ); - if ( path === activePage?.path ) return null; return () => onActivePageChange( { type, @@ -38,7 +32,7 @@ export default function NavigateToLink( { postId: post.id, }, } ); - }, [ post, activePage?.path, onActivePageChange ] ); + }, [ post, onActivePageChange ] ); return ( onClick && ( diff --git a/packages/edit-site/src/components/sidebar/index.js b/packages/edit-site/src/components/sidebar/index.js index 154fa9c0a17b48..06abec6f024cac 100644 --- a/packages/edit-site/src/components/sidebar/index.js +++ b/packages/edit-site/src/components/sidebar/index.js @@ -8,6 +8,19 @@ import { __experimentalNavigatorProvider as NavigatorProvider } from '@wordpress */ import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main'; import SidebarNavigationScreenTemplates from '../sidebar-navigation-screen-templates'; +import useSyncSidebarPathWithURL from '../sync-state-with-url/use-sync-sidebar-path-with-url'; + +function SidebarScreens() { + useSyncSidebarPathWithURL(); + + return ( + <> + + + + + ); +} export function Sidebar() { return ( @@ -15,9 +28,7 @@ export function Sidebar() { className="edit-site-sidebar__content" initialPath="/" > - - - + ); } diff --git a/packages/edit-site/src/components/use-init-edited-entity-from-url/index.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js similarity index 82% rename from packages/edit-site/src/components/use-init-edited-entity-from-url/index.js rename to packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index dec0889f38e9a9..a6061d205ffc07 100644 --- a/packages/edit-site/src/components/use-init-edited-entity-from-url/index.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -19,6 +19,8 @@ export default function useInitEditedEntityFromURL() { // Set correct entity on page navigation. useEffect( () => { + // This URL scheme mean we can't open a template part with the context of a given post. + // Potentially posts and pages could be moved to a "context" query string instead. if ( 'page' === postType || 'post' === postType ) { setPage( { context: { postType, postId } } ); // Resolves correct template based on ID. } else if ( 'wp_template' === postType ) { diff --git a/packages/edit-site/src/components/sync-state-with-url/use-sync-sidebar-path-with-url.js b/packages/edit-site/src/components/sync-state-with-url/use-sync-sidebar-path-with-url.js new file mode 100644 index 00000000000000..885772cdf4046c --- /dev/null +++ b/packages/edit-site/src/components/sync-state-with-url/use-sync-sidebar-path-with-url.js @@ -0,0 +1,36 @@ +/** + * WordPress dependencies + */ +import { __experimentalUseNavigator as useNavigator } from '@wordpress/components'; +import { useEffect, useRef } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { useLocation, useHistory } from '../routes'; + +export default function useSyncSidebarPathWithURL() { + const history = useHistory(); + const { params } = useLocation(); + const { sidebar = '/' } = params; + const { location, goTo } = useNavigator(); + const currentSidebar = useRef( sidebar ); + const currentNavigatorLocation = useRef( location.path ); + useEffect( () => { + currentSidebar.current = sidebar; + if ( sidebar !== currentNavigatorLocation.current ) { + goTo( sidebar ); + } + }, [ sidebar ] ); + useEffect( () => { + currentNavigatorLocation.current = location.path; + if ( location.path !== currentSidebar.current ) { + history.push( { + ...params, + sidebar: location.path, + } ); + } + }, [ location.path, history ] ); + + return sidebar; +} diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index b587d2fe0045ea..7c9f31bbd4308c 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -72,9 +72,10 @@ export const setTemplate = } dispatch( { - type: 'SET_TEMPLATE', - templateId, - page: { context: { templateSlug } }, + type: 'SET_EDITED_POST', + postType: 'wp_template', + id: templateId, + context: { templateSlug }, } ); }; @@ -105,9 +106,10 @@ export const addTemplate = } dispatch( { - type: 'SET_TEMPLATE', - templateId: newTemplate.id, - page: { context: { templateSlug: newTemplate.slug } }, + type: 'SET_EDITED_POST', + postType: 'wp_template', + id: newTemplate.id, + context: { templateSlug: newTemplate.slug }, } ); }; @@ -167,21 +169,37 @@ export const removeTemplate = */ export function setTemplatePart( templatePartId ) { return { - type: 'SET_TEMPLATE_PART', - templatePartId, + type: 'SET_EDITED_POST', + postType: 'wp_template_part', + id: templatePartId, }; } /** - * Action that sets the home template ID to the template ID of the page resolved - * from a given path. + * @deprecated + */ +export function setHomeTemplateId() { + deprecated( "dispatch( 'core/edit-site' ).setHomeTemplateId", { + since: '6.2', + version: '6.4', + } ); + + return { + type: 'NOTHING', + }; +} + +/** + * Set's the current block editor context. + * + * @param {Object} context The context object. * - * @param {number} homeTemplateId The template ID for the homepage. + * @return {number} The resolved template ID for the page route. */ -export function setHomeTemplateId( homeTemplateId ) { +export function setEditedPostContext( context ) { return { - type: 'SET_HOME_TEMPLATE', - homeTemplateId, + type: 'SET_EDITED_POST_CONTEXT', + context, }; } @@ -221,17 +239,13 @@ export const setPage = } dispatch( { - type: 'SET_PAGE', - page: template.slug - ? { - ...page, - context: { - ...page.context, - templateSlug: template.slug, - }, - } - : page, - templateId: template.id, + type: 'SET_EDITED_POST', + postType: 'wp_template', + id: template.id, + context: { + ...page.context, + templateSlug: template.slug, + }, } ); return template.id; diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index 327159635617aa..6a7e68fccb3c90 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -51,40 +51,22 @@ export function settings( state = {}, action ) { */ export function editedPost( state = {}, action ) { switch ( action.type ) { - case 'SET_TEMPLATE': - case 'SET_PAGE': + case 'SET_EDITED_POST': return { - type: 'wp_template', - id: action.templateId, - page: action.page, + postType: action.postType, + id: action.id, + context: action.context, }; - case 'SET_TEMPLATE_PART': + case 'SET_EDITED_POST_CONTEXT': return { - type: 'wp_template_part', - id: action.templatePartId, + ...state, + context: action.context, }; } return state; } -/** - * Reducer for information about the site's homepage. - * - * @param {Object} state Current state. - * @param {Object} action Dispatched action. - * - * @return {Object} Updated state. - */ -export function homeTemplateId( state, action ) { - switch ( action.type ) { - case 'SET_HOME_TEMPLATE': - return action.homeTemplateId; - } - - return state; -} - /** * Reducer to set the block inserter panel open or closed. * @@ -162,7 +144,6 @@ export default combineReducers( { deviceType, settings, editedPost, - homeTemplateId, blockInserterPanel, listViewPanel, saveViewPanel, diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index a99467addd334a..2137525b07b63f 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -146,18 +146,13 @@ export const getSettings = createSelector( ); /** - * Returns the current home template ID. - * - * @param {Object} state Global application state. - * - * @return {number?} Home template ID. + * @deprecated */ -export function getHomeTemplateId( state ) { - return state.homeTemplateId; -} - -function getCurrentEditedPost( state ) { - return state.editedPost; +export function getHomeTemplateId() { + deprecated( "select( 'core/edit-site' ).getHomeTemplateId", { + since: '6.2', + version: '6.4', + } ); } /** @@ -168,7 +163,7 @@ function getCurrentEditedPost( state ) { * @return {TemplateType?} Template type. */ export function getEditedPostType( state ) { - return getCurrentEditedPost( state ).type; + return state.editedPost.postType; } /** @@ -179,18 +174,31 @@ export function getEditedPostType( state ) { * @return {string?} Post ID. */ export function getEditedPostId( state ) { - return getCurrentEditedPost( state ).id; + return state.editedPost.id; +} + +/** + * Returns the edited post's context object. + * + * @deprecated + * @param {Object} state Global application state. + * + * @return {Object} Page. + */ +export function getEditedPostContext( state ) { + return state.editedPost.context; } /** * Returns the current page object. * + * @deprecated * @param {Object} state Global application state. * * @return {Object} Page. */ export function getPage( state ) { - return getCurrentEditedPost( state ).page; + return { context: state.editedPost.context }; } /** diff --git a/packages/edit-site/src/store/test/actions.js b/packages/edit-site/src/store/test/actions.js index 96fa931efc8710..fc2e5ca6a7c617 100644 --- a/packages/edit-site/src/store/test/actions.js +++ b/packages/edit-site/src/store/test/actions.js @@ -81,7 +81,7 @@ describe( 'actions', () => { const select = registry.select( editSiteStore ); expect( select.getEditedPostId() ).toBe( ID ); - expect( select.getPage().context.templateSlug ).toBe( SLUG ); + expect( select.getEditedPostContext().templateSlug ).toBe( SLUG ); } ); it( 'should set the template by fetching the template slug', async () => { @@ -109,7 +109,7 @@ describe( 'actions', () => { const select = registry.select( editSiteStore ); expect( select.getEditedPostId() ).toBe( ID ); - expect( select.getPage().context.templateSlug ).toBe( SLUG ); + expect( select.getEditedPostContext().templateSlug ).toBe( SLUG ); } ); } ); @@ -146,7 +146,7 @@ describe( 'actions', () => { const select = registry.select( editSiteStore ); expect( select.getEditedPostId() ).toBe( ID ); - expect( select.getPage().context.templateSlug ).toBe( SLUG ); + expect( select.getEditedPostContext().templateSlug ).toBe( SLUG ); } ); } ); @@ -207,18 +207,6 @@ describe( 'actions', () => { const select = registry.select( editSiteStore ); expect( select.getEditedPostId() ).toBe( 'emptytheme//single' ); expect( select.getEditedPostType() ).toBe( 'wp_template' ); - expect( select.getPage().path ).toBe( '/' ); - } ); - } ); - - describe( 'setHomeTemplateId', () => { - it( 'should set the home template ID', () => { - const registry = createRegistryWithStores(); - - registry.dispatch( editSiteStore ).setHomeTemplateId( 90 ); - expect( registry.select( editSiteStore ).getHomeTemplateId() ).toBe( - 90 - ); } ); } ); diff --git a/packages/edit-site/src/store/test/reducer.js b/packages/edit-site/src/store/test/reducer.js index a3ea8e356fc0aa..f6ce205ad63533 100644 --- a/packages/edit-site/src/store/test/reducer.js +++ b/packages/edit-site/src/store/test/reducer.js @@ -8,7 +8,6 @@ import deepFreeze from 'deep-freeze'; */ import { settings, - homeTemplateId, editedPost, blockInserterPanel, listViewPanel, @@ -46,17 +45,6 @@ describe( 'state', () => { } ); } ); - describe( 'homeTemplateId()', () => { - it( 'should apply default state', () => { - expect( homeTemplateId( undefined, {} ) ).toEqual( undefined ); - } ); - - it( 'should default to returning the same state', () => { - const state = {}; - expect( homeTemplateId( state, {} ) ).toBe( state ); - } ); - } ); - describe( 'editedPost()', () => { it( 'should apply default state', () => { expect( editedPost( undefined, {} ) ).toEqual( {} ); @@ -72,36 +60,17 @@ describe( 'state', () => { editedPost( { id: 1, type: 'wp_template' }, { - type: 'SET_TEMPLATE', - templateId: 2, - } - ) - ).toEqual( { id: 2, type: 'wp_template' } ); - } ); - - it( 'should update when a page is set', () => { - expect( - editedPost( - { id: 1, type: 'wp_template' }, - { - type: 'SET_PAGE', - templateId: 2, - page: {}, + type: 'SET_EDITED_POST', + postType: 'wp_template', + id: 2, + context: { templateSlug: 'slug' }, } ) - ).toEqual( { id: 2, type: 'wp_template', page: {} } ); - } ); - - it( 'should update when a template part is set', () => { - expect( - editedPost( - { id: 1, type: 'wp_template' }, - { - type: 'SET_TEMPLATE_PART', - templatePartId: 2, - } - ) - ).toEqual( { id: 2, type: 'wp_template_part' } ); + ).toEqual( { + postType: 'wp_template', + id: 2, + context: { templateSlug: 'slug' }, + } ); } ); } ); diff --git a/packages/edit-site/src/store/test/selectors.js b/packages/edit-site/src/store/test/selectors.js index bf0ec33452580e..223bcd1f0ba041 100644 --- a/packages/edit-site/src/store/test/selectors.js +++ b/packages/edit-site/src/store/test/selectors.js @@ -9,10 +9,8 @@ import { store as coreDataStore } from '@wordpress/core-data'; import { getCanUserCreateMedia, getSettings, - getHomeTemplateId, getEditedPostType, getEditedPostId, - getPage, getReusableBlocks, isInserterOpened, isListViewOpened, @@ -70,7 +68,7 @@ describe( 'selectors', () => { const state = { settings: {}, preferences: {}, - editedPost: { type: 'wp_template' }, + editedPost: { postType: 'wp_template' }, }; const setInserterOpened = () => {}; expect( getSettings( state, setInserterOpened ) ).toEqual( { @@ -93,7 +91,7 @@ describe( 'selectors', () => { const state = { settings: { key: 'value' }, - editedPost: { type: 'wp_template_part' }, + editedPost: { postType: 'wp_template_part' }, }; const setInserterOpened = () => {}; @@ -112,13 +110,6 @@ describe( 'selectors', () => { } ); } ); - describe( 'getHomeTemplateId', () => { - it( 'returns the home template ID', () => { - const state = { homeTemplateId: {} }; - expect( getHomeTemplateId( state ) ).toBe( state.homeTemplateId ); - } ); - } ); - describe( 'getEditedPostId', () => { it( 'returns the template ID', () => { const state = { editedPost: { id: 10 } }; @@ -128,19 +119,11 @@ describe( 'selectors', () => { describe( 'getEditedPostType', () => { it( 'returns the template type', () => { - const state = { editedPost: { type: 'wp_template' } }; + const state = { editedPost: { postType: 'wp_template' } }; expect( getEditedPostType( state ) ).toBe( 'wp_template' ); } ); } ); - describe( 'getPage', () => { - it( 'returns the page object', () => { - const page = {}; - const state = { editedPost: { page } }; - expect( getPage( state ) ).toBe( page ); - } ); - } ); - describe( 'isInserterOpened', () => { it( 'returns the block inserter panel isOpened state', () => { const state = {