From e6642bcb1b2b528c85b7912f275162f7fc8c3dcb Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Mon, 20 Nov 2017 13:27:35 -0500 Subject: [PATCH] Blocks: Allow filterable allowed inserter types --- editor/components/inserter/index.js | 55 ++++++++++------- editor/components/inserter/menu.js | 79 ++++++++++++++++--------- editor/components/inserter/test/menu.js | 40 +++++++++++++ lib/client-assets.php | 10 ++++ 4 files changed, 137 insertions(+), 47 deletions(-) diff --git a/editor/components/inserter/index.js b/editor/components/inserter/index.js index 16282bce808cdb..c13f15f35e760a 100644 --- a/editor/components/inserter/index.js +++ b/editor/components/inserter/index.js @@ -3,12 +3,13 @@ */ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { flowRight, isEmpty } from 'lodash'; /** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { Dropdown, IconButton } from '@wordpress/components'; +import { Dropdown, IconButton, withContext } from '@wordpress/components'; import { createBlock } from '@wordpress/blocks'; import { Component } from '@wordpress/element'; @@ -61,8 +62,13 @@ class Inserter extends Component { children, onInsertBlock, insertionPoint, + hasSupportedBlocks, } = this.props; + if ( ! hasSupportedBlocks ) { + return null; + } + return ( { +export default flowRight( [ + connect( + ( state ) => { + return { + insertionPoint: getBlockInsertionPoint( state ), + mode: getEditorMode( state ), + }; + }, + ( dispatch ) => ( { + onInsertBlock( name, position ) { + dispatch( hideInsertionPoint() ); + dispatch( insertBlock( + createBlock( name ), + position + ) ); + }, + ...bindActionCreators( { + setInsertionPoint: setBlockInsertionPoint, + clearInsertionPoint: clearBlockInsertionPoint, + }, dispatch ), + } ) + ), + withContext( 'editor' )( ( settings ) => { + const { blockTypes } = settings; + return { - insertionPoint: getBlockInsertionPoint( state ), - mode: getEditorMode( state ), + hasSupportedBlocks: true === blockTypes || ! isEmpty( blockTypes ), }; - }, - ( dispatch ) => ( { - onInsertBlock( name, position ) { - dispatch( hideInsertionPoint() ); - dispatch( insertBlock( - createBlock( name ), - position - ) ); - }, - ...bindActionCreators( { - setInsertionPoint: setBlockInsertionPoint, - clearInsertionPoint: clearBlockInsertionPoint, - }, dispatch ), - } ) -)( Inserter ); + } ), +] )( Inserter ); diff --git a/editor/components/inserter/menu.js b/editor/components/inserter/menu.js index 005944dde38b6d..4d6b9df6e0b145 100644 --- a/editor/components/inserter/menu.js +++ b/editor/components/inserter/menu.js @@ -24,6 +24,7 @@ import { TabbableContainer, withInstanceId, withSpokenMessages, + withContext, } from '@wordpress/components'; import { getCategories, getBlockTypes } from '@wordpress/blocks'; import { keycodes } from '@wordpress/utils'; @@ -112,8 +113,27 @@ export class InserterMenu extends Component { } getBlockTypes() { + const { blockTypes } = this.props; + + // If all block types disabled, return empty set + if ( ! blockTypes ) { + return []; + } + // Block types that are marked as private should not appear in the inserter - return getBlockTypes().filter( ( block ) => ! block.isPrivate ); + return getBlockTypes().filter( ( block ) => { + if ( block.isPrivate ) { + return false; + } + + // Block types defined as either `true` or array: + // - True: Allow + // - Array: Check block name within whitelist + return ( + ! Array.isArray( blockTypes ) || + includes( blockTypes, block.name ) + ); + } ); } searchBlocks( blockTypes ) { @@ -121,18 +141,28 @@ export class InserterMenu extends Component { } getBlocksForTab( tab ) { + const blockTypes = this.getBlockTypes(); // if we're searching, use everything, otherwise just get the blocks visible in this tab if ( this.state.filterValue ) { - return this.getBlockTypes(); + return blockTypes; } + + let predicate; switch ( tab ) { case 'recent': - return this.props.recentlyUsedBlocks; + predicate = ( block ) => find( this.props.recentlyUsedBlocks, { name: block.name } ); + break; + case 'blocks': - return filter( this.getBlockTypes(), ( block ) => block.category !== 'embed' ); + predicate = ( block ) => block.category !== 'embed'; + break; + case 'embeds': - return filter( this.getBlockTypes(), ( block ) => block.category === 'embed' ); + predicate = ( block ) => block.category === 'embed'; + break; } + + return filter( blockTypes, predicate ); } sortBlocks( blockTypes ) { @@ -201,17 +231,18 @@ export class InserterMenu extends Component { this.setState( { tab } ); } - renderTabView( tab, visibleBlocks ) { - switch ( tab ) { - case 'recent': - return this.renderBlocks( this.props.recentlyUsedBlocks, undefined ); - - case 'embed': - return this.renderBlocks( visibleBlocks.embed, undefined ); + renderTabView( tab ) { + const blocksForTab = this.getBlocksForTab( tab ); + if ( 'recent' === tab ) { + return this.renderBlocks( blocksForTab ); + } - default: - return this.renderCategories( visibleBlocks, undefined ); + const visibleBlocks = this.getVisibleBlocksByCategory( blocksForTab ); + if ( 'embed' === tab ) { + return this.renderBlocks( visibleBlocks.embed ); } + + return this.renderCategories( visibleBlocks ); } interceptArrows( event ) { @@ -266,19 +297,12 @@ export class InserterMenu extends Component { }, ] } > - { - ( tabKey ) => { - const blocksForTab = this.getBlocksForTab( tabKey ); - const visibleBlocks = this.getVisibleBlocksByCategory( blocksForTab ); - - return ( -
this.tabContainer = ref } - className="editor-inserter__content"> - { this.renderTabView( tabKey, visibleBlocks ) } -
- ); - } - } + { ( tabKey ) => ( +
this.tabContainer = ref } + className="editor-inserter__content"> + { this.renderTabView( tabKey ) } +
+ ) } } { isSearching && @@ -304,5 +328,6 @@ const connectComponent = connect( export default flow( withInstanceId, withSpokenMessages, + withContext( 'editor' )( ( settings ) => pick( settings, 'blockTypes' ) ), connectComponent )( InserterMenu ); diff --git a/editor/components/inserter/test/menu.js b/editor/components/inserter/test/menu.js index 856e0ba4f6495a..5a01a2abc30131 100644 --- a/editor/components/inserter/test/menu.js +++ b/editor/components/inserter/test/menu.js @@ -97,6 +97,7 @@ describe( 'InserterMenu', () => { blocks={ [] } recentlyUsedBlocks={ [] } debouncedSpeak={ noop } + blockTypes /> ); @@ -107,6 +108,39 @@ describe( 'InserterMenu', () => { expect( visibleBlocks.length ).toBe( 0 ); } ); + it( 'should show no blocks if all block types disabled', () => { + const wrapper = mount( + + ); + + const visibleBlocks = wrapper.find( '.editor-inserter__block' ); + expect( visibleBlocks.length ).toBe( 0 ); + } ); + + it( 'should show filtered block types', () => { + const wrapper = mount( + + ); + + const visibleBlocks = wrapper.find( '.editor-inserter__block' ); + expect( visibleBlocks.length ).toBe( 1 ); + expect( visibleBlocks.at( 0 ).text() ).toBe( 'Text' ); + } ); + it( 'should show the recently used blocks in the recent tab', () => { const wrapper = mount( { blocks={ [] } recentlyUsedBlocks={ [ advancedTextBlock ] } debouncedSpeak={ noop } + blockTypes /> ); @@ -132,6 +167,7 @@ describe( 'InserterMenu', () => { blocks={ [] } recentlyUsedBlocks={ [] } debouncedSpeak={ noop } + blockTypes /> ); const embedTab = wrapper.find( '.editor-inserter__tab' ) @@ -155,6 +191,7 @@ describe( 'InserterMenu', () => { blocks={ [] } recentlyUsedBlocks={ [] } debouncedSpeak={ noop } + blockTypes /> ); const blocksTab = wrapper.find( '.editor-inserter__tab' ) @@ -180,6 +217,7 @@ describe( 'InserterMenu', () => { blocks={ [ { name: moreBlock.name } ] } recentlyUsedBlocks={ [] } debouncedSpeak={ noop } + blockTypes /> ); const blocksTab = wrapper.find( '.editor-inserter__tab' ) @@ -200,6 +238,7 @@ describe( 'InserterMenu', () => { blocks={ [] } recentlyUsedBlocks={ [] } debouncedSpeak={ noop } + blockTypes /> ); wrapper.setState( { filterValue: 'text' } ); @@ -222,6 +261,7 @@ describe( 'InserterMenu', () => { blocks={ [] } recentlyUsedBlocks={ [] } debouncedSpeak={ noop } + blockTypes /> ); wrapper.setState( { filterValue: ' text' } ); diff --git a/lib/client-assets.php b/lib/client-assets.php index d5bd43b12aab3e..fee8be2f5ab04b 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -767,9 +767,19 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $color_palette = $gutenberg_theme_support[0]['colors']; } + /** + * Filters the allowed block types for the editor, defaulting to true (all + * block types supported). + * + * @param bool|array $allowed_block_types Array of block type slugs, or + * boolean to enable/disable all. + */ + $allowed_block_types = apply_filters( 'allowed_block_types', true ); + $editor_settings = array( 'wideImages' => ! empty( $gutenberg_theme_support[0]['wide-images'] ), 'colors' => $color_palette, + 'blockTypes' => $allowed_block_types, ); wp_add_inline_script( 'wp-editor', 'wp.api.init().done( function() {'