diff --git a/editor/components/block-settings-menu/block-transformations.js b/editor/components/block-settings-menu/block-transformations.js index 8f936e2503752a..8c863c9bd3fea2 100644 --- a/editor/components/block-settings-menu/block-transformations.js +++ b/editor/components/block-settings-menu/block-transformations.js @@ -1,13 +1,13 @@ /** * External dependencies */ -import { noop } from 'lodash'; +import { castArray, filter, first, mapKeys, noop, sortBy } from 'lodash'; /** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { IconButton } from '@wordpress/components'; +import { IconButton, ifCondition } from '@wordpress/components'; import { getPossibleBlockTransformations, switchToBlockType } from '@wordpress/blocks'; import { compose, Fragment } from '@wordpress/element'; import { withSelect, withDispatch } from '@wordpress/data'; @@ -17,9 +17,16 @@ import { withSelect, withDispatch } from '@wordpress/data'; */ import './style.scss'; -function BlockTransformations( { blocks, small = false, onTransform, onClick = noop, isLocked, itemsRole } ) { - const possibleBlockTransformations = getPossibleBlockTransformations( blocks ); - if ( isLocked || ! possibleBlockTransformations.length ) { +function BlockTransformations( { blocks, small = false, onTransform, onClick = noop, inserterItems, itemsRole } ) { + const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); + const possibleBlockTransformations = sortBy( + filter( + getPossibleBlockTransformations( blocks ), + ( block ) => !! itemsByName[ block.name ] + ), + ( block ) => -itemsByName[ block.name ].frecency, + ); + if ( ! possibleBlockTransformations.length ) { return null; } return ( @@ -52,13 +59,14 @@ function BlockTransformations( { blocks, small = false, onTransform, onClick = n } export default compose( [ withSelect( ( select, { uids } ) => { - const { getEditorSettings, getBlocksByUID } = select( 'core/editor' ); - const { templateLock } = getEditorSettings(); + const { getBlocksByUID, getBlockRootUID, getInserterItems } = select( 'core/editor' ); + const rootUID = getBlockRootUID( first( castArray( uids ) ) ); return { - isLocked: !! templateLock, blocks: getBlocksByUID( uids ), + inserterItems: getInserterItems( rootUID ), }; } ), + ifCondition( ( { inserterItems } ) => inserterItems.length > 0 ), withDispatch( ( dispatch, ownProps ) => ( { onTransform( blocks, name ) { dispatch( 'core/editor' ).replaceBlocks( diff --git a/editor/components/block-switcher/index.js b/editor/components/block-switcher/index.js index 286190136ba5f1..b68ad185e23ae7 100644 --- a/editor/components/block-switcher/index.js +++ b/editor/components/block-switcher/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { get } from 'lodash'; +import { castArray, filter, first, get, mapKeys, sortBy } from 'lodash'; /** * WordPress dependencies @@ -36,19 +36,27 @@ export class BlockSwitcher extends Component { } render() { - const { blocks, onTransform, isLocked } = this.props; + const { blocks, onTransform, inserterItems } = this.props; const { hoveredClassName } = this.state; if ( ! blocks || ! blocks.length ) { return null; } - const allowedBlocks = getPossibleBlockTransformations( blocks ); + const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); + const possibleBlockTransformations = sortBy( + filter( + getPossibleBlockTransformations( blocks ), + ( block ) => !! itemsByName[ block.name ] + ), + ( block ) => -itemsByName[ block.name ].frecency, + ); + const sourceBlockName = blocks[ 0 ].name; const blockType = getBlockType( sourceBlockName ); const hasStyles = blocks.length === 1 && get( blockType, [ 'styles' ], [] ).length !== 0; - if ( ! hasStyles && ( ! allowedBlocks.length || isLocked ) ) { + if ( ! hasStyles && ( ! possibleBlockTransformations.length ) ) { return null; } @@ -93,13 +101,13 @@ export class BlockSwitcher extends Component { } - { allowedBlocks.length !== 0 && ! isLocked && + { possibleBlockTransformations.length !== 0 && ( { + items={ possibleBlockTransformations.map( ( destinationBlockType ) => ( { id: destinationBlockType.name, icon: destinationBlockType.icon, title: destinationBlockType.title, @@ -127,12 +135,12 @@ export class BlockSwitcher extends Component { } export default compose( - withSelect( ( select, ownProps ) => { - const { getBlock, getEditorSettings } = select( 'core/editor' ); - const { templateLock } = getEditorSettings(); + withSelect( ( select, { uids } ) => { + const { getBlocksByUID, getBlockRootUID, getInserterItems } = select( 'core/editor' ); + const rootUID = getBlockRootUID( first( castArray( uids ) ) ); return { - blocks: ownProps.uids.map( getBlock ), - isLocked: !! templateLock, + blocks: getBlocksByUID( uids ), + inserterItems: getInserterItems( rootUID ), }; } ), withDispatch( ( dispatch, ownProps ) => ( { diff --git a/editor/components/block-switcher/test/index.js b/editor/components/block-switcher/test/index.js index 4b7d181ab052ef..a92d01471da0fb 100644 --- a/editor/components/block-switcher/test/index.js +++ b/editor/components/block-switcher/test/index.js @@ -62,7 +62,11 @@ describe( 'BlockSwitcher', () => { const blocks = [ headingBlock1, ]; - const wrapper = shallow( ); + const inserterItems = [ + { name: 'core/paragraph', frecency: 1 }, + ]; + + const wrapper = shallow( ); expect( wrapper ).toMatchSnapshot(); } ); @@ -92,9 +96,17 @@ describe( 'BlockSwitcher', () => { headingBlock1, ]; + const inserterItems = [ + { name: 'core/quote', frecency: 1 }, + { name: 'core/cover-image', frecency: 2 }, + { name: 'core/paragraph', frecency: 3 }, + { name: 'core/heading', frecency: 4 }, + { name: 'core/text', frecency: 5 }, + ]; + const onTransformStub = jest.fn(); const getDropdown = () => { - const blockSwitcher = shallow( ); + const blockSwitcher = shallow( ); return blockSwitcher.find( 'Dropdown' ); };