Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataViews: Removing mapping of user patterns to temporary object #63042

Merged
merged 4 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions packages/edit-site/src/components/page-patterns/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) {

function Preview( { item, viewType } ) {
const descriptionId = useId();
const description = item.description || item?.excerpt?.raw;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this was from before, but it surprized me to see raw and not rendered here..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same :) I think there's some consistency work to be done on the REST API.

const isUserPattern = item.type === PATTERN_TYPES.user;
const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
const [ backgroundColor ] = useGlobalStyle( 'color.background' );
Expand All @@ -143,7 +144,7 @@ function Preview( { item, viewType } ) {
<PreviewWrapper
item={ item }
onClick={ onClick }
ariaDescribedBy={ item.description ? descriptionId : undefined }
ariaDescribedBy={ !! description ? descriptionId : undefined }
>
{ isEmpty && isTemplatePart && __( 'Empty template part' ) }
{ isEmpty && ! isTemplatePart && __( 'Empty pattern' ) }
Expand All @@ -156,9 +157,9 @@ function Preview( { item, viewType } ) {
</Async>
) }
</PreviewWrapper>
{ item.description && (
{ !! description && (
<div hidden id={ descriptionId }>
{ item.description }
{ description }
</div>
) }
</div>
Expand Down Expand Up @@ -222,7 +223,7 @@ function Title( { item } ) {
// See https://github.com/WordPress/gutenberg/pull/51898#discussion_r1243399243.
tabIndex="-1"
>
{ title || item.name }
{ title }
</Button>
) }
</Flex>
Expand Down Expand Up @@ -300,23 +301,20 @@ export default function DataviewsPatterns() {
header: __( 'Sync status' ),
id: 'sync-status',
render: ( { item } ) => {
const syncStatus =
'wp_pattern_sync_status' in item
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can this condition be false if "type" is always user? (line 299)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably it's when we merge the theme patterns with the user ones? You can see the issue without this change in categories like about, etc..

? 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 (
<span
className={ `edit-site-patterns__field-sync-status-${ item.syncStatus }` }
className={ `edit-site-patterns__field-sync-status-${ syncStatus }` }
>
{
(
SYNC_FILTERS.find(
( { value } ) =>
value === item.syncStatus
) ||
SYNC_FILTERS.find(
( { value } ) =>
value ===
PATTERN_SYNC_TYPES.unsynced
)
SYNC_FILTERS.find(
( { value } ) => value === syncStatus
).label
}
</span>
Expand Down
41 changes: 36 additions & 5 deletions packages/edit-site/src/components/page-patterns/search-items.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
69 changes: 22 additions & 47 deletions packages/edit-site/src/components/page-patterns/use-patterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
ntsekouras marked this conversation as resolved.
Show resolved Hide resolved
} = selectUserPatterns( select );

let patterns = [
...( themePatterns || [] ),
Expand All @@ -141,16 +144,26 @@ 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;
} );
}

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, {
Expand All @@ -168,41 +181,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 {
Expand All @@ -222,12 +200,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,
Expand All @@ -236,7 +209,9 @@ const selectUserPatterns = createSelector(

if ( syncStatus ) {
patterns = patterns.filter(
( pattern ) => pattern.syncStatus === syncStatus
( pattern ) =>
pattern.wp_pattern_sync_status ||
PATTERN_SYNC_TYPES.full === syncStatus
);
}

Expand Down
12 changes: 2 additions & 10 deletions packages/editor/src/components/post-actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 } =
Expand Down Expand Up @@ -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' ),
Expand Down Expand Up @@ -810,10 +804,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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the DataViews, pattern content is indeed present in item.content.raw. But when exported from the sidebar, the content is present in item.content, so there seems to be no content field in the exported JSON file.

However, pattern export from the sidebar doesn't seem to have worked before. See this comment for more details.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syncStatus: item.wp_pattern_sync_status,
},
null,
2
Expand All @@ -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: `${
Expand Down
8 changes: 7 additions & 1 deletion packages/editor/src/dataviews/actions/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 '';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/editor/src/dataviews/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading