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

Add classic menus to menu switcher #38168

Merged
merged 4 commits into from
Jan 24, 2022
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
10 changes: 9 additions & 1 deletion packages/block-library/src/navigation/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { __ } from '@wordpress/i18n';
*/
import useListViewModal from './use-list-view-modal';
import useNavigationMenu from '../use-navigation-menu';
import useNavigationEntities from '../use-navigation-entities';
import Placeholder from './placeholder';
import PlaceholderPreview from './placeholder/placeholder-preview';
import ResponsiveWrapper from './responsive-wrapper';
Expand Down Expand Up @@ -153,6 +154,10 @@ function Navigation( {
`navigationMenu/${ ref }`
);

// Preload classic menus, so that they don't suddenly pop-in when viewing
// the Select Menu dropdown.
useNavigationEntities();

const {
hasUncontrolledInnerBlocks,
uncontrolledInnerBlocks,
Expand Down Expand Up @@ -486,12 +491,15 @@ function Navigation( {
>
{ ( { onClose } ) => (
<NavigationMenuSelector
clientId={ clientId }
onSelect={ ( { id } ) => {
setRef( id );
onClose();
} }
onCreateNew={ startWithEmptyMenu }
showCreate={ canUserCreateNavigation }
canUserCreateNavigation={
canUserCreateNavigation
}
/>
) }
</ToolbarDropdownMenu>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,47 @@ import { addQueryArgs } from '@wordpress/url';
* Internal dependencies
*/
import useNavigationMenu from '../use-navigation-menu';
import useNavigationEntities from '../use-navigation-entities';
import useConvertClassicMenu from '../use-convert-classic-menu';
import useCreateNavigationMenu from './use-create-navigation-menu';

export default function NavigationMenuSelector( {
clientId,
onSelect,
onCreateNew,
showCreate = false,
canUserCreateNavigation = false,
} ) {
const {
menus: classicMenus,
hasMenus: hasClassicMenus,
} = useNavigationEntities();
const { navigationMenus } = useNavigationMenu();
const ref = useEntityId( 'postType', 'wp_navigation' );

const createNavigationMenu = useCreateNavigationMenu( clientId );

const onFinishMenuCreation = async (
blocks,
navigationMenuTitle = null
) => {
if ( ! canUserCreateNavigation ) {
return;
}

const navigationMenu = await createNavigationMenu(
navigationMenuTitle,
blocks
);
onSelect( navigationMenu );
};

const convertClassicMenuToBlocks = useConvertClassicMenu(
onFinishMenuCreation
);

return (
<>
<MenuGroup>
<MenuGroup label={ __( 'Menus' ) }>
<MenuItemsChoice
value={ ref }
onSelect={ ( selectedId ) =>
Expand All @@ -46,19 +75,40 @@ export default function NavigationMenuSelector( {
} ) }
/>
</MenuGroup>
{ showCreate && (
<MenuGroup>
<MenuItem onClick={ onCreateNew }>
{ __( 'Create new menu' ) }
</MenuItem>
<MenuItem
href={ addQueryArgs( 'edit.php', {
post_type: 'wp_navigation',
} ) }
>
{ __( 'Manage menus' ) }
</MenuItem>
</MenuGroup>
{ canUserCreateNavigation && (
<>
{ hasClassicMenus && (
<MenuGroup label={ __( 'Classic Menus' ) }>
{ classicMenus.map( ( menu ) => {
return (
<MenuItem
onClick={ () => {
convertClassicMenuToBlocks(
menu.id,
menu.name
);
} }
key={ menu.id }
>
{ decodeEntities( menu.name ) }
</MenuItem>
);
} ) }
</MenuGroup>
) }
<MenuGroup label={ __( 'Tools' ) }>
Copy link
Member

Choose a reason for hiding this comment

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

What do you think about removing this label? I think Create new menu and Manage menus are clear enough to not need the additional context.

Screen Shot 2022-01-24 at 15 17 38

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I'll leave it. To me it feels cleaner to me to consistently have headings when there are multiple groups like this.

If only there were designers in this timezone we could ask 😄

Copy link
Member

Choose a reason for hiding this comment

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

I also like using different groups for Classic and Block menus.

Copy link
Member

Choose a reason for hiding this comment

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

Cool, your call.

If only there were designers in this timezone we could ask 😀

😅 yes unfortunately there wouldn't be enough time to do the backports if we wait. I put #36311 into the 5.9.x project board so that we can iterate asap.

<MenuItem onClick={ onCreateNew }>
{ __( 'Create new menu' ) }
</MenuItem>
<MenuItem
href={ addQueryArgs( 'edit.php', {
post_type: 'wp_navigation',
} ) }
>
{ __( 'Manage menus' ) }
</MenuItem>
</MenuGroup>
</>
) }
</>
);
Expand Down
53 changes: 9 additions & 44 deletions packages/block-library/src/navigation/edit/placeholder/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
MenuGroup,
MenuItem,
} from '@wordpress/components';
import { useCallback, useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { navigation, Icon } from '@wordpress/icons';
import { decodeEntities } from '@wordpress/html-entities';
Expand All @@ -20,14 +19,13 @@ import { decodeEntities } from '@wordpress/html-entities';

import useNavigationEntities from '../../use-navigation-entities';
import PlaceholderPreview from './placeholder-preview';
import menuItemsToBlocks from '../../menu-items-to-blocks';
import useNavigationMenu from '../../use-navigation-menu';
import useCreateNavigationMenu from '../use-create-navigation-menu';
import useConvertClassicMenu from '../../use-convert-classic-menu';

const ExistingMenusDropdown = ( {
showNavigationMenus,
navigationMenus,
setSelectedMenu,
onFinish,
menus,
onCreateFromMenu,
Expand Down Expand Up @@ -57,7 +55,6 @@ const ExistingMenusDropdown = ( {
return (
<MenuItem
onClick={ () => {
setSelectedMenu( menu.id );
onFinish( menu );
} }
onClose={ onClose }
Expand All @@ -77,8 +74,10 @@ const ExistingMenusDropdown = ( {
return (
<MenuItem
onClick={ () => {
setSelectedMenu( menu.id );
onCreateFromMenu( menu.name );
onCreateFromMenu(
menu.id,
menu.name
);
} }
onClose={ onClose }
key={ menu.id }
Expand All @@ -102,9 +101,6 @@ export default function NavigationPlaceholder( {
hasResolvedNavigationMenus,
canUserCreateNavigation = false,
} ) {
const [ selectedMenu, setSelectedMenu ] = useState();
const [ isCreatingFromMenu, setIsCreatingFromMenu ] = useState( false );
const [ menuName, setMenuName ] = useState( '' );
const createNavigationMenu = useCreateNavigationMenu( clientId );

const onFinishMenuCreation = async (
Expand All @@ -122,39 +118,18 @@ export default function NavigationPlaceholder( {
onFinish( navigationMenu, blocks );
};

const convertClassicMenu = useConvertClassicMenu( onFinishMenuCreation );

const {
isResolvingPages,
menus,
isResolvingMenus,
menuItems,
hasResolvedMenuItems,
hasPages,
hasMenus,
} = useNavigationEntities( selectedMenu );
} = useNavigationEntities();

const isStillLoading = isResolvingPages || isResolvingMenus;

const createFromMenu = useCallback(
( name ) => {
const { innerBlocks: blocks } = menuItemsToBlocks( menuItems );
onFinishMenuCreation( blocks, name );
},
[ menuItems, menuItemsToBlocks, onFinish ]
);

const onCreateFromMenu = ( name ) => {
// If we have menu items, create the block right away.
if ( hasResolvedMenuItems ) {
createFromMenu( name );
return;
}

// Otherwise, create the block when resolution finishes.
setIsCreatingFromMenu( true );
// Store the name to use later.
setMenuName( name );
};

const onCreateEmptyMenu = () => {
onFinishMenuCreation( [] );
};
Expand All @@ -164,15 +139,6 @@ export default function NavigationPlaceholder( {
onFinishMenuCreation( block );
};

useEffect( () => {
// If the user selected a menu but we had to wait for menu items to
// finish resolving, then create the block once resolution finishes.
if ( isCreatingFromMenu && hasResolvedMenuItems ) {
createFromMenu( menuName );
setIsCreatingFromMenu( false );
}
}, [ isCreatingFromMenu, hasResolvedMenuItems, menuName ] );

const { navigationMenus } = useNavigationMenu();

const hasNavigationMenus = !! navigationMenus?.length;
Expand Down Expand Up @@ -205,10 +171,9 @@ export default function NavigationPlaceholder( {
canSwitchNavigationMenu
}
navigationMenus={ navigationMenus }
setSelectedMenu={ setSelectedMenu }
onFinish={ onFinish }
menus={ menus }
onCreateFromMenu={ onCreateFromMenu }
onCreateFromMenu={ convertClassicMenu }
showClassicMenus={
canUserCreateNavigation
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* WordPress dependencies
*/
import { useCallback, useState, useEffect } from '@wordpress/element';

/**
* Internal dependencies
*/
import useNavigationEntities from './use-navigation-entities';
import menuItemsToBlocks from './menu-items-to-blocks';

export default function useConvertClassicMenu( onFinish ) {
const [ selectedMenu, setSelectedMenu ] = useState();
const [
isAwaitingMenuItemResolution,
setIsAwaitingMenuItemResolution,
] = useState( false );
const [ menuName, setMenuName ] = useState( '' );

const { menuItems, hasResolvedMenuItems } = useNavigationEntities(
selectedMenu
);

const createFromMenu = useCallback(
( name ) => {
const { innerBlocks: blocks } = menuItemsToBlocks( menuItems );
onFinish( blocks, name );
},
[ menuItems, menuItemsToBlocks, onFinish ]
);

useEffect( () => {
// If the user selected a menu but we had to wait for menu items to
// finish resolving, then create the block once resolution finishes.
if ( isAwaitingMenuItemResolution && hasResolvedMenuItems ) {
createFromMenu( menuName );
setIsAwaitingMenuItemResolution( false );
}
}, [ isAwaitingMenuItemResolution, hasResolvedMenuItems, menuName ] );

return useCallback(
( id, name ) => {
setSelectedMenu( id );

// If we have menu items, create the block right away.
if ( hasResolvedMenuItems ) {
createFromMenu( name );
return;
}

// Otherwise, create the block when resolution finishes.
setIsAwaitingMenuItemResolution( true );
// Store the name to use later.
setMenuName( name );
},
[ hasResolvedMenuItems, createFromMenu ]
);
}