-
Notifications
You must be signed in to change notification settings - Fork 10.8k
[Expreimental] Show preview taxonomy filter options in hierarchy order #60144
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
Changes from all commits
17df88c
ce6aa0c
f9bfc92
d0b5dad
44b81c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: patch | ||
Type: tweak | ||
|
||
Experimental: Show preview taxonomy filter options in hierarchy order. |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -28,6 +28,56 @@ import { Notice } from '../../components/notice'; | |||||||||||||||||||||
import { getTaxonomyLabel } from './utils'; | ||||||||||||||||||||||
import { sortFilterOptions } from '../../utils/sort-filter-options'; | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Create hierarchical structure: parents followed by their children | ||||||||||||||||||||||
function createHierarchicalList( | ||||||||||||||||||||||
terms: FilterOptionItem[], | ||||||||||||||||||||||
sortOrder: string | ||||||||||||||||||||||
) { | ||||||||||||||||||||||
const children = new Map(); | ||||||||||||||||||||||
|
||||||||||||||||||||||
// First: categorize terms | ||||||||||||||||||||||
terms.forEach( ( term ) => { | ||||||||||||||||||||||
if ( ! children.has( term.parent ) ) { | ||||||||||||||||||||||
children.set( term.parent, [] ); | ||||||||||||||||||||||
} | ||||||||||||||||||||||
children.get( term.parent ).push( term ); | ||||||||||||||||||||||
} ); | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Next: sort them | ||||||||||||||||||||||
children.keys().forEach( ( key ) => { | ||||||||||||||||||||||
children.set( | ||||||||||||||||||||||
key, | ||||||||||||||||||||||
sortFilterOptions( children.get( key ), sortOrder ) | ||||||||||||||||||||||
); | ||||||||||||||||||||||
} ); | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Last: build hierarchical list | ||||||||||||||||||||||
const result: FilterOptionItem[] = []; | ||||||||||||||||||||||
function addTermsRecursively( | ||||||||||||||||||||||
termList: FilterOptionItem[], | ||||||||||||||||||||||
depth = 0, | ||||||||||||||||||||||
visited = new Set< number >() | ||||||||||||||||||||||
) { | ||||||||||||||||||||||
if ( depth > 10 ) { | ||||||||||||||||||||||
return; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
termList.forEach( ( term ) => { | ||||||||||||||||||||||
if ( ! term.id || visited.has( term.id ) ) { | ||||||||||||||||||||||
return; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
visited.add( term.id ); | ||||||||||||||||||||||
result.push( { ...term, depth } ); | ||||||||||||||||||||||
const termChildren = children.get( term.id ) || []; | ||||||||||||||||||||||
if ( termChildren.length > 0 ) { | ||||||||||||||||||||||
addTermsRecursively( termChildren, depth + 1, visited ); | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} ); | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
addTermsRecursively( children.get( 0 ) ); | ||||||||||||||||||||||
return result; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
const Edit = ( props: EditProps ) => { | ||||||||||||||||||||||
const { attributes: blockAttributes } = props; | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
@@ -58,23 +108,21 @@ const Edit = ( props: EditProps ) => { | |||||||||||||||||||||
|
||||||||||||||||||||||
const { getEntityRecords, hasFinishedResolution } = | ||||||||||||||||||||||
select( coreStore ); | ||||||||||||||||||||||
const selectorArgs = [ | ||||||||||||||||||||||
'taxonomy', | ||||||||||||||||||||||
taxonomy, | ||||||||||||||||||||||
{ | ||||||||||||||||||||||
per_page: 15, | ||||||||||||||||||||||
hide_empty: hideEmpty, | ||||||||||||||||||||||
orderby: 'name', | ||||||||||||||||||||||
order: 'asc', | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
]; | ||||||||||||||||||||||
|
||||||||||||||||||||||
const selectArgs = { | ||||||||||||||||||||||
per_page: 15, | ||||||||||||||||||||||
hide_empty: hideEmpty, | ||||||||||||||||||||||
orderby: 'name', | ||||||||||||||||||||||
order: 'asc', | ||||||||||||||||||||||
}; | ||||||||||||||||||||||
return { | ||||||||||||||||||||||
taxonomyTerms: getEntityRecords( ...selectorArgs ) || [], | ||||||||||||||||||||||
isTermsLoading: ! hasFinishedResolution( | ||||||||||||||||||||||
'getEntityRecords', | ||||||||||||||||||||||
selectorArgs | ||||||||||||||||||||||
), | ||||||||||||||||||||||
taxonomyTerms: | ||||||||||||||||||||||
getEntityRecords( 'taxonomy', taxonomy, selectArgs ) || [], | ||||||||||||||||||||||
isTermsLoading: ! hasFinishedResolution( 'getEntityRecords', [ | ||||||||||||||||||||||
'taxonomy', | ||||||||||||||||||||||
taxonomy, | ||||||||||||||||||||||
selectArgs, | ||||||||||||||||||||||
] ), | ||||||||||||||||||||||
}; | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
[ taxonomy, hideEmpty, isPreview ] | ||||||||||||||||||||||
|
@@ -132,15 +180,21 @@ const Edit = ( props: EditProps ) => { | |||||||||||||||||||||
value: term.slug, | ||||||||||||||||||||||
selected: false, | ||||||||||||||||||||||
count, | ||||||||||||||||||||||
id: term.id, | ||||||||||||||||||||||
parent: term.parent || 0, | ||||||||||||||||||||||
Comment on lines
+183
to
+184
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation for hierarchy properties. The code assumes Apply this diff to add proper validation: acc.push( {
label: term.name,
value: term.slug,
selected: false,
count,
- id: term.id,
- parent: term.parent || 0,
+ id: typeof term.id === 'number' ? term.id : 0,
+ parent: typeof term.parent === 'number' ? term.parent : 0,
} ); 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The input of function is built internally, not from users. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dinhtungdu Thank you for the clarification! You're absolutely right - since the taxonomy terms come from WordPress core data APIs via I appreciate you explaining the context about internal vs external data sources. This makes sense given that WooCommerce can trust the data integrity from WordPress core APIs. ✏️ Learnings added
🧠 Learnings used
|
||||||||||||||||||||||
} ); | ||||||||||||||||||||||
|
||||||||||||||||||||||
return acc; | ||||||||||||||||||||||
}, | ||||||||||||||||||||||
[] | ||||||||||||||||||||||
); | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Sort the processed terms | ||||||||||||||||||||||
setTermOptions( sortFilterOptions( processedTerms, sortOrder ) ); | ||||||||||||||||||||||
// Create hierarchical structure then apply sorting | ||||||||||||||||||||||
const hierarchicalTerms = createHierarchicalList( | ||||||||||||||||||||||
processedTerms, | ||||||||||||||||||||||
sortOrder | ||||||||||||||||||||||
); | ||||||||||||||||||||||
setTermOptions( hierarchicalTerms ); | ||||||||||||||||||||||
setIsOptionsLoading( false ); | ||||||||||||||||||||||
}, [ | ||||||||||||||||||||||
taxonomy, | ||||||||||||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.