Skip to content

Commit

Permalink
Fix template part selection searches to use title/area instead of slu…
Browse files Browse the repository at this point in the history
…g/theme. (#31520)

* updated base results

* update search results

* add comment

* add default value for area prop

* Update packages/block-library/src/template-part/edit/selection/template-part-previews.js

Co-authored-by: Dávid Szabó <[email protected]>

* show all variations by default for general/uncategorized case

Co-authored-by: Dávid Szabó <[email protected]>
  • Loading branch information
Addison-Stavlo and david-szabo97 authored May 11, 2021
1 parent 896ed84 commit cb9fd48
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 62 deletions.
17 changes: 12 additions & 5 deletions packages/block-library/src/template-part/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ export default function TemplatePartEdit( {
// Set the postId block attribute if it did not exist,
// but wait until the inner blocks have loaded to allow
// new edits to trigger this.
const { isResolved, innerBlocks, isMissing, defaultWrapper } = useSelect(
const {
isResolved,
innerBlocks,
isMissing,
defaultWrapper,
area,
} = useSelect(
( select ) => {
const { getEditedEntityRecord, hasFinishedResolution } = select(
coreStore
Expand All @@ -57,6 +63,8 @@ export default function TemplatePartEdit( {
const entityRecord = templatePartId
? getEditedEntityRecord( ...getEntityArgs )
: null;
const _area = entityRecord?.area || attributes.area;

const hasResolvedEntity = templatePartId
? hasFinishedResolution(
'getEditedEntityRecord',
Expand All @@ -66,16 +74,14 @@ export default function TemplatePartEdit( {

const defaultWrapperElement = select( editorStore )
.__experimentalGetDefaultTemplatePartAreas()
.find(
( { area } ) =>
area === ( entityRecord?.area || attributes.area )
)?.area_tag;
.find( ( { area: value } ) => value === _area )?.area_tag;

return {
innerBlocks: getBlocks( clientId ),
isResolved: hasResolvedEntity,
isMissing: hasResolvedEntity && ! entityRecord,
defaultWrapper: defaultWrapperElement || 'div',
area: _area,
};
},
[ templatePartId, clientId ]
Expand Down Expand Up @@ -157,6 +163,7 @@ export default function TemplatePartEdit( {
<TemplatePartSelection
setAttributes={ setAttributes }
onClose={ onClose }
area={ area }
/>
) }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export default function TemplatePartPlaceholder( {
<TemplatePartSelection
setAttributes={ setAttributes }
onClose={ onClose }
area={ area }
/>
) }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ const stopKeyPropagation = ( event ) => event.stopPropagation();
// Disable reason (no-static-element-interactions): Navigational key-presses within
// the menu are prevented from triggering WritingFlow and ObserveTyping interactions.
/* eslint-disable jsx-a11y/no-static-element-interactions */
export default function TemplatePartSelection( { setAttributes, onClose } ) {
export default function TemplatePartSelection( {
setAttributes,
onClose,
area,
} ) {
const [ filterValue, setFilterValue ] = useState( '' );
return (
<div
Expand All @@ -39,6 +43,7 @@ export default function TemplatePartSelection( { setAttributes, onClose } ) {
setAttributes={ setAttributes }
filterValue={ filterValue }
onClose={ onClose }
area={ area }
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import { useAsyncList } from '@wordpress/compose';
import { store as noticesStore } from '@wordpress/notices';
import { store as coreStore } from '@wordpress/core-data';
import { store as editorStore } from '@wordpress/editor';

function PreviewPlaceholder() {
return (
Expand Down Expand Up @@ -102,34 +103,48 @@ function PanelGroup( { title, icon, children } ) {
);
}

function TemplatePartsByTheme( {
function TemplatePartsByArea( {
templateParts,
setAttributes,
onClose,
composite,
area = 'uncategorized',
labelsByArea,
} ) {
const templatePartsByTheme = useMemo( () => {
return Object.values( groupBy( templateParts, 'theme' ) );
}, [ templateParts ] );
const templatePartsByArea = useMemo( () => {
return Object.values( groupBy( templateParts, 'area' ) );
}, [ templateParts, area ] );
const currentShownTPs = useAsyncList( templateParts );

return templatePartsByTheme.map( ( templatePartList ) => (
<PanelGroup key={ templatePartList[ 0 ].theme }>
{ templatePartList.map( ( templatePart ) => {
return currentShownTPs.includes( templatePart ) ? (
<TemplatePartItem
key={ templatePart.id }
templatePart={ templatePart }
setAttributes={ setAttributes }
onClose={ onClose }
composite={ composite }
/>
) : (
<PreviewPlaceholder key={ templatePart.id } />
);
} ) }
</PanelGroup>
) );
return templatePartsByArea.map( ( templatePartList ) => {
// Only return corresponding area if block/entity is not uncategorized/general version.
if ( 'uncategorized' !== area && templatePartList[ 0 ].area !== area ) {
return null;
}
return (
<PanelGroup
key={ templatePartList[ 0 ].area }
title={
labelsByArea[ templatePartList[ 0 ].area ] ||
__( 'General' )
}
>
{ templatePartList.map( ( templatePart ) => {
return currentShownTPs.includes( templatePart ) ? (
<TemplatePartItem
key={ templatePart.id }
templatePart={ templatePart }
setAttributes={ setAttributes }
onClose={ onClose }
composite={ composite }
/>
) : (
<PreviewPlaceholder key={ templatePart.id } />
);
} ) }
</PanelGroup>
);
} );
}

function TemplatePartSearchResults( {
Expand All @@ -138,62 +153,89 @@ function TemplatePartSearchResults( {
filterValue,
onClose,
composite,
labelsByArea,
} ) {
const filteredTPs = useMemo( () => {
const { filteredTPs, groupedResults } = useMemo( () => {
// Filter based on value.
// Remove diacritics and convert to lowercase to normalize.
const normalizedFilterValue = deburr( filterValue ).toLowerCase();
const searchResults = templateParts.filter(
( { slug, theme } ) =>
slug.toLowerCase().includes( normalizedFilterValue ) ||
( { title: { rendered: title }, area } ) =>
deburr( title )
.toLowerCase()
.includes( normalizedFilterValue ) ||
// Since diacritics can be used in theme names, remove them for the comparison.
deburr( theme ).toLowerCase().includes( normalizedFilterValue )
deburr( labelsByArea[ area ] )
.toLowerCase()
.includes( normalizedFilterValue )
);
// Order based on value location.
searchResults.sort( ( a, b ) => {
// First prioritize index found in slug.
const indexInSlugA = a.slug
// First prioritize index found in title.
// Deburr for diacritics.
const indexInTitleA = deburr( a.title.rendered )
.toLowerCase()
.indexOf( normalizedFilterValue );
const indexInSlugB = b.slug
const indexInTitleB = deburr( b.title.rendered )
.toLowerCase()
.indexOf( normalizedFilterValue );
if ( indexInSlugA !== -1 && indexInSlugB !== -1 ) {
return indexInSlugA - indexInSlugB;
} else if ( indexInSlugA !== -1 ) {
if ( indexInTitleA !== -1 && indexInTitleB !== -1 ) {
return indexInTitleA - indexInTitleB;
} else if ( indexInTitleA !== -1 ) {
return -1;
} else if ( indexInSlugB !== -1 ) {
} else if ( indexInTitleB !== -1 ) {
return 1;
}
// Second prioritize index found in theme.
// Since diacritics can be used in theme names, remove them for the comparison.
// Second prioritize index found in area.
return (
deburr( a.theme )
deburr( labelsByArea[ a.area ] )
.toLowerCase()
.indexOf( normalizedFilterValue ) -
deburr( b.theme ).toLowerCase().indexOf( normalizedFilterValue )
deburr( labelsByArea[ b.area ] )
.toLowerCase()
.indexOf( normalizedFilterValue )
);
} );
return searchResults;
// Group filtered results together if their neighbors share the same area.
// This helps not show redundant panel groups side by side in the results.
const _groupedResults = [];
for ( let i = 0; i < searchResults.length; i++ ) {
if (
i !== 0 &&
searchResults[ i ].area === searchResults[ i - 1 ].area
) {
_groupedResults[ _groupedResults.length - 1 ].push(
searchResults[ i ]
);
} else {
_groupedResults.push( [ searchResults[ i ] ] );
}
}
return {
filteredTPs: searchResults,
groupedResults: _groupedResults,
};
}, [ filterValue, templateParts ] );

const currentShownTPs = useAsyncList( filteredTPs );

return filteredTPs.map( ( templatePart ) => (
return groupedResults.map( ( group ) => (
<PanelGroup
key={ templatePart.id }
title={ templatePart.theme || __( 'Custom' ) }
key={ group[ 0 ].id }
title={ labelsByArea[ group[ 0 ].area ] || __( 'General' ) }
>
{ currentShownTPs.includes( templatePart ) ? (
<TemplatePartItem
key={ templatePart.id }
templatePart={ templatePart }
setAttributes={ setAttributes }
onClose={ onClose }
composite={ composite }
/>
) : (
<PreviewPlaceholder key={ templatePart.id } />
{ group.map( ( templatePart ) =>
currentShownTPs.includes( templatePart ) ? (
<TemplatePartItem
key={ templatePart.id }
templatePart={ templatePart }
setAttributes={ setAttributes }
onClose={ onClose }
composite={ composite }
/>
) : (
<PreviewPlaceholder key={ templatePart.id } />
)
) }
</PanelGroup>
) );
Expand All @@ -203,15 +245,32 @@ export default function TemplatePartPreviews( {
setAttributes,
filterValue,
onClose,
area,
} ) {
const composite = useCompositeState();
const templateParts = useSelect( ( select ) => {
return (

const { templateParts, labelsByArea } = useSelect( ( select ) => {
const _templateParts =
select( coreStore ).getEntityRecords(
'postType',
'wp_template_part'
) || []
);
'wp_template_part',
{
per_page: -1,
}
) || [];

const definedAreas = select(
editorStore
).__experimentalGetDefaultTemplatePartAreas();
const _labelsByArea = {};
definedAreas.forEach( ( item ) => {
_labelsByArea[ item.area ] = item.label;
} );

return {
templateParts: _templateParts,
labelsByArea: _labelsByArea,
};
}, [] );

if ( ! templateParts || ! templateParts.length ) {
Expand All @@ -231,6 +290,7 @@ export default function TemplatePartPreviews( {
filterValue={ filterValue }
onClose={ onClose }
composite={ composite }
labelsByArea={ labelsByArea }
/>
</Composite>
);
Expand All @@ -242,11 +302,13 @@ export default function TemplatePartPreviews( {
role="listbox"
aria-label={ __( 'List of template parts' ) }
>
<TemplatePartsByTheme
<TemplatePartsByArea
templateParts={ templateParts }
setAttributes={ setAttributes }
onClose={ onClose }
composite={ composite }
area={ area }
labelsByArea={ labelsByArea }
/>
</Composite>
);
Expand Down

0 comments on commit cb9fd48

Please sign in to comment.