[6.x] Hierarchical Taxonomies - #15192
Open
jackmcdade wants to merge 28 commits into
Open
Conversation
Opt-in trees live beside collection/nav trees, with parent/child/ancestor accessors on terms and a listener that keeps the tree in sync when terms are saved or deleted. Co-authored-by: Cursor <cursoragent@cursor.com>
Reuse the collection page tree so terms can be nested, reordered, and created as children, with max depth and a reorder permission. Co-authored-by: Cursor <cursoragent@cursor.com>
Tree position drives URIs (with a 301 from the old flat path), and taxonomy/collection tags can filter by parent, depth, and descendant terms. Co-authored-by: Cursor <cursoragent@cursor.com>
Indent options by depth, search by path, create missing segments from a typed path, and show ancestor hints on selected items. Co-authored-by: Cursor <cursoragent@cursor.com>
Add a tree endpoint plus parent/children/ancestors/depth on terms so frontends can walk the hierarchy without the CP. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…-scoped twins. Co-authored-by: Cursor <cursoragent@cursor.com>
Make it obvious you can search or type a path, preview the hierarchy as badges in the create option, and drop the redundant parent hint once items are indented. Co-authored-by: Cursor <cursoragent@cursor.com>
A parent typed in the same path was not in the tree yet, so the child never grafted and both terms appeared at the root. Co-authored-by: Cursor <cursoragent@cursor.com>
Association indexes created stub keys for sites the taxonomy doesn't use, so Term::find() returned a title-from-slug stub that overwrote the real file on reload. Co-authored-by: Cursor <cursoragent@cursor.com>
The tree previously always promoted child terms into the deleted parent's place, with no way to remove the whole branch. Co-authored-by: Cursor <cursoragent@cursor.com>
…he tree. Co-authored-by: Cursor <cursoragent@cursor.com>
…ions. Co-authored-by: Cursor <cursoragent@cursor.com>
…m ones. Co-authored-by: Cursor <cursoragent@cursor.com>
…ing with reorder permission. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…rees. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…follow tree order. Co-authored-by: Cursor <cursoragent@cursor.com>
… collections. Co-authored-by: Cursor <cursoragent@cursor.com>
…te URLs follow the selected site. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
… branch. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…when structured. Co-authored-by: Cursor <cursoragent@cursor.com>
…reparent from the publish form. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(I know, finally)
Taxonomies can now be hierarchical, using the same structure/tree model as collections.
Enable it on a taxonomy, drag terms into a tree, and you get nested URLs, parent/children/ancestors/depth in tags, a CP tree view, and a parent relationship field on the publish form. Max depth 1 stays a flat reorderable list, same as collections.
See it in action – https://screen.studio/share/IeuqzNy2
A few constraints worth knowing:
expectsRoot. Terms don't have a collection-style root page.Templating
Tree, same as nav/collection structures. Recursive children work the usual way.
nav:taxonomy:…is an alias.{{ structure:taxonomy:categories }} {{ title }} {{ if children }}{{ *recursive children* }}{{ /if }} {{ /structure:taxonomy:categories }} {{ structure for="taxonomy::categories" from="animals" max_depth="2" }} {{ title }} (depth {{ depth }}) {{ /structure }}On a term, the tree is just variables:
{{ parent:title }} {{ depth }} {{ children }}{{ title }}{{ /children }} {{ ancestors }}{{ title }}{{ /ancestors }}List terms by branch with
{{ taxonomy }}.parentwithoutdepthis direct children; adddepthto go further.depthalone is top N levels of the whole tree.{{ taxonomy from="categories" parent="animals" }} {{ title }} {{ /taxonomy }} {{ taxonomy from="categories" parent="animals" depth="2" }} {{ title }} {{ /taxonomy }} {{ taxonomy from="categories" depth="1" }} {{ title }} {{ /taxonomy }}Entry listings include the whole branch by default. Opt out with
with_descendants="false".{{ collection:blog taxonomy:categories="animals" }} {{ title }} {{ /collection:blog }} {{ collection:blog taxonomy:categories="animals" with_descendants="false" }} {{ title }} {{ /collection:blog }}Still needed
statamic/eloquent-drivergrows taxonomy trees.with_descendants, the parent field, and the "typed paths don't re-parent" rule.Test plan
{{ structure:taxonomy:… }}and collection/entry filters include descendants by defaultIssues
Closes statamic/ideas#92, statamic/ideas#264, statamic/ideas#1053, and #2334.
Related: #74, statamic/ideas#839, statamic/ideas#580.