From 3ebd509015372dfd6e2bf9674335625e3c911a0d Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 15 Feb 2021 18:30:09 +0100 Subject: [PATCH 01/21] feature to change navigation menu name --- .../src/components/header/save-button.js | 5 + .../src/components/layout/index.js | 93 +++++----- .../src/components/name-editor/index.js | 35 ++++ .../src/filters/add-menu-name-editor.js | 33 ++++ ...disable-inserting-non-navigation-blocks.js | 22 +++ packages/edit-navigation/src/filters/index.js | 18 ++ .../remove-edit-unsupported-features.js | 30 ++++ .../remove-settings-unsupported-features.js | 28 +++ packages/edit-navigation/src/hooks/index.js | 14 ++ .../src/hooks/use-menu-entity.js | 39 +++++ .../src/hooks/use-menu-notifications.js | 50 ++++++ .../src/hooks/use-navigation-block-editor.js | 37 ++++ .../src/hooks/use-navigation-editor-menu.js | 24 +++ .../src/hooks/use-navigation-editor.js | 61 +++++++ packages/edit-navigation/src/index.js | 160 +----------------- .../edit-navigation/src/store/resolvers.js | 16 +- .../edit-navigation/src/store/selectors.js | 15 +- .../src/store/test/resolvers.js | 23 ++- .../src/store/test/selectors.js | 17 +- packages/edit-navigation/src/store/utils.js | 14 -- packages/edit-navigation/src/style.scss | 4 - .../edit-navigation/src/utils/constants.js | 27 +++ .../src/utils/fetch-link-suggestions.js | 101 +++++++++++ 23 files changed, 631 insertions(+), 235 deletions(-) create mode 100644 packages/edit-navigation/src/components/name-editor/index.js create mode 100644 packages/edit-navigation/src/filters/add-menu-name-editor.js create mode 100644 packages/edit-navigation/src/filters/disable-inserting-non-navigation-blocks.js create mode 100644 packages/edit-navigation/src/filters/index.js create mode 100644 packages/edit-navigation/src/filters/remove-edit-unsupported-features.js create mode 100644 packages/edit-navigation/src/filters/remove-settings-unsupported-features.js create mode 100644 packages/edit-navigation/src/hooks/index.js create mode 100644 packages/edit-navigation/src/hooks/use-menu-entity.js create mode 100644 packages/edit-navigation/src/hooks/use-menu-notifications.js create mode 100644 packages/edit-navigation/src/hooks/use-navigation-block-editor.js create mode 100644 packages/edit-navigation/src/hooks/use-navigation-editor-menu.js create mode 100644 packages/edit-navigation/src/hooks/use-navigation-editor.js create mode 100644 packages/edit-navigation/src/utils/constants.js create mode 100644 packages/edit-navigation/src/utils/fetch-link-suggestions.js diff --git a/packages/edit-navigation/src/components/header/save-button.js b/packages/edit-navigation/src/components/header/save-button.js index 4d526ebbe40ed3..604a7812cc92d1 100644 --- a/packages/edit-navigation/src/components/header/save-button.js +++ b/packages/edit-navigation/src/components/header/save-button.js @@ -9,8 +9,12 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import { store as editNavigationStore } from '../../store'; +import { useMenuEntity, MenuIdContext } from '../../hooks'; +import { useContext } from '@wordpress/element'; export default function SaveButton( { navigationPost } ) { + const menuId = useContext( MenuIdContext ); + const { saveMenuName } = useMenuEntity( menuId ); const { saveNavigationPost } = useDispatch( editNavigationStore ); return ( @@ -19,6 +23,7 @@ export default function SaveButton( { navigationPost } ) { isPrimary onClick={ () => { saveNavigationPost( navigationPost ); + saveMenuName(); } } disabled={ ! navigationPost } > diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index c773a79cfddf06..bd5d5edd689cd5 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -25,9 +25,12 @@ import { useRef } 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 { + MenuIdContext, + useNavigationEditor, + useNavigationBlockEditor, + useMenuNotifications, +} from '../../hooks'; import ErrorBoundary from '../error-boundary'; import NavigationEditorShortcuts from './shortcuts'; import Header from '../header'; @@ -76,51 +79,55 @@ export default function Layout( { blockEditorSettings } ) { 'has-block-inspector': isBlockEditorReady, } ) } > -
+ +
- { ! hasFinishedInitialLoad && } + { ! hasFinishedInitialLoad && } - { hasFinishedInitialLoad && ! hasMenus && ( - - ) } + { hasFinishedInitialLoad && ! hasMenus && ( + + ) } - { isBlockEditorReady && ( - - - -
- + +
+ +
+ + -
- - -
- ) } + + ) } + diff --git a/packages/edit-navigation/src/components/name-editor/index.js b/packages/edit-navigation/src/components/name-editor/index.js new file mode 100644 index 00000000000000..c2dee85fd0bb2d --- /dev/null +++ b/packages/edit-navigation/src/components/name-editor/index.js @@ -0,0 +1,35 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useEffect, useState } from '@wordpress/element'; +/** + * Internal dependencies + */ +import { BlockControls } from '@wordpress/block-editor'; +import { ToolbarGroup, ToolbarItem } from '@wordpress/components'; +import { useMenuEntity, useNavigationEditorMenu } from '../../hooks'; + +export function NameEditor() { + const { menuName, menuId } = useNavigationEditorMenu(); + const { editMenuName } = useMenuEntity( menuId ); + const [ tmpMenuName, setTmpMenuName ] = useState( menuName ); + useEffect( () => setTmpMenuName( menuName ), [ menuName ] ); + return ( + <> + + + { + setTmpMenuName( value ); + editMenuName( value ); + } } + aria-label={ __( 'Edit menu name' ) } + /> + + + + ); +} diff --git a/packages/edit-navigation/src/filters/add-menu-name-editor.js b/packages/edit-navigation/src/filters/add-menu-name-editor.js new file mode 100644 index 00000000000000..b047c0df5c310f --- /dev/null +++ b/packages/edit-navigation/src/filters/add-menu-name-editor.js @@ -0,0 +1,33 @@ +/** + * WordPress dependencies + */ +/** + * Internal dependencies + */ +import { NameEditor } from '../components/name-editor'; +import { addFilter } from '@wordpress/hooks'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { useNavigationEditor } from '../hooks'; + +const addMenuNameEditor = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + if ( props.name !== 'core/navigation' ) { + return ; + } + const { menuName } = useNavigationEditor(); + return ( + <> + + ; + + ); + }, + 'withMenuName' +); + +export default () => + addFilter( + 'editor.BlockEdit', + 'core/edit-navigation/with-menu-name', + addMenuNameEditor + ); diff --git a/packages/edit-navigation/src/filters/disable-inserting-non-navigation-blocks.js b/packages/edit-navigation/src/filters/disable-inserting-non-navigation-blocks.js new file mode 100644 index 00000000000000..c9a34fe168b0f1 --- /dev/null +++ b/packages/edit-navigation/src/filters/disable-inserting-non-navigation-blocks.js @@ -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 + ); diff --git a/packages/edit-navigation/src/filters/index.js b/packages/edit-navigation/src/filters/index.js new file mode 100644 index 00000000000000..96315b46b7eb8d --- /dev/null +++ b/packages/edit-navigation/src/filters/index.js @@ -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(); +}; diff --git a/packages/edit-navigation/src/filters/remove-edit-unsupported-features.js b/packages/edit-navigation/src/filters/remove-edit-unsupported-features.js new file mode 100644 index 00000000000000..a2074e2216501c --- /dev/null +++ b/packages/edit-navigation/src/filters/remove-edit-unsupported-features.js @@ -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 ; + } + + return ( + + ); + }, + 'removeNavigationBlockEditUnsupportedFeatures' +); + +export default () => + addFilter( + 'editor.BlockEdit', + 'core/edit-navigation/remove-navigation-block-edit-unsupported-features', + removeNavigationBlockEditUnsupportedFeatures + ); diff --git a/packages/edit-navigation/src/filters/remove-settings-unsupported-features.js b/packages/edit-navigation/src/filters/remove-settings-unsupported-features.js new file mode 100644 index 00000000000000..26d62f9ec6448c --- /dev/null +++ b/packages/edit-navigation/src/filters/remove-settings-unsupported-features.js @@ -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 + ); diff --git a/packages/edit-navigation/src/hooks/index.js b/packages/edit-navigation/src/hooks/index.js new file mode 100644 index 00000000000000..46d262d90a56ce --- /dev/null +++ b/packages/edit-navigation/src/hooks/index.js @@ -0,0 +1,14 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { createContext } from '@wordpress/element'; + +export const untitledMenu = __( '(untitled menu)' ); +export const MenuIdContext = createContext(); + +export { default as useMenuEntity } from './use-menu-entity'; +export { default as useNavigationEditor } from './use-navigation-editor'; +export { default as useNavigationBlockEditor } from './use-navigation-block-editor'; +export { default as useMenuNotifications } from './use-menu-notifications'; +export { default as useNavigationEditorMenu } from './use-navigation-editor-menu'; diff --git a/packages/edit-navigation/src/hooks/use-menu-entity.js b/packages/edit-navigation/src/hooks/use-menu-entity.js new file mode 100644 index 00000000000000..6c5fbd408a261a --- /dev/null +++ b/packages/edit-navigation/src/hooks/use-menu-entity.js @@ -0,0 +1,39 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +/** + * External dependencies + */ +import { isUndefined, negate } from 'lodash'; +/** + * Internal dependencies + */ +import { MENU_KIND, MENU_POST_TYPE } from '../utils/constants'; + +import { untitledMenu } from './index'; + +export default function useMenuEntity( menuId ) { + const { editEntityRecord, saveEditedEntityRecord } = useDispatch( 'core' ); + + const menuEntityData = [ MENU_KIND, MENU_POST_TYPE, menuId ]; + const editedMenu = useSelect( + ( select ) => + select( 'core' ).getEditedEntityRecord( ...menuEntityData ), + [ menuId ] + ); + + const editedMenuName = menuId && editedMenu.name; + + const saveMenuName = () => + negate( isUndefined )( editedMenuName ) && + saveEditedEntityRecord( ...menuEntityData ); + + const editMenuName = ( name = untitledMenu ) => + editEntityRecord( ...menuEntityData, { name } ); + + return { + saveMenuName, + editMenuName, + }; +} diff --git a/packages/edit-navigation/src/hooks/use-menu-notifications.js b/packages/edit-navigation/src/hooks/use-menu-notifications.js new file mode 100644 index 00000000000000..e85f33f164fdd8 --- /dev/null +++ b/packages/edit-navigation/src/hooks/use-menu-notifications.js @@ -0,0 +1,50 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +/** + * Internal dependencies + */ +import { MENU_POST_TYPE, MENU_KIND } from '../utils/constants'; + +export default function useMenuNotifications( menuId ) { + const { lastSaveError, lastDeleteError } = useSelect( + ( select ) => ( { + lastSaveError: select( 'core' ).getLastEntitySaveError( + MENU_KIND, + MENU_POST_TYPE + ), + lastDeleteError: select( 'core' ).getLastEntityDeleteError( + MENU_KIND, + MENU_POST_TYPE, + menuId + ), + } ), + [ menuId ] + ); + + const { createErrorNotice } = useDispatch( noticesStore ); + + const processError = ( error ) => { + const document = new window.DOMParser().parseFromString( + error.message, + 'text/html' + ); + const errorText = document.body.textContent || ''; + createErrorNotice( errorText, { id: 'edit-navigation-error' } ); + }; + + useEffect( () => { + if ( lastSaveError ) { + processError( lastSaveError ); + } + }, [ lastSaveError ] ); + + useEffect( () => { + if ( lastDeleteError ) { + processError( lastDeleteError ); + } + }, [ lastDeleteError ] ); +} diff --git a/packages/edit-navigation/src/hooks/use-navigation-block-editor.js b/packages/edit-navigation/src/hooks/use-navigation-block-editor.js new file mode 100644 index 00000000000000..855bd92b758705 --- /dev/null +++ b/packages/edit-navigation/src/hooks/use-navigation-block-editor.js @@ -0,0 +1,37 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { useCallback } from '@wordpress/element'; +import { useEntityBlockEditor } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import { + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, +} from '../utils/constants'; +import { store as editNavigationStore } from '../store'; + +export default function useNavigationBlockEditor( post ) { + const { createMissingMenuItems } = useDispatch( editNavigationStore ); + + const [ blocks, onInput, onEntityChange ] = useEntityBlockEditor( + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, + { + id: post?.id, + } + ); + + const onChange = useCallback( + async ( ...args ) => { + await onEntityChange( ...args ); + createMissingMenuItems( post ); + }, + [ onEntityChange, post ] + ); + + return [ blocks, onInput, onChange ]; +} diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor-menu.js b/packages/edit-navigation/src/hooks/use-navigation-editor-menu.js new file mode 100644 index 00000000000000..4c8d2f3267f7b0 --- /dev/null +++ b/packages/edit-navigation/src/hooks/use-navigation-editor-menu.js @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import { useDispatch, useSelect } from '@wordpress/data'; +import { useContext } from '@wordpress/element'; +/** + * Internal dependencies + */ +import { MenuIdContext, untitledMenu } from './index'; + +export default function useNavigationEditorMenu() { + const { saveMenu } = useDispatch( 'core' ); + const menuId = useContext( MenuIdContext ); + const menu = useSelect( ( select ) => select( 'core' ).getMenu( menuId ), [ + menuId, + ] ); + const menuName = menu?.name ?? untitledMenu; + return { + saveMenu, + menuId, + menu, + menuName, + }; +} diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor.js b/packages/edit-navigation/src/hooks/use-navigation-editor.js new file mode 100644 index 00000000000000..297d4badf075dd --- /dev/null +++ b/packages/edit-navigation/src/hooks/use-navigation-editor.js @@ -0,0 +1,61 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useState, useEffect } from '@wordpress/element'; +/** + * Internal dependencies + */ +import { store as editNavigationStore } from '../store'; + +export default function useNavigationEditor() { + const { deleteMenu: _deleteMenu } = useDispatch( 'core' ); + const { menus, hasLoadedMenus } = useSelect( ( select ) => { + const selectors = select( 'core' ); + const params = { per_page: -1 }; + return { + menus: selectors.getMenus( params ), + hasLoadedMenus: selectors.hasFinishedResolution( 'getMenus', [ + params, + ] ), + }; + }, [] ); + + const [ selectedMenuId, setSelectedMenuId ] = useState( null ); + + useEffect( () => { + if ( ! selectedMenuId && menus?.length ) { + setSelectedMenuId( menus[ 0 ].id ); + } + }, [ selectedMenuId, menus ] ); + + const navigationPost = useSelect( + ( select ) => + select( editNavigationStore ).getNavigationPostForMenu( + selectedMenuId + ), + [ selectedMenuId ] + ); + + const selectMenu = ( menuId ) => { + setSelectedMenuId( menuId ); + }; + + const deleteMenu = async () => { + const didDeleteMenu = await _deleteMenu( selectedMenuId, { + force: true, + } ); + if ( didDeleteMenu ) { + setSelectedMenuId( null ); + } + }; + + return { + menus, + selectedMenuId, + navigationPost, + selectMenu, + deleteMenu, + hasLoadedMenus, + }; +} diff --git a/packages/edit-navigation/src/index.js b/packages/edit-navigation/src/index.js index ef67e940a67599..4744f8b29d6f5e 100644 --- a/packages/edit-navigation/src/index.js +++ b/packages/edit-navigation/src/index.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import { map, set, flatten, partialRight } from 'lodash'; - /** * WordPress dependencies */ @@ -11,167 +6,28 @@ import { __experimentalRegisterExperimentalCoreBlocks, } from '@wordpress/block-library'; import { render } from '@wordpress/element'; -import { createHigherOrderComponent } from '@wordpress/compose'; -import { __ } from '@wordpress/i18n'; -import apiFetch from '@wordpress/api-fetch'; -import { addQueryArgs } from '@wordpress/url'; -import { decodeEntities } from '@wordpress/html-entities'; -import { addFilter } from '@wordpress/hooks'; - /** * Internal dependencies */ -import Layout from './components/layout'; -import './store'; - -function disableInsertingNonNavigationBlocks( settings, name ) { - if ( ! [ 'core/navigation', 'core/navigation-link' ].includes( name ) ) { - set( settings, [ 'supports', 'inserter' ], false ); - } - return settings; -} - -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, - }; -} - -const removeNavigationBlockEditUnsupportedFeatures = createHigherOrderComponent( - ( BlockEdit ) => ( props ) => { - if ( props.name !== 'core/navigation' ) { - return ; - } - - return ( - - ); - }, - 'removeNavigationBlockEditUnsupportedFeatures' -); +import { addFilters } from './filters'; +import fetchLinkSuggestions from './utils/fetch-link-suggestions'; /** - * Fetches link suggestions from the API. This function is an exact copy of a function found at: - * - * packages/editor/src/components/provider/index.js - * - * It seems like there is no suitable package to import this from. Ideally it would be either part of core-data. - * Until we refactor it, just copying the code is the simplest solution. - * - * @param {string} search - * @param {Object} [searchArguments] - * @param {number} [searchArguments.isInitialSuggestions] - * @param {number} [searchArguments.type] - * @param {number} [searchArguments.subtype] - * @param {Object} [editorSettings] - * @param {boolean} [editorSettings.disablePostFormats=false] - * @return {Promise} List of suggestions + * Internal dependencies */ -const fetchLinkSuggestions = ( - search, - { isInitialSuggestions, type, subtype } = {}, - { disablePostFormats = false } = {} -) => { - const perPage = isInitialSuggestions ? 3 : 20; - - const queries = []; - - if ( ! type || type === 'post' ) { - queries.push( - apiFetch( { - path: addQueryArgs( '/wp/v2/search', { - search, - per_page: perPage, - type: 'post', - subtype, - } ), - } ).catch( () => [] ) // fail by returning no results - ); - } - - if ( ! type || type === 'term' ) { - queries.push( - apiFetch( { - path: addQueryArgs( '/wp/v2/search', { - search, - per_page: perPage, - type: 'term', - subtype, - } ), - } ).catch( () => [] ) - ); - } - - if ( ! disablePostFormats && ( ! type || type === 'post-format' ) ) { - queries.push( - apiFetch( { - path: addQueryArgs( '/wp/v2/search', { - search, - per_page: perPage, - type: 'post-format', - subtype, - } ), - } ).catch( () => [] ) - ); - } - - return Promise.all( queries ).then( ( results ) => { - return map( flatten( results ).slice( 0, perPage ), ( result ) => ( { - id: result.id, - url: result.url, - title: decodeEntities( result.title ) || __( '(no title)' ), - type: result.subtype || result.type, - } ) ); - } ); -}; +import Layout from './components/layout'; +import './store'; export function initialize( id, settings ) { - if ( ! settings.blockNavMenus ) { - addFilter( - 'blocks.registerBlockType', - 'core/edit-navigation/disable-inserting-non-navigation-blocks', - disableInsertingNonNavigationBlocks - ); - } - - addFilter( - 'blocks.registerBlockType', - 'core/edit-navigation/remove-navigation-block-settings-unsupported-features', - removeNavigationBlockSettingsUnsupportedFeatures - ); - - addFilter( - 'editor.BlockEdit', - 'core/edit-navigation/remove-navigation-block-edit-unsupported-features', - removeNavigationBlockEditUnsupportedFeatures - ); - + addFilters( ! settings.blockNavMenus ); registerCoreBlocks(); if ( process.env.GUTENBERG_PHASE === 2 ) { __experimentalRegisterExperimentalCoreBlocks(); } - settings.__experimentalFetchLinkSuggestions = partialRight( - fetchLinkSuggestions, - settings - ); + settings.__experimentalFetchLinkSuggestions = () => + fetchLinkSuggestions( settings ); render( , diff --git a/packages/edit-navigation/src/store/resolvers.js b/packages/edit-navigation/src/store/resolvers.js index 5a5a06438b371d..aaecaec940c1e3 100644 --- a/packages/edit-navigation/src/store/resolvers.js +++ b/packages/edit-navigation/src/store/resolvers.js @@ -11,8 +11,12 @@ import { parse, createBlock } from '@wordpress/blocks'; /** * Internal dependencies */ +import { + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, +} from '../utils/constants'; import { resolveMenuItems, dispatch } from './controls'; -import { KIND, POST_TYPE, buildNavigationPostId } from './utils'; +import { buildNavigationPostId } from './utils'; /** * Creates a "stub" navigation post reflecting the contents of menu with id=menuId. The @@ -35,7 +39,11 @@ export function* getNavigationPostForMenu( menuId ) { // Dispatch startResolution to skip the execution of the real getEntityRecord resolver - it would // issue an http request and fail. - const args = [ KIND, POST_TYPE, stubPost.id ]; + const args = [ + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, + stubPost.id, + ]; yield dispatch( 'core', 'startResolution', 'getEntityRecord', args ); // Now let's create a proper one hydrated using actual menu items @@ -73,8 +81,8 @@ const persistPost = ( post ) => dispatch( 'core', 'receiveEntityRecords', - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, post, { id: post.id }, false diff --git a/packages/edit-navigation/src/store/selectors.js b/packages/edit-navigation/src/store/selectors.js index 2891e1ac3046dd..48261838028161 100644 --- a/packages/edit-navigation/src/store/selectors.js +++ b/packages/edit-navigation/src/store/selectors.js @@ -11,7 +11,12 @@ import { createRegistrySelector } from '@wordpress/data'; /** * Internal dependencies */ -import { KIND, POST_TYPE, buildNavigationPostId } from './utils'; +import { + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, +} from '../utils/constants'; + +import { buildNavigationPostId } from './utils'; /** * Returns a "stub" navigation post reflecting the contents of menu with id=menuId. The @@ -32,8 +37,8 @@ export const getNavigationPostForMenu = createRegistrySelector( return null; } return select( 'core' ).getEditedEntityRecord( - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, buildNavigationPostId( menuId ) ); } @@ -48,8 +53,8 @@ export const getNavigationPostForMenu = createRegistrySelector( export const hasResolvedNavigationPost = createRegistrySelector( ( select ) => ( state, menuId ) => { return select( 'core' ).hasFinishedResolution( 'getEntityRecord', [ - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, buildNavigationPostId( menuId ), ] ); } diff --git a/packages/edit-navigation/src/store/test/resolvers.js b/packages/edit-navigation/src/store/test/resolvers.js index da79100c4458ce..af3e0ef2b6cd1c 100644 --- a/packages/edit-navigation/src/store/test/resolvers.js +++ b/packages/edit-navigation/src/store/test/resolvers.js @@ -3,7 +3,12 @@ */ import { getNavigationPostForMenu } from '../resolvers'; import { resolveMenuItems, dispatch } from '../controls'; -import { KIND, POST_TYPE, buildNavigationPostId } from '../utils'; +import { + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, +} from '../../utils/constants'; + +import { buildNavigationPostId } from '../utils'; // Mock createBlock to avoid creating block in test environment jest.mock( '@wordpress/blocks', () => { @@ -52,8 +57,8 @@ describe( 'getNavigationPostForMenu', () => { dispatch( 'core', 'receiveEntityRecords', - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, stubPost, { id: stubPost.id }, false @@ -63,8 +68,8 @@ describe( 'getNavigationPostForMenu', () => { // Dispatch startResolution. expect( generator.next().value ).toEqual( dispatch( 'core', 'startResolution', 'getEntityRecord', [ - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, stubPost.id, ] ) ); @@ -164,8 +169,8 @@ describe( 'getNavigationPostForMenu', () => { dispatch( 'core', 'receiveEntityRecords', - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, navigationBlockStubPost, { id: navigationBlockStubPost.id }, false @@ -174,8 +179,8 @@ describe( 'getNavigationPostForMenu', () => { expect( generator.next().value ).toEqual( dispatch( 'core', 'finishResolution', 'getEntityRecord', [ - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, stubPost.id, ] ) ); diff --git a/packages/edit-navigation/src/store/test/selectors.js b/packages/edit-navigation/src/store/test/selectors.js index 450283f2661d23..67b7a25f932cb8 100644 --- a/packages/edit-navigation/src/store/test/selectors.js +++ b/packages/edit-navigation/src/store/test/selectors.js @@ -6,7 +6,12 @@ import { hasResolvedNavigationPost, getMenuItemForClientId, } from '../selectors'; -import { KIND, POST_TYPE, buildNavigationPostId } from '../utils'; +import { + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, +} from '../../utils/constants'; + +import { buildNavigationPostId } from '../utils'; describe( 'getNavigationPostForMenu', () => { it( 'gets navigation post for menu', () => { @@ -29,8 +34,8 @@ describe( 'getNavigationPostForMenu', () => { expect( registry.select ).toHaveBeenCalledWith( 'core' ); expect( getEditedEntityRecord ).toHaveBeenCalledWith( - KIND, - POST_TYPE, + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, buildNavigationPostId( menuId ) ); @@ -83,7 +88,11 @@ describe( 'hasResolvedNavigationPost', () => { expect( registry.select ).toHaveBeenCalledWith( 'core' ); expect( hasFinishedResolution ).toHaveBeenCalledWith( 'getEntityRecord', - [ KIND, POST_TYPE, buildNavigationPostId( menuId ) ] + [ + NAVIGATION_POST_KIND, + NAVIGATION_POST_POST_TYPE, + buildNavigationPostId( menuId ), + ] ); hasResolvedNavigationPost.registry = defaultRegistry; diff --git a/packages/edit-navigation/src/store/utils.js b/packages/edit-navigation/src/store/utils.js index 64bbab6d69a18f..fe28772fadeb4c 100644 --- a/packages/edit-navigation/src/store/utils.js +++ b/packages/edit-navigation/src/store/utils.js @@ -17,20 +17,6 @@ import { isProcessingPost, } from './controls'; -/** - * "Kind" of the navigation post. - * - * @type {string} - */ -export const KIND = 'root'; - -/** - * "post type" of the navigation post. - * - * @type {string} - */ -export const POST_TYPE = 'postType'; - /** * Builds an ID for a new navigation post. * diff --git a/packages/edit-navigation/src/style.scss b/packages/edit-navigation/src/style.scss index 170cbcefe55131..b3309df35db84b 100644 --- a/packages/edit-navigation/src/style.scss +++ b/packages/edit-navigation/src/style.scss @@ -1,13 +1,9 @@ -$navigation-editor-width: 420px; -$navigation-editor-spacing-top: $grid-unit-40 * 2; - *, *::before, *::after { box-sizing: border-box; } -@import "./components/add-menu/style.scss"; @import "./components/editor/style.scss"; @import "./components/error-boundary/style.scss"; @import "./components/header/style.scss"; diff --git a/packages/edit-navigation/src/utils/constants.js b/packages/edit-navigation/src/utils/constants.js new file mode 100644 index 00000000000000..9074d2f5e0a59e --- /dev/null +++ b/packages/edit-navigation/src/utils/constants.js @@ -0,0 +1,27 @@ +/** + * "Kind" of the menu post. + * + * @type {string} + */ +export const MENU_KIND = 'root'; + +/** + * "post type" of the menu post. + * + * @type {string} + */ +export const MENU_POST_TYPE = 'menu'; + +/** + * "Kind" of the navigation post. + * + * @type {string} + */ +export const NAVIGATION_POST_KIND = 'root'; + +/** + * "post type" of the navigation post. + * + * @type {string} + */ +export const NAVIGATION_POST_POST_TYPE = 'postType'; diff --git a/packages/edit-navigation/src/utils/fetch-link-suggestions.js b/packages/edit-navigation/src/utils/fetch-link-suggestions.js new file mode 100644 index 00000000000000..94a4e1587b15d7 --- /dev/null +++ b/packages/edit-navigation/src/utils/fetch-link-suggestions.js @@ -0,0 +1,101 @@ +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; +import { addQueryArgs } from '@wordpress/url'; +/** + * External dependencies + */ +import { flatten, map } from 'lodash'; +import { decodeEntities } from '@wordpress/html-entities'; +import { __ } from '@wordpress/i18n'; + +/** + * Fetches link suggestions from the API. This function is an exact copy of a function found at: + * + * packages/editor/src/components/provider/index.js + * + * It seems like there is no suitable package to import this from. Ideally it would be either part of core-data. + * Until we refactor it, just copying the code is the simplest solution. + * + * @param {string} search + * @param {Object} [searchArguments] + * @param {number} [searchArguments.isInitialSuggestions] + * @param {number} [searchArguments.type] + * @param {number} [searchArguments.subtype] + * @param {Object} [editorSettings] + * @param {boolean} [editorSettings.disablePostFormats=false] + * @return {Promise} List of suggestions + */ + +export default function fetchLinkSuggestions( + search, + { isInitialSuggestions, type, subtype } = {}, + { disablePostFormats = false } = {} +) { + const perPage = isInitialSuggestions ? 3 : 20; + + const linkTypes = [ 'post', 'term', 'post-format' ]; + + linkTypes.forEach( ( linkType ) => { + if ( ! type || type === linkType ) { + apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'post', + subtype, + } ), + } ).catch( () => [] ); // fail by returning no results + } + } ); + const queries = []; + + if ( ! type || type === 'post' ) { + queries.push( + apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'post', + subtype, + } ), + } ).catch( () => [] ) // fail by returning no results + ); + } + + if ( ! type || type === 'term' ) { + queries.push( + apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'term', + subtype, + } ), + } ).catch( () => [] ) + ); + } + + if ( ! disablePostFormats && ( ! type || type === 'post-format' ) ) { + queries.push( + apiFetch( { + path: addQueryArgs( '/wp/v2/search', { + search, + per_page: perPage, + type: 'post-format', + subtype, + } ), + } ).catch( () => [] ) + ); + } + + return Promise.all( queries ).then( ( results ) => { + return map( flatten( results ).slice( 0, perPage ), ( result ) => ( { + id: result.id, + url: result.url, + title: decodeEntities( result.title ) || __( '(no title)' ), + type: result.subtype || result.type, + } ) ); + } ); +} From b5ee7298f1571b28ed66bf46309a7892687c05b0 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 15 Feb 2021 18:30:52 +0100 Subject: [PATCH 02/21] name editor component added --- packages/edit-navigation/src/components/name-editor/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/components/name-editor/index.js b/packages/edit-navigation/src/components/name-editor/index.js index c2dee85fd0bb2d..1769b974673551 100644 --- a/packages/edit-navigation/src/components/name-editor/index.js +++ b/packages/edit-navigation/src/components/name-editor/index.js @@ -22,7 +22,7 @@ export function NameEditor() { { + onChange={ ( { target: { value } } ) => { setTmpMenuName( value ); editMenuName( value ); } } From d3ce125683e5295a5c970565b97adc36f2a52529 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 15 Feb 2021 18:34:25 +0100 Subject: [PATCH 03/21] add missing styles| --- packages/edit-navigation/src/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/edit-navigation/src/style.scss b/packages/edit-navigation/src/style.scss index b3309df35db84b..170cbcefe55131 100644 --- a/packages/edit-navigation/src/style.scss +++ b/packages/edit-navigation/src/style.scss @@ -1,9 +1,13 @@ +$navigation-editor-width: 420px; +$navigation-editor-spacing-top: $grid-unit-40 * 2; + *, *::before, *::after { box-sizing: border-box; } +@import "./components/add-menu/style.scss"; @import "./components/editor/style.scss"; @import "./components/error-boundary/style.scss"; @import "./components/header/style.scss"; From 2295c5af964d65b515dd70beebc1ff516e69f81b Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 15 Feb 2021 19:09:24 +0100 Subject: [PATCH 04/21] remove doubled hooks --- .../layout/use-menu-notifications.js | 46 ----------- .../layout/use-navigation-block-editor.js | 32 -------- .../layout/use-navigation-editor.js | 77 ------------------- .../src/hooks/use-navigation-editor.js | 9 +++ 4 files changed, 9 insertions(+), 155 deletions(-) delete mode 100644 packages/edit-navigation/src/components/layout/use-menu-notifications.js delete mode 100644 packages/edit-navigation/src/components/layout/use-navigation-block-editor.js delete mode 100644 packages/edit-navigation/src/components/layout/use-navigation-editor.js diff --git a/packages/edit-navigation/src/components/layout/use-menu-notifications.js b/packages/edit-navigation/src/components/layout/use-menu-notifications.js deleted file mode 100644 index 16e7076c0011d2..00000000000000 --- a/packages/edit-navigation/src/components/layout/use-menu-notifications.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; -import { store as noticesStore } from '@wordpress/notices'; - -export default function useMenuNotifications( menuId ) { - const { lastSaveError, lastDeleteError } = useSelect( - ( select ) => ( { - lastSaveError: select( 'core' ).getLastEntitySaveError( - 'root', - 'menu' - ), - lastDeleteError: select( 'core' ).getLastEntityDeleteError( - 'root', - 'menu', - menuId - ), - } ), - [ menuId ] - ); - - const { createErrorNotice } = useDispatch( noticesStore ); - - const processError = ( error ) => { - const document = new window.DOMParser().parseFromString( - error.message, - 'text/html' - ); - const errorText = document.body.textContent || ''; - createErrorNotice( errorText, { id: 'edit-navigation-error' } ); - }; - - useEffect( () => { - if ( lastSaveError ) { - processError( lastSaveError ); - } - }, [ lastSaveError ] ); - - useEffect( () => { - if ( lastDeleteError ) { - processError( lastDeleteError ); - } - }, [ lastDeleteError ] ); -} diff --git a/packages/edit-navigation/src/components/layout/use-navigation-block-editor.js b/packages/edit-navigation/src/components/layout/use-navigation-block-editor.js deleted file mode 100644 index 902e77ac22bbd4..00000000000000 --- a/packages/edit-navigation/src/components/layout/use-navigation-block-editor.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * WordPress dependencies - */ -import { useDispatch } from '@wordpress/data'; -import { useCallback } from '@wordpress/element'; -import { useEntityBlockEditor } from '@wordpress/core-data'; - -/** - * Internal dependencies - */ -import { KIND, POST_TYPE } from '../../store/utils'; -import { store as editNavigationStore } from '../../store'; - -export default function useNavigationBlockEditor( post ) { - const { createMissingMenuItems } = useDispatch( editNavigationStore ); - - const [ blocks, onInput, _onChange ] = useEntityBlockEditor( - KIND, - POST_TYPE, - { id: post?.id } - ); - - const onChange = useCallback( - async ( ...args ) => { - await _onChange( ...args ); - createMissingMenuItems( post ); - }, - [ _onChange, post ] - ); - - return [ blocks, onInput, onChange ]; -} diff --git a/packages/edit-navigation/src/components/layout/use-navigation-editor.js b/packages/edit-navigation/src/components/layout/use-navigation-editor.js deleted file mode 100644 index e6439e804062bb..00000000000000 --- a/packages/edit-navigation/src/components/layout/use-navigation-editor.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { useState, useEffect } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import { store as editNavigationStore } from '../../store'; - -export default function useNavigationEditor() { - const [ hasFinishedInitialLoad, setHasFinishedInitialLoad ] = useState( - false - ); - const { menus, hasLoadedMenus } = useSelect( ( select ) => { - const selectors = select( 'core' ); - const params = { per_page: -1 }; - return { - menus: selectors.getMenus( params ), - hasLoadedMenus: selectors.hasFinishedResolution( 'getMenus', [ - params, - ] ), - }; - }, [] ); - - useEffect( () => { - if ( hasLoadedMenus ) { - setHasFinishedInitialLoad( true ); - } - }, [ hasLoadedMenus ] ); - - const [ selectedMenuId, setSelectedMenuId ] = useState( null ); - - useEffect( () => { - if ( ! selectedMenuId && menus?.length ) { - setSelectedMenuId( menus[ 0 ].id ); - } - }, [ selectedMenuId, menus ] ); - - const navigationPost = useSelect( - ( select ) => { - if ( ! selectedMenuId ) { - return; - } - return select( editNavigationStore ).getNavigationPostForMenu( - selectedMenuId - ); - }, - [ selectedMenuId ] - ); - - const selectMenu = ( menuId ) => { - setSelectedMenuId( menuId ); - }; - - const { deleteMenu: _deleteMenu } = useDispatch( 'core' ); - - const deleteMenu = async () => { - const didDeleteMenu = await _deleteMenu( selectedMenuId, { - force: true, - } ); - if ( didDeleteMenu ) { - setSelectedMenuId( null ); - } - }; - - return { - menus, - hasLoadedMenus, - hasFinishedInitialLoad, - selectedMenuId, - navigationPost, - selectMenu, - deleteMenu, - }; -} diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor.js b/packages/edit-navigation/src/hooks/use-navigation-editor.js index 297d4badf075dd..e7a2c7dda21eb6 100644 --- a/packages/edit-navigation/src/hooks/use-navigation-editor.js +++ b/packages/edit-navigation/src/hooks/use-navigation-editor.js @@ -10,6 +10,9 @@ import { store as editNavigationStore } from '../store'; export default function useNavigationEditor() { const { deleteMenu: _deleteMenu } = useDispatch( 'core' ); + const [ hasFinishedInitialLoad, setHasFinishedInitialLoad ] = useState( + false + ); const { menus, hasLoadedMenus } = useSelect( ( select ) => { const selectors = select( 'core' ); const params = { per_page: -1 }; @@ -20,6 +23,11 @@ export default function useNavigationEditor() { ] ), }; }, [] ); + useEffect( () => { + if ( hasLoadedMenus ) { + setHasFinishedInitialLoad( true ); + } + }, [ hasLoadedMenus ] ); const [ selectedMenuId, setSelectedMenuId ] = useState( null ); @@ -56,6 +64,7 @@ export default function useNavigationEditor() { navigationPost, selectMenu, deleteMenu, + hasFinishedInitialLoad, hasLoadedMenus, }; } From 19ea70c1a7de0fcbc65d54b0ee121614c6a63be2 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 15 Feb 2021 20:30:12 +0100 Subject: [PATCH 05/21] remove ; --- packages/edit-navigation/src/filters/add-menu-name-editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/filters/add-menu-name-editor.js b/packages/edit-navigation/src/filters/add-menu-name-editor.js index b047c0df5c310f..edf7437a27d297 100644 --- a/packages/edit-navigation/src/filters/add-menu-name-editor.js +++ b/packages/edit-navigation/src/filters/add-menu-name-editor.js @@ -18,7 +18,7 @@ const addMenuNameEditor = createHigherOrderComponent( return ( <> - ; + ); }, From 2f0531f2fb8474d837f38ca6fca621e680fac01d Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 15 Feb 2021 20:40:39 +0100 Subject: [PATCH 06/21] navigation post variable updated --- .../edit-navigation/src/hooks/use-navigation-editor.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor.js b/packages/edit-navigation/src/hooks/use-navigation-editor.js index e7a2c7dda21eb6..1ef85405438a78 100644 --- a/packages/edit-navigation/src/hooks/use-navigation-editor.js +++ b/packages/edit-navigation/src/hooks/use-navigation-editor.js @@ -38,10 +38,14 @@ export default function useNavigationEditor() { }, [ selectedMenuId, menus ] ); const navigationPost = useSelect( - ( select ) => - select( editNavigationStore ).getNavigationPostForMenu( + ( select ) => { + if ( ! selectedMenuId ) { + return; + } + return select( editNavigationStore ).getNavigationPostForMenu( selectedMenuId - ), + ); + }, [ selectedMenuId ] ); From 2b55320c4ae6487d9a4533934c2db3f88c2befb4 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 15 Feb 2021 21:13:11 +0100 Subject: [PATCH 07/21] use-menu-locations hook moved to hooks directory --- .../edit-navigation/src/components/header/manage-locations.js | 2 +- packages/edit-navigation/src/hooks/index.js | 1 + .../src/{components/header => hooks}/use-menu-locations.js | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename packages/edit-navigation/src/{components/header => hooks}/use-menu-locations.js (100%) diff --git a/packages/edit-navigation/src/components/header/manage-locations.js b/packages/edit-navigation/src/components/header/manage-locations.js index 480917f901924c..f9d2e31f5b0804 100644 --- a/packages/edit-navigation/src/components/header/manage-locations.js +++ b/packages/edit-navigation/src/components/header/manage-locations.js @@ -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(), [] ); diff --git a/packages/edit-navigation/src/hooks/index.js b/packages/edit-navigation/src/hooks/index.js index 46d262d90a56ce..0aad08a834d2dc 100644 --- a/packages/edit-navigation/src/hooks/index.js +++ b/packages/edit-navigation/src/hooks/index.js @@ -12,3 +12,4 @@ export { default as useNavigationEditor } from './use-navigation-editor'; export { default as useNavigationBlockEditor } from './use-navigation-block-editor'; export { default as useMenuNotifications } from './use-menu-notifications'; export { default as useNavigationEditorMenu } from './use-navigation-editor-menu'; +export { default as useMenuLocations } from './use-menu-locations'; diff --git a/packages/edit-navigation/src/components/header/use-menu-locations.js b/packages/edit-navigation/src/hooks/use-menu-locations.js similarity index 100% rename from packages/edit-navigation/src/components/header/use-menu-locations.js rename to packages/edit-navigation/src/hooks/use-menu-locations.js From 416f946068875c0d877dc6f5979bcaea17ec2d9c Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Tue, 16 Feb 2021 19:35:22 +0100 Subject: [PATCH 08/21] console error fixed --- packages/edit-navigation/src/hooks/use-menu-entity.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/edit-navigation/src/hooks/use-menu-entity.js b/packages/edit-navigation/src/hooks/use-menu-entity.js index 6c5fbd408a261a..2010730ceff24b 100644 --- a/packages/edit-navigation/src/hooks/use-menu-entity.js +++ b/packages/edit-navigation/src/hooks/use-menu-entity.js @@ -2,10 +2,6 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -/** - * External dependencies - */ -import { isUndefined, negate } from 'lodash'; /** * Internal dependencies */ @@ -19,6 +15,7 @@ export default function useMenuEntity( menuId ) { const menuEntityData = [ MENU_KIND, MENU_POST_TYPE, menuId ]; const editedMenu = useSelect( ( select ) => + menuId && select( 'core' ).getEditedEntityRecord( ...menuEntityData ), [ menuId ] ); @@ -26,8 +23,7 @@ export default function useMenuEntity( menuId ) { const editedMenuName = menuId && editedMenu.name; const saveMenuName = () => - negate( isUndefined )( editedMenuName ) && - saveEditedEntityRecord( ...menuEntityData ); + editedMenuName && saveEditedEntityRecord( ...menuEntityData ); const editMenuName = ( name = untitledMenu ) => editEntityRecord( ...menuEntityData, { name } ); From e6b09928649b25ed3afc7358ab2185ec2be4d313 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Wed, 17 Feb 2021 16:46:20 +0100 Subject: [PATCH 09/21] name edition moved to the sidebar. In toolbar manu name changed to button, when clicked name editor is focused --- .../src/components/name-display/index.js | 22 +++++++ .../src/components/name-editor/index.js | 58 +++++++++++++------ .../src/components/name-editor/style.scss | 5 ++ .../src/filters/add-menu-name-editor.js | 18 ++++-- 4 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 packages/edit-navigation/src/components/name-display/index.js create mode 100644 packages/edit-navigation/src/components/name-editor/style.scss diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js new file mode 100644 index 00000000000000..a8ec642767311e --- /dev/null +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -0,0 +1,22 @@ +/** + * WordPress dependencies + */ +import { ToolbarGroup, ToolbarButton } from '@wordpress/components'; +import { BlockControls } from '@wordpress/block-editor'; +/** + * Internal dependencies + */ +import { useNavigationEditorMenu } from '../../hooks'; + +export default function NameDisplay( { setIsMenuNameEditFocused } ) { + const { menuName } = useNavigationEditorMenu(); + return ( + + + + { menuName } + + + + ); +} diff --git a/packages/edit-navigation/src/components/name-editor/index.js b/packages/edit-navigation/src/components/name-editor/index.js index 1769b974673551..ba08a7c4988198 100644 --- a/packages/edit-navigation/src/components/name-editor/index.js +++ b/packages/edit-navigation/src/components/name-editor/index.js @@ -2,34 +2,58 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useEffect, useState } from '@wordpress/element'; +import { useEffect, useRef, useState } from '@wordpress/element'; /** * Internal dependencies */ -import { BlockControls } from '@wordpress/block-editor'; -import { ToolbarGroup, ToolbarItem } from '@wordpress/components'; +import { InspectorControls } from '@wordpress/block-editor'; +import { PanelBody, BaseControl } from '@wordpress/components'; import { useMenuEntity, useNavigationEditorMenu } from '../../hooks'; +import { useInstanceId } from '@wordpress/compose'; -export function NameEditor() { +export function NameEditor( { + setIsMenuNameEditFocused, + isMenuNameEditFocused, +} ) { const { menuName, menuId } = useNavigationEditorMenu(); const { editMenuName } = useMenuEntity( menuId ); + const inputRef = useRef(); const [ tmpMenuName, setTmpMenuName ] = useState( menuName ); + const instanceId = useInstanceId( NameEditor ); + const id = `components-edit-navigation-name-editor__input-${ instanceId }`; useEffect( () => setTmpMenuName( menuName ), [ menuName ] ); + useEffect( () => { + if ( isMenuNameEditFocused ) inputRef.current.focus(); + }, [ isMenuNameEditFocused ] ); return ( <> - - - { - setTmpMenuName( value ); - editMenuName( value ); - } } - aria-label={ __( 'Edit menu name' ) } - /> - - + + + +
+ + setIsMenuNameEditFocused( false ) + } + className="components-text-control__input" + value={ tmpMenuName } + onChange={ ( { target: { value } } ) => { + setTmpMenuName( value ); + editMenuName( value ); + } } + aria-label={ __( 'Edit menu name' ) } + /> +
+
+
+ { __( + 'A short, descriptive name used to refer to this menu elsewhere.' + ) } +
+
+
); } diff --git a/packages/edit-navigation/src/components/name-editor/style.scss b/packages/edit-navigation/src/components/name-editor/style.scss new file mode 100644 index 00000000000000..1657ce9bf81b6e --- /dev/null +++ b/packages/edit-navigation/src/components/name-editor/style.scss @@ -0,0 +1,5 @@ +.edit-navigation-name-editor__edit-name-description { + font-size: $helptext-font-size; + font-style: normal; + color: $gray-700; +} diff --git a/packages/edit-navigation/src/filters/add-menu-name-editor.js b/packages/edit-navigation/src/filters/add-menu-name-editor.js index edf7437a27d297..4b538ec064f273 100644 --- a/packages/edit-navigation/src/filters/add-menu-name-editor.js +++ b/packages/edit-navigation/src/filters/add-menu-name-editor.js @@ -4,21 +4,31 @@ /** * Internal dependencies */ +import { useState } from '@wordpress/element'; import { NameEditor } from '../components/name-editor'; import { addFilter } from '@wordpress/hooks'; import { createHigherOrderComponent } from '@wordpress/compose'; -import { useNavigationEditor } from '../hooks'; +import NameDisplay from '../components/name-display'; const addMenuNameEditor = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { + const [ isMenuNameEditFocused, setIsMenuNameEditFocused ] = useState( + false + ); if ( props.name !== 'core/navigation' ) { return ; } - const { menuName } = useNavigationEditor(); return ( <> - - + + + ); }, From e724897c5bc9ae177f6085a3ae43c37c88f2abf7 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Thu, 18 Feb 2021 14:56:15 +0100 Subject: [PATCH 10/21] move NameEditor to InspectorControls in InspectorAdditions in order to preserve the same order of items in navbar --- .../components/inspector-additions/index.js | 10 +- .../src/components/layout/index.js | 98 ++++++++++--------- .../src/components/name-display/index.js | 6 +- .../src/components/name-editor/index.js | 68 +++++++------ .../src/filters/add-menu-name-editor.js | 14 +-- packages/edit-navigation/src/hooks/index.js | 1 + 6 files changed, 101 insertions(+), 96 deletions(-) diff --git a/packages/edit-navigation/src/components/inspector-additions/index.js b/packages/edit-navigation/src/components/inspector-additions/index.js index e9cc696bd7c1fd..50fddb1987785c 100644 --- a/packages/edit-navigation/src/components/inspector-additions/index.js +++ b/packages/edit-navigation/src/components/inspector-additions/index.js @@ -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( @@ -22,8 +25,11 @@ export default function InspectorAdditions( { menuId, onDeleteMenu } ) { return ( - - + + + + + ); } diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index bd5d5edd689cd5..92a7a9473478bf 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -19,13 +19,14 @@ import { BlockInspector, __unstableUseBlockSelectionClearer as useBlockSelectionClearer, } from '@wordpress/block-editor'; -import { useRef } from '@wordpress/element'; +import { useRef, useState } from '@wordpress/element'; /** * Internal dependencies */ import EmptyState from './empty-state'; import { + IsMenuEditorFocused, MenuIdContext, useNavigationEditor, useNavigationBlockEditor, @@ -42,7 +43,9 @@ import { store as editNavigationStore } from '../../store'; export default function Layout( { blockEditorSettings } ) { const canvasRef = useRef(); useBlockSelectionClearer( canvasRef ); - + const [ isMenuNameEditFocused, setIsMenuNameEditFocused ] = useState( + false + ); const { saveNavigationPost } = useDispatch( editNavigationStore ); const savePost = () => saveNavigationPost( navigationPost ); @@ -80,53 +83,60 @@ export default function Layout( { blockEditorSettings } ) { } ) } > -
+ +
- { ! hasFinishedInitialLoad && } + { ! hasFinishedInitialLoad && } - { hasFinishedInitialLoad && ! hasMenus && ( - - ) } + { hasFinishedInitialLoad && ! hasMenus && ( + + ) } - { isBlockEditorReady && ( - - - -
- + +
+ +
+ + -
- - -
- ) } + + ) } + diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js index a8ec642767311e..f06d772153a552 100644 --- a/packages/edit-navigation/src/components/name-display/index.js +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -6,10 +6,12 @@ import { BlockControls } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { useNavigationEditorMenu } from '../../hooks'; +import { useNavigationEditorMenu, IsMenuEditorFocused } from '../../hooks'; +import { useContext } from '@wordpress/element'; -export default function NameDisplay( { setIsMenuNameEditFocused } ) { +export default function NameDisplay() { const { menuName } = useNavigationEditorMenu(); + const [ , setIsMenuNameEditFocused ] = useContext( IsMenuEditorFocused ); return ( diff --git a/packages/edit-navigation/src/components/name-editor/index.js b/packages/edit-navigation/src/components/name-editor/index.js index ba08a7c4988198..3c0cd012d43e73 100644 --- a/packages/edit-navigation/src/components/name-editor/index.js +++ b/packages/edit-navigation/src/components/name-editor/index.js @@ -2,19 +2,23 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useEffect, useRef, useState } from '@wordpress/element'; +import { useEffect, useRef, useState, useContext } from '@wordpress/element'; /** * Internal dependencies */ -import { InspectorControls } from '@wordpress/block-editor'; -import { PanelBody, BaseControl } from '@wordpress/components'; -import { useMenuEntity, useNavigationEditorMenu } from '../../hooks'; +import { BaseControl } from '@wordpress/components'; +import { + IsMenuEditorFocused, + useMenuEntity, + useNavigationEditorMenu, +} from '../../hooks'; import { useInstanceId } from '@wordpress/compose'; -export function NameEditor( { - setIsMenuNameEditFocused, - isMenuNameEditFocused, -} ) { +export function NameEditor() { + const [ isMenuNameEditFocused, setIsMenuNameEditFocused ] = useContext( + IsMenuEditorFocused + ); + const { menuName, menuId } = useNavigationEditorMenu(); const { editMenuName } = useMenuEntity( menuId ); const inputRef = useRef(); @@ -27,33 +31,27 @@ export function NameEditor( { }, [ isMenuNameEditFocused ] ); return ( <> - - - -
- - setIsMenuNameEditFocused( false ) - } - className="components-text-control__input" - value={ tmpMenuName } - onChange={ ( { target: { value } } ) => { - setTmpMenuName( value ); - editMenuName( value ); - } } - aria-label={ __( 'Edit menu name' ) } - /> -
-
-
- { __( - 'A short, descriptive name used to refer to this menu elsewhere.' - ) } -
-
-
+ +
+ setIsMenuNameEditFocused( false ) } + className="components-text-control__input" + value={ tmpMenuName } + onChange={ ( { target: { value } } ) => { + setTmpMenuName( value ); + editMenuName( value ); + } } + aria-label={ __( 'Edit menu name' ) } + /> +
+
+
+ { __( + 'A short, descriptive name used to refer to this menu elsewhere.' + ) } +
); } diff --git a/packages/edit-navigation/src/filters/add-menu-name-editor.js b/packages/edit-navigation/src/filters/add-menu-name-editor.js index 4b538ec064f273..e7c0e4210aeb62 100644 --- a/packages/edit-navigation/src/filters/add-menu-name-editor.js +++ b/packages/edit-navigation/src/filters/add-menu-name-editor.js @@ -4,31 +4,19 @@ /** * Internal dependencies */ -import { useState } from '@wordpress/element'; -import { NameEditor } from '../components/name-editor'; import { addFilter } from '@wordpress/hooks'; import { createHigherOrderComponent } from '@wordpress/compose'; import NameDisplay from '../components/name-display'; const addMenuNameEditor = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { - const [ isMenuNameEditFocused, setIsMenuNameEditFocused ] = useState( - false - ); if ( props.name !== 'core/navigation' ) { return ; } return ( <> - - + ); }, diff --git a/packages/edit-navigation/src/hooks/index.js b/packages/edit-navigation/src/hooks/index.js index 0aad08a834d2dc..0d5736cf304298 100644 --- a/packages/edit-navigation/src/hooks/index.js +++ b/packages/edit-navigation/src/hooks/index.js @@ -6,6 +6,7 @@ import { createContext } from '@wordpress/element'; export const untitledMenu = __( '(untitled menu)' ); export const MenuIdContext = createContext(); +export const IsMenuEditorFocused = createContext(); export { default as useMenuEntity } from './use-menu-entity'; export { default as useNavigationEditor } from './use-navigation-editor'; From bec25b53319e1362583d209ed63cf695f478cab8 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Thu, 18 Feb 2021 22:20:26 +0100 Subject: [PATCH 11/21] use TextControl component in name-editor --- .../src/components/name-editor/index.js | 49 +++++++++++-------- .../src/components/name-editor/style.scss | 6 +++ 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/packages/edit-navigation/src/components/name-editor/index.js b/packages/edit-navigation/src/components/name-editor/index.js index 3c0cd012d43e73..aa6181988b31d6 100644 --- a/packages/edit-navigation/src/components/name-editor/index.js +++ b/packages/edit-navigation/src/components/name-editor/index.js @@ -6,7 +6,7 @@ import { useEffect, useRef, useState, useContext } from '@wordpress/element'; /** * Internal dependencies */ -import { BaseControl } from '@wordpress/components'; +import { TextControl } from '@wordpress/components'; import { IsMenuEditorFocused, useMenuEntity, @@ -31,27 +31,36 @@ export function NameEditor() { }, [ isMenuNameEditFocused ] ); return ( <> - -
- setIsMenuNameEditFocused( false ) } - className="components-text-control__input" - value={ tmpMenuName } - onChange={ ( { target: { value } } ) => { - setTmpMenuName( value ); - editMenuName( value ); - } } - aria-label={ __( 'Edit menu name' ) } - /> -
-
-
- { __( + + label={ __( 'Name' ) } + id={ id } + onBlur={ () => setIsMenuNameEditFocused( false ) } + className="components-name-editor__text-control" + value={ tmpMenuName } + onChange={ ( value ) => { + setTmpMenuName( value ); + editMenuName( value ); + } } + aria-label={ __( 'Edit menu name' ) } + /> + { /*
*/ } + { /* setIsMenuNameEditFocused( false ) }*/ } + { /* className="components-text-control__input"*/ } + { /* value={ tmpMenuName }*/ } + { /* onChange={ ( { target: { value } } ) => {*/ } + { /* setTmpMenuName( value );*/ } + { /* editMenuName( value );*/ } + { /* } }*/ } + { /* aria-label={ __( 'Edit menu name' ) }*/ } + { /* />*/ } + { /*
*/ } ); } diff --git a/packages/edit-navigation/src/components/name-editor/style.scss b/packages/edit-navigation/src/components/name-editor/style.scss index 1657ce9bf81b6e..48b438b288564e 100644 --- a/packages/edit-navigation/src/components/name-editor/style.scss +++ b/packages/edit-navigation/src/components/name-editor/style.scss @@ -3,3 +3,9 @@ font-style: normal; color: $gray-700; } + +.components-name-editor__text-control { + .components-base-control { + border: none; + } +} From 1c8a9a2d5ba2c926f743e8c080b8c0d2894aaa56 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 22 Feb 2021 08:54:01 +0100 Subject: [PATCH 12/21] changes according to CR --- .../src/components/layout/index.js | 21 ++++++----- .../src/components/name-display/index.js | 6 +-- .../src/components/name-editor/index.js | 37 ++++--------------- .../src/components/name-editor/style.scss | 8 +--- packages/edit-navigation/src/hooks/index.js | 4 +- .../src/hooks/use-menu-entity.js | 1 + .../src/hooks/use-navigation-editor.js | 31 +++++++--------- ...itor-menu.js => use-selected-menu-data.js} | 6 +-- 8 files changed, 43 insertions(+), 71 deletions(-) rename packages/edit-navigation/src/hooks/{use-navigation-editor-menu.js => use-selected-menu-data.js} (70%) diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index 92a7a9473478bf..26f834a7544774 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -19,14 +19,14 @@ import { BlockInspector, __unstableUseBlockSelectionClearer as useBlockSelectionClearer, } from '@wordpress/block-editor'; -import { useRef, useState } from '@wordpress/element'; +import { useMemo, useRef, useState } from '@wordpress/element'; /** * Internal dependencies */ import EmptyState from './empty-state'; import { - IsMenuEditorFocused, + IsMenuNameControlFocusedContext, MenuIdContext, useNavigationEditor, useNavigationBlockEditor, @@ -43,7 +43,7 @@ import { store as editNavigationStore } from '../../store'; export default function Layout( { blockEditorSettings } ) { const canvasRef = useRef(); useBlockSelectionClearer( canvasRef ); - const [ isMenuNameEditFocused, setIsMenuNameEditFocused ] = useState( + const [ isMenuNameControlFocused, setIsMenuNameControlFocused ] = useState( false ); const { saveNavigationPost } = useDispatch( editNavigationStore ); @@ -83,11 +83,14 @@ export default function Layout( { blockEditorSettings } ) { } ) } > - [ + isMenuNameControlFocused, + setIsMenuNameControlFocused, + ], + [ isMenuNameControlFocused ] + ) } >
) } - +
diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js index f06d772153a552..8c18a27874e5aa 100644 --- a/packages/edit-navigation/src/components/name-display/index.js +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -6,12 +6,12 @@ import { BlockControls } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { useNavigationEditorMenu, IsMenuEditorFocused } from '../../hooks'; +import { useSelectedMenuData, IsMenuNameControlFocusedContext } from '../../hooks'; import { useContext } from '@wordpress/element'; export default function NameDisplay() { - const { menuName } = useNavigationEditorMenu(); - const [ , setIsMenuNameEditFocused ] = useContext( IsMenuEditorFocused ); + const { menuName } = useSelectedMenuData(); + const [ , setIsMenuNameEditFocused ] = useContext( IsMenuNameControlFocusedContext ); return ( diff --git a/packages/edit-navigation/src/components/name-editor/index.js b/packages/edit-navigation/src/components/name-editor/index.js index aa6181988b31d6..917ce41c90944f 100644 --- a/packages/edit-navigation/src/components/name-editor/index.js +++ b/packages/edit-navigation/src/components/name-editor/index.js @@ -2,30 +2,25 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useEffect, useRef, useState, useContext } from '@wordpress/element'; +import { useEffect, useRef, useContext } from '@wordpress/element'; /** * Internal dependencies */ import { TextControl } from '@wordpress/components'; import { - IsMenuEditorFocused, + IsMenuNameControlFocusedContext, useMenuEntity, - useNavigationEditorMenu, + useSelectedMenuData, } from '../../hooks'; -import { useInstanceId } from '@wordpress/compose'; export function NameEditor() { const [ isMenuNameEditFocused, setIsMenuNameEditFocused ] = useContext( - IsMenuEditorFocused + IsMenuNameControlFocusedContext ); - const { menuName, menuId } = useNavigationEditorMenu(); - const { editMenuName } = useMenuEntity( menuId ); + const { menuId } = useSelectedMenuData(); + const { editMenuName, editedMenuName } = useMenuEntity( menuId ); const inputRef = useRef(); - const [ tmpMenuName, setTmpMenuName ] = useState( menuName ); - const instanceId = useInstanceId( NameEditor ); - const id = `components-edit-navigation-name-editor__input-${ instanceId }`; - useEffect( () => setTmpMenuName( menuName ), [ menuName ] ); useEffect( () => { if ( isMenuNameEditFocused ) inputRef.current.focus(); }, [ isMenuNameEditFocused ] ); @@ -37,30 +32,14 @@ export function NameEditor() { 'A short, descriptive name used to refer to this menu elsewhere.' ) } label={ __( 'Name' ) } - id={ id } onBlur={ () => setIsMenuNameEditFocused( false ) } - className="components-name-editor__text-control" - value={ tmpMenuName } + className="edit-navigation-name-editor__text-control" + value={ editedMenuName } onChange={ ( value ) => { - setTmpMenuName( value ); editMenuName( value ); } } aria-label={ __( 'Edit menu name' ) } /> - { /*
*/ } - { /* setIsMenuNameEditFocused( false ) }*/ } - { /* className="components-text-control__input"*/ } - { /* value={ tmpMenuName }*/ } - { /* onChange={ ( { target: { value } } ) => {*/ } - { /* setTmpMenuName( value );*/ } - { /* editMenuName( value );*/ } - { /* } }*/ } - { /* aria-label={ __( 'Edit menu name' ) }*/ } - { /* />*/ } - { /*
*/ } ); } diff --git a/packages/edit-navigation/src/components/name-editor/style.scss b/packages/edit-navigation/src/components/name-editor/style.scss index 48b438b288564e..206c60f92fb8bd 100644 --- a/packages/edit-navigation/src/components/name-editor/style.scss +++ b/packages/edit-navigation/src/components/name-editor/style.scss @@ -1,10 +1,4 @@ -.edit-navigation-name-editor__edit-name-description { - font-size: $helptext-font-size; - font-style: normal; - color: $gray-700; -} - -.components-name-editor__text-control { +.edit-navigation-name-editor__text-control { .components-base-control { border: none; } diff --git a/packages/edit-navigation/src/hooks/index.js b/packages/edit-navigation/src/hooks/index.js index 0d5736cf304298..5d2c4f94745657 100644 --- a/packages/edit-navigation/src/hooks/index.js +++ b/packages/edit-navigation/src/hooks/index.js @@ -6,11 +6,11 @@ import { createContext } from '@wordpress/element'; export const untitledMenu = __( '(untitled menu)' ); export const MenuIdContext = createContext(); -export const IsMenuEditorFocused = createContext(); +export const IsMenuNameControlFocusedContext = createContext(); export { default as useMenuEntity } from './use-menu-entity'; export { default as useNavigationEditor } from './use-navigation-editor'; export { default as useNavigationBlockEditor } from './use-navigation-block-editor'; export { default as useMenuNotifications } from './use-menu-notifications'; -export { default as useNavigationEditorMenu } from './use-navigation-editor-menu'; +export { default as useSelectedMenuData } from './use-selected-menu-data'; export { default as useMenuLocations } from './use-menu-locations'; diff --git a/packages/edit-navigation/src/hooks/use-menu-entity.js b/packages/edit-navigation/src/hooks/use-menu-entity.js index 2010730ceff24b..9f20f3241630f2 100644 --- a/packages/edit-navigation/src/hooks/use-menu-entity.js +++ b/packages/edit-navigation/src/hooks/use-menu-entity.js @@ -29,6 +29,7 @@ export default function useMenuEntity( menuId ) { editEntityRecord( ...menuEntityData, { name } ); return { + editedMenuName, saveMenuName, editMenuName, }; diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor.js b/packages/edit-navigation/src/hooks/use-navigation-editor.js index 1ef85405438a78..3af9a2b1003860 100644 --- a/packages/edit-navigation/src/hooks/use-navigation-editor.js +++ b/packages/edit-navigation/src/hooks/use-navigation-editor.js @@ -8,29 +8,30 @@ import { useState, useEffect } from '@wordpress/element'; */ import { store as editNavigationStore } from '../store'; +const getMenusData = ( select ) => { + const selectors = select( 'core' ); + const params = { per_page: -1 }; + return { + menus: selectors.getMenus( params ), + hasLoadedMenus: selectors.hasFinishedResolution( 'getMenus', [ + params, + ] ), + }; +}; export default function useNavigationEditor() { const { deleteMenu: _deleteMenu } = useDispatch( 'core' ); + const [ selectedMenuId, setSelectedMenuId ] = useState( null ); const [ hasFinishedInitialLoad, setHasFinishedInitialLoad ] = useState( false ); - const { menus, hasLoadedMenus } = useSelect( ( select ) => { - const selectors = select( 'core' ); - const params = { per_page: -1 }; - return { - menus: selectors.getMenus( params ), - hasLoadedMenus: selectors.hasFinishedResolution( 'getMenus', [ - params, - ] ), - }; - }, [] ); + + const { menus, hasLoadedMenus } = useSelect( getMenusData, [] ); useEffect( () => { if ( hasLoadedMenus ) { setHasFinishedInitialLoad( true ); } }, [ hasLoadedMenus ] ); - const [ selectedMenuId, setSelectedMenuId ] = useState( null ); - useEffect( () => { if ( ! selectedMenuId && menus?.length ) { setSelectedMenuId( menus[ 0 ].id ); @@ -49,10 +50,6 @@ export default function useNavigationEditor() { [ selectedMenuId ] ); - const selectMenu = ( menuId ) => { - setSelectedMenuId( menuId ); - }; - const deleteMenu = async () => { const didDeleteMenu = await _deleteMenu( selectedMenuId, { force: true, @@ -66,7 +63,7 @@ export default function useNavigationEditor() { menus, selectedMenuId, navigationPost, - selectMenu, + selectMenu: setSelectedMenuId, deleteMenu, hasFinishedInitialLoad, hasLoadedMenus, diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor-menu.js b/packages/edit-navigation/src/hooks/use-selected-menu-data.js similarity index 70% rename from packages/edit-navigation/src/hooks/use-navigation-editor-menu.js rename to packages/edit-navigation/src/hooks/use-selected-menu-data.js index 4c8d2f3267f7b0..7947bd49699659 100644 --- a/packages/edit-navigation/src/hooks/use-navigation-editor-menu.js +++ b/packages/edit-navigation/src/hooks/use-selected-menu-data.js @@ -1,22 +1,20 @@ /** * WordPress dependencies */ -import { useDispatch, useSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { useContext } from '@wordpress/element'; /** * Internal dependencies */ import { MenuIdContext, untitledMenu } from './index'; -export default function useNavigationEditorMenu() { - const { saveMenu } = useDispatch( 'core' ); +export default function useSelectedMenuData() { const menuId = useContext( MenuIdContext ); const menu = useSelect( ( select ) => select( 'core' ).getMenu( menuId ), [ menuId, ] ); const menuName = menu?.name ?? untitledMenu; return { - saveMenu, menuId, menu, menuName, From 0a90dda48ea0b256f32ecbd61e31ef2578ce5279 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 22 Feb 2021 09:02:14 +0100 Subject: [PATCH 13/21] add missing file --- .../edit-navigation/src/components/name-display/index.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js index 8c18a27874e5aa..d08942f5c0338b 100644 --- a/packages/edit-navigation/src/components/name-display/index.js +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -6,12 +6,17 @@ import { BlockControls } from '@wordpress/block-editor'; /** * Internal dependencies */ -import { useSelectedMenuData, IsMenuNameControlFocusedContext } from '../../hooks'; +import { + useSelectedMenuData, + IsMenuNameControlFocusedContext, +} from '../../hooks'; import { useContext } from '@wordpress/element'; export default function NameDisplay() { const { menuName } = useSelectedMenuData(); - const [ , setIsMenuNameEditFocused ] = useContext( IsMenuNameControlFocusedContext ); + const [ , setIsMenuNameEditFocused ] = useContext( + IsMenuNameControlFocusedContext + ); return ( From bbfbff185abe0fc5968c6c4986312381b8d67ef8 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Wed, 24 Feb 2021 14:41:20 +0100 Subject: [PATCH 14/21] changes according to CR: removed aria-label from name-display/index.js and added aria-label in /name-editor/index.js --- .../edit-navigation/src/components/name-display/index.js | 5 ++++- packages/edit-navigation/src/components/name-editor/index.js | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js index d08942f5c0338b..676ca20a23dafc 100644 --- a/packages/edit-navigation/src/components/name-display/index.js +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -20,7 +20,10 @@ export default function NameDisplay() { return ( - + { menuName } diff --git a/packages/edit-navigation/src/components/name-editor/index.js b/packages/edit-navigation/src/components/name-editor/index.js index 917ce41c90944f..b948ee893d23a1 100644 --- a/packages/edit-navigation/src/components/name-editor/index.js +++ b/packages/edit-navigation/src/components/name-editor/index.js @@ -38,7 +38,6 @@ export function NameEditor() { onChange={ ( value ) => { editMenuName( value ); } } - aria-label={ __( 'Edit menu name' ) } /> ); From 4073edaaeea5b1ed8444aea695a0f19ffe8dd36f Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 2 Mar 2021 18:17:05 +0800 Subject: [PATCH 15/21] Dispatch save requests sequentially instead of in parallel --- .../src/components/header/save-button.js | 5 ----- .../edit-navigation/src/hooks/use-menu-entity.js | 6 +----- packages/edit-navigation/src/store/actions.js | 16 ++++++++++++++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/edit-navigation/src/components/header/save-button.js b/packages/edit-navigation/src/components/header/save-button.js index 604a7812cc92d1..4d526ebbe40ed3 100644 --- a/packages/edit-navigation/src/components/header/save-button.js +++ b/packages/edit-navigation/src/components/header/save-button.js @@ -9,12 +9,8 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import { store as editNavigationStore } from '../../store'; -import { useMenuEntity, MenuIdContext } from '../../hooks'; -import { useContext } from '@wordpress/element'; export default function SaveButton( { navigationPost } ) { - const menuId = useContext( MenuIdContext ); - const { saveMenuName } = useMenuEntity( menuId ); const { saveNavigationPost } = useDispatch( editNavigationStore ); return ( @@ -23,7 +19,6 @@ export default function SaveButton( { navigationPost } ) { isPrimary onClick={ () => { saveNavigationPost( navigationPost ); - saveMenuName(); } } disabled={ ! navigationPost } > diff --git a/packages/edit-navigation/src/hooks/use-menu-entity.js b/packages/edit-navigation/src/hooks/use-menu-entity.js index 9f20f3241630f2..0b092f62a5d837 100644 --- a/packages/edit-navigation/src/hooks/use-menu-entity.js +++ b/packages/edit-navigation/src/hooks/use-menu-entity.js @@ -10,7 +10,7 @@ import { MENU_KIND, MENU_POST_TYPE } from '../utils/constants'; import { untitledMenu } from './index'; export default function useMenuEntity( menuId ) { - const { editEntityRecord, saveEditedEntityRecord } = useDispatch( 'core' ); + const { editEntityRecord } = useDispatch( 'core' ); const menuEntityData = [ MENU_KIND, MENU_POST_TYPE, menuId ]; const editedMenu = useSelect( @@ -22,15 +22,11 @@ export default function useMenuEntity( menuId ) { const editedMenuName = menuId && editedMenu.name; - const saveMenuName = () => - editedMenuName && saveEditedEntityRecord( ...menuEntityData ); - const editMenuName = ( name = untitledMenu ) => editEntityRecord( ...menuEntityData, { name } ); return { editedMenuName, - saveMenuName, editMenuName, }; } diff --git a/packages/edit-navigation/src/store/actions.js b/packages/edit-navigation/src/store/actions.js index 1b95b2950d37b2..90dcf5aa192270 100644 --- a/packages/edit-navigation/src/store/actions.js +++ b/packages/edit-navigation/src/store/actions.js @@ -88,14 +88,26 @@ export const saveNavigationPost = serializeProcessing( function* ( post ) { ); try { - const response = yield* batchSave( + // Save edits to the menu, like the menu name. + const menuResponse = yield dispatch( + 'core', + 'saveEditedEntityRecord', + 'root', + 'menu', + menuId + ); + + // Save blocks as menu items. + const batchSaveResponse = yield* batchSave( menuId, menuItemsByClientId, post.blocks[ 0 ] ); - if ( ! response.success ) { + + if ( ! batchSaveResponse.success || ! menuResponse ) { throw new Error(); } + yield dispatch( noticesStore, 'createSuccessNotice', From fcdab0a39d4f5d987983e353db7f582c96e26c33 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Wed, 3 Mar 2021 12:27:20 +0100 Subject: [PATCH 16/21] explicitly set () => setIsMenuNameEditFocused( true ) --- packages/edit-navigation/src/components/name-display/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js index 676ca20a23dafc..5d16a5246a59f6 100644 --- a/packages/edit-navigation/src/components/name-display/index.js +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -22,7 +22,7 @@ export default function NameDisplay() { setIsMenuNameEditFocused( true ) } > { menuName } From e6415bea74f72ad14204a2c5229b273e32bee153 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Wed, 3 Mar 2021 12:29:03 +0100 Subject: [PATCH 17/21] add translation to the file --- packages/edit-navigation/src/components/name-display/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js index 5d16a5246a59f6..ad6c852096540e 100644 --- a/packages/edit-navigation/src/components/name-display/index.js +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -12,6 +12,7 @@ import { } from '../../hooks'; import { useContext } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; export default function NameDisplay() { const { menuName } = useSelectedMenuData(); const [ , setIsMenuNameEditFocused ] = useContext( @@ -21,7 +22,7 @@ export default function NameDisplay() { setIsMenuNameEditFocused( true ) } > { menuName } From 2dfb3addd7ccea492bc36f5d5104f4c3748ec073 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Sat, 6 Mar 2021 21:21:45 +0100 Subject: [PATCH 18/21] resolved conflicts with trunk --- packages/edit-navigation/src/components/layout/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index 26f834a7544774..a2825d4c28dbe7 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -19,6 +19,7 @@ import { BlockInspector, __unstableUseBlockSelectionClearer as useBlockSelectionClearer, } from '@wordpress/block-editor'; + import { useMemo, useRef, useState } from '@wordpress/element'; /** From d3cb3df47f844441a6367402b27dfb8a1585a65d Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Sat, 6 Mar 2021 21:29:56 +0100 Subject: [PATCH 19/21] resolved conflicts with trunk 2 --- packages/edit-navigation/src/components/layout/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index a2825d4c28dbe7..6f735b4754fcf8 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -20,7 +20,7 @@ import { __unstableUseBlockSelectionClearer as useBlockSelectionClearer, } from '@wordpress/block-editor'; -import { useMemo, useRef, useState } from '@wordpress/element'; +import { useMemo, useState } from '@wordpress/element'; /** * Internal dependencies @@ -42,8 +42,7 @@ import InspectorAdditions from '../inspector-additions'; import { store as editNavigationStore } from '../../store'; export default function Layout( { blockEditorSettings } ) { - const canvasRef = useRef(); - useBlockSelectionClearer( canvasRef ); + const canvasRef = useBlockSelectionClearer(); const [ isMenuNameControlFocused, setIsMenuNameControlFocused ] = useState( false ); From 00561ebf6228bf25f46701514169a99d8b6a559e Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 8 Mar 2021 10:10:46 +0100 Subject: [PATCH 20/21] sprintf added --- .../edit-navigation/src/components/name-display/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/components/name-display/index.js b/packages/edit-navigation/src/components/name-display/index.js index ad6c852096540e..1778f21651e865 100644 --- a/packages/edit-navigation/src/components/name-display/index.js +++ b/packages/edit-navigation/src/components/name-display/index.js @@ -12,7 +12,7 @@ import { } from '../../hooks'; import { useContext } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; +import { sprintf, __ } from '@wordpress/i18n'; export default function NameDisplay() { const { menuName } = useSelectedMenuData(); const [ , setIsMenuNameEditFocused ] = useContext( @@ -22,7 +22,11 @@ export default function NameDisplay() { setIsMenuNameEditFocused( true ) } > { menuName } From 2f53f2f49726a1fd14e7358e156ab094063df410 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 8 Mar 2021 17:49:44 +0800 Subject: [PATCH 21/21] Update unit test to take into account the call to saveEditedEntityRecord --- packages/edit-navigation/src/store/test/actions.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/edit-navigation/src/store/test/actions.js b/packages/edit-navigation/src/store/test/actions.js index 0a2acb9560c15e..9f24671057feaf 100644 --- a/packages/edit-navigation/src/store/test/actions.js +++ b/packages/edit-navigation/src/store/test/actions.js @@ -324,6 +324,10 @@ describe( 'saveNavigationPost', () => { ); expect( action.next( mapping ).value ).toEqual( + dispatch( 'core', 'saveEditedEntityRecord', 'root', 'menu', 1 ) + ); + + expect( action.next( { id: 1 } ).value ).toEqual( apiFetch( { path: '/__experimental/customizer-nonces/get-save-nonce', } ) @@ -454,6 +458,10 @@ describe( 'saveNavigationPost', () => { ); expect( action.next( mapping ).value ).toEqual( + dispatch( 'core', 'saveEditedEntityRecord', 'root', 'menu', 1 ) + ); + + expect( action.next().value ).toEqual( apiFetch( { path: '/__experimental/customizer-nonces/get-save-nonce', } )