Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Site editor - try redirecting to homepage before the react render #37248

Merged
merged 5 commits into from
Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions packages/edit-site/src/components/routes/redirect-to-homepage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* WordPress dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';

/**
* Internal dependencies
*/
import history from '../../utils/history';
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( siteUrl ) {
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,
};
}
Comment on lines +29 to +40
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this code is replicating showHomepage, but I wasn't sure how to test this as there's no customizer where this setting can be changed. Is it still possible to configure a homepage in this way?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can change some of these via Settings -> Reading -> Your homepage displays.


// Else get the home template.
// This matches the logic in `__experimentalGetTemplateForLink`.
// (packages/core-data/src/resolvers.js)
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 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( siteUrl );

if ( homepageParams ) {
history.replace( homepageParams );
}
}
}
38 changes: 3 additions & 35 deletions packages/edit-site/src/components/url-query-controller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion packages/edit-site/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -32,7 +33,13 @@ 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.
await redirectToHomepage( settings.siteUrl );

// This will be a no-op if the target doesn't have any React nodes.
unmountComponentAtNode( target );
const reboot = reinitializeEditor.bind( null, target, settings );
Expand All @@ -41,6 +48,7 @@ export function reinitializeEditor( target, settings ) {
// 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,
Expand Down
34 changes: 0 additions & 34 deletions packages/edit-site/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
90 changes: 0 additions & 90 deletions packages/edit-site/src/store/test/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
addTemplate,
setTemplatePart,
setPage,
showHomepage,
setHomeTemplateId,
setIsListViewOpened,
} from '../actions';
Expand Down Expand Up @@ -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;
Expand Down