diff --git a/packages/editor/src/components/provider/constants.js b/packages/editor/src/components/provider/constants.js deleted file mode 100644 index a81b2fd37563af..00000000000000 --- a/packages/editor/src/components/provider/constants.js +++ /dev/null @@ -1,5 +0,0 @@ -export const PAGE_CONTENT_BLOCK_TYPES = [ - 'core/post-title', - 'core/post-featured-image', - 'core/post-content', -]; diff --git a/packages/editor/src/components/provider/disable-non-page-content-blocks.js b/packages/editor/src/components/provider/disable-non-page-content-blocks.js index 48a8119350d78f..fd4722ebe40f4d 100644 --- a/packages/editor/src/components/provider/disable-non-page-content-blocks.js +++ b/packages/editor/src/components/provider/disable-non-page-content-blocks.js @@ -2,39 +2,46 @@ * WordPress dependencies */ import { useSelect, useDispatch } from '@wordpress/data'; -import { - useBlockEditingMode, - store as blockEditorStore, -} from '@wordpress/block-editor'; +import { store as blockEditorStore } from '@wordpress/block-editor'; import { useEffect } from '@wordpress/element'; -/** - * Internal dependencies - */ -import { PAGE_CONTENT_BLOCK_TYPES } from './constants'; +const PAGE_CONTENT_BLOCKS = [ + 'core/post-title', + 'core/post-featured-image', + 'core/post-content', +]; + +function useDisableNonPageContentBlocks() { + const contentIds = useSelect( ( select ) => { + const { getBlocksByName, getBlockParents, getBlockName } = + select( blockEditorStore ); + return getBlocksByName( PAGE_CONTENT_BLOCKS ).filter( ( clientId ) => + getBlockParents( clientId ).every( ( parentClientId ) => { + const parentBlockName = getBlockName( parentClientId ); + return ( + parentBlockName !== 'core/query' && + ! PAGE_CONTENT_BLOCKS.includes( parentBlockName ) + ); + } ) + ); + }, [] ); -function DisableBlock( { clientId } ) { - const isDescendentOfQueryLoop = useSelect( - ( select ) => { - const { getBlockParentsByBlockName } = select( blockEditorStore ); - return ( - getBlockParentsByBlockName( clientId, 'core/query' ).length !== - 0 - ); - }, - [ clientId ] - ); - const mode = isDescendentOfQueryLoop ? undefined : 'contentOnly'; const { setBlockEditingMode, unsetBlockEditingMode } = useDispatch( blockEditorStore ); + useEffect( () => { - if ( mode ) { - setBlockEditingMode( clientId, mode ); - return () => { - unsetBlockEditingMode( clientId ); - }; + setBlockEditingMode( '', 'disabled' ); // Disable editing at the root level. + + for ( const contentId of contentIds ) { + setBlockEditingMode( contentId, 'contentOnly' ); // Re-enable each content block. } - }, [ clientId, mode, setBlockEditingMode, unsetBlockEditingMode ] ); + return () => { + unsetBlockEditingMode( '' ); + for ( const contentId of contentIds ) { + unsetBlockEditingMode( contentId ); + } + }; + }, [ contentIds, setBlockEditingMode, unsetBlockEditingMode ] ); } /** @@ -42,14 +49,5 @@ function DisableBlock( { clientId } ) { * page content to be edited. */ export default function DisableNonPageContentBlocks() { - useBlockEditingMode( 'disabled' ); - const clientIds = useSelect( ( select ) => { - return select( blockEditorStore ).getBlocksByName( - PAGE_CONTENT_BLOCK_TYPES - ); - }, [] ); - - return clientIds.map( ( clientId ) => { - return ; - } ); + useDisableNonPageContentBlocks(); } diff --git a/packages/editor/src/components/provider/test/disable-non-page-content-blocks.js b/packages/editor/src/components/provider/test/disable-non-page-content-blocks.js new file mode 100644 index 00000000000000..d76530828a7999 --- /dev/null +++ b/packages/editor/src/components/provider/test/disable-non-page-content-blocks.js @@ -0,0 +1,90 @@ +/** + * External dependencies + */ +import { render } from '@testing-library/react'; + +/** + * WordPress dependencies + */ +import { createRegistry, RegistryProvider } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import DisableNonPageContentBlocks from '../disable-non-page-content-blocks'; + +describe( 'DisableNonPageContentBlocks', () => { + it( 'disables page content blocks', () => { + const testBlocks = { + 0: 'core/template-part', + /**/ '00': 'core/site-title', + /**/ '01': 'core/navigation', + 1: 'core/group', + /**/ 10: 'core/post-title', + /**/ 11: 'core/post-featured-image', + /**/ 12: 'core/post-content', + /**/ /**/ 120: 'core/paragraph', + /**/ /**/ 121: 'core/post-featured-image', + 2: 'core/query', + /**/ 20: 'core/post-title', + /**/ 21: 'core/post-featured-image', + /**/ 22: 'core/post-content', + 3: 'core/template-part', + /**/ 30: 'core/paragraph', + }; + + const setBlockEditingMode = jest.fn( () => ( { + type: 'SET_BLOCK_EDITING_MODE', + } ) ); + const unsetBlockEditingMode = jest.fn( () => ( { + type: 'UNSET_BLOCK_EDITING_MODE', + } ) ); + + const registry = createRegistry( { + 'core/block-editor': { + reducer: () => {}, + selectors: { + getBlocksByName( state, blockNames ) { + return Object.keys( testBlocks ).filter( ( clientId ) => + blockNames.includes( testBlocks[ clientId ] ) + ); + }, + getBlockParents( state, clientId ) { + return clientId.slice( 0, -1 ).split( '' ); + }, + getBlockName( state, clientId ) { + return testBlocks[ clientId ]; + }, + }, + actions: { + setBlockEditingMode, + unsetBlockEditingMode, + }, + }, + } ); + + const { unmount } = render( + + + + ); + + expect( setBlockEditingMode.mock.calls ).toEqual( [ + [ '', 'disabled' ], // root + [ '10', 'contentOnly' ], // post-title + [ '11', 'contentOnly' ], // post-featured-image + [ '12', 'contentOnly' ], // post-content + // NOT the post-featured-image nested within post-content + // NOT any of the content blocks within query + ] ); + + unmount(); + + expect( unsetBlockEditingMode.mock.calls ).toEqual( [ + [ '' ], // root + [ '10' ], // post-title + [ '11' ], // post-featured-image + [ '12' ], // post-content + ] ); + } ); +} );