From 974613e12ed4b845261d5955793cb70c06fa05b3 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 9 Dec 2021 15:01:07 +0800 Subject: [PATCH 1/5] Replace showHomepage with a selector and dedicate redirect component --- .../edit-site/src/components/app/index.js | 15 +++++++ .../src/components/homepage-redirect/index.js | 26 +++++++++++ .../components/url-query-controller/index.js | 38 ++-------------- packages/edit-site/src/store/selectors.js | 45 +++++++++++++++++++ 4 files changed, 89 insertions(+), 35 deletions(-) create mode 100644 packages/edit-site/src/components/homepage-redirect/index.js diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index bf367f36740ba..1f8b6241e46f3 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -11,8 +11,19 @@ import { Routes } from '../routes'; import Editor from '../editor'; import List from '../list'; import NavigationSidebar from '../navigation-sidebar'; +import HomepageRedirect from '../homepage-redirect'; import getIsListPage from '../../utils/get-is-list-page'; +function getNeedsHomepageRedirect( params ) { + const { postType } = params; + return ( + ! getIsListPage( params ) && + ! [ 'post', 'page', 'wp_template', 'wp_template_part' ].includes( + postType + ) + ); +} + export default function EditSiteApp( { reboot } ) { return ( @@ -20,6 +31,10 @@ export default function EditSiteApp( { reboot } ) { { ( { params } ) => { + if ( getNeedsHomepageRedirect( params ) ) { + return ; + } + const isListPage = getIsListPage( params ); return ( diff --git a/packages/edit-site/src/components/homepage-redirect/index.js b/packages/edit-site/src/components/homepage-redirect/index.js new file mode 100644 index 0000000000000..a024f8f9c7bda --- /dev/null +++ b/packages/edit-site/src/components/homepage-redirect/index.js @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { useHistory } from '../routes'; +import { store as editSiteStore } from '../../store'; + +export default function HomepageRedirect() { + const params = useSelect( + ( select ) => select( editSiteStore ).getHomepageParams(), + [] + ); + + const history = useHistory(); + + if ( params ) { + history.replace( params ); + } + + // TODO - a loading state might be an option here. + return null; +} diff --git a/packages/edit-site/src/components/url-query-controller/index.js b/packages/edit-site/src/components/url-query-controller/index.js index 2b0d6d88414cc..8e4f8b17aef6f 100644 --- a/packages/edit-site/src/components/url-query-controller/index.js +++ b/packages/edit-site/src/components/url-query-controller/index.js @@ -2,63 +2,31 @@ * WordPress dependencies */ import { useEffect } from '@wordpress/element'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch } from '@wordpress/data'; /** * Internal dependencies */ -import { useLocation, useHistory } from '../routes'; +import { useLocation } from '../routes'; import { store as editSiteStore } from '../../store'; export default function URLQueryController() { - const { setTemplate, setTemplatePart, showHomepage, setPage } = useDispatch( + const { setTemplate, setTemplatePart, setPage } = useDispatch( editSiteStore ); - const history = useHistory(); const { params: { postId, postType }, } = useLocation(); - const { getPage, getEditedPostId, getEditedPostType } = useSelect( - editSiteStore - ); // Set correct entity on page navigation. useEffect( () => { - let isMounted = true; - if ( 'page' === postType || 'post' === postType ) { setPage( { context: { postType, postId } } ); // Resolves correct template based on ID. } else if ( 'wp_template' === postType ) { setTemplate( postId ); } else if ( 'wp_template_part' === postType ) { setTemplatePart( postId ); - } else { - showHomepage().then( () => { - if ( ! isMounted ) { - return; - } - - const page = getPage(); - const editedPostId = getEditedPostId(); - const editedPostType = getEditedPostType(); - - if ( page?.context?.postId && page?.context?.postType ) { - history.replace( { - postId: page.context.postId, - postType: page.context.postType, - } ); - } else if ( editedPostId && editedPostType ) { - history.replace( { - postId: editedPostId, - postType: editedPostType, - } ); - } - } ); } - - return () => { - isMounted = false; - }; }, [ postId, postType ] ); return null; diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index e64dd8ad8cd5e..4ebc2ff2a170e 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -123,6 +123,51 @@ export const getSettings = createSelector( ] ); +/** + * Get the homepage query parameters. These are used to redirect the site + * editor when entered accessed without postType or postId params. + * + * @param {Object} state Global application state. + * + * @return {?Object} An object containing postType and postId properties. + */ +export const getHomepageParams = createRegistrySelector( + ( select ) => ( state ) => { + const siteSettings = select( coreDataStore ).getSite(); + if ( ! siteSettings ) { + return; + } + + const { + show_on_front: showOnFront, + page_on_front: frontpageId, + } = siteSettings; + + // If the user has set a page as the homepage, use those details. + if ( showOnFront === 'page' ) { + return { + postType: 'page', + postId: frontpageId, + }; + } + + // Else get the home template. + const { siteUrl } = getSettings( state ); + const template = select( + coreDataStore + ).__experimentalGetTemplateForLink( siteUrl ); + + if ( ! template ) { + return; + } + + return { + postType: 'wp_template', + postId: template.id, + }; + } +); + /** * Returns the current home template ID. * From b8954275ddf13ca98d05a66d8648cfa20634256b Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 9 Dec 2021 16:14:12 +0800 Subject: [PATCH 2/5] Remove show homepage --- packages/edit-site/src/store/actions.js | 34 -------- packages/edit-site/src/store/test/actions.js | 90 -------------------- 2 files changed, 124 deletions(-) diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index b43b1e5b83fca..be629d34b3c66 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -230,40 +230,6 @@ export function* setPage( page ) { return templateId; } -/** - * Displays the site homepage for editing in the editor. - */ -export function* showHomepage() { - const { - show_on_front: showOnFront, - page_on_front: frontpageId, - } = yield controls.resolveSelect( - coreStore, - 'getEntityRecord', - 'root', - 'site' - ); - - const { siteUrl } = yield controls.select( - editSiteStoreName, - 'getSettings' - ); - - const page = { - path: siteUrl, - context: - showOnFront === 'page' - ? { - postType: 'page', - postId: frontpageId, - } - : {}, - }; - - const homeTemplate = yield* setPage( page ); - yield setHomeTemplateId( homeTemplate ); -} - /** * Returns an action object used to set the active navigation panel menu. * diff --git a/packages/edit-site/src/store/test/actions.js b/packages/edit-site/src/store/test/actions.js index 8e5ebc09a8a5f..54be488b77dba 100644 --- a/packages/edit-site/src/store/test/actions.js +++ b/packages/edit-site/src/store/test/actions.js @@ -7,7 +7,6 @@ import { addTemplate, setTemplatePart, setPage, - showHomepage, setHomeTemplateId, setIsListViewOpened, } from '../actions'; @@ -105,95 +104,6 @@ describe( 'actions', () => { } ); } ); - describe( 'showHomepage', () => { - it( 'should calculate and set the homepage if it is set to show posts', () => { - const it = showHomepage(); - - expect( it.next().value ).toEqual( { - args: [ 'root', 'site' ], - selectorName: 'getEntityRecord', - storeKey: 'core', - type: '@@data/RESOLVE_SELECT', - } ); - - expect( it.next( { show_on_front: 'posts' } ).value ).toEqual( { - args: [], - selectorName: 'getSettings', - storeKey: 'core/edit-site', - type: '@@data/SELECT', - } ); - - const page = { - path: 'http:/my-site', - context: {}, - }; - - expect( it.next( { siteUrl: 'http:/my-site' } ).value ).toEqual( { - type: '@@data/RESOLVE_SELECT', - storeKey: 'core', - selectorName: '__experimentalGetTemplateForLink', - args: [ page.path ], - } ); - expect( it.next( { id: 'theme//slug' } ).value ).toEqual( { - type: 'SET_PAGE', - page, - templateId: 'theme//slug', - } ); - expect( it.next( 'theme//slug' ).value ).toEqual( { - type: 'SET_HOME_TEMPLATE', - homeTemplateId: 'theme//slug', - } ); - expect( it.next().done ).toBe( true ); - } ); - - it( 'should calculate and set the homepage if it is set to show a page', () => { - const pageId = 2; - - const it = showHomepage(); - - expect( it.next().value ).toEqual( { - args: [ 'root', 'site' ], - selectorName: 'getEntityRecord', - storeKey: 'core', - type: '@@data/RESOLVE_SELECT', - } ); - - expect( - it.next( { show_on_front: 'page', page_on_front: pageId } ) - .value - ).toEqual( { - args: [], - selectorName: 'getSettings', - storeKey: 'core/edit-site', - type: '@@data/SELECT', - } ); - - const page = { - path: 'http:/my-site', - context: { - postType: 'page', - postId: pageId, - }, - }; - expect( it.next( { siteUrl: 'http:/my-site' } ).value ).toEqual( { - type: '@@data/RESOLVE_SELECT', - storeKey: 'core', - selectorName: '__experimentalGetTemplateForLink', - args: [ page.path ], - } ); - expect( it.next( { id: 'theme//slug' } ).value ).toEqual( { - type: 'SET_PAGE', - page, - templateId: 'theme//slug', - } ); - expect( it.next( 'theme//slug' ).value ).toEqual( { - type: 'SET_HOME_TEMPLATE', - homeTemplateId: 'theme//slug', - } ); - expect( it.next().done ).toBe( true ); - } ); - } ); - describe( 'setHomeTemplateId', () => { it( 'should return the SET_HOME_TEMPLATE action', () => { const homeTemplateId = 90; From b3a595f39c3f5cbbc723e99fe9e4bfef8950bb2a Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 13 Dec 2021 16:43:03 +0800 Subject: [PATCH 3/5] Remove component based redirect, instead use an async function prior to rendering app --- .../edit-site/src/components/app/index.js | 15 ---- .../src/components/homepage-redirect/index.js | 26 ------- .../components/routes/redirect-to-homepage.js | 74 +++++++++++++++++++ packages/edit-site/src/index.js | 11 ++- packages/edit-site/src/store/selectors.js | 45 ----------- 5 files changed, 83 insertions(+), 88 deletions(-) delete mode 100644 packages/edit-site/src/components/homepage-redirect/index.js create mode 100644 packages/edit-site/src/components/routes/redirect-to-homepage.js diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js index 1f8b6241e46f3..bf367f36740ba 100644 --- a/packages/edit-site/src/components/app/index.js +++ b/packages/edit-site/src/components/app/index.js @@ -11,19 +11,8 @@ import { Routes } from '../routes'; import Editor from '../editor'; import List from '../list'; import NavigationSidebar from '../navigation-sidebar'; -import HomepageRedirect from '../homepage-redirect'; import getIsListPage from '../../utils/get-is-list-page'; -function getNeedsHomepageRedirect( params ) { - const { postType } = params; - return ( - ! getIsListPage( params ) && - ! [ 'post', 'page', 'wp_template', 'wp_template_part' ].includes( - postType - ) - ); -} - export default function EditSiteApp( { reboot } ) { return ( @@ -31,10 +20,6 @@ export default function EditSiteApp( { reboot } ) { { ( { params } ) => { - if ( getNeedsHomepageRedirect( params ) ) { - return ; - } - const isListPage = getIsListPage( params ); return ( diff --git a/packages/edit-site/src/components/homepage-redirect/index.js b/packages/edit-site/src/components/homepage-redirect/index.js deleted file mode 100644 index a024f8f9c7bda..0000000000000 --- a/packages/edit-site/src/components/homepage-redirect/index.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { useHistory } from '../routes'; -import { store as editSiteStore } from '../../store'; - -export default function HomepageRedirect() { - const params = useSelect( - ( select ) => select( editSiteStore ).getHomepageParams(), - [] - ); - - const history = useHistory(); - - if ( params ) { - history.replace( params ); - } - - // TODO - a loading state might be an option here. - return null; -} diff --git a/packages/edit-site/src/components/routes/redirect-to-homepage.js b/packages/edit-site/src/components/routes/redirect-to-homepage.js new file mode 100644 index 0000000000000..29fd0d1bcb054 --- /dev/null +++ b/packages/edit-site/src/components/routes/redirect-to-homepage.js @@ -0,0 +1,74 @@ +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; +import { select } from '@wordpress/data'; +import { addQueryArgs } from '@wordpress/url'; + +/** + * Internal dependencies + */ +import history from '../../utils/history'; +import { store as editSiteStore } from '../../store'; +import getIsListPage from '../../utils/get-is-list-page'; + +function getNeedsHomepageRedirect( params ) { + const { postType } = params; + return ( + ! getIsListPage( params ) && + ! [ 'post', 'page', 'wp_template', 'wp_template_part' ].includes( + postType + ) + ); +} + +async function getHomepageParams() { + const siteSettings = await apiFetch( { path: '/wp/v2/settings' } ); + if ( ! siteSettings ) { + return; + } + + const { + show_on_front: showOnFront, + page_on_front: frontpageId, + } = siteSettings; + + // If the user has set a page as the homepage, use those details. + if ( showOnFront === 'page' ) { + return { + postType: 'page', + postId: frontpageId, + }; + } + + // Else get the home template. + // This matches the logic in `__experimentalGetTemplateForLink`. + // (packages/core-data/src/resolvers.js) + const { siteUrl } = select( editSiteStore ).getSettings(); + const template = await window + .fetch( addQueryArgs( siteUrl, { '_wp-find-template': true } ) ) + .then( ( res ) => res.json() ) + .then( ( { data } ) => data ); + + if ( ! template?.id ) { + return; + } + + return { + postType: 'wp_template', + postId: template.id, + }; +} + +export async function redirectToHomepage() { + const searchParams = new URLSearchParams( history.location.search ); + const params = Object.fromEntries( searchParams.entries() ); + + if ( getNeedsHomepageRedirect( params ) ) { + const homepageParams = await getHomepageParams(); + + if ( homepageParams ) { + history.replace( homepageParams ); + } + } +} diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 3237c89f15bc0..9da90c6e9e8e1 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -23,6 +23,7 @@ import './hooks'; import { store as editSiteStore } from './store'; import EditSiteApp from './components/app'; import getIsListPage from './utils/get-is-list-page'; +import { redirectToHomepage } from './components/routes/redirect-to-homepage'; /** * Reinitializes the editor after the user chooses to reboot the editor after @@ -32,7 +33,14 @@ import getIsListPage from './utils/get-is-list-page'; * @param {Element} target DOM node in which editor is rendered. * @param {?Object} settings Editor settings object. */ -export function reinitializeEditor( target, settings ) { +export async function reinitializeEditor( target, settings ) { + // The site editor relies on `postType` and `postId` params in the URL to + // define what's being edited. When visiting via the dashboard link, these + // won't be present. Do a client side redirect to the 'homepage' if that's + // the case. This requires editor settings, so dispatch that first. + dispatch( editSiteStore ).updateSettings( settings ); + await redirectToHomepage(); + // This will be a no-op if the target doesn't have any React nodes. unmountComponentAtNode( target ); const reboot = reinitializeEditor.bind( null, target, settings ); @@ -40,7 +48,6 @@ export function reinitializeEditor( target, settings ) { // We dispatch actions and update the store synchronously before rendering // so that we won't trigger unnecessary re-renders with useEffect. { - dispatch( editSiteStore ).updateSettings( settings ); // Keep the defaultTemplateTypes in the core/editor settings too, // so that they can be selected with core/editor selectors in any editor. // This is needed because edit-site doesn't initialize with EditorProvider, diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index 4ebc2ff2a170e..e64dd8ad8cd5e 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -123,51 +123,6 @@ export const getSettings = createSelector( ] ); -/** - * Get the homepage query parameters. These are used to redirect the site - * editor when entered accessed without postType or postId params. - * - * @param {Object} state Global application state. - * - * @return {?Object} An object containing postType and postId properties. - */ -export const getHomepageParams = createRegistrySelector( - ( select ) => ( state ) => { - const siteSettings = select( coreDataStore ).getSite(); - if ( ! siteSettings ) { - return; - } - - const { - show_on_front: showOnFront, - page_on_front: frontpageId, - } = siteSettings; - - // If the user has set a page as the homepage, use those details. - if ( showOnFront === 'page' ) { - return { - postType: 'page', - postId: frontpageId, - }; - } - - // Else get the home template. - const { siteUrl } = getSettings( state ); - const template = select( - coreDataStore - ).__experimentalGetTemplateForLink( siteUrl ); - - if ( ! template ) { - return; - } - - return { - postType: 'wp_template', - postId: template.id, - }; - } -); - /** * Returns the current home template ID. * From 0179fccbfda7e13c8b4f0f5b7d2a05d02d600880 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 13 Dec 2021 16:45:17 +0800 Subject: [PATCH 4/5] Use a default export --- .../edit-site/src/components/routes/redirect-to-homepage.js | 2 +- packages/edit-site/src/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/routes/redirect-to-homepage.js b/packages/edit-site/src/components/routes/redirect-to-homepage.js index 29fd0d1bcb054..c1ff1f7112be7 100644 --- a/packages/edit-site/src/components/routes/redirect-to-homepage.js +++ b/packages/edit-site/src/components/routes/redirect-to-homepage.js @@ -60,7 +60,7 @@ async function getHomepageParams() { }; } -export async function redirectToHomepage() { +export default async function redirectToHomepage() { const searchParams = new URLSearchParams( history.location.search ); const params = Object.fromEntries( searchParams.entries() ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 9da90c6e9e8e1..b73a80f19849c 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -23,7 +23,7 @@ import './hooks'; import { store as editSiteStore } from './store'; import EditSiteApp from './components/app'; import getIsListPage from './utils/get-is-list-page'; -import { redirectToHomepage } from './components/routes/redirect-to-homepage'; +import redirectToHomepage from './components/routes/redirect-to-homepage'; /** * Reinitializes the editor after the user chooses to reboot the editor after From 7cdd4bebfbe7a4f98404b7d200aae6fbfc915ad4 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 13 Dec 2021 17:05:32 +0800 Subject: [PATCH 5/5] Pass siteUrl in as a param --- .../src/components/routes/redirect-to-homepage.js | 9 +++------ packages/edit-site/src/index.js | 7 ++++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/edit-site/src/components/routes/redirect-to-homepage.js b/packages/edit-site/src/components/routes/redirect-to-homepage.js index c1ff1f7112be7..bb68c6f44aad3 100644 --- a/packages/edit-site/src/components/routes/redirect-to-homepage.js +++ b/packages/edit-site/src/components/routes/redirect-to-homepage.js @@ -2,14 +2,12 @@ * WordPress dependencies */ import apiFetch from '@wordpress/api-fetch'; -import { select } from '@wordpress/data'; import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies */ import history from '../../utils/history'; -import { store as editSiteStore } from '../../store'; import getIsListPage from '../../utils/get-is-list-page'; function getNeedsHomepageRedirect( params ) { @@ -22,7 +20,7 @@ function getNeedsHomepageRedirect( params ) { ); } -async function getHomepageParams() { +async function getHomepageParams( siteUrl ) { const siteSettings = await apiFetch( { path: '/wp/v2/settings' } ); if ( ! siteSettings ) { return; @@ -44,7 +42,6 @@ async function getHomepageParams() { // Else get the home template. // This matches the logic in `__experimentalGetTemplateForLink`. // (packages/core-data/src/resolvers.js) - const { siteUrl } = select( editSiteStore ).getSettings(); const template = await window .fetch( addQueryArgs( siteUrl, { '_wp-find-template': true } ) ) .then( ( res ) => res.json() ) @@ -60,12 +57,12 @@ async function getHomepageParams() { }; } -export default async function redirectToHomepage() { +export default async function redirectToHomepage( siteUrl ) { const searchParams = new URLSearchParams( history.location.search ); const params = Object.fromEntries( searchParams.entries() ); if ( getNeedsHomepageRedirect( params ) ) { - const homepageParams = await getHomepageParams(); + const homepageParams = await getHomepageParams( siteUrl ); if ( homepageParams ) { history.replace( homepageParams ); diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index b73a80f19849c..c6dcdf3073f4c 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -37,9 +37,8 @@ export async function reinitializeEditor( target, settings ) { // The site editor relies on `postType` and `postId` params in the URL to // define what's being edited. When visiting via the dashboard link, these // won't be present. Do a client side redirect to the 'homepage' if that's - // the case. This requires editor settings, so dispatch that first. - dispatch( editSiteStore ).updateSettings( settings ); - await redirectToHomepage(); + // the case. + await redirectToHomepage( settings.siteUrl ); // This will be a no-op if the target doesn't have any React nodes. unmountComponentAtNode( target ); @@ -48,6 +47,8 @@ export async function reinitializeEditor( target, settings ) { // We dispatch actions and update the store synchronously before rendering // so that we won't trigger unnecessary re-renders with useEffect. { + dispatch( editSiteStore ).updateSettings( settings ); + // Keep the defaultTemplateTypes in the core/editor settings too, // so that they can be selected with core/editor selectors in any editor. // This is needed because edit-site doesn't initialize with EditorProvider,