Skip to content

Commit

Permalink
Library: Reinstate sidebar navigation menu editing for template parts
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw committed Jun 23, 2023
1 parent 5fa3f81 commit 734e024
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -1,91 +1,21 @@
/**
* WordPress dependencies
*/
import { __, sprintf, _x } from '@wordpress/i18n';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { useDispatch } from '@wordpress/data';
import { pencil } from '@wordpress/icons';
import {
__experimentalUseNavigator as useNavigator,
Icon,
} from '@wordpress/components';
import { store as coreStore } from '@wordpress/core-data';
import { __experimentalUseNavigator as useNavigator } from '@wordpress/components';

/**
* Internal dependencies
*/
import SidebarButton from '../sidebar-button';
import SidebarNavigationScreen from '../sidebar-navigation-screen';
import useEditedEntityRecord from '../use-edited-entity-record';
import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url';
import { unlock } from '../../lock-unlock';
import usePatternDetails from './use-pattern-details';
import useNavigationMenuContent from './use-navigation-menu-content';
import { store as editSiteStore } from '../../store';
import SidebarButton from '../sidebar-button';
import { useAddedBy } from '../list/added-by';

function usePatternTitleAndDescription( postType, postId ) {
const { getDescription, getTitle, record } = useEditedEntityRecord(
postType,
postId
);
const currentTheme = useSelect(
( select ) => select( coreStore ).getCurrentTheme(),
[]
);
const addedBy = useAddedBy( postType, postId );
const isAddedByActiveTheme =
addedBy.type === 'theme' && record.theme === currentTheme?.stylesheet;
const title = getTitle();
let descriptionText = getDescription();

if ( ! descriptionText && addedBy.text ) {
descriptionText = sprintf(
// translators: %s: pattern title e.g: "Header".
__( 'This is your %s pattern.' ),
getTitle()
);
}

if ( ! descriptionText && postType === 'wp_block' && record?.title ) {
descriptionText = sprintf(
// translators: %s: user created pattern title e.g. "Footer".
__( 'This is your %s pattern.' ),
record.title
);
}

const description = (
<>
{ descriptionText }

{ addedBy.text && ! isAddedByActiveTheme && (
<span className="edit-site-sidebar-navigation-screen-pattern__added-by-description">
<span className="edit-site-sidebar-navigation-screen-pattern__added-by-description-author">
<span className="edit-site-sidebar-navigation-screen-pattern__added-by-description-author-icon">
{ addedBy.imageUrl ? (
<img
src={ addedBy.imageUrl }
alt=""
width="24"
height="24"
/>
) : (
<Icon icon={ addedBy.icon } />
) }
</span>
{ addedBy.text }
</span>

{ addedBy.isCustomized && (
<span className="edit-site-sidebar-navigation-screen-pattern__added-by-description-customized">
{ _x( '(Customized)', 'pattern' ) }
</span>
) }
</span>
) }
</>
);

return { title, description };
}
import { unlock } from '../../lock-unlock';

