From 0169fe40960b9cc8b944efdd1984efa4fb2bc36b Mon Sep 17 00:00:00 2001 From: Noah Allen Date: Mon, 20 Jul 2020 12:34:21 -0700 Subject: [PATCH] Site Editor: Remove more initial PHP state (#23775) --- lib/edit-site-page.php | 42 +++++--- .../edit-site/src/components/editor/index.js | 45 +++++---- .../edit-site/src/components/header/index.js | 8 +- .../src/components/page-switcher/index.js | 13 ++- .../src/components/save-button/index.js | 1 - .../src/components/template-switcher/index.js | 25 ++--- packages/edit-site/src/index.js | 5 +- packages/edit-site/src/store/actions.js | 58 ++++++++--- packages/edit-site/src/store/index.js | 5 +- packages/edit-site/src/store/reducer.js | 28 +++--- packages/edit-site/src/store/selectors.js | 19 +--- packages/edit-site/src/store/test/actions.js | 99 +++++++++++++++++-- packages/edit-site/src/store/test/reducer.js | 16 +-- .../edit-site/src/store/test/selectors.js | 8 -- 14 files changed, 235 insertions(+), 137 deletions(-) diff --git a/lib/edit-site-page.php b/lib/edit-site-page.php index 60fbc1460b595..0d3411de9803c 100644 --- a/lib/edit-site-page.php +++ b/lib/edit-site-page.php @@ -145,18 +145,6 @@ function gutenberg_edit_site_init( $hook ) { } $settings['styles'] = gutenberg_get_editor_styles(); - $settings['editSiteInitialState'] = array(); - - $settings['editSiteInitialState']['templateType'] = 'wp_template'; - $settings['editSiteInitialState']['showOnFront'] = get_option( 'show_on_front' ); - $settings['editSiteInitialState']['page'] = array( - 'path' => '/', - 'context' => 'page' === $settings['editSiteInitialState']['showOnFront'] ? array( - 'postType' => 'page', - 'postId' => get_option( 'page_on_front' ), - ) : array(), - ); - // This is so other parts of the code can hook their own settings. // Example: Global Styles. global $post; @@ -225,3 +213,33 @@ function gutenberg_edit_site_init( $hook ) { wp_enqueue_style( 'wp-format-library' ); } add_action( 'admin_enqueue_scripts', 'gutenberg_edit_site_init' ); + +/** + * Register a core site setting for front page information. + */ +function register_site_editor_homepage_settings() { + register_setting( + 'general', + 'show_on_front', + array( + 'show_in_rest' => array( + 'name' => 'show_on_front', + ), + 'type' => 'string', + 'description' => __( 'What to show on the front page', 'gutenberg' ), + ) + ); + + register_setting( + 'general', + 'page_on_front', + array( + 'show_in_rest' => array( + 'name' => 'page_on_front', + ), + 'type' => 'number', + 'description' => __( 'The ID of the page that should be displayed on the front page', 'gutenberg' ), + ) + ); +} +add_action( 'rest_api_init', 'register_site_editor_homepage_settings', 10 ); diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index f61e30ecf34f3..e67aaa4b73823 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -52,8 +52,7 @@ function Editor() { deviceType, sidebarIsOpened, settings, - templateId, - templatePartId, + entityId, templateType, page, template, @@ -71,6 +70,14 @@ function Editor() { const _templateId = getTemplateId(); const _templatePartId = getTemplatePartId(); const _templateType = getTemplateType(); + + // The currently selected entity to display. Typically template or template part. + let _entityId; + if ( _templateType ) { + _entityId = + _templateType === 'wp_template' ? _templateId : _templatePartId; + } + return { isFullscreenActive: isFeatureActive( 'fullscreenMode' ), deviceType: __experimentalGetPreviewDeviceType(), @@ -78,16 +85,17 @@ function Editor() { 'core/interface' ).getActiveComplementaryArea( 'core/edit-site' ), settings: getSettings(), - templateId: _templateId, - templatePartId: _templatePartId, templateType: _templateType, page: getPage(), - template: _select( 'core' ).getEntityRecord( - 'postType', - _templateType, - _templateType === 'wp_template' ? _templateId : _templatePartId - ), + template: _templateType + ? _select( 'core' ).getEntityRecord( + 'postType', + _templateType, + _entityId + ) + : null, select: _select, + entityId: _entityId, }; }, [] ); const { editEntityRecord } = useDispatch( 'core' ); @@ -125,25 +133,26 @@ function Editor() { // and Query Pagination blocks. const blockContext = useMemo( () => ( { - ...page.context, - query: page.context.query || { categoryIds: [] }, + ...page?.context, + query: page?.context.query || { categoryIds: [] }, queryContext: [ - page.context.queryContext || { page: 1 }, + page?.context.queryContext || { page: 1 }, ( newQueryContext ) => setPage( { ...page, context: { - ...page.context, + ...page?.context, queryContext: { - ...page.context.queryContext, + ...page?.context.queryContext, ...newQueryContext, }, }, } ), ], } ), - [ page.context ] + [ page?.context ] ); + return ( <> @@ -154,11 +163,7 @@ function Editor() { diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js index 3cb84b3b68e89..1dcdb84737876 100644 --- a/packages/edit-site/src/components/header/index.js +++ b/packages/edit-site/src/components/header/index.js @@ -49,8 +49,12 @@ export default function Header( { getTemplatePartId, getTemplateType, getPage, - getShowOnFront, } = select( 'core/edit-site' ); + + const { show_on_front: _showOnFront } = select( + 'core' + ).getEditedEntityRecord( 'root', 'site' ); + return { deviceType: __experimentalGetPreviewDeviceType(), hasFixedToolbar: isFeatureActive( 'fixedToolbar' ), @@ -58,7 +62,7 @@ export default function Header( { templatePartId: getTemplatePartId(), templateType: getTemplateType(), page: getPage(), - showOnFront: getShowOnFront(), + showOnFront: _showOnFront, }; }, [] ); diff --git a/packages/edit-site/src/components/page-switcher/index.js b/packages/edit-site/src/components/page-switcher/index.js index 53629bd88ea7a..ffef44bc45dc2 100644 --- a/packages/edit-site/src/components/page-switcher/index.js +++ b/packages/edit-site/src/components/page-switcher/index.js @@ -97,6 +97,7 @@ export default function PageSwitcher( { ].find( ( choice ) => choice.value === newPath ); onActivePageChange( { ...rest, path } ); }; + const onPostSelect = ( post ) => onActivePageChange( { type: 'post', @@ -104,6 +105,8 @@ export default function PageSwitcher( { path: getPathAndQueryString( post.url ), context: { postType: post.type, postId: post.id }, } ); + + const activePath = activePage?.path; return ( choice.value === activePage.path - )?.label || activePage.path, + ( choice ) => choice.value === activePath + )?.label || activePath, } } menuProps={ { className: 'edit-site-page-switcher__menu' } } > @@ -121,21 +124,21 @@ export default function PageSwitcher( { isSavingEntityRecord( record.kind, record.name, record.key ) ), - templateType: select( 'core/edit-site' ).getTemplateType(), }; } ); diff --git a/packages/edit-site/src/components/template-switcher/index.js b/packages/edit-site/src/components/template-switcher/index.js index e713cbaf8c1ab..a1537253dbe0b 100644 --- a/packages/edit-site/src/components/template-switcher/index.js +++ b/packages/edit-site/src/components/template-switcher/index.js @@ -2,8 +2,8 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useRegistry, useSelect } from '@wordpress/data'; -import { useEffect, useState } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { useState } from '@wordpress/element'; import { Tooltip, DropdownMenu, @@ -16,7 +16,6 @@ import { Icon, home, plus, undo } from '@wordpress/icons'; /** * Internal dependencies */ -import { findTemplate } from '../../utils'; import TemplatePreview from './template-preview'; import ThemePreview from './theme-preview'; @@ -69,20 +68,7 @@ export default function TemplateSwitcher( { setThemePreviewVisible( () => false ); }; - const registry = useRegistry(); - const [ homeId, setHomeId ] = useState(); - - useEffect( () => { - findTemplate( - '/', - registry.__experimentalResolveSelect( 'core' ).getEntityRecords - ).then( - ( newHomeId ) => setHomeId( newHomeId ), - () => setHomeId( null ) - ); - }, [ registry ] ); - - const { currentTheme, template, templateParts } = useSelect( + const { currentTheme, template, templateParts, homeId } = useSelect( ( select ) => { const { getCurrentTheme, @@ -96,6 +82,8 @@ export default function TemplateSwitcher( { activeId ); + const { getHomeTemplateId } = select( 'core/edit-site' ); + return { currentTheme: getCurrentTheme(), template: _template, @@ -105,6 +93,7 @@ export default function TemplateSwitcher( { template: _template.slug, } ) : null, + homeId: getHomeTemplateId(), }; }, [ activeId ] @@ -128,9 +117,11 @@ export default function TemplateSwitcher( { } ) ); const overwriteSlug = + page && TEMPLATE_OVERRIDES[ page.type ] && page.slug && TEMPLATE_OVERRIDES[ page.type ]( page.slug ); + const overwriteTemplate = () => onAddTemplate( { slug: overwriteSlug, diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 3607eae790820..08a0e3993f0e9 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -54,10 +54,7 @@ const fetchLinkSuggestions = ( search, { perPage = 20 } = {} ) => export function initialize( id, settings ) { settings.__experimentalFetchLinkSuggestions = fetchLinkSuggestions; - const initialState = settings.editSiteInitialState; - delete settings.editSiteInitialState; - initialState.settings = settings; - registerEditSiteStore( initialState ); + registerEditSiteStore( { settings } ); registerCoreBlocks(); if ( process.env.GUTENBERG_PHASE === 2 ) { diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index c68baf50a5509..9785b46a5ddbe 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -75,15 +75,13 @@ export function* addTemplate( template ) { * Removes a template, and updates the current page and template. * * @param {number} templateId The template ID. - * - * @return {Object} Action object used to set the current page and template. */ export function* removeTemplate( templateId ) { yield apiFetch( { path: `/wp/v2/templates/${ templateId }`, method: 'DELETE', } ); - return dispatch( + yield dispatch( 'core/edit-site', 'setPage', yield select( 'core/edit-site', 'getPage' ) @@ -105,21 +103,59 @@ export function setTemplatePart( templatePartId ) { } /** - * Resolves the template for a page and sets them. + * Updates the homeTemplateId state with the templateId of the page resolved + * from the given path. * - * @param {Object} page The page object. - * @param {string} page.type The page type. - * @param {string} page.slug The page slug. - * @param {string} page.path The page path. - * @param {Object} page.context The page context. + * @param {number} homeTemplateId The template ID for the homepage. + */ +export function setHomeTemplateId( homeTemplateId ) { + return { + type: 'SET_HOME_TEMPLATE', + homeTemplateId, + }; +} + +/** + * Resolves the template for a page and displays both. * - * @return {Object} Action object. + * @param {Object} page The page object. + * @param {string} page.type The page type. + * @param {string} page.slug The page slug. + * @param {string} page.path The page path. + * @param {Object} page.context The page context. + * + * @return {number} The resolved template ID for the page route. */ export function* setPage( page ) { const templateId = yield findTemplate( page.path ); - return { + yield { type: 'SET_PAGE', page, templateId, }; + return templateId; +} + +/** + * Displays the site homepage for editing in the editor. + */ +export function* showHomepage() { + const { + show_on_front: showOnFront, + page_on_front: frontpageId, + } = yield select( 'core', 'getEntityRecord', 'root', 'site' ); + + const page = { + path: '/', + context: + showOnFront === 'page' + ? { + postType: 'page', + postId: frontpageId, + } + : {}, + }; + + const homeTemplate = yield* setPage( page ); + yield setHomeTemplateId( homeTemplate ); } diff --git a/packages/edit-site/src/store/index.js b/packages/edit-site/src/store/index.js index 06bcf529febe1..fa012273201cd 100644 --- a/packages/edit-site/src/store/index.js +++ b/packages/edit-site/src/store/index.js @@ -23,8 +23,7 @@ export default function registerEditSiteStore( initialState ) { initialState, } ); - // We set the initial page here to include the template fetch which will - // resolve the correct homepage template. - store.dispatch( actions.setPage( initialState.page ) ); + store.dispatch( actions.showHomepage() ); + return store; } diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js index bd7cfd8740eb1..a079efb6a4d55 100644 --- a/packages/edit-site/src/store/reducer.js +++ b/packages/edit-site/src/store/reducer.js @@ -85,17 +85,6 @@ export function settings( state = {}, action ) { return state; } -/** - * Reducer returning the home template ID. - * - * @param {Object} state Current state. - * - * @return {Object} Updated state. - */ -export function homeTemplateId( state ) { - return state; -} - /** * Reducer returning the template ID. * @@ -139,7 +128,7 @@ export function templatePartId( state, action ) { * * @return {Object} Updated state. */ -export function templateType( state, action ) { +export function templateType( state = 'wp_template', action ) { switch ( action.type ) { case 'SET_TEMPLATE': case 'SET_PAGE': @@ -159,7 +148,7 @@ export function templateType( state, action ) { * * @return {Object} Updated state. */ -export function page( state = {}, action ) { +export function page( state, action ) { switch ( action.type ) { case 'SET_PAGE': return action.page; @@ -169,13 +158,19 @@ export function page( state = {}, action ) { } /** - * Reducer returning the site's `show_on_front` setting. + * Reducer for information about the site's homepage. * * @param {Object} state Current state. + * @param {Object} action Dispatched action. * * @return {Object} Updated state. */ -export function showOnFront( state ) { +export function homeTemplateId( state, action ) { + switch ( action.type ) { + case 'SET_HOME_TEMPLATE': + return action.homeTemplateId; + } + return state; } @@ -183,10 +178,9 @@ export default combineReducers( { preferences, deviceType, settings, - homeTemplateId, templateId, templatePartId, templateType, page, - showOnFront, + homeTemplateId, } ); diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 9e98f3ba36191..48e67fca292ee 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -88,7 +88,7 @@ export const getSettings = createSelector( * * @param {Object} state Global application state. * - * @return {number} Home template ID. + * @return {number?} Home template ID. */ export function getHomeTemplateId( state ) { return state.homeTemplateId; @@ -99,7 +99,7 @@ export function getHomeTemplateId( state ) { * * @param {Object} state Global application state. * - * @return {number} Template ID. + * @return {number?} Template ID. */ export function getTemplateId( state ) { return state.templateId; @@ -110,7 +110,7 @@ export function getTemplateId( state ) { * * @param {Object} state Global application state. * - * @return {number} Template part ID. + * @return {number?} Template part ID. */ export function getTemplatePartId( state ) { return state.templatePartId; @@ -121,7 +121,7 @@ export function getTemplatePartId( state ) { * * @param {Object} state Global application state. * - * @return {string} Template type. + * @return {string?} Template type. */ export function getTemplateType( state ) { return state.templateType; @@ -137,14 +137,3 @@ export function getTemplateType( state ) { export function getPage( state ) { return state.page; } - -/** - * Returns the site's current `show_on_front` setting. - * - * @param {Object} state Global application state. - * - * @return {Object} The setting. - */ -export function getShowOnFront( state ) { - return state.showOnFront; -} diff --git a/packages/edit-site/src/store/test/actions.js b/packages/edit-site/src/store/test/actions.js index 07776d9d8bae6..4f687e2d45214 100644 --- a/packages/edit-site/src/store/test/actions.js +++ b/packages/edit-site/src/store/test/actions.js @@ -8,6 +8,8 @@ import { removeTemplate, setTemplatePart, setPage, + showHomepage, + setHomeTemplateId, } from '../actions'; describe( 'actions', () => { @@ -72,13 +74,13 @@ describe( 'actions', () => { selectorName: 'getPage', args: [], } ); - // @FIXME: Test for done: true. expect( it.next( page ).value ).toEqual( { type: 'DISPATCH', storeKey: 'core/edit-site', actionName: 'setPage', args: [ page ], } ); + expect( it.next().done ).toBe( true ); } ); } ); @@ -93,7 +95,7 @@ describe( 'actions', () => { } ); describe( 'setPage', () => { - it( 'should yield the FIND_TEMPLATE control and return the SET_TEMPLATE_PART action', () => { + it( 'should yield the FIND_TEMPLATE control and return the SET_PAGE action', () => { const page = { path: '/' }; const templateId = 1; @@ -102,13 +104,94 @@ describe( 'actions', () => { type: 'FIND_TEMPLATE', path: page.path, } ); - expect( it.next( templateId ) ).toEqual( { - value: { - type: 'SET_PAGE', - page, - templateId, + expect( it.next( templateId ).value ).toEqual( { + type: 'SET_PAGE', + page, + templateId, + } ); + expect( it.next().done ).toBe( true ); + } ); + } ); + + describe( 'showHomepage', () => { + it( 'should calculate and set the homepage if it is set to show posts', () => { + const templateId = 1; + + const it = showHomepage(); + + expect( it.next().value ).toEqual( { + args: [ 'root', 'site' ], + selectorName: 'getEntityRecord', + storeKey: 'core', + type: 'SELECT', + } ); + + const page = { + path: '/', + context: {}, + }; + expect( it.next( { show_on_front: 'posts' } ).value ).toEqual( { + type: 'FIND_TEMPLATE', + path: page.path, + } ); + expect( it.next( templateId ).value ).toEqual( { + type: 'SET_PAGE', + page, + templateId, + } ); + expect( it.next( templateId ).value ).toEqual( { + type: 'SET_HOME_TEMPLATE', + homeTemplateId: templateId, + } ); + expect( it.next().done ).toBe( true ); + } ); + + it( 'should calculate and set the homepage if it is set to show a page', () => { + const templateId = 2; + const pageId = 2; + + const it = showHomepage(); + + expect( it.next().value ).toEqual( { + args: [ 'root', 'site' ], + selectorName: 'getEntityRecord', + storeKey: 'core', + type: 'SELECT', + } ); + + const page = { + path: '/', + context: { + postType: 'page', + postId: pageId, }, - done: true, + }; + expect( + it.next( { show_on_front: 'page', page_on_front: pageId } ) + .value + ).toEqual( { + type: 'FIND_TEMPLATE', + path: page.path, + } ); + expect( it.next( templateId ).value ).toEqual( { + type: 'SET_PAGE', + page, + templateId, + } ); + expect( it.next( templateId ).value ).toEqual( { + type: 'SET_HOME_TEMPLATE', + homeTemplateId: templateId, + } ); + expect( it.next().done ).toBe( true ); + } ); + } ); + + describe( 'setHomeTemplateId', () => { + it( 'should return the SET_HOME_TEMPLATE action', () => { + const homeTemplateId = 90; + expect( setHomeTemplateId( homeTemplateId ) ).toEqual( { + type: 'SET_HOME_TEMPLATE', + homeTemplateId, } ); } ); } ); diff --git a/packages/edit-site/src/store/test/reducer.js b/packages/edit-site/src/store/test/reducer.js index c220305c6dd70..6f0c5fffaf6b9 100644 --- a/packages/edit-site/src/store/test/reducer.js +++ b/packages/edit-site/src/store/test/reducer.js @@ -14,7 +14,6 @@ import { templatePartId, templateType, page, - showOnFront, } from '../reducer'; import { PREFERENCES_DEFAULTS } from '../defaults'; @@ -130,7 +129,7 @@ describe( 'state', () => { describe( 'templateType()', () => { it( 'should apply default state', () => { - expect( templateType( undefined, {} ) ).toEqual( undefined ); + expect( templateType( undefined, {} ) ).toEqual( 'wp_template' ); } ); it( 'should default to returning the same state', () => { @@ -165,7 +164,7 @@ describe( 'state', () => { describe( 'page()', () => { it( 'should apply default state', () => { - expect( page( undefined, {} ) ).toEqual( {} ); + expect( page( undefined, {} ) ).toEqual( undefined ); } ); it( 'should default to returning the same state', () => { @@ -183,15 +182,4 @@ describe( 'state', () => { ).toBe( newPage ); } ); } ); - - describe( 'showOnFront()', () => { - it( 'should apply default state', () => { - expect( showOnFront( undefined, {} ) ).toEqual( undefined ); - } ); - - it( 'should default to returning the same state', () => { - const state = {}; - expect( showOnFront( state, {} ) ).toBe( state ); - } ); - } ); } ); diff --git a/packages/edit-site/src/store/test/selectors.js b/packages/edit-site/src/store/test/selectors.js index f71e885b6b147..688c6b053fac5 100644 --- a/packages/edit-site/src/store/test/selectors.js +++ b/packages/edit-site/src/store/test/selectors.js @@ -10,7 +10,6 @@ import { getTemplatePartId, getTemplateType, getPage, - getShowOnFront, } from '../selectors'; describe( 'selectors', () => { @@ -142,11 +141,4 @@ describe( 'selectors', () => { expect( getPage( state ) ).toBe( state.page ); } ); } ); - - describe( 'getShowOnFront', () => { - it( 'returns the `show_on_front` setting', () => { - const state = { showOnFront: {} }; - expect( getShowOnFront( state ) ).toBe( state.showOnFront ); - } ); - } ); } );