diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js
index e9114e53184ccf..2fe8a543a8663b 100644
--- a/packages/edit-site/src/components/page-patterns/index.js
+++ b/packages/edit-site/src/components/page-patterns/index.js
@@ -117,6 +117,7 @@ function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) {
function Preview( { item, viewType } ) {
const descriptionId = useId();
+ const description = item.description || item?.excerpt?.raw;
const isUserPattern = item.type === PATTERN_TYPES.user;
const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
const [ backgroundColor ] = useGlobalStyle( 'color.background' );
@@ -143,7 +144,7 @@ function Preview( { item, viewType } ) {
{ isEmpty && isTemplatePart && __( 'Empty template part' ) }
{ isEmpty && ! isTemplatePart && __( 'Empty pattern' ) }
@@ -156,9 +157,9 @@ function Preview( { item, viewType } ) {
) }
- { item.description && (
+ { !! description && (
- { item.description }
+ { description }
) }
@@ -222,7 +223,7 @@ function Title( { item } ) {
// See https://github.com/WordPress/gutenberg/pull/51898#discussion_r1243399243.
tabIndex="-1"
>
- { title || item.name }
+ { title }
) }
@@ -300,23 +301,20 @@ export default function DataviewsPatterns() {
header: __( 'Sync status' ),
id: 'sync-status',
render: ( { item } ) => {
+ const syncStatus =
+ 'wp_pattern_sync_status' in item
+ ? item.wp_pattern_sync_status ||
+ PATTERN_SYNC_TYPES.full
+ : PATTERN_SYNC_TYPES.unsynced;
// User patterns can have their sync statuses checked directly.
// Non-user patterns are all unsynced for the time being.
return (
{
- (
- SYNC_FILTERS.find(
- ( { value } ) =>
- value === item.syncStatus
- ) ||
- SYNC_FILTERS.find(
- ( { value } ) =>
- value ===
- PATTERN_SYNC_TYPES.unsynced
- )
+ SYNC_FILTERS.find(
+ ( { value } ) => value === syncStatus
).label
}
diff --git a/packages/edit-site/src/components/page-patterns/search-items.js b/packages/edit-site/src/components/page-patterns/search-items.js
index 64565d951e833f..1d03400c86c8cc 100644
--- a/packages/edit-site/src/components/page-patterns/search-items.js
+++ b/packages/edit-site/src/components/page-patterns/search-items.js
@@ -24,11 +24,42 @@ import {
} from '../../utils/constants';
// Default search helpers.
-const defaultGetName = ( item ) =>
- item.type !== TEMPLATE_PART_POST_TYPE ? item.name || '' : '';
-export const defaultGetTitle = ( item ) =>
- typeof item.title === 'string' ? item.title : item.title.rendered;
-const defaultGetDescription = ( item ) => item.description || '';
+const defaultGetName = ( item ) => {
+ if ( item.type === PATTERN_TYPES.user ) {
+ return item.slug;
+ }
+
+ if ( item.type === TEMPLATE_PART_POST_TYPE ) {
+ return '';
+ }
+
+ return item.name || '';
+};
+
+export const defaultGetTitle = ( item ) => {
+ if ( typeof item.title === 'string' ) {
+ return item.title;
+ }
+
+ if ( item.title && item.title.rendered ) {
+ return item.title.rendered;
+ }
+
+ if ( item.title && item.title.raw ) {
+ return item.title.raw;
+ }
+
+ return '';
+};
+
+const defaultGetDescription = ( item ) => {
+ if ( item.type === PATTERN_TYPES.user ) {
+ return item.excerpt.raw;
+ }
+
+ return item.description || '';
+};
+
const defaultGetKeywords = ( item ) => item.keywords || [];
const defaultHasCategory = () => false;
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 dc5a92b560537d..ecbc6adee75587 100644
--- a/packages/edit-site/src/components/page-patterns/use-patterns.js
+++ b/packages/edit-site/src/components/page-patterns/use-patterns.js
@@ -128,8 +128,11 @@ const selectPatterns = createSelector(
patterns: themePatterns,
isResolving: isResolvingThemePatterns,
} = selectThemePatterns( select );
- const { patterns: userPatterns, isResolving: isResolvingUserPatterns } =
- selectUserPatterns( select );
+ const {
+ patterns: userPatterns,
+ isResolving: isResolvingUserPatterns,
+ categories: userPatternCategories,
+ } = selectUserPatterns( select );
let patterns = [
...( themePatterns || [] ),
@@ -141,7 +144,8 @@ const selectPatterns = createSelector(
// Non-user patterns are all unsynced for the time being.
patterns = patterns.filter( ( pattern ) => {
return pattern.type === PATTERN_TYPES.user
- ? pattern.syncStatus === syncStatus
+ ? ( pattern.wp_pattern_sync_status ||
+ PATTERN_SYNC_TYPES.full ) === syncStatus
: syncStatus === PATTERN_SYNC_TYPES.unsynced;
} );
}
@@ -149,12 +153,35 @@ const selectPatterns = createSelector(
if ( categoryId ) {
patterns = searchItems( patterns, search, {
categoryId,
- hasCategory: ( item, currentCategory ) =>
- item.categories?.includes( currentCategory ),
+ hasCategory: ( item, currentCategory ) => {
+ if ( item.type === PATTERN_TYPES.user ) {
+ return item.wp_pattern_category.some(
+ ( catId ) =>
+ userPatternCategories.find(
+ ( cat ) => cat.id === catId
+ )?.slug === currentCategory
+ );
+ }
+ return item.categories?.includes( currentCategory );
+ },
} );
} else {
patterns = searchItems( patterns, search, {
- hasCategory: ( item ) => ! item.hasOwnProperty( 'categories' ),
+ hasCategory: ( item ) => {
+ if ( item.type === PATTERN_TYPES.user ) {
+ return (
+ userPatternCategories?.length &&
+ ( ! item.wp_pattern_category?.length ||
+ ! item.wp_pattern_category.some( ( catId ) =>
+ userPatternCategories.find(
+ ( cat ) => cat.id === catId
+ )
+ ) )
+ );
+ }
+
+ return ! item.hasOwnProperty( 'categories' );
+ },
} );
}
return {
@@ -168,41 +195,6 @@ const selectPatterns = createSelector(
]
);
-/**
- * Converts a post of type `wp_block` to a 'pattern item' that more closely
- * matches the structure of theme provided patterns.
- *
- * @param {Object} patternPost The `wp_block` record being normalized.
- * @param {Map} categories A Map of user created categories.
- *
- * @return {Object} The normalized item.
- */
-const convertPatternPostToItem = ( patternPost, categories ) => ( {
- blocks: parse( patternPost.content.raw, {
- __unstableSkipMigrationLogs: true,
- } ),
- ...( patternPost.wp_pattern_category.length > 0 && {
- categories: patternPost.wp_pattern_category.map(
- ( patternCategoryId ) =>
- categories && categories.get( patternCategoryId )
- ? categories.get( patternCategoryId ).slug
- : patternCategoryId
- ),
- } ),
- termLabels: patternPost.wp_pattern_category.map( ( patternCategoryId ) =>
- categories?.get( patternCategoryId )
- ? categories.get( patternCategoryId ).label
- : patternCategoryId
- ),
- id: patternPost.id,
- name: patternPost.slug,
- syncStatus: patternPost.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full,
- title: patternPost.title.raw,
- type: patternPost.type,
- description: patternPost.excerpt.raw,
- patternPost,
-} );
-
const selectUserPatterns = createSelector(
( select, syncStatus, search = '' ) => {
const {
@@ -222,12 +214,7 @@ const selectUserPatterns = createSelector(
userPatternCategories.forEach( ( userCategory ) =>
categories.set( userCategory.id, userCategory )
);
- let patterns = patternPosts
- ? patternPosts.map( ( record ) =>
- convertPatternPostToItem( record, categories )
- )
- : EMPTY_PATTERN_LIST;
-
+ let patterns = patternPosts ?? EMPTY_PATTERN_LIST;
const isResolving = isResolvingSelector( 'getEntityRecords', [
'postType',
PATTERN_TYPES.user,
@@ -236,7 +223,9 @@ const selectUserPatterns = createSelector(
if ( syncStatus ) {
patterns = patterns.filter(
- ( pattern ) => pattern.syncStatus === syncStatus
+ ( pattern ) =>
+ pattern.wp_pattern_sync_status ||
+ PATTERN_SYNC_TYPES.full === syncStatus
);
}
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js
index 4d80d838ae90d5..a41e0ea7660616 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-patterns/use-pattern-categories.js
@@ -58,13 +58,21 @@ export default function usePatternCategories() {
// Update the category counts to reflect user registered patterns.
userPatterns.forEach( ( pattern ) => {
- pattern.categories?.forEach( ( category ) => {
+ pattern.wp_pattern_category?.forEach( ( catId ) => {
+ const category = userPatternCategories.find(
+ ( cat ) => cat.id === catId
+ )?.name;
if ( categoryMap[ category ] ) {
categoryMap[ category ].count += 1;
}
} );
// If the pattern has no categories, add it to uncategorized.
- if ( ! pattern.categories?.length ) {
+ if (
+ ! pattern.wp_pattern_category?.length ||
+ ! pattern.wp_pattern_category.some( ( catId ) =>
+ userPatternCategories.find( ( cat ) => cat.id === catId )
+ )
+ ) {
categoryMap.uncategorized.count += 1;
}
} );
diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js
index 8050999e8a71bc..c750c202e76fe4 100644
--- a/packages/editor/src/components/post-actions/actions.js
+++ b/packages/editor/src/components/post-actions/actions.js
@@ -33,6 +33,7 @@ import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
import { exportPatternAsJSONAction } from './export-pattern-action';
import { CreateTemplatePartModalContents } from '../create-template-part-modal';
+import { getItemTitle } from '../../dataviews/actions/utils';
// Patterns.
const { PATTERN_TYPES, CreatePatternModalContents, useDuplicatePatternProps } =
@@ -72,13 +73,6 @@ function isTemplateRemovable( template ) {
);
}
-function getItemTitle( item ) {
- if ( typeof item.title === 'string' ) {
- return decodeEntities( item.title );
- }
- return decodeEntities( item.title?.rendered || '' );
-}
-
const trashPostAction = {
id: 'move-to-trash',
label: __( 'Move to Trash' ),
@@ -805,10 +799,8 @@ export const duplicatePatternAction = {
modalHeader: _x( 'Duplicate pattern', 'action label' ),
RenderModal: ( { items, closeModal } ) => {
const [ item ] = items;
- const isThemePattern = item.type === PATTERN_TYPES.theme;
const duplicatedProps = useDuplicatePatternProps( {
- pattern:
- isThemePattern || ! item.patternPost ? item : item.patternPost,
+ pattern: item,
onSuccess: () => closeModal(),
} );
return (
diff --git a/packages/editor/src/components/post-actions/export-pattern-action.js b/packages/editor/src/components/post-actions/export-pattern-action.js
index deeac4314f653f..959cfe1a4abc7b 100644
--- a/packages/editor/src/components/post-actions/export-pattern-action.js
+++ b/packages/editor/src/components/post-actions/export-pattern-action.js
@@ -15,6 +15,7 @@ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
+import { getItemTitle } from '../../dataviews/actions/utils';
// Patterns.
const { PATTERN_TYPES } = unlock( patternsPrivateApis );
@@ -23,9 +24,9 @@ function getJsonFromItem( item ) {
return JSON.stringify(
{
__file: item.type,
- title: item.title || item.name,
- content: item.patternPost.content.raw,
- syncStatus: item.patternPost.wp_pattern_sync_status,
+ title: getItemTitle( item ),
+ content: item.content.raw,
+ syncStatus: item.wp_pattern_sync_status,
},
null,
2
@@ -45,14 +46,16 @@ export const exportPatternAsJSONAction = {
callback: async ( items ) => {
if ( items.length === 1 ) {
return downloadBlob(
- `${ kebabCase( items[ 0 ].title || items[ 0 ].name ) }.json`,
+ `${ kebabCase(
+ getItemTitle( items[ 0 ] ) || items[ 0 ].slug
+ ) }.json`,
getJsonFromItem( items[ 0 ] ),
'application/json'
);
}
const nameCount = {};
const filesToZip = items.map( ( item ) => {
- const name = kebabCase( item.title || item.name );
+ const name = kebabCase( getItemTitle( item ) || item.slug );
nameCount[ name ] = ( nameCount[ name ] || 0 ) + 1;
return {
name: `${
diff --git a/packages/editor/src/dataviews/actions/utils.ts b/packages/editor/src/dataviews/actions/utils.ts
index efbb7c590e6510..56c8c9f54c8507 100644
--- a/packages/editor/src/dataviews/actions/utils.ts
+++ b/packages/editor/src/dataviews/actions/utils.ts
@@ -24,7 +24,13 @@ export function getItemTitle( item: Post ) {
if ( typeof item.title === 'string' ) {
return decodeEntities( item.title );
}
- return decodeEntities( item.title?.rendered || '' );
+ if ( 'rendered' in item.title ) {
+ return decodeEntities( item.title.rendered );
+ }
+ if ( 'raw' in item.title ) {
+ return decodeEntities( item.title.raw );
+ }
+ return '';
}
/**
diff --git a/packages/editor/src/dataviews/types.ts b/packages/editor/src/dataviews/types.ts
index 29f4358456324d..3d8906284a5971 100644
--- a/packages/editor/src/dataviews/types.ts
+++ b/packages/editor/src/dataviews/types.ts
@@ -9,7 +9,7 @@ type PostStatus =
export interface BasePost {
status?: PostStatus;
- title: string | { rendered: string };
+ title: string | { rendered: string } | { raw: string };
type: string;
id: string | number;
}