Skip to content

Commit

Permalink
Blocks: Allow filterable allowed inserter types
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth committed Nov 20, 2017
1 parent d9ec693 commit e6642bc
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 47 deletions.
55 changes: 35 additions & 20 deletions editor/components/inserter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -61,8 +62,13 @@ class Inserter extends Component {
children,
onInsertBlock,
insertionPoint,
hasSupportedBlocks,
} = this.props;

if ( ! hasSupportedBlocks ) {
return null;
}

return (
<Dropdown
className="editor-inserter"
Expand Down Expand Up @@ -97,24 +103,33 @@ class Inserter extends Component {
}
}

export default connect(
( state ) => {
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 );
79 changes: 52 additions & 27 deletions editor/components/inserter/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
TabbableContainer,
withInstanceId,
withSpokenMessages,
withContext,
} from '@wordpress/components';
import { getCategories, getBlockTypes } from '@wordpress/blocks';
import { keycodes } from '@wordpress/utils';
Expand Down Expand Up @@ -112,27 +113,56 @@ 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 ) {
return searchBlocks( blockTypes, this.state.filterValue );
}

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 ) {
Expand Down Expand Up @@ -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 ) {
Expand Down Expand Up @@ -266,19 +297,12 @@ export class InserterMenu extends Component {
},
] }
>
{
( tabKey ) => {
const blocksForTab = this.getBlocksForTab( tabKey );
const visibleBlocks = this.getVisibleBlocksByCategory( blocksForTab );

return (
<div ref={ ( ref ) => this.tabContainer = ref }
className="editor-inserter__content">
{ this.renderTabView( tabKey, visibleBlocks ) }
</div>
);
}
}
{ ( tabKey ) => (
<div ref={ ( ref ) => this.tabContainer = ref }
className="editor-inserter__content">
{ this.renderTabView( tabKey ) }
</div>
) }
</TabPanel>
}
{ isSearching &&
Expand All @@ -304,5 +328,6 @@ const connectComponent = connect(
export default flow(
withInstanceId,
withSpokenMessages,
withContext( 'editor' )( ( settings ) => pick( settings, 'blockTypes' ) ),
connectComponent
)( InserterMenu );
40 changes: 40 additions & 0 deletions editor/components/inserter/test/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ describe( 'InserterMenu', () => {
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
blockTypes
/>
);

Expand All @@ -107,6 +108,39 @@ describe( 'InserterMenu', () => {
expect( visibleBlocks.length ).toBe( 0 );
} );

it( 'should show no blocks if all block types disabled', () => {
const wrapper = mount(
<InserterMenu
position={ 'top center' }
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [ advancedTextBlock ] }
debouncedSpeak={ noop }
blockTypes={ false }
/>
);

const visibleBlocks = wrapper.find( '.editor-inserter__block' );
expect( visibleBlocks.length ).toBe( 0 );
} );

it( 'should show filtered block types', () => {
const wrapper = mount(
<InserterMenu
position={ 'top center' }
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [ textBlock, advancedTextBlock ] }
debouncedSpeak={ noop }
blockTypes={ [ textBlock.name ] }
/>
);

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(
<InserterMenu
Expand All @@ -115,6 +149,7 @@ describe( 'InserterMenu', () => {
blocks={ [] }
recentlyUsedBlocks={ [ advancedTextBlock ] }
debouncedSpeak={ noop }
blockTypes
/>
);

Expand All @@ -132,6 +167,7 @@ describe( 'InserterMenu', () => {
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
blockTypes
/>
);
const embedTab = wrapper.find( '.editor-inserter__tab' )
Expand All @@ -155,6 +191,7 @@ describe( 'InserterMenu', () => {
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
blockTypes
/>
);
const blocksTab = wrapper.find( '.editor-inserter__tab' )
Expand All @@ -180,6 +217,7 @@ describe( 'InserterMenu', () => {
blocks={ [ { name: moreBlock.name } ] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
blockTypes
/>
);
const blocksTab = wrapper.find( '.editor-inserter__tab' )
Expand All @@ -200,6 +238,7 @@ describe( 'InserterMenu', () => {
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
blockTypes
/>
);
wrapper.setState( { filterValue: 'text' } );
Expand All @@ -222,6 +261,7 @@ describe( 'InserterMenu', () => {
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
blockTypes
/>
);
wrapper.setState( { filterValue: ' text' } );
Expand Down
10 changes: 10 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -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() {'
Expand Down

0 comments on commit e6642bc

Please sign in to comment.