From 3a4e932bbb6bd08af43a872402e9569eeb91f738 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 24 Jan 2022 11:09:37 +0800 Subject: [PATCH 1/4] Add classic menus to switch menu dropdown --- .../src/navigation/edit/index.js | 5 +- .../edit/navigation-menu-selector.js | 73 +++++++++++++++---- .../src/navigation/edit/placeholder/index.js | 53 +++----------- .../navigation/use-convert-classic-menu.js | 55 ++++++++++++++ 4 files changed, 127 insertions(+), 59 deletions(-) create mode 100644 packages/block-library/src/navigation/use-convert-classic-menu.js diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 261176369d960d..f8ace0b723bfee 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -486,12 +486,15 @@ function Navigation( { > { ( { onClose } ) => ( { setRef( id ); onClose(); } } onCreateNew={ startWithEmptyMenu } - showCreate={ canUserCreateNavigation } + canUserCreateNavigation={ + canUserCreateNavigation + } /> ) } diff --git a/packages/block-library/src/navigation/edit/navigation-menu-selector.js b/packages/block-library/src/navigation/edit/navigation-menu-selector.js index 6bda1603b626ad..9e89756661b0a1 100644 --- a/packages/block-library/src/navigation/edit/navigation-menu-selector.js +++ b/packages/block-library/src/navigation/edit/navigation-menu-selector.js @@ -11,18 +11,44 @@ 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 } = 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 ( <> - + @@ -46,19 +72,38 @@ export default function NavigationMenuSelector( { } ) } /> - { showCreate && ( - - - { __( 'Create new menu' ) } - - + + { classicMenus.map( ( menu ) => { + return ( + { + convertClassicMenuToBlocks( + menu.id, + menu.name + ); + } } + key={ menu.id } + > + { decodeEntities( menu.name ) } + + ); } ) } - > - { __( 'Manage menus' ) } - - + + + + { __( 'Create new menu' ) } + + + { __( 'Manage menus' ) } + + + ) } ); diff --git a/packages/block-library/src/navigation/edit/placeholder/index.js b/packages/block-library/src/navigation/edit/placeholder/index.js index 7e6fe10220328d..6557418b3ce177 100644 --- a/packages/block-library/src/navigation/edit/placeholder/index.js +++ b/packages/block-library/src/navigation/edit/placeholder/index.js @@ -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'; @@ -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, @@ -57,7 +55,6 @@ const ExistingMenusDropdown = ( { return ( { - setSelectedMenu( menu.id ); onFinish( menu ); } } onClose={ onClose } @@ -77,8 +74,10 @@ const ExistingMenusDropdown = ( { return ( { - setSelectedMenu( menu.id ); - onCreateFromMenu( menu.name ); + onCreateFromMenu( + menu.id, + menu.name + ); } } onClose={ onClose } key={ menu.id } @@ -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 ( @@ -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( [] ); }; @@ -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; @@ -205,10 +171,9 @@ export default function NavigationPlaceholder( { canSwitchNavigationMenu } navigationMenus={ navigationMenus } - setSelectedMenu={ setSelectedMenu } onFinish={ onFinish } menus={ menus } - onCreateFromMenu={ onCreateFromMenu } + onCreateFromMenu={ convertClassicMenu } showClassicMenus={ canUserCreateNavigation } diff --git a/packages/block-library/src/navigation/use-convert-classic-menu.js b/packages/block-library/src/navigation/use-convert-classic-menu.js new file mode 100644 index 00000000000000..cc5e886b1d7546 --- /dev/null +++ b/packages/block-library/src/navigation/use-convert-classic-menu.js @@ -0,0 +1,55 @@ +/** + * 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 ( 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 ); + }; +} From 5684f93fe37f5ab6947e12d3a7ab6c509973d752 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 24 Jan 2022 11:11:21 +0800 Subject: [PATCH 2/4] Preload entities --- packages/block-library/src/navigation/edit/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index f8ace0b723bfee..19b506fcf2796e 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -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'; @@ -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, From f0a8100e7a2e44772ecf331860541de1ac8f32a3 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 24 Jan 2022 11:22:22 +0800 Subject: [PATCH 3/4] Hide classic menus when there are none --- .../edit/navigation-menu-selector.js | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/block-library/src/navigation/edit/navigation-menu-selector.js b/packages/block-library/src/navigation/edit/navigation-menu-selector.js index 9e89756661b0a1..7ba8c5bffe8840 100644 --- a/packages/block-library/src/navigation/edit/navigation-menu-selector.js +++ b/packages/block-library/src/navigation/edit/navigation-menu-selector.js @@ -21,7 +21,10 @@ export default function NavigationMenuSelector( { onCreateNew, canUserCreateNavigation = false, } ) { - const { menus: classicMenus } = useNavigationEntities(); + const { + menus: classicMenus, + hasMenus: hasClassicMenus, + } = useNavigationEntities(); const { navigationMenus } = useNavigationMenu(); const ref = useEntityId( 'postType', 'wp_navigation' ); @@ -74,23 +77,25 @@ export default function NavigationMenuSelector( { { canUserCreateNavigation && ( <> - - { classicMenus.map( ( menu ) => { - return ( - { - convertClassicMenuToBlocks( - menu.id, - menu.name - ); - } } - key={ menu.id } - > - { decodeEntities( menu.name ) } - - ); - } ) } - + { hasClassicMenus && ( + + { classicMenus.map( ( menu ) => { + return ( + { + convertClassicMenuToBlocks( + menu.id, + menu.name + ); + } } + key={ menu.id } + > + { decodeEntities( menu.name ) } + + ); + } ) } + + ) } { __( 'Create new menu' ) } From cc14a6b5da295e1070b5fef39d3f6d8ababf91e5 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 24 Jan 2022 13:03:15 +0800 Subject: [PATCH 4/4] Memoize callback --- .../navigation/use-convert-classic-menu.js | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/block-library/src/navigation/use-convert-classic-menu.js b/packages/block-library/src/navigation/use-convert-classic-menu.js index cc5e886b1d7546..c857e9c97cb0db 100644 --- a/packages/block-library/src/navigation/use-convert-classic-menu.js +++ b/packages/block-library/src/navigation/use-convert-classic-menu.js @@ -38,18 +38,21 @@ export default function useConvertClassicMenu( onFinish ) { } }, [ isAwaitingMenuItemResolution, hasResolvedMenuItems, menuName ] ); - return ( 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 ); - }; + 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 ] + ); }