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: Navigation templates #25739

Merged
merged 60 commits into from
Oct 6, 2020
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
da18be9
Extract everything we can and refactor
david-szabo97 Sep 30, 2020
186b244
Autodrafting for theme templates
david-szabo97 Sep 30, 2020
6c720c2
Remove unneccessary code
david-szabo97 Sep 30, 2020
dd60398
Extend findTemplate
david-szabo97 Sep 30, 2020
790ac20
Rename args
david-szabo97 Sep 30, 2020
5921992
Move optional parameters to the end
david-szabo97 Sep 30, 2020
4036921
Fix old name
david-szabo97 Sep 30, 2020
5b76047
Show all template parts
david-szabo97 Sep 30, 2020
9e74cc1
Remove current theme and preview
david-szabo97 Oct 1, 2020
4195108
Remove unused styles
david-szabo97 Oct 1, 2020
8cb3123
Remove current template group
david-szabo97 Oct 1, 2020
b9b2c02
Cleanup component and styles
david-szabo97 Oct 1, 2020
3d6a135
Remove template switcher folder
david-szabo97 Oct 1, 2020
637354a
Use original NavigationItem
david-szabo97 Oct 1, 2020
f34fc16
Remove NavigationItemWithIcon
david-szabo97 Oct 1, 2020
af092c0
Remove unused styles
david-szabo97 Oct 1, 2020
06faa7c
Remove unused prop
david-szabo97 Oct 2, 2020
3ba796d
Fix typo
david-szabo97 Oct 2, 2020
969ff62
Remove unused property
david-szabo97 Oct 2, 2020
6e1c693
Return template directly
david-szabo97 Oct 2, 2020
c40e390
Merge selects
david-szabo97 Oct 2, 2020
9c6e04a
Extract templates as a hook
david-szabo97 Oct 5, 2020
9e2b8e8
Extract useTemplates to its own file
david-szabo97 Oct 5, 2020
88e3f45
Create TemplateNavigationItems component
david-szabo97 Oct 5, 2020
485f5fb
Fix prop
david-szabo97 Oct 5, 2020
1608e3a
Add titles
david-szabo97 Oct 5, 2020
0817526
Move preview to TemplateNavigationItems
david-szabo97 Oct 5, 2020
0d8ab08
Add description to items
david-szabo97 Oct 5, 2020
e694a7b
Use destructuring
david-szabo97 Oct 5, 2020
e5711c2
Fix height of item
david-szabo97 Oct 5, 2020
1a56595
Use slug for template parts too
david-szabo97 Oct 5, 2020
ba847e8
Create slot-fill for preview panel
david-szabo97 Oct 5, 2020
c6b07a0
Add query args to show all
david-szabo97 Oct 5, 2020
4f7c00a
NavigationMenu must be rendered
david-szabo97 Oct 5, 2020
6ba556d
Add posts
david-szabo97 Oct 5, 2020
976ed93
Add titles and descriptions for items
david-szabo97 Oct 5, 2020
e72bba7
Fix stying
david-szabo97 Oct 5, 2020
4e3b47b
Fix typo
david-szabo97 Oct 5, 2020
d4873a6
Add page title and desc
david-szabo97 Oct 5, 2020
1218680
Use ID for activeItem
david-szabo97 Oct 6, 2020
086e39e
Fix cache invalidation
david-szabo97 Oct 6, 2020
c8b1d4c
Add documentation
david-szabo97 Oct 6, 2020
71ceb5b
Return template file content
david-szabo97 Oct 6, 2020
7990a9b
Sort by slug to make order deterministic
david-szabo97 Oct 6, 2020
bf02206
Revert "Use ID for activeItem"
david-szabo97 Oct 6, 2020
a081994
Add comment
david-szabo97 Oct 6, 2020
24d2293
Use destructured
david-szabo97 Oct 6, 2020
d239fbb
Extract constants
david-szabo97 Oct 6, 2020
7a2600d
Create auto-draft automatically when templates are requested
david-szabo97 Oct 6, 2020
38c4ce5
Revert "Revert "Use ID for activeItem""
david-szabo97 Oct 6, 2020
787e076
Inline useTemplates
david-szabo97 Oct 6, 2020
2cc0c62
Format PHP
david-szabo97 Oct 6, 2020
a369fd7
Update e2e tests
david-szabo97 Oct 6, 2020
34d5078
Use entityType
david-szabo97 Oct 6, 2020
83b3597
Use title and excerpt if available
david-szabo97 Oct 6, 2020
d74ae61
Format PHP
david-szabo97 Oct 6, 2020
51c9075
Rename constants
david-szabo97 Oct 6, 2020
abfcfa5
Standarize activate prop
david-szabo97 Oct 6, 2020
41c0bd3
Fix title
david-szabo97 Oct 6, 2020
6a4d721
Add all templates menu
david-szabo97 Oct 6, 2020
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
13 changes: 1 addition & 12 deletions lib/template-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -255,18 +255,7 @@ function gutenberg_find_template_post_and_parts( $template_type, $template_hiera
// See if there is a theme block template with higher priority than the resolved template post.
$higher_priority_block_template_path = null;
$higher_priority_block_template_priority = PHP_INT_MAX;
$block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html' );
$block_template_files = is_array( $block_template_files ) ? $block_template_files : array();
if ( is_child_theme() ) {
$child_block_template_files = glob( get_template_directory() . '/block-templates/*.html' );
$child_block_template_files = is_array( $child_block_template_files ) ? $child_block_template_files : array();
$block_template_files = array_merge( $block_template_files, $child_block_template_files );
}
if ( gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing-demo' ) ) {
$demo_block_template_files = glob( dirname( __FILE__ ) . '/demo-block-templates/*.html' );
$demo_block_template_files = is_array( $demo_block_template_files ) ? $demo_block_template_files : array();
$block_template_files = array_merge( $block_template_files, $demo_block_template_files );
}
$block_template_files = gutenberg_get_template_paths();
foreach ( $block_template_files as $path ) {
if ( ! isset( $slug_priorities[ basename( $path, '.html' ) ] ) ) {
continue;
Expand Down
32 changes: 32 additions & 0 deletions lib/templates.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@
* @package gutenberg
*/

/**
* Returns all block template file path of the current theme and its parent theme.
* Includes demo block template files if demo experiment is enabled.
*
* @return array $block_template_files A list of paths to all template files.
*/
function gutenberg_get_template_paths() {
$block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html' );
$block_template_files = is_array( $block_template_files ) ? $block_template_files : array();

if ( is_child_theme() ) {
$child_block_template_files = glob( get_template_directory() . '/block-templates/*.html' );
$child_block_template_files = is_array( $child_block_template_files ) ? $child_block_template_files : array();
$block_template_files = array_merge( $block_template_files, $child_block_template_files );
}

if ( gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing-demo' ) ) {
$demo_block_template_files = glob( dirname( __FILE__ ) . '/demo-block-templates/*.html' );
$demo_block_template_files = is_array( $demo_block_template_files ) ? $demo_block_template_files : array();
$block_template_files = array_merge( $block_template_files, $demo_block_template_files );
}

return $block_template_files;
}

/**
* Registers block editor 'wp_template' post type.
*/
Expand Down Expand Up @@ -177,6 +202,13 @@ function filter_rest_wp_template_collection_params( $query_params ) {
* @return array Filtered $args.
*/
function filter_rest_wp_template_query( $args, $request ) {
// Create auto-drafts for each theme template files
$block_template_files = gutenberg_get_template_paths();
Copy link
Member

Choose a reason for hiding this comment

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

As already mentioned, accessing these files on each request is going to have a negative impact on performance. We can probably store this info once on theme activation and we'll also need it after theme updates.

foreach ( $block_template_files as $path ) {
$template_type = basename( $path, '.html' );
gutenberg_find_template_post_and_parts( $template_type, array( $template_type ) );
}

if ( $request['resolved'] ) {
$template_ids = array( 0 ); // Return nothing by default (the 0 is needed for `post__in`).
$template_types = $request['slug'] ? $request['slug'] : get_template_types();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export const ITEM_CONTENTS = {
// General
'front-page': {
title: 'Front page',
description: '',
Copy link
Member

Choose a reason for hiding this comment

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

We could've added "Display the contents of your Front Page" here, or something along the similar lines.

Copy link
Contributor

Choose a reason for hiding this comment

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

@david-szabo97 @vindl — Let's not forget i18n. Constants files like this should be i18n-ready from the start, otherwise getting everything ready for a testable Site Editor around WP 5.6 will be much more difficult.

Copy link
Contributor

Choose a reason for hiding this comment

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

@mcsf My fault, I should have caught this in review!
I'll spin up a PR ASAP.

},
archive: {
title: 'Archive',
description:
'Displays the content lists when no other template is found',
},
single: {
title: 'Single',
description: 'Displays the content of a single post',
},
singular: {
title: 'Singular',
description: 'Displays the content of a single page',
},
index: {
title: 'Default (index)',
description: 'Displays the content of a single page',
},
search: {
title: 'Search results',
description: '',
},
'404': {
title: '404',
description: 'Displayed when a non-existing page requested',
},

// Pages
page: {
title: 'Default (Page)',
description: 'Displays the content of a single page',
},

// Posts
home: {
title: 'Posts (home)',
description: 'Displayed on your homepage',
},
'archive-post': {
title: 'Default (Post archive)',
description: 'Displays a list of posts',
},
'single-post': {
title: 'Default (Single post)',
description: 'Displays the content of a single post',
},
};

export const GENERAL_TEMPLATES = [
'front-page',
'archive',
'single',
'singular',
'index',
'search',
'404',
];

export const POSTS_GENERAL_TEMPLATES = [
'single-post',
'archive-post',
'home',
];
Original file line number Diff line number Diff line change
@@ -1,52 +1,54 @@
/**
* WordPress dependencies
*/
import { useEffect, useRef } from '@wordpress/element';
import { useEffect, useRef, useState } from '@wordpress/element';
import {
__experimentalNavigation as Navigation,
__experimentalNavigationMenu as NavigationMenu,
__experimentalNavigationItem as NavigationItem,
__experimentalNavigationBackButton as NavigationBackButton,
createSlotFill,
} from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import TemplateSwitcher from './template-switcher';
import TemplatesMenu from './menus/templates';
import TemplatePartsMenu from './menus/template-parts';

export const {
Fill: NavigationPanelPreviewFill,
Slot: NavigationPanelPreviewSlot,
} = createSlotFill( 'EditSiteNavigationPanelPreview' );

const NavigationPanel = () => {
const [ activeMenu, setActiveMenu ] = useState( 'root' );
const ref = useRef();

useEffect( () => {
ref.current.focus();
}, [ ref ] );

const { templateId, templatePartId, templateType, page } = useSelect(
const { templateId, templatePartId, templateType } = useSelect(
( select ) => {
const {
getTemplateId,
getTemplatePartId,
getTemplateType,
getPage,
} = select( 'core/edit-site' );

return {
templateId: getTemplateId(),
templatePartId: getTemplatePartId(),
templateType: getTemplateType(),
page: getPage(),
};
},
[]
);

const {
setTemplate,
addTemplate,
removeTemplate,
setTemplatePart,
} = useDispatch( 'core/edit-site' );
const { setTemplate, setTemplatePart } = useDispatch( 'core/edit-site' );

return (
<div className="edit-site-navigation-panel">
Expand All @@ -56,25 +58,37 @@ const NavigationPanel = () => {
? `template-${ templateId }`
: `template-part-${ templatePartId }`
}
onActivateMenu={ setActiveMenu }
>
<NavigationBackButton
backButtonLabel={ __( 'Dashboard' ) }
className="edit-site-navigation-panel__back-to-dashboard"
href="index.php"
ref={ ref }
/>
{ activeMenu === 'root' && (
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm cool with this change, but I wonder if it might have a11y implications — either way I mean. 🤔

Copy link
Member Author

@david-szabo97 david-szabo97 Oct 6, 2020

Choose a reason for hiding this comment

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

Two back button is strange, that was the main reason I removed this back button. I'm not sure how it affects a11y.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, two back buttons is strange, but at the same time one of them (back to dashboard) is "outside" the navigation menu context.
So, it might not be clear for visually impaired users why that button disappeared while navigating through the menu.

This is all anecdotal, though.
As I said, the change looks good to me, and it's super simple to revert. 🙂

<NavigationBackButton
backButtonLabel={ __( 'Dashboard' ) }
className="edit-site-navigation-panel__back-to-dashboard"
href="index.php"
ref={ ref }
/>
) }

<NavigationMenu title="Theme">
<NavigationItem
title="Templates"
navigateToMenu="templates"
/>

<NavigationMenu title="Home">
<TemplateSwitcher
page={ page }
activeId={ templateId }
onActiveIdChange={ setTemplate }
<NavigationItem
title="Template parts"
navigateToMenu="template-parts"
/>

<TemplatesMenu onActiveIdChange={ setTemplate } />

<TemplatePartsMenu
onActiveTemplatePartIdChange={ setTemplatePart }
onAddTemplate={ addTemplate }
onRemoveTemplate={ removeTemplate }
/>
</NavigationMenu>
</Navigation>

<NavigationPanelPreviewSlot />
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import {
__experimentalNavigationItem as NavigationItem,
__experimentalNavigationMenu as NavigationMenu,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import TemplateNavigationItems from '../template-navigation-items';

export default function TemplatePartsMenu( { onActiveTemplatePartIdChange } ) {
const templateParts = useSelect( ( select ) => {
const currentTheme = select( 'core' ).getCurrentTheme()?.textdomain;

return select( 'core' ).getEntityRecords(
'postType',
'wp_template_part',
{
theme: currentTheme,
status: [ 'publish', 'auto-draft' ],
per_page: -1,
}
);
}, [] );

return (
<NavigationMenu
menu="template-parts"
title="Template Parts"
parentMenu="root"
>
<TemplateNavigationItems
entityType="wp_template_part"
templates={ templateParts }
onActivate={ onActiveTemplatePartIdChange }
/>

{ ! templateParts && <NavigationItem title={ __( 'Loading…' ) } /> }
</NavigationMenu>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* WordPress dependencies
*/
import {
__experimentalNavigationGroup as NavigationGroup,
__experimentalNavigationMenu as NavigationMenu,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import TemplateNavigationItems from '../template-navigation-items';

export default function TemplatesPagesMenu( { templates, onActiveIdChange } ) {
const defaultTemplate = templates?.find( ( { slug } ) => slug === 'page' );
const specificPageTemplates = templates?.filter( ( { slug } ) =>
slug.startsWith( 'page-' )
);

return (
<NavigationMenu
menu="templates-pages"
title="Pages"
parentMenu="templates"
>
<NavigationGroup title="Specific">
<TemplateNavigationItems
templates={ specificPageTemplates }
onActivate={ onActiveIdChange }
/>
</NavigationGroup>

{ defaultTemplate && (
<NavigationGroup title="General">
<TemplateNavigationItems
templates={ defaultTemplate }
onActivate={ onActiveIdChange }
/>
</NavigationGroup>
) }
</NavigationMenu>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* WordPress dependencies
*/
import {
__experimentalNavigationGroup as NavigationGroup,
__experimentalNavigationMenu as NavigationMenu,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import TemplateNavigationItems from '../template-navigation-items';
import { POSTS_GENERAL_TEMPLATES } from '../constants';

export default function TemplatePostsMenu( { templates, onActiveIdChange } ) {
const generalTemplates = templates?.find( ( { slug } ) =>
POSTS_GENERAL_TEMPLATES.includes( slug )
);
const specificTemplates = templates?.filter( ( { slug } ) =>
slug.startsWith( 'post-' )
);

return (
<NavigationMenu
Copy link
Member

Choose a reason for hiding this comment

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

We could've delayed adding this until we had actual content for it.

menu="templates-posts"
title="Posts"
parentMenu="templates"
>
<NavigationGroup title="Specific">
<TemplateNavigationItems
templates={ specificTemplates }
onActivate={ onActiveIdChange }
/>
</NavigationGroup>

<NavigationGroup title="General">
<TemplateNavigationItems
templates={ generalTemplates }
onActivate={ onActiveIdChange }
/>
</NavigationGroup>
</NavigationMenu>
);
}
Loading