Skip to content

Commit

Permalink
Inserter: Always show the list of all patterns in the inserter (#65611)
Browse files Browse the repository at this point in the history
Co-authored-by: youknowriad <[email protected]>
Co-authored-by: richtabor <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
  • Loading branch information
4 people authored Sep 24, 2024
1 parent 892d9a5 commit c1fe482
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,66 @@ import { store as noticesStore } from '@wordpress/notices';
* Internal dependencies
*/
import { store as blockEditorStore } from '../../../store';
import { unlock } from '../../../lock-unlock';
import { INSERTER_PATTERN_TYPES } from '../block-patterns-tab/utils';
import { getParsedPattern } from '../../../store/utils';

/**
* Retrieves the block patterns inserter state.
*
* @param {Function} onInsert function called when inserter a list of blocks.
* @param {string=} rootClientId Insertion's root client ID.
*
* @param {string} selectedCategory The selected pattern category.
* @param {boolean} isQuick For the quick inserter render only allowed patterns.
*
* @return {Array} Returns the patterns state. (patterns, categories, onSelect handler)
*/
const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => {
const { patternCategories, patterns, userPatternCategories } = useSelect(
const usePatternsState = (
onInsert,
rootClientId,
selectedCategory,
isQuick
) => {
const { patternCategories, allPatterns, userPatternCategories } = useSelect(
( select ) => {
const { __experimentalGetAllowedPatterns, getSettings } =
select( blockEditorStore );
const {
getAllPatterns,
getSettings,
__experimentalGetAllowedPatterns,
} = unlock( select( blockEditorStore ) );
const {
__experimentalUserPatternCategories,
__experimentalBlockPatternCategories,
} = getSettings();
return {
patterns: __experimentalGetAllowedPatterns( rootClientId ),
allPatterns: isQuick
? __experimentalGetAllowedPatterns()
: getAllPatterns(),
userPatternCategories: __experimentalUserPatternCategories,
patternCategories: __experimentalBlockPatternCategories,
};
},
[ rootClientId ]
[ isQuick ]
);
const { getClosestAllowedInsertionPointForPattern } = unlock(
useSelect( blockEditorStore )
);

const patterns = useMemo(
() =>
isQuick
? allPatterns
: allPatterns
.filter( ( { inserter = true } ) => !! inserter )
.map( ( pattern ) => {
return {
...pattern,
get blocks() {
return getParsedPattern( pattern ).blocks;
},
};
} ),
[ isQuick, allPatterns ]
);

const allCategories = useMemo( () => {
Expand All @@ -58,6 +91,15 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => {
const { createSuccessNotice } = useDispatch( noticesStore );
const onClickPattern = useCallback(
( pattern, blocks ) => {
const destinationRootClientId = isQuick
? rootClientId
: getClosestAllowedInsertionPointForPattern(
pattern,
rootClientId
);
if ( destinationRootClientId === null ) {
return;
}
const patternBlocks =
pattern.type === INSERTER_PATTERN_TYPES.user &&
pattern.syncStatus !== 'unsynced'
Expand All @@ -77,7 +119,9 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => {
}
return clonedBlock;
} ),
pattern.name
pattern.name,
false,
destinationRootClientId
);
createSuccessNotice(
sprintf(
Expand All @@ -91,7 +135,14 @@ const usePatternsState = ( onInsert, rootClientId, selectedCategory ) => {
}
);
},
[ createSuccessNotice, onInsert, selectedCategory ]
[
createSuccessNotice,
onInsert,
selectedCategory,
rootClientId,
getClosestAllowedInsertionPointForPattern,
isQuick,
]
);

return [ patterns, allCategories, onClickPattern ];
Expand Down
4 changes: 2 additions & 2 deletions packages/block-editor/src/components/inserter/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ function InserterMenu(
);

const onInsertPattern = useCallback(
( blocks, patternName ) => {
( blocks, patternName, ...args ) => {
onToggleInsertionPoint( false );
onInsertBlocks( blocks, { patternName } );
onInsertBlocks( blocks, { patternName }, ...args );
onSelect();
},
[ onInsertBlocks, onSelect ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ export default function QuickInserter( {
onInsertBlocks,
true
);

const [ patterns ] = usePatternsState(
onInsertBlocks,
destinationRootClientId
destinationRootClientId,
undefined,
true
);

const { setInserterIsOpened, insertionIndex } = useSelect(
Expand Down
35 changes: 29 additions & 6 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -642,24 +642,30 @@ export function isZoomOut( state ) {
/**
* Finds the closest block where the block is allowed to be inserted.
*
* @param {Object} state Editor state.
* @param {string} name Block name.
* @param {string} clientId Default insertion point.
* @param {Object} state Editor state.
* @param {string[] | string} name Block name or names.
* @param {string} clientId Default insertion point.
*
* @return {string} clientID of the closest container when the block name can be inserted.
*/
export function getClosestAllowedInsertionPoint( state, name, clientId = '' ) {
const blockNames = Array.isArray( name ) ? name : [ name ];
const areBlockNamesAllowedInClientId = ( id ) =>
blockNames.every( ( currentName ) =>
canInsertBlockType( state, currentName, id )
);

// If we're trying to insert at the root level and it's not allowed
// Try the section root instead.
if ( ! clientId ) {
if ( canInsertBlockType( state, name, clientId ) ) {
if ( areBlockNamesAllowedInClientId( clientId ) ) {
return clientId;
}

const sectionRootClientId = getSectionRootClientId( state );
if (
sectionRootClientId &&
canInsertBlockType( state, name, sectionRootClientId )
areBlockNamesAllowedInClientId( sectionRootClientId )
) {
return sectionRootClientId;
}
Expand All @@ -668,10 +674,27 @@ export function getClosestAllowedInsertionPoint( state, name, clientId = '' ) {

// Traverse the block tree up until we find a place where we can insert.
let current = clientId;
while ( current !== null && ! canInsertBlockType( state, name, current ) ) {
while ( current !== null && ! areBlockNamesAllowedInClientId( current ) ) {
const parentClientId = getBlockRootClientId( state, current );
current = parentClientId;
}

return current;
}

export function getClosestAllowedInsertionPointForPattern(
state,
pattern,
clientId
) {
const { allowedBlockTypes } = getSettings( state );
const isAllowed = checkAllowListRecursive(
getGrammar( pattern ),
allowedBlockTypes
);
if ( ! isAllowed ) {
return null;
}
const names = getGrammar( pattern ).map( ( { blockName: name } ) => name );
return getClosestAllowedInsertionPoint( state, names, clientId );
}
13 changes: 7 additions & 6 deletions test/e2e/specs/editor/various/allowed-patterns.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ test.describe( 'Allowed Patterns', () => {
);
} );

test( 'should show all patterns when all blocks are allowed', async ( {
admin,
page,
} ) => {
test( 'should show all patterns by default', async ( { admin, page } ) => {
await admin.createNewPost();
await page
.getByRole( 'toolbar', { name: 'Document tools' } )
Expand Down Expand Up @@ -57,7 +54,7 @@ test.describe( 'Allowed Patterns', () => {
);
} );

test( 'should show only allowed patterns', async ( {
test( 'should show all patterns even if not allowed', async ( {
admin,
page,
} ) => {
Expand All @@ -80,7 +77,11 @@ test.describe( 'Allowed Patterns', () => {
page
.getByRole( 'listbox', { name: 'Block patterns' } )
.getByRole( 'option' )
).toHaveText( [ 'Test: Single heading' ] );
).toHaveText( [
'Test: Single heading',
'Test: Single paragraph',
'Test: Paragraph inside group',
] );
} );
} );
} );

0 comments on commit c1fe482

Please sign in to comment.