Admin Menu Id's #19731
JesseRigon
started this conversation in
Ideas
Admin Menu Id's
#19731
Replies: 1 comment 3 replies
|
Wow, this is elaborate :).
Also:
You can affect that, though, with the |
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Admin menu nodes have a stable
UniqueIdthat never reachesMenuItem.IdI'm building a Blazor admin on Orchard Core, so I consume the admin menu outside Razor and persist per-item state against it: layout overrides, icon overrides, ordering. That needs a stable per-item key, and I can get one for provider items but not for Admin Menu nodes.
Provider items: the caption literal works as a key
S["Configuration"]produces aLocalizedStringwith two halves.Text.Nameis the literal from the source,Text.Valueis the translation for the request.NavigationItemBuilder.Caption()assigns the whole object ontoMenuItem.Text, so both halves survive onto the built item, andMergematches onText.Name.That makes
Text.Namea culture-invariant key I can read straight off the menu item. It moves if a developer rewords the literal, but that's avoidable: ship anentranslation keyed on the literal and the displayed caption changes while the key stays put. English isn't special toIStringLocalizer. So the literal becomes a stable key that happens to read like English.Admin Menu nodes: no key to read
The node builders construct the caption differently:
Both halves are the same value, the string the admin typed. These items are localized, but through
IDataLocalizerat render time inTheAdmin/Views/NavigationItemText.cshtml, usingTextitself as the lookup key:DataLocalizerworks likeIStringLocalizer: resolve against the current culture, fall back to the key. So the sameentrick applies for display. What it doesn't do is leave a key on the item. For provider items the key/translation split lives in the object; here it lives only in the translation store, and the built item carries one raw string. FreezingLinkTextby convention doesn't help me, because I still can't tell which built item that frozen string belongs to.The identifier already exists
Assigned at creation, persisted with the node, unaffected by renames.
NodeControlleralready edits nodes by it.AdminNodederives fromMenuItem, which has anId.But none of the four builders (
LinkAdminNode,PlaceholderAdminNode,ContentTypesAdminNode,ListsAdminNode) callitemBuilder.Id(...). They copyMenuName,Url,Target,Priority,Position, permissions and icon classes;UniqueIdisn't among them. SinceAddAsyncconstructs a freshMenuItemrather than carrying theAdminNodethrough,MenuItem.Idends up null.Why I can't bridge it myself
MenuItemis a new instance, so I can't cast it back toAdminNode.IAdminNodeNavigationBuilderunder a stockNamedepends on module load order.IAdminMenuServiceand see everyUniqueId, but then I have to work out which built item came from which node.Merge,AuthorizeAsyncandReducerun after the builders, so what comes back is a filtered, merged version of the node tree. Matching on caption is what started with, doesn't work on translations obviously, and matching structurally is guess work.Proposal
One line in each of the four builders:
For
ContentTypesAdminNodeandListsAdminNode, which expand one node into many items, qualified per item ($"{node.UniqueId}-{ctd.Name}").MenuItem.Idis null for these items today and nothing reads it.Mergematches onText.Namewhether or notIdis set, so merging is unchanged. The one visible effect is aNavigationItemText_Id__{UniqueId}shape alternate that no template defines, so rendering falls through as it does now.Questions
UniqueIdnot reachingMenuItem.Iddeliberate, or just something nobody has needed?All reactions