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: Organise semantic template parts #29030

Merged
merged 5 commits into from
Feb 17, 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
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ describe( 'Document Settings', () => {
// Navigate to a template part
await navigationPanel.open();
await navigationPanel.backToRoot();
await navigationPanel.navigate( 'Template Parts' );
// TODO: Change General to Headers once TT1 blocks categorise the template parts
await navigationPanel.navigate( [ 'Template Parts', 'General' ] );
await navigationPanel.clickItemByText( 'header' );

// Evaluate the document settings title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ describe( 'Multi-entity editor states', () => {

it( 'should not dirty an entity by switching to it in the template dropdown', async () => {
await siteEditor.visit();
await clickTemplateItem( 'Template Parts', 'header' );
// TODO: Change General to Headers once TT1 blocks categorise the template parts
await clickTemplateItem( [ 'Template Parts', 'General' ], 'header' );
await page.waitForFunction( () =>
Array.from( window.frames ).find(
( { name } ) => name === 'editor-canvas'
Expand Down
3 changes: 2 additions & 1 deletion packages/e2e-tests/specs/experiments/template-part.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ describe( 'Template Part', () => {
// Switch to editing the header template part.
await navigationPanel.open();
await navigationPanel.backToRoot();
await navigationPanel.navigate( 'Template Parts' );
// TODO: Change General to Headers once TT1 blocks categorise the template parts
await navigationPanel.navigate( [ 'Template Parts', 'General' ] );
await navigationPanel.clickItemByText( 'header' );

// Edit it.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

export const TEMPLATES_GENERAL = [
'front-page',
'archive',
Expand Down Expand Up @@ -30,3 +35,35 @@ export const MENU_TEMPLATES_PAGES = 'templates-pages';
export const MENU_TEMPLATES_POSTS = 'templates-posts';

export const SEARCH_DEBOUNCE_IN_MS = 75;

export const MENU_TEMPLATE_PARTS_HEADERS = 'template-parts-headers';
export const MENU_TEMPLATE_PARTS_FOOTERS = 'template-parts-footers';
export const MENU_TEMPLATE_PARTS_SIDEBARS = 'template-parts-sidebars';
export const MENU_TEMPLATE_PARTS_GENERAL = 'template-parts-general';

export const TEMPLATE_PART_AREA_HEADER = 'header';
export const TEMPLATE_PART_AREA_FOOTER = 'footer';
export const TEMPLATE_PART_AREA_SIDEBAR = 'sidebar';

export const TEMPLATE_PARTS_SUB_MENUS = [
{
area: TEMPLATE_PART_AREA_HEADER,
menu: MENU_TEMPLATE_PARTS_HEADERS,
title: __( 'Headers' ),
},
{
area: TEMPLATE_PART_AREA_FOOTER,
menu: MENU_TEMPLATE_PARTS_FOOTERS,
title: __( 'Footers' ),
},
{
area: TEMPLATE_PART_AREA_SIDEBAR,
menu: MENU_TEMPLATE_PARTS_SIDEBARS,
title: __( 'Sidebars' ),
},
{
area: 'uncategorized',
menu: MENU_TEMPLATE_PARTS_GENERAL,
title: __( 'General' ),
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* External dependencies
*/
import { map } from 'lodash';

/**
* WordPress dependencies
*/
import { __experimentalNavigationMenu as NavigationMenu } from '@wordpress/components';

/**
* Internal dependencies
*/
import TemplateNavigationItem from '../template-navigation-item';
import { MENU_TEMPLATE_PARTS } from '../constants';

export default function TemplatePartsSubMenu( { menu, title, templateParts } ) {
return (
<NavigationMenu
menu={ menu }
title={ title }
parentMenu={ MENU_TEMPLATE_PARTS }
isEmpty={ ! templateParts || templateParts.length === 0 }
>
{ map( templateParts, ( templatePart ) => (
<TemplateNavigationItem
item={ templatePart }
key={ `wp_template_part-${ templatePart.id }` }
/>
) ) }
</NavigationMenu>
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { map } from 'lodash';
import { groupBy } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -13,53 +13,81 @@ import {
__experimentalNavigationItem as NavigationItem,
} from '@wordpress/components';
import { useState, useCallback } from '@wordpress/element';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import TemplateNavigationItem from '../template-navigation-item';
import { MENU_ROOT, MENU_TEMPLATE_PARTS } from '../constants';
import {
MENU_ROOT,
MENU_TEMPLATE_PARTS,
TEMPLATE_PARTS_SUB_MENUS,
} from '../constants';
import SearchResults from '../search-results';
import TemplatePartsSubMenu from './template-parts-sub';

export default function TemplatePartsMenu() {
const [ search, setSearch ] = useState( '' );
const onSearch = useCallback( ( value ) => {
setSearch( value );
} );

const templateParts = useSelect(
( select ) =>
select( 'core' ).getEntityRecords(
const { isLoading, templateParts, templatePartsByArea } = useSelect(
( select ) => {
const templatePartRecords = select( coreStore ).getEntityRecords(
'postType',
'wp_template_part'
) || [],
);

const _templateParts = templatePartRecords || [];
const _templatePartsByArea = groupBy( _templateParts, 'area' );

return {
isLoading: templatePartRecords === null,
templateParts: _templateParts,
templatePartsByArea: _templatePartsByArea,
};
},
[]
);

return (
<NavigationMenu
menu={ MENU_TEMPLATE_PARTS }
title={ __( 'Template Parts' ) }
parentMenu={ MENU_ROOT }
hasSearch={ true }
onSearch={ onSearch }
search={ search }
>
{ search && (
<SearchResults items={ templateParts } search={ search } />
) }
<>
<NavigationMenu
menu={ MENU_TEMPLATE_PARTS }
title={ __( 'Template Parts' ) }
parentMenu={ MENU_ROOT }
hasSearch={ true }
onSearch={ onSearch }
search={ search }
>
{ search && (
<SearchResults items={ templateParts } search={ search } />
) }

{ ! search &&
TEMPLATE_PARTS_SUB_MENUS.map( ( { title, menu } ) => (
<NavigationItem
key={ `template-parts-navigate-to-${ menu }` }
navigateToMenu={ menu }
title={ title }
hideIfTargetMenuEmpty
/>
) ) }

{ ! search &&
map( templateParts, ( templatePart ) => (
<TemplateNavigationItem
item={ templatePart }
key={ `wp_template_part-${ templatePart.id }` }
/>
) ) }
{ ! search && isLoading && (
<NavigationItem title={ __( 'Loading…' ) } isText />
) }
</NavigationMenu>

{ ! search && templateParts === null && (
<NavigationItem title={ __( 'Loading…' ) } isText />
) }
</NavigationMenu>
{ TEMPLATE_PARTS_SUB_MENUS.map( ( { area, menu, title } ) => (
<TemplatePartsSubMenu
key={ `template-parts-menu-${ menu }` }
menu={ menu }
title={ title }
templateParts={ templatePartsByArea[ area ] }
/>
) ) }
</>
);
}