feat(part-page): show a part's ancestors in the breadcrumb - #719
ashleycaselli wants to merge 2 commits into
Conversation
A part page's breadcrumb now shows the parts above it, top-down, between the context resource and the part itself: a paragraph reached from a topic reads Docs > Person > Approval, and one reached from that paragraph reads Docs > Person > Approval > Rounds. The chain starts at the part the page was reached from (the incoming part parameter), or, without one, at the first resource the part's defining nanopublication declares it to be about or part of (schema:about in either spelling, or dct:isPartOf) that is itself a part of the context. It then follows each part's own declared parent upwards, stopping when a part declares none, a part would repeat, or five ancestors are shown. A part whose definition declares no parent in the context sits at the top level, like a documentation topic, and gets no ancestors even when reached from another part, so Trust and approval opened from a paragraph reads Docs > Trust and approval. A part without a known definition keeps the part it was reached from. The rdfs:label / schema:title lookup for the page title moves into a helper shared with the ancestor crumbs. Closes #718 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
I think we should show this always according to the defined hierarchy, so and never like this: And the defined hierarchy should probably use dct:isPartOf, which we currently don't use properly for the Docs. So this would involve changing the Docs definition as well as the behavior of this here. Ideally parts of parts of parts should show too, and arbitrarily deep into the hierarchy. Not sure to what extent this is possible (might not be a proper tree...). |
Review of #718: a part page should read the same wherever it was opened from, so the breadcrumb now shows only the hierarchy the parts themselves declare. The incoming part parameter no longer starts the chain; Rounds reads Docs > Trust and approval > Rounds whether it is opened from the Approval paragraph or directly. That parameter keeps serving the back-link (#697). The hierarchy is dct:isPartOf: candidates are ordered with it first and schema:about only after, so parts that state it properly take precedence while those published before it keep their breadcrumb until they are republished. The chain already walked upwards; the cap is now 20 rather than 5, so parts of parts of parts are shown as deep as they go. The cycle guard stays, since parts of parts need not form a tree: a part that would repeat ends the chain. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Done in a0ac17c — the breadcrumb now shows only the declared hierarchy.
Tests (15, full suite 1426 passing) cover your example explicitly — opening Rounds from Approval gives the same crumbs as opening it directly — plus a three-level chain ( On the data side: the Docs paragraphs currently declare |
Closes #718.
What changes
A part page's breadcrumb now shows the parts above it, top-down, between the context resource and the part itself.
How the ancestors are found
part(set byNavigationContext.withPartonly together with its own context, so it is trusted as the back-link already trusts it). Without one, it starts at the declared parent.schema:about(either spelling) ordct:isPartOfobject thatViewDataFetcher.partDefinitionQueryRefresolves as a part of the same context. It stops when a part declares none, when a part would repeat, or afterMAX_ANCESTORS(5).A part without a known definition cannot tell its level, so it keeps the part it was reached from. Each crumb links to the ancestor's part page under the same context; labels come from
part-label, else the ancestor'srdfs:label, else itsschema:title, else its short name.The label lookup the page title already did (
rdfs:label, elseschema:title, #701) moves intogetDeclaredLabel, shared with the crumbs; the title behaves as before.Cost
One cached part-definition lookup per ancestor crumb, synchronous in the constructor like the page's own definition lookup.
Tests
ResourcePartPageParentTest(17 tests): the chain logic takes the part-definition lookup as a function, so it is tested without the network. Covers the Rounds and Trust and approval cases above, the fallback without an incoming part, parents that are not parts of the context, cycles, the depth limit, label fallbacks, and the candidate predicates.🤖 Generated with Claude Code