Skip to content

Commit

Permalink
Add classic menus to menu switcher (#38168)
Browse files Browse the repository at this point in the history
* Add classic menus to switch menu dropdown

* Preload entities

* Hide classic menus when there are none

* Memoize callback
  • Loading branch information
talldan committed Jan 24, 2022
1 parent 34ed60b commit debd225
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 60 deletions.
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' ) }>
<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
58 changes: 58 additions & 0 deletions packages/block-library/src/navigation/use-convert-classic-menu.js
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 ]
);
}

0 comments on commit debd225

Please sign in to comment.