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

Add client side routing for Site Editor #36488

Merged
merged 15 commits into from Dec 9, 2021
Merged
67 changes: 12 additions & 55 deletions lib/full-site-editing/edit-site-page.php
Expand Up @@ -76,55 +76,6 @@ function gutenberg_get_editor_styles() {
return $styles;
}

/**
* Initialize the Gutenberg Templates List Page.
*
* @param array $settings The editor settings.
*/
function gutenberg_edit_site_list_init( $settings ) {
wp_enqueue_script( 'wp-edit-site' );
wp_enqueue_style( 'wp-edit-site' );
wp_enqueue_media();

$post_type = get_post_type_object( $_GET['postType'] );

if ( ! $post_type ) {
wp_die( __( 'Invalid post type.', 'gutenberg' ) );
}

$preload_data = array_reduce(
array(
'/',
"/wp/v2/types/$post_type->name?context=edit",
'/wp/v2/types?context=edit',
"/wp/v2/$post_type->rest_base?context=edit&per_page=-1",
),
'rest_preload_api_request',
array()
);

wp_add_inline_script(
'wp-api-fetch',
sprintf(
'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );',
wp_json_encode( $preload_data )
),
'after'
);

wp_add_inline_script(
'wp-edit-site',
sprintf(
'wp.domReady( function() {
wp.editSite.initializeList( "%s", "%s", %s );
} );',
'edit-site-editor',
$post_type->name,
wp_json_encode( $settings )
)
);
}

/**
* Initialize the Gutenberg Site Editor.
*
Expand All @@ -139,6 +90,14 @@ function gutenberg_edit_site_init( $hook ) {
return;
}

if ( gutenberg_is_edit_site_list_page() ) {
$post_type = get_post_type_object( $_GET['postType'] );

if ( ! $post_type ) {
wp_die( __( 'Invalid post type.', 'gutenberg' ) );
}
}

// Default to is-fullscreen-mode to avoid rendering wp-admin navigation menu while loading and
// having jumps in the UI.
add_filter(
Expand All @@ -158,10 +117,6 @@ static function( $classes ) {
'__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
);

if ( gutenberg_is_edit_site_list_page() ) {
return gutenberg_edit_site_list_init( $custom_settings );
}

/**
* Make the WP Screen object aware that this is a block editor page.
* Since custom blocks check whether the screen is_block_editor,
Expand All @@ -183,13 +138,15 @@ static function( $classes ) {
array( '/wp/v2/media', 'OPTIONS' ),
'/',
'/wp/v2/types?context=edit',
'/wp/v2/types/wp_template?context=edit',
'/wp/v2/types/wp_template-part?context=edit',
'/wp/v2/taxonomies?context=edit',
'/wp/v2/pages?context=edit',
'/wp/v2/categories?context=edit',
'/wp/v2/posts?context=edit',
'/wp/v2/tags?context=edit',
'/wp/v2/templates?context=edit',
'/wp/v2/template-parts?context=edit',
'/wp/v2/templates?context=edit&per_page=-1',
'/wp/v2/template-parts?context=edit&per_page=-1',
'/wp/v2/settings',
'/wp/v2/themes?context=edit&status=active',
'/wp/v2/global-styles/' . $active_global_styles_id . '?context=edit',
Expand Down
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/edit-site/package.json
Expand Up @@ -56,6 +56,7 @@
"classnames": "^2.3.1",
"downloadjs": "^1.4.7",
"file-saver": "^2.0.2",
"history": "^5.1.0",
"jszip": "^3.2.2",
"lodash": "^4.17.21",
"rememo": "^3.0.0"
Expand Down
Expand Up @@ -7,21 +7,24 @@ import { kebabCase } from 'lodash';
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';
import { Button } from '@wordpress/components';
import { addQueryArgs } from '@wordpress/url';
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import { useHistory } from '../routes';
import CreateTemplatePartModal from '../create-template-part-modal';

export default function NewTemplatePart( { postType } ) {
const history = useHistory();
const [ isModalOpen, setIsModalOpen ] = useState( false );
const { createErrorNotice } = useDispatch( noticesStore );
const { saveEntityRecord } = useDispatch( coreStore );
const { getLastEntitySaveError } = useSelect( coreStore );

async function createTemplatePart( { title, area } ) {
if ( ! title ) {
Expand All @@ -32,22 +35,35 @@ export default function NewTemplatePart( { postType } ) {
}

try {
const templatePart = await apiFetch( {
path: '/wp/v2/template-parts',
method: 'POST',
data: {
const templatePart = await saveEntityRecord(
'postType',
'wp_template_part',
{
slug: kebabCase( title ),
title,
content: '',
area,
},
} );
}
);

const lastEntitySaveError = getLastEntitySaveError(
'postType',
'wp_template_part',
templatePart.id
);
if ( lastEntitySaveError ) {
throw lastEntitySaveError;
}

setIsModalOpen( false );

// Navigate to the created template part editor.
window.location.href = addQueryArgs( window.location.href, {
history.push( {
postId: templatePart.id,
postType: 'wp_template_part',
postType: templatePart.type,
} );

// TODO: Add a success notice?
} catch ( error ) {
const errorMessage =
error.message && error.code !== 'unknown_error'
Expand All @@ -57,6 +73,8 @@ export default function NewTemplatePart( { postType } ) {
);

createErrorNotice( errorMessage, { type: 'snackbar' } );

setIsModalOpen( false );
}
}

Expand Down
38 changes: 26 additions & 12 deletions packages/edit-site/src/components/add-new-template/new-template.js
Expand Up @@ -15,11 +15,14 @@ import {
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { store as editorStore } from '@wordpress/editor';
import { addQueryArgs } from '@wordpress/url';
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';

/**
* Internal dependencies
*/
import { useHistory } from '../routes';