export default function SidebarNavigationScreenPattern() {
const { params } = useNavigator();
Expand All @@ -94,14 +24,11 @@ export default function SidebarNavigationScreenPattern() {

useInitEditedEntityFromURL();

const { title, description } = usePatternTitleAndDescription(
postType,
postId
);
const patternDetails = usePatternDetails( postType, postId );
const content = useNavigationMenuContent( postType, postId );

return (
<SidebarNavigationScreen
title={ title }
actions={
<SidebarButton
onClick={ () => setCanvasMode( 'edit' ) }
Expand All @@ -110,7 +37,8 @@ export default function SidebarNavigationScreenPattern() {
/>
}
backPath={ '/library' }
description={ description }
content={ content }
{ ...patternDetails }
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* WordPress dependencies
*/
import { useEntityProp } from '@wordpress/core-data';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import SidebarNavigationItem from '../sidebar-navigation-item';
import { useLink } from '../routes/link';

export default function TemplatePartNavigationMenuListItem( { id } ) {
const [ title ] = useEntityProp( 'postType', 'wp_navigation', 'title', id );

const linkInfo = useLink( {
postId: id,
postType: 'wp_navigation',
} );

if ( ! id ) return null;

return (
<SidebarNavigationItem withChevron { ...linkInfo }>
{ title || __( '(no title)' ) }
</SidebarNavigationItem>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* WordPress dependencies
*/
import { __experimentalItemGroup as ItemGroup } from '@wordpress/components';
/**
* Internal dependencies
*/
import TemplatePartNavigationMenuListItem from './template-part-navigation-menu-list-item';

export default function TemplatePartNavigationMenuList( { menus } ) {
return (
<ItemGroup className="edit-site-sidebar-navigation-screen-template-part-navigation-menu-list">
{ menus.map( ( menuId ) => (
<TemplatePartNavigationMenuListItem
key={ menuId }
id={ menuId }
/>
) ) }
</ItemGroup>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { __experimentalHeading as Heading } from '@wordpress/components';
import { useEntityProp } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import NavigationMenuEditor from '../sidebar-navigation-screen-navigation-menu/navigation-menu-editor';

export default function TemplatePartNavigationMenu( { id } ) {
const [ title ] = useEntityProp( 'postType', 'wp_navigation', 'title', id );

if ( ! id ) return null;

return (
<>
<Heading
className="edit-site-sidebar-navigation-screen-template-part-navigation-menu__title"
size="12"
upperCase={ true }
>
{ title?.rendered || __( 'Navigation' ) }
</Heading>
<NavigationMenuEditor navigationMenuId={ id } />
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { __experimentalHeading as Heading } from '@wordpress/components';
/**
* Internal dependencies
*/
import TemplatePartNavigationMenu from './template-part-navigation-menu';
import TemplatePartNavigationMenuList from './template-part-navigation-menu-list';

export default function TemplatePartNavigationMenus( { menus } ) {
if ( ! menus.length ) return null;

// if there is a single menu then render TemplatePartNavigationMenu
if ( menus.length === 1 ) {
return <TemplatePartNavigationMenu id={ menus[ 0 ] } />;
}

// if there are multiple menus then render TemplatePartNavigationMenuList
return (
<>
<Heading
className="edit-site-sidebar-navigation-screen-template-part-navigation-menu__title"
size="12"
upperCase={ true }
>
{ __( 'Navigation' ) }
</Heading>
<TemplatePartNavigationMenuList menus={ menus } />
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Internal dependencies
*/
import TemplatePartNavigationMenus from './template-part-navigation-menus';
import useEditedEntityRecord from '../use-edited-entity-record';

/**
* Retrieves a list of specific blocks from a given tree of blocks.
*
* @param {string} targetBlockType The name of the block type to find.
* @param {Array} blocks A list of blocks from a template part entity.
*
* @return {Array} A list of any navigation blocks found in the blocks.
*/
function getBlocksOfTypeFromBlocks( targetBlockType, blocks ) {
if ( ! targetBlockType || ! blocks?.length ) {
return [];
}

const findInBlocks = ( _blocks ) => {
if ( ! _blocks ) {
return [];
}

const navigationBlocks = [];

for ( const block of _blocks ) {
if ( block.name === targetBlockType ) {
navigationBlocks.push( block );
}

if ( block?.innerBlocks ) {
const innerNavigationBlocks = findInBlocks( block.innerBlocks );

if ( innerNavigationBlocks.length ) {
navigationBlocks.push( ...innerNavigationBlocks );
}
}
}

return navigationBlocks;
};

return findInBlocks( blocks );
}

export default function useNavigationMenuContent( postType, postId ) {
const { record } = useEditedEntityRecord( postType, postId );

// Only managing navigation menus in template parts is supported
// to match previous behaviour. This could potentially be expanded
// to patterns as well.
if ( postType !== 'wp_template_part' ) {
return;
}

const navigationBlocks = getBlocksOfTypeFromBlocks(
'core/navigation',
record?.blocks
);

const navigationMenuIds = navigationBlocks?.map(
( block ) => block.attributes.ref
);

if ( ! navigationMenuIds?.length ) {
return;
}

return <TemplatePartNavigationMenus menus={ navigationMenuIds } />;
}
Loading

0 comments on commit 734e024

Please sign in to comment.