diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index ea97ce28e4d85..e96e28c6793da 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -458,6 +458,18 @@ _Returns_ - `Array< UserPatternCategory >`: User patterns category array. +### getUserPatterns + +Retrieve the list of registered user patterns. + +_Parameters_ + +- _state_ `State`: Data state. + +_Returns_ + +- `Array< UserPattern >`: User pattern list. + ### getUserQueryResults Returns all the users returned by a query ID. diff --git a/packages/block-editor/src/components/block-patterns-list/index.js b/packages/block-editor/src/components/block-patterns-list/index.js index bebeb1f44184c..ecae484462bfb 100644 --- a/packages/block-editor/src/components/block-patterns-list/index.js +++ b/packages/block-editor/src/components/block-patterns-list/index.js @@ -105,16 +105,16 @@ function BlockPattern( { blocks={ blocks } viewportWidth={ viewportWidth } /> - - { pattern.id && ! pattern.syncStatus && ( -
- -
- ) } + { pattern.id && + pattern.syncStatus === 'fully' && ( +
+ +
+ ) } { ( ! showTooltip || pattern.id ) && (
{ pattern.title } diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 548ad71664b5e..8f33cbd4c8354 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2274,31 +2274,6 @@ const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => { return true; }; -function getUserPatterns( state ) { - const userPatterns = - state?.settings?.__experimentalReusableBlocks ?? EMPTY_ARRAY; - const userPatternCategories = - state?.settings?.__experimentalUserPatternCategories ?? []; - const categories = new Map(); - userPatternCategories.forEach( ( userCategory ) => - categories.set( userCategory.id, userCategory ) - ); - return userPatterns.map( ( userPattern ) => { - return { - name: `core/block/${ userPattern.id }`, - id: userPattern.id, - title: userPattern.title.raw, - categories: userPattern.wp_pattern_category.map( ( catId ) => - categories && categories.get( catId ) - ? categories.get( catId ).slug - : catId - ), - content: userPattern.content.raw, - syncStatus: userPattern.wp_pattern_sync_status, - }; - } ); -} - export const __experimentalUserPatternCategories = createSelector( ( state ) => { return state?.settings?.__experimentalUserPatternCategories; @@ -2309,7 +2284,7 @@ export const __experimentalUserPatternCategories = createSelector( export const __experimentalGetParsedPattern = createSelector( ( state, patternName ) => { const patterns = state.settings.__experimentalBlockPatterns; - const userPatterns = getUserPatterns( state ); + const userPatterns = state.settings.__experimentalUserPatterns || []; const pattern = [ ...patterns, ...userPatterns ].find( ( { name } ) => name === patternName @@ -2317,24 +2292,27 @@ export const __experimentalGetParsedPattern = createSelector( if ( ! pattern ) { return null; } + return { ...pattern, - blocks: parse( pattern.content, { - __unstableSkipMigrationLogs: true, - } ), + blocks: pattern.blocks + ? pattern.blocks + : parse( pattern.content, { + __unstableSkipMigrationLogs: true, + } ), }; }, ( state ) => [ state.settings.__experimentalBlockPatterns, - state.settings.__experimentalReusableBlocks, state?.settings?.__experimentalUserPatternCategories, + state?.settings?.__experimentalUserPatterns, ] ); const getAllAllowedPatterns = createSelector( ( state ) => { const patterns = state.settings.__experimentalBlockPatterns; - const userPatterns = getUserPatterns( state ); + const userPatterns = state.settings.__experimentalUserPatterns || []; const { allowedBlockTypes } = getSettings( state ); @@ -2350,7 +2328,7 @@ const getAllAllowedPatterns = createSelector( }, ( state ) => [ state.settings.__experimentalBlockPatterns, - state.settings.__experimentalReusableBlocks, + state.settings.__experimentalUserPatterns, state.settings.allowedBlockTypes, state?.settings?.__experimentalUserPatternCategories, ] diff --git a/packages/core-data/README.md b/packages/core-data/README.md index ef5d9c1197f09..4feae756e7d86 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -765,6 +765,18 @@ _Returns_ - `Array< UserPatternCategory >`: User patterns category array. +### getUserPatterns + +Retrieve the list of registered user patterns. + +_Parameters_ + +- _state_ `State`: Data state. + +_Returns_ + +- `Array< UserPattern >`: User pattern list. + ### getUserQueryResults Returns all the users returned by a query ID. diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index a21623d8ba89d..89239126bd88a 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -535,6 +535,15 @@ export function blockPatternCategories( state = [], action ) { return state; } +export function userPatterns( state = [], action ) { + switch ( action.type ) { + case 'RECEIVE_USER_PATTERNS': + return action.userPatterns; + } + + return state; +} + export function userPatternCategories( state = [], action ) { switch ( action.type ) { case 'RECEIVE_USER_PATTERN_CATEGORIES': @@ -610,6 +619,7 @@ export default combineReducers( { autosaves, blockPatterns, blockPatternCategories, + userPatterns, userPatternCategories, navigationFallbackId, defaultTemplates, diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index cd2a65a60b013..4c6f53eb9f607 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -668,6 +668,23 @@ export const getUserPatternCategories = } ); }; +export const getUserPatterns = + () => + async ( { dispatch, resolveSelect } ) => { + const userPatterns = await resolveSelect.getEntityRecords( + 'postType', + 'wp_block', + { + per_page: -1, + } + ); + + dispatch( { + type: 'RECEIVE_USER_PATTERNS', + userPatterns, + } ); + }; + export const getNavigationFallbackId = () => async ( { dispatch, select } ) => { diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index 2a046941611c7..baa6fa8d2b6bb 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -9,6 +9,7 @@ import createSelector from 'rememo'; import { createRegistrySelector } from '@wordpress/data'; import { addQueryArgs } from '@wordpress/url'; import deprecated from '@wordpress/deprecated'; +import { parse } from '@wordpress/blocks'; /** * Internal dependencies @@ -45,6 +46,7 @@ export interface State { userPermissions: Record< string, boolean >; users: UserState; navigationFallbackId: EntityRecordKey; + userPatterns: Array< UserPattern >; userPatternCategories: Array< UserPatternCategory >; defaultTemplates: Record< string, string >; } @@ -96,6 +98,17 @@ export interface UserPatternCategory { description: string; } +export interface UserPattern { + blocks: Array< unknown >; + categories?: Array< string >; + id: string; + name: string; + slug: string; + syncStatus: string; + title: string; + type: string; +} + type Optional< T > = T | undefined; /** @@ -1325,6 +1338,43 @@ export function getBlockPatternCategories( state: State ): Array< any > { return state.blockPatternCategories; } +/** + * Retrieve the list of registered user patterns. + * + * @param state Data state. + * + * @return User pattern list. + */ +export const getUserPatterns = createSelector( + ( state: State ): Array< UserPattern > => { + const categories = new Map(); + state.userPatternCategories.forEach( ( userCategory ) => + categories.set( userCategory.id, userCategory ) + ); + + return state.userPatterns.map( ( patternBlock: any ) => ( { + blocks: parse( patternBlock.content.raw, { + __unstableSkipMigrationLogs: true, + } ), + ...( patternBlock.wp_pattern_category.length > 0 && { + categories: patternBlock.wp_pattern_category.map( + ( patternCategoryId: number ) => + categories && categories.get( patternCategoryId ) + ? categories.get( patternCategoryId ).slug + : patternCategoryId + ), + } ), + id: patternBlock.id, + name: `core/block/${ patternBlock.id }`, + slug: patternBlock.slug, + syncStatus: patternBlock.wp_pattern_sync_status || 'fully', + title: patternBlock.title.raw, + type: 'wp_block', + } ) ); + }, + ( state ) => [ state.userPatternCategories, state.userPatterns ] +); + /** * Retrieve the registered user pattern categories. * @@ -1332,7 +1382,6 @@ export function getBlockPatternCategories( state: State ): Array< any > { * * @return User patterns category array. */ - export function getUserPatternCategories( state: State ): Array< UserPatternCategory > { diff --git a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js index 0a9a36d93d009..a900aae71f2d9 100644 --- a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js +++ b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js @@ -43,11 +43,7 @@ export default function DeleteCategoryMenuItem( { category, onClose } ) { // Prevent the need to refresh the page to get up-to-date categories // and pattern categorization. invalidateResolution( 'getUserPatternCategories' ); - invalidateResolution( 'getEntityRecords', [ - 'postType', - PATTERN_TYPES.user, - { per_page: -1 }, - ] ); + invalidateResolution( 'getUserPatterns' ); createSuccessNotice( sprintf( diff --git a/packages/edit-site/src/components/page-patterns/use-patterns.js b/packages/edit-site/src/components/page-patterns/use-patterns.js index 9cb6c8b998c41..61dd09bdb6b31 100644 --- a/packages/edit-site/src/components/page-patterns/use-patterns.js +++ b/packages/edit-site/src/components/page-patterns/use-patterns.js @@ -184,58 +184,19 @@ const selectPatterns = createSelector( ] ); -const patternBlockToPattern = ( patternBlock, categories ) => ( { - blocks: parse( patternBlock.content.raw, { - __unstableSkipMigrationLogs: true, - } ), - ...( patternBlock.wp_pattern_category.length > 0 && { - categories: patternBlock.wp_pattern_category.map( - ( patternCategoryId ) => - categories && categories.get( patternCategoryId ) - ? categories.get( patternCategoryId ).slug - : patternCategoryId - ), - } ), - termLabels: patternBlock.wp_pattern_category.map( ( patternCategoryId ) => - categories?.get( patternCategoryId ) - ? categories.get( patternCategoryId ).label - : patternCategoryId - ), - id: patternBlock.id, - name: patternBlock.slug, - syncStatus: patternBlock.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full, - title: patternBlock.title.raw, - type: PATTERN_TYPES.user, - patternBlock, -} ); - const selectUserPatterns = createSelector( ( select, syncStatus, search = '' ) => { - const { getEntityRecords, getIsResolving, getUserPatternCategories } = + const { getIsResolving, getUserPatternCategories, getUserPatterns } = select( coreStore ); - const query = { per_page: -1 }; - const records = getEntityRecords( - 'postType', - PATTERN_TYPES.user, - query - ); + let patterns = getUserPatterns(); const userPatternCategories = getUserPatternCategories(); const categories = new Map(); userPatternCategories.forEach( ( userCategory ) => categories.set( userCategory.id, userCategory ) ); - let patterns = records - ? records.map( ( record ) => - patternBlockToPattern( record, categories ) - ) - : EMPTY_PATTERN_LIST; - const isResolving = getIsResolving( 'getEntityRecords', [ - 'postType', - PATTERN_TYPES.user, - query, - ] ); + const isResolving = getIsResolving( 'getUserPatterns' ); if ( syncStatus ) { patterns = patterns.filter( @@ -257,14 +218,8 @@ const selectUserPatterns = createSelector( }; }, ( select ) => [ - select( coreStore ).getEntityRecords( 'postType', PATTERN_TYPES.user, { - per_page: -1, - } ), - select( coreStore ).getIsResolving( 'getEntityRecords', [ - 'postType', - PATTERN_TYPES.user, - { per_page: -1 }, - ] ), + select( coreStore ).getUserPatterns(), + select( coreStore ).getIsResolving( 'getUserPatterns' ), select( coreStore ).getUserPatternCategories(), ] ); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index c0804febab0db..ed5a2182c0b5b 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -98,6 +98,7 @@ function useBlockEditorSettings( settings, postType, postId ) { pageOnFront, pageForPosts, userPatternCategories, + userPatterns, } = useSelect( ( select ) => { const isWeb = Platform.OS === 'web'; @@ -107,6 +108,7 @@ function useBlockEditorSettings( settings, postType, postId ) { getEntityRecord, getUserPatternCategories, getEntityRecords, + getUserPatterns, } = select( coreStore ); const siteSettings = canUser( 'read', 'settings' ) @@ -129,6 +131,7 @@ function useBlockEditorSettings( settings, postType, postId ) { pageOnFront: siteSettings?.page_on_front, pageForPosts: siteSettings?.page_for_posts, userPatternCategories: getUserPatternCategories(), + userPatterns: getUserPatterns(), }; }, [ postType, postId ] @@ -219,6 +222,7 @@ function useBlockEditorSettings( settings, postType, postId ) { __experimentalBlockPatterns: blockPatterns, __experimentalBlockPatternCategories: blockPatternCategories, __experimentalUserPatternCategories: userPatternCategories, + __experimentalUserPatterns: userPatterns, __experimentalFetchLinkSuggestions: ( search, searchOptions ) => fetchLinkSuggestions( search, searchOptions, settings ), inserterMediaCategories, @@ -252,6 +256,7 @@ function useBlockEditorSettings( settings, postType, postId ) { pageOnFront, pageForPosts, postType, + userPatterns, ] ); } diff --git a/packages/patterns/src/components/create-pattern-modal.js b/packages/patterns/src/components/create-pattern-modal.js index 22d20fd037265..494095aa3c19c 100644 --- a/packages/patterns/src/components/create-pattern-modal.js +++ b/packages/patterns/src/components/create-pattern-modal.js @@ -103,6 +103,7 @@ export default function CreatePatternModal( { typeof content === 'function' ? content() : content, categories ); + invalidateResolution( 'getUserPatterns' ); onSuccess( { pattern: newPattern, categoryId: PATTERN_DEFAULT_CATEGORY,