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

Navigation: Improve flow when creating from menu #23187

Merged
merged 2 commits into from
Jun 16, 2020
Merged
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
131 changes: 63 additions & 68 deletions packages/block-library/src/navigation/placeholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ import {
Placeholder,
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { forwardRef, useCallback, useMemo, useState } from '@wordpress/element';
import {
forwardRef,
useCallback,
useMemo,
useState,
useEffect,
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { navigation as icon } from '@wordpress/icons';

Expand Down Expand Up @@ -137,51 +143,11 @@ function convertPagesToBlocks( pages ) {
);
}

/**
* Returns a value that indicates whether the create button should be disabled.
*
* @param {Object} selectedCreateOption An object containing details of
* the selected create option.
* @param {boolean} hasResolvedPages Indicates whether pages have loaded.
* @param {boolean} hasResolvedMenuItems Indicates whether menu items have loaded.
*
* @return {boolean} A value that indicates whether the create button is disabled.
*/
function getIsCreateButtonDisabled(
selectedCreateOption,
hasResolvedPages,
hasResolvedMenuItems
) {
// If there is no key at all then disable.
if ( ! selectedCreateOption ) {
return true;
}

const optionKey = selectedCreateOption?.key;

// Always disable if the default "placeholder" option is selected.
if ( optionKey === CREATE_PLACEHOLDER_VALUE ) {
return true;
}

// Always enable if Create Empty is selected.
if ( optionKey === CREATE_EMPTY_OPTION_VALUE ) {
return false;
}

// Enable if Pages option selected and we have Pages available.
if ( optionKey === CREATE_FROM_PAGES_OPTION_VALUE && hasResolvedPages ) {
return false;
}

// Enable if a menu is selected and menu items have loaded.
const selectedMenu = getSelectedMenu( selectedCreateOption );
return selectedMenu === undefined || ! hasResolvedMenuItems;
}

function NavigationPlaceholder( { onCreate }, ref ) {
const [ selectedCreateOption, setSelectedCreateOption ] = useState();

const [ isCreatingFromMenu, setIsCreatingFromMenu ] = useState( false );

const {
pages,
isResolvingPages,
Expand Down Expand Up @@ -279,38 +245,65 @@ function NavigationPlaceholder( { onCreate }, ref ) {
[ menus, hasMenus, hasPages ]
);

const createFromMenu = useCallback( () => {
// If an empty menu was selected, create an empty block.
if ( ! menuItems.length ) {
const blocks = [ createBlock( 'core/navigation-link' ) ];
onCreate( blocks );
return;
}

const blocks = convertMenuItemsToBlocks( menuItems );
const selectNavigationBlock = true;
onCreate( blocks, selectNavigationBlock );
} );

const onCreateButtonClick = useCallback( () => {
if ( ! selectedCreateOption ) {
return;
}

const { key } = selectedCreateOption;
switch ( key ) {
case CREATE_PLACEHOLDER_VALUE:
// Do nothing.
return;

case CREATE_EMPTY_OPTION_VALUE: {
const blocks = [ createBlock( 'core/navigation-link' ) ];
onCreate( blocks );
return;
}

if ( key === CREATE_FROM_PAGES_OPTION_VALUE && hasPages ) {
const blocks = convertPagesToBlocks( pages );
const selectNavigationBlock = true;
onCreate( blocks, selectNavigationBlock );
return;
}
case CREATE_FROM_PAGES_OPTION_VALUE: {
const blocks = convertPagesToBlocks( pages );
const selectNavigationBlock = true;
onCreate( blocks, selectNavigationBlock );
return;
}

if ( key === CREATE_EMPTY_OPTION_VALUE || ! menuItems?.length ) {
noisysocks marked this conversation as resolved.
Show resolved Hide resolved
const blocks = [ createBlock( 'core/navigation-link' ) ];
onCreate( blocks );
}
// The default case indicates that a menu was selected.
default:
// If we have menu items, create the block right away.
if ( hasResolvedMenuItems ) {
createFromMenu();
return;
}

// Infer that the user selected a menu to create from.
// If either there's no selected menu or menu items are undefined
// this is undefined behavior, do nothing.
const selectedMenu = getSelectedMenu( selectedCreateOption );
if ( selectedMenu === undefined || menuItems === undefined ) {
return;
// Otherwise, create the block when resolution finishes.
setIsCreatingFromMenu( true );
}

const blocks = convertMenuItemsToBlocks( menuItems );
const selectNavigationBlock = true;
onCreate( blocks, selectNavigationBlock );
} );

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();
setIsCreatingFromMenu( false );
}
}, [ isCreatingFromMenu, hasResolvedMenuItems ] );

return (
<Placeholder
className="wp-block-navigation-placeholder"
Expand Down Expand Up @@ -349,6 +342,7 @@ function NavigationPlaceholder( { onCreate }, ref ) {
return;
}
setSelectedCreateOption( selectedItem );
setIsCreatingFromMenu( false );
} }
options={ createOptions.map( ( option ) => {
return {
Expand All @@ -360,12 +354,13 @@ function NavigationPlaceholder( { onCreate }, ref ) {
<Button
isSecondary
className="wp-block-navigation-placeholder__button"
disabled={
! selectedCreateOption ||
selectedCreateOption.key ===
CREATE_PLACEHOLDER_VALUE
}
isBusy={ isCreatingFromMenu }
onClick={ onCreateButtonClick }
disabled={ getIsCreateButtonDisabled(
selectedCreateOption,
hasResolvedPages,
hasResolvedMenuItems
) }
>
{ __( 'Create' ) }
</Button>
Expand Down