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

Patterns: Add user categories to site editor sidebar navigation screen #53837

Merged
merged 15 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,14 @@ import { privateApis as routerPrivateApis } from '@wordpress/router';
/**
* Internal dependencies
*/
import {
TEMPLATE_PARTS,
PATTERNS,
SYNC_TYPES,
USER_PATTERNS,
USER_PATTERN_CATEGORY,
} from './utils';
import { TEMPLATE_PARTS, PATTERNS, SYNC_TYPES, USER_PATTERNS } from './utils';
import {
useExistingTemplateParts,
getUniqueTemplatePartTitle,
getCleanTemplatePartSlug,
} from '../../utils/template-part-create';
import { unlock } from '../../lock-unlock';
import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories';

const { useHistory } = unlock( routerPrivateApis );

Expand All @@ -32,11 +27,11 @@ function getPatternMeta( item ) {
return { wp_pattern_sync_status: SYNC_TYPES.unsynced };
}

const syncStatus = item.reusableBlock.wp_pattern_sync_status;
const syncStatus = item.patternBlock.wp_pattern_sync_status;
const isUnsynced = syncStatus === SYNC_TYPES.unsynced;

return {
...item.reusableBlock.meta,
...item.patternBlock.meta,
wp_pattern_sync_status: isUnsynced ? syncStatus : undefined,
};
}
Expand All @@ -47,12 +42,13 @@ export default function DuplicateMenuItem( {
label = __( 'Duplicate' ),
onClose,
} ) {
const { saveEntityRecord } = useDispatch( coreStore );
const { saveEntityRecord, invalidateResolution } = useDispatch( coreStore );
const { createErrorNotice, createSuccessNotice } =
useDispatch( noticesStore );

const history = useHistory();
const existingTemplateParts = useExistingTemplateParts();
const { patternCategories } = usePatternCategories();

async function createTemplatePart() {
try {
Expand Down Expand Up @@ -111,6 +107,45 @@ export default function DuplicateMenuItem( {
}
}

async function findOrCreateTerm( term ) {
try {
const newTerm = await saveEntityRecord(
'taxonomy',
'wp_pattern_category',
{
name: term.label,
slug: term.name,
description: term.description,
},
{
throwOnError: true,
}
);
invalidateResolution( 'getUserPatternCategories' );
return newTerm.id;
} catch ( error ) {
if ( error.code !== 'term_exists' ) {
throw error;
}

return error.data.term_id;
}
}

async function getCategories( categories ) {
const terms = categories.map( ( category ) => {
const fullCategory = patternCategories.find(
( cat ) => cat.name === category
);
if ( fullCategory.id ) {
return fullCategory.id;
}
return findOrCreateTerm( fullCategory );
} );

return Promise.all( terms );
}

async function createPattern() {
try {
const isThemePattern = item.type === PATTERNS;
Expand All @@ -119,17 +154,19 @@ export default function DuplicateMenuItem( {
__( '%s (Copy)' ),
item.title
);
const categories = await getCategories( item.categories );

const result = await saveEntityRecord(
'postType',
'wp_block',
{
content: isThemePattern
? item.content
: item.reusableBlock.content,
: item.patternBlock.content,
meta: getPatternMeta( item ),
status: 'publish',
title,
wp_pattern_category: categories,
},
{ throwOnError: true }
);
Expand All @@ -147,8 +184,8 @@ export default function DuplicateMenuItem( {
);

history.push( {
categoryType: USER_PATTERNS,
categoryId: USER_PATTERN_CATEGORY,
categoryType: PATTERNS,
categoryId,
postType: USER_PATTERNS,
postId: result?.id,
} );
Expand Down
15 changes: 7 additions & 8 deletions packages/edit-site/src/components/page-patterns/grid-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,12 @@ function GridItem( { categoryId, item, ...props } ) {
);
}

const itemIcon =
templatePartIcons[ categoryId ] ||
( item.syncStatus === SYNC_TYPES.full ? symbol : undefined );
let itemIcon;
if ( ! isUserPattern && templatePartIcons[ categoryId ] ) {
itemIcon = templatePartIcons[ categoryId ];
} else {
itemIcon = item.syncStatus === SYNC_TYPES.full ? symbol : undefined;
}

const confirmButtonText = hasThemeFile ? __( 'Clear' ) : __( 'Delete' );
const confirmPrompt = hasThemeFile
Expand Down Expand Up @@ -245,11 +248,7 @@ function GridItem( { categoryId, item, ...props } ) {
categoryId={ categoryId }
item={ item }
onClose={ onClose }
label={
isNonUserPattern
? __( 'Copy to My patterns' )
: __( 'Duplicate' )
}
label={ __( 'Duplicate' ) }
/>
{ isCustomPattern && (
<MenuItem
Expand Down
13 changes: 2 additions & 11 deletions packages/edit-site/src/components/page-patterns/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,14 @@ import {
__experimentalHeading as Heading,
__experimentalText as Text,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { store as editorStore } from '@wordpress/editor';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories';
import {
USER_PATTERN_CATEGORY,
USER_PATTERNS,
TEMPLATE_PARTS,
PATTERNS,
} from './utils';
import { TEMPLATE_PARTS, PATTERNS } from './utils';

export default function PatternsHeader( {
categoryId,
Expand All @@ -35,10 +29,7 @@ export default function PatternsHeader( {
);

let title, description;
if ( categoryId === USER_PATTERN_CATEGORY && type === USER_PATTERNS ) {
title = __( 'My Patterns' );
description = '';
} else if ( type === TEMPLATE_PARTS ) {
if ( type === TEMPLATE_PARTS ) {
const templatePartArea = templatePartAreas.find(
( area ) => area.area === categoryId
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import usePatterns from './use-patterns';
import SidebarButton from '../sidebar-button';
import useDebouncedInput from '../../utils/use-debounced-input';
import { unlock } from '../../lock-unlock';
import { SYNC_TYPES, USER_PATTERN_CATEGORY, PATTERNS } from './utils';
import { SYNC_TYPES, PATTERNS } from './utils';
import Pagination from './pagination';

const { useLocation, useHistory } = unlock( routerPrivateApis );
Expand Down Expand Up @@ -155,7 +155,7 @@ export default function PatternsList( { categoryId, type } ) {
__nextHasNoMarginBottom
/>
</FlexBlock>
{ categoryId === USER_PATTERN_CATEGORY && (
{ type === PATTERNS && (
<ToggleGroupControl
className="edit-site-patterns__sync-status-filter"
hideLabelFromVision
Expand Down
14 changes: 12 additions & 2 deletions packages/edit-site/src/components/page-patterns/search-items.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
import removeAccents from 'remove-accents';
import { noCase } from 'change-case';

/**
* Internal dependencies
*/
import { ALL_PATTERNS_CATEGORY } from './utils';

// Default search helpers.
const defaultGetName = ( item ) => item.name || '';
const defaultGetTitle = ( item ) => item.title;
Expand Down Expand Up @@ -84,7 +89,9 @@ const removeMatchingTerms = ( unmatchedTerms, unprocessedTerms ) => {
*/
export const searchItems = ( items = [], searchInput = '', config = {} ) => {
const normalizedSearchTerms = getNormalizedSearchTerms( searchInput );
const onlyFilterByCategory = ! normalizedSearchTerms.length;
const onlyFilterByCategory =
config.categoryId !== ALL_PATTERNS_CATEGORY &&
! normalizedSearchTerms.length;
const searchRankConfig = { ...config, onlyFilterByCategory };

// If we aren't filtering on search terms, matching on category is satisfactory.
Expand Down Expand Up @@ -131,7 +138,10 @@ function getItemSearchRank( item, searchTerm, config ) {
onlyFilterByCategory,
} = config;

let rank = hasCategory( item, categoryId ) ? 1 : 0;
let rank =
categoryId === ALL_PATTERNS_CATEGORY || hasCategory( item, categoryId )
? 1
: 0;

// If an item doesn't belong to the current category or we don't have
// search terms to filter by, return the initial rank value.
Expand Down
66 changes: 49 additions & 17 deletions packages/edit-site/src/components/page-patterns/use-patterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const selectTemplatePartsAsPatterns = (
return { patterns, isResolving };
};

const selectThemePatterns = ( select, { categoryId, search = '' } = {} ) => {
const selectThemePatterns = ( select ) => {
const { getSettings } = unlock( select( editSiteStore ) );
const settings = getSettings();
const blockPatterns =
Expand All @@ -96,7 +96,7 @@ const selectThemePatterns = ( select, { categoryId, search = '' } = {} ) => {

const restBlockPatterns = select( coreStore ).getBlockPatterns();

let patterns = [
const patterns = [
...( blockPatterns || [] ),
...( restBlockPatterns || [] ),
]
Expand All @@ -114,6 +114,23 @@ const selectThemePatterns = ( select, { categoryId, search = '' } = {} ) => {
} ),
} ) );

return { patterns, isResolving: false };
};
const selectPatterns = (
select,
{ categoryId, search = '', syncStatus } = {}
) => {
const { patterns: themePatterns } = selectThemePatterns( select );
const { patterns: userPatterns } = selectUserPatterns( select );

let patterns = [ ...( themePatterns || [] ), ...( userPatterns || [] ) ];

if ( syncStatus ) {
patterns = patterns.filter(
( pattern ) => pattern.syncStatus === syncStatus
);
}

if ( categoryId ) {
patterns = searchItems( patterns, search, {
categoryId,
Expand All @@ -125,32 +142,43 @@ const selectThemePatterns = ( select, { categoryId, search = '' } = {} ) => {
hasCategory: ( item ) => ! item.hasOwnProperty( 'categories' ),
} );
}

return { patterns, isResolving: false };
};

const reusableBlockToPattern = ( reusableBlock ) => ( {
blocks: parse( reusableBlock.content.raw, {
const patternBlockToPattern = ( patternBlock, categories ) => ( {
blocks: parse( patternBlock.content.raw, {
__unstableSkipMigrationLogs: true,
} ),
categories: reusableBlock.wp_pattern,
id: reusableBlock.id,
name: reusableBlock.slug,
syncStatus: reusableBlock.wp_pattern_sync_status || SYNC_TYPES.full,
title: reusableBlock.title.raw,
type: reusableBlock.type,
reusableBlock,
...( patternBlock.wp_pattern_category.length > 0 && {
categories: patternBlock.wp_pattern_category.map(
( patternCategoryId ) =>
categories && categories.get( patternCategoryId )
? categories.get( patternCategoryId ).slug
: patternCategoryId
),
} ),
id: patternBlock.id,
name: patternBlock.slug,
syncStatus: patternBlock.wp_pattern_sync_status || SYNC_TYPES.full,
title: patternBlock.title.raw,
type: USER_PATTERNS,
patternBlock,
} );

const selectUserPatterns = ( select, { search = '', syncStatus } = {} ) => {
const { getEntityRecords, getIsResolving } = select( coreStore );
const { getEntityRecords, getIsResolving, getUserPatternCategories } =
select( coreStore );

const query = { per_page: -1 };
const records = getEntityRecords( 'postType', USER_PATTERNS, query );
const categories = getUserPatternCategories();

let patterns = records
? records.map( ( record ) => reusableBlockToPattern( record ) )
? records.map( ( record ) =>
patternBlockToPattern( record, categories.patternCategoriesMap )
)
: EMPTY_PATTERN_LIST;

const isResolving = getIsResolving( 'getEntityRecords', [
'postType',
USER_PATTERNS,
Expand All @@ -170,13 +198,13 @@ const selectUserPatterns = ( select, { search = '', syncStatus } = {} ) => {
hasCategory: () => true,
} );

return { patterns, isResolving };
return { patterns, isResolving, categories: categories.patternCategories };
};

export const usePatterns = (
categoryType,
categoryId,
{ search = '', syncStatus }
{ search = '', syncStatus } = {}
) => {
return useSelect(
( select ) => {
Expand All @@ -186,7 +214,11 @@ export const usePatterns = (
search,
} );
} else if ( categoryType === PATTERNS ) {
return selectThemePatterns( select, { categoryId, search } );
return selectPatterns( select, {
categoryId,
search,
syncStatus,
} );
} else if ( categoryType === USER_PATTERNS ) {
return selectUserPatterns( select, { search, syncStatus } );
}
Expand Down
5 changes: 3 additions & 2 deletions packages/edit-site/src/components/page-patterns/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const DEFAULT_CATEGORY = 'my-patterns';
export const DEFAULT_TYPE = 'wp_block';
export const ALL_PATTERNS_CATEGORY = 'all-patterns';
export const DEFAULT_CATEGORY = ALL_PATTERNS_CATEGORY;
export const PATTERNS = 'pattern';
export const DEFAULT_TYPE = PATTERNS;
export const TEMPLATE_PARTS = 'wp_template_part';
export const USER_PATTERNS = 'wp_block';
export const USER_PATTERN_CATEGORY = 'my-patterns';
Expand Down
Loading
Loading