Skip to content

Commit

Permalink
Navigation Editor: Allow menu renaming (#29012)
Browse files Browse the repository at this point in the history
* feature to change navigation menu name

* name editor component added

* add missing styles|

* remove doubled hooks

* remove ;

* navigation post variable updated

* use-menu-locations hook moved to hooks directory

* console error fixed

* name edition moved to the sidebar. In toolbar manu name changed to button, when clicked name editor is focused

* move NameEditor to InspectorControls in InspectorAdditions in order to preserve the same order of items in navbar

* use TextControl component in name-editor

* changes according to CR

* add missing file

* changes according to CR: removed aria-label from name-display/index.js and added aria-label in /name-editor/index.js

* Dispatch save requests sequentially instead of in parallel

* explicitly set () => setIsMenuNameEditFocused( true )

* add translation to the file

* resolved conflicts with trunk

* resolved conflicts with trunk 2

* sprintf added

* Update unit test to take into account the call to saveEditedEntityRecord

Co-authored-by: grzegorz_marzencki <[email protected]>
Co-authored-by: Daniel Richards <[email protected]>
  • Loading branch information
3 people authored Mar 8, 2021
1 parent e8ffe04 commit e8c6106
Show file tree
Hide file tree
Showing 28 changed files with 606 additions and 274 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import useMenuLocations from './use-menu-locations';
import useMenuLocations from '../../hooks/use-menu-locations';

export default function ManageLocations() {
const menus = useSelect( ( select ) => select( 'core' ).getMenus(), [] );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { InspectorControls } from '@wordpress/block-editor';
*/
import AutoAddPagesPanel from './auto-add-pages-panel';
import DeleteMenuPanel from './delete-menu-panel';
import { NameEditor } from '../name-editor';
import { PanelBody } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

export default function InspectorAdditions( { menuId, onDeleteMenu } ) {
const selectedBlock = useSelect(
Expand All @@ -22,8 +25,11 @@ export default function InspectorAdditions( { menuId, onDeleteMenu } ) {

return (
<InspectorControls>
<AutoAddPagesPanel menuId={ menuId } />
<DeleteMenuPanel onDeleteMenu={ onDeleteMenu } />
<PanelBody title={ __( 'Menu Settings' ) }>
<NameEditor />
<AutoAddPagesPanel menuId={ menuId } />
<DeleteMenuPanel onDeleteMenu={ onDeleteMenu } />
</PanelBody>
</InspectorControls>
);
}
113 changes: 67 additions & 46 deletions packages/edit-navigation/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,19 @@ import {
BlockInspector,
__unstableUseBlockSelectionClearer as useBlockSelectionClearer,
} from '@wordpress/block-editor';
import { useMemo, useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import EmptyState from './empty-state';
import useNavigationEditor from './use-navigation-editor';
import useNavigationBlockEditor from './use-navigation-block-editor';
import useMenuNotifications from './use-menu-notifications';
import {
IsMenuNameControlFocusedContext,
MenuIdContext,
useNavigationEditor,
useNavigationBlockEditor,
useMenuNotifications,
} from '../../hooks';
import ErrorBoundary from '../error-boundary';
import NavigationEditorShortcuts from './shortcuts';
import Header from '../header';
Expand All @@ -37,7 +42,9 @@ import { store as editNavigationStore } from '../../store';

export default function Layout( { blockEditorSettings } ) {
const canvasRef = useBlockSelectionClearer();

const [ isMenuNameControlFocused, setIsMenuNameControlFocused ] = useState(
false
);
const { saveNavigationPost } = useDispatch( editNavigationStore );
const savePost = () => saveNavigationPost( navigationPost );

Expand Down Expand Up @@ -74,51 +81,65 @@ export default function Layout( { blockEditorSettings } ) {
'has-block-inspector': isBlockEditorReady,
} ) }
>
<Header
isPending={ ! hasLoadedMenus }
menus={ menus }
selectedMenuId={ selectedMenuId }
onSelectMenu={ selectMenu }
navigationPost={ navigationPost }
/>
<MenuIdContext.Provider value={ selectedMenuId }>
<IsMenuNameControlFocusedContext.Provider
value={ useMemo(
() => [
isMenuNameControlFocused,
setIsMenuNameControlFocused,
],
[ isMenuNameControlFocused ]
) }
>
<Header
isPending={ ! hasLoadedMenus }
menus={ menus }
selectedMenuId={ selectedMenuId }
onSelectMenu={ selectMenu }
navigationPost={ navigationPost }
/>

{ ! hasFinishedInitialLoad && <Spinner /> }
{ ! hasFinishedInitialLoad && <Spinner /> }

{ hasFinishedInitialLoad && ! hasMenus && (
<EmptyState />
) }
{ hasFinishedInitialLoad && ! hasMenus && (
<EmptyState />
) }

{ isBlockEditorReady && (
<BlockEditorProvider
value={ blocks }
onInput={ onInput }
onChange={ onChange }
settings={ {
...blockEditorSettings,
templateLock: 'all',
} }
useSubRegistry={ false }
>
<BlockEditorKeyboardShortcuts />
<NavigationEditorShortcuts
saveBlocks={ savePost }
/>
<div
className="edit-navigation-layout__canvas"
ref={ canvasRef }
>
<Editor
isPending={ ! hasLoadedMenus }
blocks={ blocks }
/>
</div>
<InspectorAdditions
menuId={ selectedMenuId }
onDeleteMenu={ deleteMenu }
/>
<BlockInspector bubblesVirtually={ false } />
</BlockEditorProvider>
) }
{ isBlockEditorReady && (
<BlockEditorProvider
value={ blocks }
onInput={ onInput }
onChange={ onChange }
settings={ {
...blockEditorSettings,
templateLock: 'all',
} }
useSubRegistry={ false }
>
<BlockEditorKeyboardShortcuts />
<NavigationEditorShortcuts
saveBlocks={ savePost }
/>
<div
className="edit-navigation-layout__canvas"
ref={ canvasRef }
>
<Editor
isPending={ ! hasLoadedMenus }
blocks={ blocks }
/>
</div>
<InspectorAdditions
menuId={ selectedMenuId }
onDeleteMenu={ deleteMenu }
/>
<BlockInspector
bubblesVirtually={ false }
/>
</BlockEditorProvider>
) }
</IsMenuNameControlFocusedContext.Provider>
</MenuIdContext.Provider>
</div>

<Popover.Slot />
Expand Down
37 changes: 37 additions & 0 deletions packages/edit-navigation/src/components/name-display/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* WordPress dependencies
*/
import { ToolbarGroup, ToolbarButton } from '@wordpress/components';
import { BlockControls } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import {
useSelectedMenuData,
IsMenuNameControlFocusedContext,
} from '../../hooks';
import { useContext } from '@wordpress/element';

import { sprintf, __ } from '@wordpress/i18n';
export default function NameDisplay() {
const { menuName } = useSelectedMenuData();
const [ , setIsMenuNameEditFocused ] = useContext(
IsMenuNameControlFocusedContext
);
return (
<BlockControls>
<ToolbarGroup>
<ToolbarButton
aria-label={ sprintf(
// translators: %s: the name of a menu.
__( `Edit menu name: %s` ),
menuName
) }
onClick={ () => setIsMenuNameEditFocused( true ) }
>
{ menuName }
</ToolbarButton>
</ToolbarGroup>
</BlockControls>
);
}
44 changes: 44 additions & 0 deletions packages/edit-navigation/src/components/name-editor/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useEffect, useRef, useContext } from '@wordpress/element';
/**
* Internal dependencies
*/
import { TextControl } from '@wordpress/components';
import {
IsMenuNameControlFocusedContext,
useMenuEntity,
useSelectedMenuData,
} from '../../hooks';

export function NameEditor() {
const [ isMenuNameEditFocused, setIsMenuNameEditFocused ] = useContext(
IsMenuNameControlFocusedContext
);

const { menuId } = useSelectedMenuData();
const { editMenuName, editedMenuName } = useMenuEntity( menuId );
const inputRef = useRef();
useEffect( () => {
if ( isMenuNameEditFocused ) inputRef.current.focus();
}, [ isMenuNameEditFocused ] );
return (
<>
<TextControl
ref={ inputRef }
help={ __(
'A short, descriptive name used to refer to this menu elsewhere.'
) }
label={ __( 'Name' ) }
onBlur={ () => setIsMenuNameEditFocused( false ) }
className="edit-navigation-name-editor__text-control"
value={ editedMenuName }
onChange={ ( value ) => {
editMenuName( value );
} }
/>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.edit-navigation-name-editor__text-control {
.components-base-control {
border: none;
}
}
31 changes: 31 additions & 0 deletions packages/edit-navigation/src/filters/add-menu-name-editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
import { addFilter } from '@wordpress/hooks';
import { createHigherOrderComponent } from '@wordpress/compose';
import NameDisplay from '../components/name-display';

const addMenuNameEditor = createHigherOrderComponent(
( BlockEdit ) => ( props ) => {
if ( props.name !== 'core/navigation' ) {
return <BlockEdit { ...props } />;
}
return (
<>
<BlockEdit { ...props } />
<NameDisplay />
</>
);
},
'withMenuName'
);

export default () =>
addFilter(
'editor.BlockEdit',
'core/edit-navigation/with-menu-name',
addMenuNameEditor
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* WordPress dependencies
*/
import { addFilter } from '@wordpress/hooks';
/**
* External dependencies
*/
import { set } from 'lodash';

function disableInsertingNonNavigationBlocks( settings, name ) {
if ( ! [ 'core/navigation', 'core/navigation-link' ].includes( name ) ) {
set( settings, [ 'supports', 'inserter' ], false );
}
return settings;
}

export default () =>
addFilter(
'blocks.registerBlockType',
'core/edit-navigation/disable-inserting-non-navigation-blocks',
disableInsertingNonNavigationBlocks
);
18 changes: 18 additions & 0 deletions packages/edit-navigation/src/filters/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Internal dependencies
*/
import addMenuNameEditor from './add-menu-name-editor';
import disableInsertingNonNavigationBlocks from './disable-inserting-non-navigation-blocks';
import removeEditUnsupportedFeatures from './remove-edit-unsupported-features';
import removeSettingsUnsupportedFeatures from './remove-settings-unsupported-features';

export const addFilters = (
shouldAddDisableInsertingNonNavigationBlocksFilter
) => {
addMenuNameEditor();
if ( shouldAddDisableInsertingNonNavigationBlocksFilter ) {
disableInsertingNonNavigationBlocks();
}
removeEditUnsupportedFeatures();
removeSettingsUnsupportedFeatures();
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* WordPress dependencies
*/
import { addFilter } from '@wordpress/hooks';
import { createHigherOrderComponent } from '@wordpress/compose';

const removeNavigationBlockEditUnsupportedFeatures = createHigherOrderComponent(
( BlockEdit ) => ( props ) => {
if ( props.name !== 'core/navigation' ) {
return <BlockEdit { ...props } />;
}

return (
<BlockEdit
{ ...props }
hasSubmenuIndicatorSetting={ false }
hasItemJustificationControls={ false }
hasListViewModal={ false }
/>
);
},
'removeNavigationBlockEditUnsupportedFeatures'
);

export default () =>
addFilter(
'editor.BlockEdit',
'core/edit-navigation/remove-navigation-block-edit-unsupported-features',
removeNavigationBlockEditUnsupportedFeatures
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* WordPress dependencies
*/
import { addFilter } from '@wordpress/hooks';

function removeNavigationBlockSettingsUnsupportedFeatures( settings, name ) {
if ( name !== 'core/navigation' ) {
return settings;
}

return {
...settings,
supports: {
customClassName: false,
html: false,
inserter: true,
},
// Remove any block variations.
variations: undefined,
};
}

export default () =>
addFilter(
'blocks.registerBlockType',
'core/edit-navigation/remove-navigation-block-settings-unsupported-features',
removeNavigationBlockSettingsUnsupportedFeatures
);
Loading

0 comments on commit e8c6106

Please sign in to comment.