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
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
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 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
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