Skip to content

Commit

Permalink
Convert To Links modal shows up
Browse files Browse the repository at this point in the history
  • Loading branch information
George Hotelling committed Nov 7, 2022
1 parent e1b012a commit 7b96174
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 27 deletions.
1 change: 1 addition & 0 deletions packages/block-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <div>Block Edit Panel</div>;
// 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 (
<Modal
closeLabel={ __( 'Close' ) }
onRequestClose={ onClose }
title={ __( 'Convert to links' ) }
className={ 'wp-block-page-list-modal' }
aria={ { describedby: 'wp-block-page-list-modal__description' } }
>
<p id={ 'wp-block-page-list-modal__description' }>
{ __(
'To edit this navigation menu, convert it to single page links. This allows you to add, re-order, remove items, or edit their labels.'
) }
</p>
<p>
{ __(
"Note: if you add new pages to your site, you'll need to add them to your navigation menu."
) }
</p>
<div className="wp-block-page-list-modal-buttons">
<Button variant="tertiary" onClick={ onClose }>
{ __( 'Cancel' ) }
</Button>
<Button
variant="primary"
disabled={ ! pagesFinished }
onClick={ convertSelectedBlockToNavigationLinks( {
pages,
replaceBlock,
clientId,
createBlock: create,
} ) }
>
{ __( 'Convert' ) }
</Button>
</div>
</Modal>
);
};

// const BlockEditPanel = () => {
// return <div>Block Edit Panel</div>;
// };

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 );
Expand All @@ -26,8 +199,15 @@ const BlockEditButton = ( { label, clientId } ) => {

return (
<>
{ panelOpen && <BlockEditPanel /> }
<Button icon={ edit } label={ label } onClick={ onClick } />
{ panelOpen && (
<ConvertToLinksModal
onClose={ () => setPanelOpen( false ) }
clientId={ clientId }
/>
) }
{ allowConvertToLinks && (
<Button icon={ edit } label={ label } onClick={ onClick } />
) }
</>
);
};
Expand Down
76 changes: 55 additions & 21 deletions packages/block-editor/src/components/off-canvas-editor/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
} from '../block-mover/button';
import ListViewBlockContents from './block-contents';
import BlockSettingsDropdown from '../block-settings-menu/block-settings-dropdown';
import BlockEditButton from './block-edit-button';
import { useListViewContext } from './context';
import { getBlockPositionDescription } from './utils';
import { store as blockEditorStore } from '../../store';
Expand Down Expand Up @@ -132,6 +133,14 @@ function ListViewBlock( {
)
: __( 'Options' );

const editAriaLabel = blockInformation
? sprintf(
// translators: %s: The title of the block.
__( 'Edit %s block' ),
blockInformation.title
)
: __( 'Edit' );

const { isTreeGridMounted, expand, collapse } = useListViewContext();

const hasSiblings = siblingBlockCount > 0;
Expand All @@ -146,6 +155,11 @@ function ListViewBlock( {
{ 'is-visible': isHovered || isFirstSelectedBlock }
);

const listViewBlockEditClassName = classnames(
'block-editor-list-view-block__menu-cell',
{ 'is-visible': isHovered || isFirstSelectedBlock }
);

// If ListView has experimental features related to the Persistent List View,
// only focus the selected list item on mount; otherwise the list would always
// try to steal the focus from the editor canvas.
Expand Down Expand Up @@ -249,7 +263,9 @@ function ListViewBlock( {
onClick={
selectBlockInCanvas
? selectEditorBlock
: () => {}
: ( event ) => {
event.preventDefault();
}
}
onToggleExpanded={ toggleExpanded }
isSelected={ isSelected }
Expand Down Expand Up @@ -305,26 +321,44 @@ function ListViewBlock( {
) }

{ showBlockActions && (
<TreeGridCell
className={ listViewBlockSettingsClassName }
aria-selected={ !! isSelected || forceSelectionContentLock }
>
{ ( { ref, tabIndex, onFocus } ) => (
<BlockSettingsDropdown
clientIds={ dropdownClientIds }
icon={ moreVertical }
label={ settingsAriaLabel }
toggleProps={ {
ref,
className: 'block-editor-list-view-block__menu',
tabIndex,
onFocus,
} }
disableOpenOnArrowDown
__experimentalSelectBlock={ updateSelection }
/>
) }
</TreeGridCell>
<>
<TreeGridCell
className={ listViewBlockEditClassName }
aria-selected={
!! isSelected || forceSelectionContentLock
}
>
{ () => (
<BlockEditButton
label={ editAriaLabel }
clientId={ clientId }
/>
) }
</TreeGridCell>
<TreeGridCell
className={ listViewBlockSettingsClassName }
aria-selected={
!! isSelected || forceSelectionContentLock
}
>
{ ( { ref, tabIndex, onFocus } ) => (
<BlockSettingsDropdown
clientIds={ dropdownClientIds }
icon={ moreVertical }
label={ settingsAriaLabel }
toggleProps={ {
ref,
className:
'block-editor-list-view-block__menu',
tabIndex,
onFocus,
} }
disableOpenOnArrowDown
__experimentalSelectBlock={ updateSelection }
/>
) }
</TreeGridCell>
</>
) }
</ListViewLeaf>
);
Expand Down

0 comments on commit 7b96174

Please sign in to comment.