fix(dot-roles): UI feedback round 2 — dialog buttons, node icons, submit errors, parent picker - #37334
Conversation
… spacing Give the role detail tablist a surface-50 background with a bottom border so the tab strip reads as a distinct band against the panel. Space the Grant to User row consistently: the column's gap-4 only spaces siblings, so with no cannot-grant banner the row sat flush against the tab strip. first:pt-4 stands in for the missing gap and switches off once the banner renders, leaving 1rem above the button either way. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @hmoreras's task in 2m 29s —— View job Code Review
Reviewed both commits ( New Issues
Everything else checks out:
No blocking issues. • |
…mit errors Four adjustments from the design review of the Roles & Tools Beta portlet. Cancel buttons The three confirm dialogs already agreed on a text-styled reject; the two form dialogs used `[outlined]`. Add and Edit now use `[text]` too, so every Cancel in the portlet matches the one in Remove User. Node icons Design dropped the folder-vs-shield_person distinction, so the icon is gone from both places that drew it: the tree node label and the detail header. That made `DotRolesStore.selectedRoleIsParent` dead — its only consumer was the header's `$icon` computed, as its docstring admitted — along with the `@let isLeaf` in the tree template and three specs that mocked or exercised it. The header skeleton's circle went too: it existed to mirror an icon that no longer renders. `node.leaf` is untouched; it feeds PrimeNG's chevron, not the icon. Delete Role Drops `severity="danger"`. The confirm dialog it opens was already carrying a comment that it uses primary styling per UX guidance "even though the action is destructive" — the trigger button was the only red left. Submit errors Save is no longer disabled by validation in either dialog. An invalid submit now calls `markAllAsTouched()` and names the problem in the footer, left of the buttons — to the right of Delete in the Edit dialog, per design. A disabled Save gave the admin nothing to act on, which is what the review flagged. `readOnly` still disables Save in Edit: that is a permission gate, not a validation one, and keeps its own tooltip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…option
Design asked for an explicit root entry at the top of the parent dropdown in
both the Add and Edit dialogs, selected by default.
The entry is prepended in each component's `$parentTree` computed rather than
inside `#toTreeNodes`, so it survives the paths that rebuild the tree: the
server search replaces the whole list, and the Edit dialog strips the edited
role and its descendants to prevent cycles. "None (Top Level)" is a choice,
not a candidate, so neither should touch it.
Its key is a sentinel, `__root__`, and `toParentRoleId` in the shared models
is what keeps it out of the API. Both `onSave` paths went through it: the old
`parent?.key ?? null` would have sent the sentinel as a real parent id and
been answered with a 404 "parent role not found". Tests in both dialogs pin
that mapping.
Selected by default, but only where there is nothing else to show. Add
defaults to it when opened from `New`, and leaves the parent alone when the
row's `+` prefilled one — clobbering it would silently create a root role
instead of the child that was asked for. Edit defaults to it when the role is
already a root, and keeps the current parent otherwise. Save behaviour is
unchanged either way: an empty picker and the root entry both mean
`parentRoleId: null`. The field now states that instead of leaving it to be
inferred from a blank.
The placeholder moves to its own key, `roles.form.parent.placeholder`
("Select a parent"), freeing `roles.form.parent.root` to label the option and
picking up design's capitalisation. `showClear` stays for now, though the
default makes it redundant — clearing changes the display and not the outcome.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Part of #36930.
Proposed Changes
UI feedback round 2 on the Roles & Tools Beta portlet.
p-tablistwas visually flush with the panel below it, so the tabs read as floating over the content instead of heading it. Addsborder-b border-gray-200 bg-surface-50!.first:pt-4, so the padding applies only when the row is the first child (the inherited-users notice above it is conditional) and no double gap appears when it is not.[outlined]. Add and Edit now use[text]too, so every Cancel in the portlet matches the one in the Remove User dialog.shield_persondistinction, so the icon is gone from both places that drew it: the tree node label and the detail header.severity="danger". The confirm dialog it opens already carried a comment that it uses primary styling per UX guidance "even though the action is destructive"; the trigger button was the only red left.markAllAsTouched()and names the problem in the footer instead of leaving a dead button with nothing to act on. The message sits left of the buttons, and to the right of Delete in the Edit dialog.Checklist
Additional Info
Parent picker — where the entry is added, and why it matters. It is prepended in each component's
$parentTreecomputed rather than inside#toTreeNodes, so it survives the two paths that rebuild the tree: the server search replaces the whole list, and the Edit dialog strips the edited role and its descendants to prevent cycles. It is a choice, not a candidate, so neither should touch it.The sentinel must not reach the API. The entry's key is
__root__, andtoParentRoleIdin the shared models maps it — and an empty picker — back tonull. BothonSavepaths went through it: the previousparent?.key ?? nullwould have sent the sentinel as a real parent id and been answered with a 404 "parent role not found". There is a test pinning that mapping in each dialog.Default only where there is nothing else to show. Add defaults to the root entry when opened from
New, and leaves the parent alone when the row's+prefilled one — clobbering it would silently create a root role instead of the child that was asked for, which has its own regression test. Edit defaults to it when the role is already a root, and keeps the current parent otherwise. Save behaviour is unchanged in every case: an empty picker and the root entry both meanparentRoleId: null.Dead code removed with the icons.
DotRolesStore.selectedRoleIsParentexisted only to feed the header's$iconcomputed — its docstring said as much ("folder icon in the header") — so it went, along with the@let isLeafin the tree template and three specs that mocked or exercised it. The header skeleton'sshape="circle"placeholder went too: it existed to mirror an icon that no longer renders.node.leafis deliberately untouched. It drives PrimeNG's chevron-vs-leaf rendering and thechildCountlogic that has its own specs — it never fed the icon.Save button scope.
readOnlystill disables Save in the Edit dialog. That is a permission gate for system/locked roles, not a validation one, and it keeps its explanatory tooltip. Only theform.invalidcondition was removed.Open question, not addressed here. With the root entry selected by default,
[showClear]changes what the field displays but not what is saved — clearing and picking "None (Top Level)" are the same outcome. It is left in place; removing it (and the now barely-reachableroles.form.parent.placeholder) is a one-line follow-up if design wants a single route to root.Translations. Two new keys —
roles.form.error.requiredandroles.form.parent.placeholder— plus a text change toroles.form.parent.root("None (top level)" → "None (Top Level)") so it can label the option.Screenshots
This PR fixes: #36930