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

Implement "Add New" for templates list in Site Editor #36592

Merged
merged 5 commits into from Nov 19, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 17 additions & 13 deletions lib/full-site-editing/edit-site-page.php
Expand Up @@ -78,8 +78,10 @@ function gutenberg_get_editor_styles() {

/**
* Initialize the Gutenberg Templates List Page.
*
* @param array $settings The editor settings.
*/
function gutenberg_edit_site_list_init() {
function gutenberg_edit_site_list_init( $settings ) {
wp_enqueue_script( 'wp-edit-site' );
wp_enqueue_style( 'wp-edit-site' );
wp_enqueue_media();
Expand Down Expand Up @@ -111,10 +113,11 @@ function gutenberg_edit_site_list_init() {
'wp-edit-site',
sprintf(
'wp.domReady( function() {
wp.editSite.initializeList( "%s", "%s" );
wp.editSite.initializeList( "%s", "%s", %s );
} );',
'edit-site-editor',
$template_type
$template_type,
wp_json_encode( $settings )
)
);
}
Expand Down Expand Up @@ -142,8 +145,18 @@ static function( $classes ) {
}
);

$custom_settings = array(
'siteUrl' => site_url(),
'postsPerPage' => get_option( 'posts_per_page' ),
'styles' => gutenberg_get_editor_styles(),
'defaultTemplateTypes' => gutenberg_get_indexed_default_template_types(),
'defaultTemplatePartAreas' => get_allowed_block_template_part_areas(),
'__experimentalBlockPatterns' => WP_Block_Patterns_Registry::get_instance()->get_all_registered(),
'__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
);

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

/**
Expand All @@ -154,15 +167,6 @@ static function( $classes ) {
*/
$current_screen->is_block_editor( true );

$custom_settings = array(
'siteUrl' => site_url(),
'postsPerPage' => get_option( 'posts_per_page' ),
'styles' => gutenberg_get_editor_styles(),
'defaultTemplateTypes' => gutenberg_get_indexed_default_template_types(),
'defaultTemplatePartAreas' => get_allowed_block_template_part_areas(),
'__experimentalBlockPatterns' => WP_Block_Patterns_Registry::get_instance()->get_all_registered(),
'__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
);
$site_editor_context = new WP_Block_Editor_Context();
$settings = gutenberg_get_block_editor_settings( $custom_settings, $site_editor_context );
$active_global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_custom_post_type_id();
Expand Down
2 changes: 1 addition & 1 deletion packages/base-styles/_z-index.scss
Expand Up @@ -139,7 +139,7 @@ $z-layers: (

// Should be above the popover (dropdown)
".reusable-blocks-menu-items__convert-modal": 1000001,
".edit-site-template-part-converter__modal": 1000001,
".edit-site-create-template-part-modal": 1000001,

// ...Except for popovers immediately beneath wp-admin menu on large breakpoints
".components-popover.block-editor-inserter__popover": 99999,
Expand Down
Expand Up @@ -19,7 +19,7 @@ import {
import { siteEditor } from '../../experimental-features';

const templatePartNameInput =
'.edit-site-template-part-converter__modal .components-text-control__input';
'.edit-site-create-template-part-modal .components-text-control__input';

describe( 'Template Part', () => {
beforeAll( async () => {
Expand Down
30 changes: 30 additions & 0 deletions packages/edit-site/src/components/add-new-template/index.js
@@ -0,0 +1,30 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import NewTemplate from './new-template';
import NewTemplatePart from './new-template-part';

export default function AddNewTemplate( { templateType = 'wp_template' } ) {
const postType = useSelect(
( select ) => select( coreStore ).getPostType( templateType ),
[ templateType ]
);

if ( ! postType ) {
return null;
}

if ( templateType === 'wp_template' ) {
return <NewTemplate postType={ postType } />;
} else if ( templateType === 'wp_template_part' ) {
return <NewTemplatePart postType={ postType } />;
}

return null;
}
@@ -0,0 +1,67 @@
/**
* External dependencies
*/
import { kebabCase } from 'lodash';

/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
import { Button } from '@wordpress/components';
import { addQueryArgs } from '@wordpress/url';
import apiFetch from '@wordpress/api-fetch';

/**
* Internal dependencies
*/
import CreateTemplatePartModal from '../create-template-part-modal';

export default function NewTemplatePart( { postType } ) {
const [ isModalOpen, setIsModalOpen ] = useState( false );

async function createTemplatePart( { title, area } ) {
if ( ! title ) {
return;
}

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

// Navigate to the created template part editor.
window.location.search = addQueryArgs( '', {
page: 'gutenberg-edit-site',
postId: templatePart.id,
postType: 'wp_template_part',
} );

// Wait for async navigation to happen before closing the modal.
await new Promise( () => {} );
}

return (
<>
<Button
variant="primary"
onClick={ () => {
setIsModalOpen( true );
} }
>
{ postType.labels.add_new }
</Button>
{ isModalOpen && (
<CreateTemplatePartModal
closeModal={ () => setIsModalOpen( false ) }
onCreate={ createTemplatePart }
/>
) }
</>
);
}
117 changes: 117 additions & 0 deletions packages/edit-site/src/components/add-new-template/new-template.js
@@ -0,0 +1,117 @@
/**
* External dependencies
*/
import { filter, find, includes, map } from 'lodash';

/**
* WordPress dependencies
*/
import {
DropdownMenu,
MenuGroup,
MenuItem,
NavigableMenu,
} from '@wordpress/components';
import { useSelect } 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';

const DEFAULT_TEMPLATE_SLUGS = [
'front-page',
'single-post',
'page',
'archive',
'search',
'404',
'index',
];

export default function NewTemplate( { postType } ) {
const { templates, defaultTemplateTypes } = useSelect(
( select ) => ( {
templates: select( coreStore ).getEntityRecords(
'postType',
'wp_template'
),
defaultTemplateTypes: select(
editorStore
).__experimentalGetDefaultTemplateTypes(),
} ),
[]
);

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

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

// Navigate to the created template editor.
window.location.search = addQueryArgs( '', {
page: 'gutenberg-edit-site',
postId: template.id,
postType: 'wp_template',
} );
}

const existingTemplateSlugs = map( templates, 'slug' );

const missingTemplates = filter(
defaultTemplateTypes,
( template ) =>
includes( DEFAULT_TEMPLATE_SLUGS, template.slug ) &&
! includes( existingTemplateSlugs, template.slug )
);

if ( ! missingTemplates.length ) {
return null;
}

return (
<DropdownMenu
className="edit-site-new-template-dropdown"
icon={ null }
text={ postType.labels.add_new }
label={ postType.labels.add_new_item }
popoverProps={ {
noArrow: false,
} }
toggleProps={ {
variant: 'primary',
} }
>
{ () => (
<NavigableMenu className="edit-site-new-template-dropdown__popover">
<MenuGroup label={ postType.labels.add_new_item }>
{ map(
missingTemplates,
( { title, description, slug } ) => (
<MenuItem
info={ description }
key={ slug }
onClick={ () => {
createTemplate( { slug } );
// We will be navigated way so no need to close the dropdown.
} }
>
{ title }
</MenuItem>
)
) }
</MenuGroup>
</NavigableMenu>
) }
</DropdownMenu>
);
}
11 changes: 11 additions & 0 deletions packages/edit-site/src/components/add-new-template/style.scss
@@ -0,0 +1,11 @@
.edit-site-new-template-dropdown {
.components-dropdown-menu__toggle {
padding: 6px 12px;
}

.edit-site-new-template-dropdown__popover {
@include break-small() {
min-width: 300px;
}
}
}