Skip to content

Commit

Permalink
Add client side routing for Site Editor (#36488)
Browse files Browse the repository at this point in the history
* Add client side router

* Use saveEntityRecord to update the store

* Fix updating state in unmounted components

* Update titles when page navigates

* Use slot/fill for NavigationSidebar

* Announce title change

* Inline all api requests

* Fix php lint errors

* Make title announcement assertive

* Fix infinite loop in page navigation

* Fix duplicate main roles

* Fix not announcing same titles

* Try to fix url query controller

* Add UnsavedWarning to list page too

* Add now displaying to use-title's speak
  • Loading branch information
kevin940726 authored and noisysocks committed Dec 13, 2021
1 parent 9e1d551 commit c78c7ac
Show file tree
Hide file tree
Showing 30 changed files with 632 additions and 539 deletions.
67 changes: 12 additions & 55 deletions lib/full-site-editing/edit-site-page.php
Original file line number Diff line number Diff line change
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 Down Expand Up @@ -166,10 +125,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 @@ -191,13 +146,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ export default function CreateTemplatePartModal( { closeModal, onCreate } ) {
}
setIsSubmitting( true );
await onCreate( { title, area } );
setIsSubmitting( false );
closeModal();
} }
>
<TextControl
Expand Down
Loading

0 comments on commit c78c7ac

Please sign in to comment.