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 all 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
60 changes: 51 additions & 9 deletions packages/e2e-tests/experimental-features.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,55 @@ export function useExperimentalFeatures( features ) {
afterAll( () => setExperimentalFeaturesState( features, false ) );
}

export const openNavigation = async () => {
const isOpen = !! ( await page.$(
'.edit-site-navigation-toggle.is-open'
) );

if ( ! isOpen ) {
await page.click( '.edit-site-navigation-toggle__button' );
await page.waitForSelector( '.edit-site-navigation-panel' );
}
export const navigationPanel = {
async open() {
const isOpen = !! ( await page.$(
'.edit-site-navigation-toggle.is-open'
) );

if ( ! isOpen ) {
await page.click( '.edit-site-navigation-toggle__button' );
await page.waitForSelector( '.edit-site-navigation-panel' );
}
},

async isRoot() {
const isBackToDashboardButtonVisible = !! ( await page.$(
'.edit-site-navigation-panel .edit-site-navigation-panel__back-to-dashboard'
) );

return isBackToDashboardButtonVisible;
},

async back() {
await page.click( '.components-navigation__back-button' );
},

async navigate( menus ) {
if ( ! Array.isArray( menus ) ) {
menus = [ menus ];
}

for ( const menu of menus ) {
( await this.getItemByText( menu ) ).click();
}
},

async backToRoot() {
while ( ! ( await this.isRoot() ) ) {
await this.back();
}
},

async getItemByText( text ) {
const selector = `//div[contains(@class, "edit-site-navigation-panel")]//button[contains(., "${ text }")]`;
await page.waitForXPath( selector );
const [ item ] = await page.$x( selector );
return item;
},

async clickItemByText( text ) {
const item = await this.getItemByText( text );
await item.click();
},
};
19 changes: 8 additions & 11 deletions packages/e2e-tests/specs/experiments/multi-entity-editing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { addQueryArgs } from '@wordpress/url';
*/
import {
useExperimentalFeatures,
openNavigation,
navigationPanel,
} from '../../experimental-features';

const visitSiteEditor = async () => {
Expand All @@ -34,12 +34,11 @@ const visitSiteEditor = async () => {
);
};

const getTemplateDropdownElement = async ( itemName ) => {
await openNavigation();
const selector = `//div[contains(@class, "edit-site-navigation-panel")]//button[contains(., "${ itemName }")]`;
await page.waitForXPath( selector );
const [ item ] = await page.$x( selector );
return item;
const clickTemplateItem = async ( menus, itemName ) => {
await navigationPanel.open();
await navigationPanel.backToRoot();
await navigationPanel.navigate( menus );
await navigationPanel.clickItemByText( itemName );
};

const createTemplatePart = async (
Expand Down Expand Up @@ -169,17 +168,15 @@ describe( 'Multi-entity editor states', () => {
} );

it( 'should not dirty an entity by switching to it in the template dropdown', async () => {
const templatePartButton = await getTemplateDropdownElement( 'header' );
await templatePartButton.click();
await clickTemplateItem( 'Template parts', 'header' );

// Wait for blocks to load.
await page.waitForSelector( '.wp-block' );
expect( await isEntityDirty( 'header' ) ).toBe( false );
expect( await isEntityDirty( 'front-page' ) ).toBe( false );

// Switch back and make sure it is still clean.
const templateButton = await getTemplateDropdownElement( 'front-page' );
await templateButton.click();
await clickTemplateItem( 'Templates', 'Front page' );
await page.waitForSelector( '.wp-block' );
expect( await isEntityDirty( 'header' ) ).toBe( false );
expect( await isEntityDirty( 'front-page' ) ).toBe( false );
Expand Down
12 changes: 5 additions & 7 deletions packages/e2e-tests/specs/experiments/multi-entity-saving.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { addQueryArgs } from '@wordpress/url';
*/
import {
useExperimentalFeatures,
openNavigation,
navigationPanel,
} from '../../experimental-features';

describe( 'Multi-entity save flow', () => {
Expand Down Expand Up @@ -221,7 +221,6 @@ describe( 'Multi-entity save flow', () => {

describe( 'Site Editor', () => {
// Selectors - Site editor specific.
const demoTemplateSelector = '//button[contains(., "front-page")]';
const saveSiteSelector = '.edit-site-save-button__button';
const activeSaveSiteSelector = `${ saveSiteSelector }[aria-disabled=false]`;
const disabledSaveSiteSelector = `${ saveSiteSelector }[aria-disabled=true]`;
Expand All @@ -235,11 +234,10 @@ describe( 'Multi-entity save flow', () => {
await visitAdminPage( 'admin.php', query );

// Ensure we are on 'front-page' demo template.
await openNavigation();
const demoTemplateButton = await page.waitForXPath(
demoTemplateSelector
);
await demoTemplateButton.click();
await navigationPanel.open();
await navigationPanel.backToRoot();
await navigationPanel.navigate( 'Templates' );
await navigationPanel.clickItemByText( 'Front page' );

// Insert a new template part placeholder.
await insertBlock( 'Template Part' );
Expand Down
20 changes: 9 additions & 11 deletions packages/e2e-tests/specs/experiments/template-part.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { addQueryArgs } from '@wordpress/url';
*/
import {
useExperimentalFeatures,
openNavigation,
navigationPanel,
} from '../../experimental-features';

describe( 'Template Part', () => {
Expand Down Expand Up @@ -46,11 +46,10 @@ describe( 'Template Part', () => {

it( 'Should load customizations when in a template even if only the slug and theme attributes are set.', async () => {
// Switch to editing the header template part.
await openNavigation();
const switchToHeaderTemplatePartButton = await page.waitForXPath(
'//button[contains(text(), "header")]'
);
await switchToHeaderTemplatePartButton.click();
await navigationPanel.open();
await navigationPanel.backToRoot();
await navigationPanel.navigate( 'Template parts' );
await navigationPanel.clickItemByText( 'header' );

// Edit it.
await insertBlock( 'Paragraph' );
Expand All @@ -64,11 +63,10 @@ describe( 'Template Part', () => {
);

// Switch back to the front page template.
await openNavigation();
const [ switchToFrontPageTemplateButton ] = await page.$x(
'//button[contains(text(), "front-page")]'
);
await switchToFrontPageTemplateButton.click();
await navigationPanel.open();
await navigationPanel.backToRoot();
await navigationPanel.navigate( 'Templates' );
await navigationPanel.clickItemByText( 'Front page' );

// Verify that the header template part is updated.
const [ headerTemplatePart ] = await page.$x(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
export const TEMPLATES_DEFAULT_DETAILS = {
// 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 TEMPLATES_GENERAL = [
'front-page',
'archive',
'single',
'singular',
'index',
'search',
'404',
];

export const TEMPLATES_POSTS = [ 'single-post', 'archive-post', 'home' ];
Loading