From 7b961741bfb038b68ede78ae658485268dc88d52 Mon Sep 17 00:00:00 2001 From: George Hotelling Date: Mon, 7 Nov 2022 16:53:16 -0700 Subject: [PATCH] Convert To Links modal shows up --- packages/block-editor/package.json | 1 + .../off-canvas-editor/block-edit-button.js | 192 +++++++++++++++++- .../src/components/off-canvas-editor/block.js | 76 +++++-- 3 files changed, 242 insertions(+), 27 deletions(-) diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index b5d6212930a86..8b7b9d6269e80 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -39,6 +39,7 @@ "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", + "@wordpress/core-data": "file:../core-data", "@wordpress/data": "file:../data", "@wordpress/date": "file:../date", "@wordpress/deprecated": "file:../deprecated", diff --git a/packages/block-editor/src/components/off-canvas-editor/block-edit-button.js b/packages/block-editor/src/components/off-canvas-editor/block-edit-button.js index 43263f292137e..55f72492906d4 100644 --- a/packages/block-editor/src/components/off-canvas-editor/block-edit-button.js +++ b/packages/block-editor/src/components/off-canvas-editor/block-edit-button.js @@ -1,23 +1,196 @@ /** * WordPress dependencies */ -import { Button } from '@wordpress/components'; import { edit } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; +import { useMemo, useState } from '@wordpress/element'; +import { Button, Modal } from '@wordpress/components'; import { useDispatch } from '@wordpress/data'; -import { useState } from '@wordpress/element'; +import { useEntityRecords } from '@wordpress/core-data'; +import { createBlock as create } from '@wordpress/blocks'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../store'; -const BlockEditPanel = () => { - return
Block Edit Panel
; +// copied from packages/block-library/src/page-list/edit.js + +// We only show the edit option when page count is <= MAX_PAGE_COUNT +// Performance of Navigation Links is not good past this value. +const MAX_PAGE_COUNT = 100; + +const usePageData = () => { + const { records: pages, hasResolved: hasResolvedPages } = useEntityRecords( + 'postType', + 'page', + { + orderby: 'menu_order', + order: 'asc', + _fields: [ 'id', 'link', 'parent', 'title', 'menu_order' ], + per_page: -1, + context: 'view', + } + ); + + return useMemo( () => { + // TODO: Once the REST API supports passing multiple values to + // 'orderby', this can be removed. + // https://core.trac.wordpress.org/ticket/39037 + const sortedPages = [ ...( pages ?? [] ) ].sort( ( a, b ) => { + if ( a.menu_order === b.menu_order ) { + return a.title.rendered.localeCompare( b.title.rendered ); + } + return a.menu_order - b.menu_order; + } ); + const pagesByParentId = sortedPages.reduce( ( accumulator, page ) => { + const { parent } = page; + if ( accumulator.has( parent ) ) { + accumulator.get( parent ).push( page ); + } else { + accumulator.set( parent, [ page ] ); + } + return accumulator; + }, new Map() ); + + return { + pagesByParentId, + hasResolvedPages, + totalPages: pages?.length ?? null, + }; + }, [ pages, hasResolvedPages ] ); }; +// copied from convert-to-links-modal.js +/** + * WordPress dependencies + */ +const PAGE_FIELDS = [ 'id', 'title', 'link', 'type', 'parent' ]; + +const convertSelectedBlockToNavigationLinks = + ( { pages, clientId, replaceBlock, createBlock } ) => + () => { + if ( ! pages ) { + return; + } + + const linkMap = {}; + const navigationLinks = []; + pages.forEach( ( { id, title, link: url, type, parent } ) => { + // See if a placeholder exists. This is created if children appear before parents in list. + const innerBlocks = linkMap[ id ]?.innerBlocks ?? []; + linkMap[ id ] = createBlock( + 'core/navigation-link', + { + id, + label: title.rendered, + url, + type, + kind: 'post-type', + }, + innerBlocks + ); + + if ( ! parent ) { + navigationLinks.push( linkMap[ id ] ); + } else { + if ( ! linkMap[ parent ] ) { + // Use a placeholder if the child appears before parent in list. + linkMap[ parent ] = { innerBlocks: [] }; + } + const parentLinkInnerBlocks = linkMap[ parent ].innerBlocks; + parentLinkInnerBlocks.push( linkMap[ id ] ); + } + } ); + + // Transform all links with innerBlocks into Submenus. This can't be done + // sooner because page objects have no information on their children. + + const transformSubmenus = ( listOfLinks ) => { + listOfLinks.forEach( ( block, index, listOfLinksArray ) => { + const { attributes, innerBlocks } = block; + if ( innerBlocks.length !== 0 ) { + transformSubmenus( innerBlocks ); + const transformedBlock = createBlock( + 'core/navigation-submenu', + attributes, + innerBlocks + ); + listOfLinksArray[ index ] = transformedBlock; + } + } ); + }; + + transformSubmenus( navigationLinks ); + + replaceBlock( clientId, navigationLinks ); + }; + +const ConvertToLinksModal = ( { onClose, clientId } ) => { + const { records: pages, hasResolved: pagesFinished } = useEntityRecords( + 'postType', + 'page', + { + per_page: MAX_PAGE_COUNT, + _fields: PAGE_FIELDS, + // TODO: When https://core.trac.wordpress.org/ticket/39037 REST API support for multiple orderby + // values is resolved, update 'orderby' to [ 'menu_order', 'post_title' ] to provide a consistent + // sort. + orderby: 'menu_order', + order: 'asc', + } + ); + + const { replaceBlock } = useDispatch( blockEditorStore ); + + return ( + +

+ { __( + 'To edit this navigation menu, convert it to single page links. This allows you to add, re-order, remove items, or edit their labels.' + ) } +

+

+ { __( + "Note: if you add new pages to your site, you'll need to add them to your navigation menu." + ) } +

+
+ + +
+
+ ); +}; + +// const BlockEditPanel = () => { +// return
Block Edit Panel
; +// }; + const BlockEditButton = ( { label, clientId } ) => { const { toggleBlockHighlight } = useDispatch( blockEditorStore ); const [ panelOpen, setPanelOpen ] = useState( false ); + const { totalPages } = usePageData(); + const allowConvertToLinks = totalPages <= MAX_PAGE_COUNT; const onClick = () => { toggleBlockHighlight( clientId, true ); @@ -26,8 +199,15 @@ const BlockEditButton = ( { label, clientId } ) => { return ( <> - { panelOpen && } -