const DEFAULT_TEMPLATE_SLUGS = [
'front-page',
'single-post',
Expand All @@ -31,6 +34,7 @@ const DEFAULT_TEMPLATE_SLUGS = [
];

export default function NewTemplate( { postType } ) {
const history = useHistory();
const { templates, defaultTemplateTypes } = useSelect(
( select ) => ( {
templates: select( coreStore ).getEntityRecords(
Expand All @@ -44,34 +48,44 @@ export default function NewTemplate( { postType } ) {
} ),
[]
);
const { saveEntityRecord } = useDispatch( coreStore );
const { createErrorNotice } = useDispatch( noticesStore );
const { getLastEntitySaveError } = useSelect( coreStore );

async function createTemplate( { slug } ) {
try {
const { title, description } = find( defaultTemplateTypes, {
slug,
} );

const template = await apiFetch( {
path: '/wp/v2/templates',
method: 'POST',
data: {
const template = await saveEntityRecord(
'postType',
'wp_template',
{
excerpt: description,
// Slugs need to be strings, so this is for template `404`
slug: slug.toString(),
status: 'publish',
title,
},
} );
}
);

const lastEntitySaveError = getLastEntitySaveError(
'postType',
'wp_template',
template.id
);
if ( lastEntitySaveError ) {
throw lastEntitySaveError;
}

// Navigate to the created template editor.
window.location.href = addQueryArgs( window.location.href, {
history.push( {
postId: template.id,
postType: 'wp_template',
postType: template.type,
} );

// Wait for async navigation to happen before closing the modal.
await new Promise( () => {} );
// TODO: Add a success notice?
} catch ( error ) {
const errorMessage =
error.message && error.code !== 'unknown_error'
Expand Down
47 changes: 47 additions & 0 deletions packages/edit-site/src/components/app/index.js
@@ -0,0 +1,47 @@
/**
* WordPress dependencies
*/
import { SlotFillProvider } from '@wordpress/components';
import { UnsavedChangesWarning } from '@wordpress/editor';

/**
* Internal dependencies
*/
import { Routes } from '../routes';
import Editor from '../editor';
import List from '../list';
import NavigationSidebar from '../navigation-sidebar';
import getIsListPage from '../../utils/get-is-list-page';

export default function EditSiteApp( { reboot } ) {
return (
<SlotFillProvider>
<UnsavedChangesWarning />

<Routes>
{ ( { params } ) => {
const isListPage = getIsListPage( params );

return (
<>
{ isListPage ? (
<List />
) : (
<Editor onError={ reboot } />
) }
{ /* Keep the instance of the sidebar to ensure focus will not be lost
* when navigating to other pages. */ }
<NavigationSidebar
// Open the navigation sidebar by default when in the list page.
isDefaultOpen={ !! isListPage }
activeTemplateType={
isListPage ? params.postType : undefined
}
/>
</>
);
} }
</Routes>
</SlotFillProvider>
);
}
20 changes: 6 additions & 14 deletions packages/edit-site/src/components/block-editor/back-button.js
Expand Up @@ -3,26 +3,18 @@
*/
import { Button } from '@wordpress/components';
import { arrowLeft } from '@wordpress/icons';
import { useSelect, useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../store';
import { useLocation, useHistory } from '../routes';

function BackButton() {
const { isTemplatePart, previousTemplateId } = useSelect( ( select ) => {
const { getEditedPostType, getPreviousEditedPostId } = select(
editSiteStore
);

return {
isTemplatePart: getEditedPostType() === 'wp_template_part',
previousTemplateId: getPreviousEditedPostId(),
};
}, [] );
const { goBack } = useDispatch( editSiteStore );
const location = useLocation();
const history = useHistory();
const isTemplatePart = location.params.postType === 'wp_template_part';
const previousTemplateId = location.state?.fromTemplateId;

if ( ! isTemplatePart || ! previousTemplateId ) {
return null;
Expand All @@ -33,7 +25,7 @@ function BackButton() {
className="edit-site-visual-editor__back-button"
icon={ arrowLeft }
onClick={ () => {
goBack();
history.back();
} }
>
{ __( 'Back' ) }
Expand Down
Expand Up @@ -52,8 +52,6 @@ export default function CreateTemplatePartModal( { closeModal, onCreate } ) {
}
setIsSubmitting( true );
await onCreate( { title, area } );
setIsSubmitting( false );
closeModal();
} }
>
<TextControl
Expand Down