feat(tools): Angular Tools portlet (Beta) with dialogs, drag-drop and mocked backend - #37481
Draft
AP2300 wants to merge 7 commits into
Draft
feat(tools): Angular Tools portlet (Beta) with dialogs, drag-drop and mocked backend#37481AP2300 wants to merge 7 commits into
AP2300 wants to merge 7 commits into
Conversation
Adds the three pieces the beta pattern needs so the Angular Tools portlet becomes reachable through Add Portlet: portlet.xml entry, Language.properties title, and the SerializationHelperTest assertion. Mirrors the users-beta and roles-beta registrations. No PortletID enum entry yet — that lands with #37353 when the write endpoints gate on requiredPortlet("tools"). Refs #37354 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nd PrimeNG UI
Adds the Beta Tools portlet under Settings — a two-column master/detail where
an admin shapes the backend navigation by managing sections, choosing tools in
each one via checkbox, ordering both by drag, and creating custom content
tools.
Structure follows the dot-roles / dot-users convention (shell → page → store)
and the reference conventions in libs/portlets/CLAUDE.md.
Included:
* Sections panel with CDK drag reorder, hover-revealed overflow menu, and
inline nested tool list on the selected section
* Available Tools panel with search, p-checkbox rows, load-more pagination
(15 initial, +40 per click), and per-row overflow menu on custom tools
* Section dialog: name + curated Material Symbols icon picker
* Tool dialog: name + auto-slug id + base/content-type multi-select against
real DotContentTypeService + List/Card view mode toggle
* Drag polish via *cdkDragPreview / *cdkDragPlaceholder templates plus
arbitrary-variant Tailwind on drop lists (no scss, no ::ng-deep)
* Form submission: submit is always enabled, invalid submit lights up field
outlines and shows a warning icon + text opposite the submit button
* p-confirmDialog with count-driven delete copy for section and catalog-tool
scope
* DotToolsService with WAITING FOR BACKEND stubs mirroring the endpoint
contract in #37353; swap point is the service body only
* DotToolsStore signal store owning all client-side derivations (selection,
filter, pagination, delete-impact counts, optimistic reorder patches)
Route registered at /c/tools-beta with MenuGuardService gating, matching
users-beta and roles-beta.
Refs #37354
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extracts every hardcoded English string in the Tools portlet — labels, form
placeholders, error copy, delete-confirmation bodies, tooltip text — to
tools.* keys in Language.properties and wires them through DotMessagePipe
(templates) and DotMessageService.get() (dialog headers, menu items, confirm
copy).
Two-key pluralization for the delete-confirm counts ("1 tool assignment" vs
"N tool assignments") keeps grammar right without a plural library.
Also pulls the catalog pagination constants into the shared constants file so
the store's slice count, the load-more button label and the tests upcoming
next stay in agreement.
Refs #37354
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds view-state helpers on the store (showLoading, showError, showEmptySections) so the page template stays a plain reader and never inlines status checks. The left panel now renders four distinct states depending on the store: spinner while first-loading, error card with retry when the load failed, empty-state with a "New Section" call to action when the store settled with no sections, and the normal drag-sortable list otherwise. The right panel gets a "Select a section" empty state whenever no section is chosen and the store is not still loading or errored. Also fills in the accessibility gaps flagged by the portlets CLAUDE.md: aria-labels on the section/tool overflow menu triggers, the "remove from section" button and both drag handles. Icon-only p-buttons use PrimeNG's [ariaLabel] input; the drag-handle spans use [attr.aria-label]. All new strings are i18n keys under tools.* — no hardcoded English added. Refs #37354 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tions, forms DotToolsStore: 23 tests, 96% coverage. Every computed (filter, pagination, selectedSectionToolIds, toolSectionCount, showLoading / showError / showEmptySections), every mutation (create/update/delete for sections and custom tools, toggle/remove/reorder for tools inside a section), and the error paths that revert the store to `loaded` on a mutation failure. DotToolsSectionDialogComponent: 5 tests covering create and edit modes — initial state, submit warning + field error on invalid submit, close with form value on valid submit, prefill from incoming section. DotToolsToolDialogComponent: 7 tests across three describe blocks — create mode (content-type loading, auto-slug id, submit flow), edit mode with explicit prefill (all fields), edit mode without prefill (catalog fallback for name and id, matching the interim UX until the GET /v1/portlet/custom/ endpoint lands per #37353). Refs #37354 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AP2300
force-pushed
the
issue-37354-tools-portlet-modernization
branch
from
September 9, 2026 19:30
acdbacc to
726c37c
Compare
15 tasks
Previous placeholder / preview were indigo-branded with dashed borders and
shadow-xl, which felt heavier than the rest of the portlet and off-key
against the design's minimal slate palette. Three moves:
* Placeholder is now a faded ghost of the row itself (same layout, same
content, opacity 40%, slate-100 tint) so the eye tracks where the item
will land instead of a highlighted callout.
* Preview mirrors the row's own styling with a soft lift — slate-200
border, slate text, shadow-lg — no indigo tint, no rotation, no
scale-up. "The same row, lifted" instead of a distinct card.
* Drop list gets a subtle slate-100 tint via the .cdk-drop-list-dragging
class while a drag is in progress, so the active target reads without
being noisy. Uses a transition-colors so the tint fades in/out cleanly.
Same slate treatment applied to the nested tool list. All Tailwind, no scss.
Refs #37354
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rewires the DnD interaction so it matches the design's intent instead of
CDK's default sort-live-during-drag behavior:
* cdkDropListSortingDisabled on both drop lists. The original row stays
visible in place (rendered by the placeholder template at opacity 40)
and siblings do not shift while dragging.
* A 2px indigo drop-line renders in the gap the pointer is closest to,
driven by $sectionDropIndex / $toolDropIndex signals updated on every
cdkDragMoved. The trailing gap (after the last row) is supported too.
* The preview is a translucent copy of the row (opacity 70, subtle
shadow) — no borders, no branding, "the same row, lifted".
* onSectionDragEnded / onToolDragEnded use the tracked drop index rather
than CdkDragDrop.currentIndex (which is unreliable when sorting is
disabled), normalizing the gap index for insertion via a small helper
that accounts for the source being removed first.
Row and placeholder both carry a data-row attribute so the pointer-position
computation always sees N slots regardless of which one is the source
(placeholder replaces the source li at drag start, keeping its slot).
Refs #37354
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.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.
Summary
Builds the Tools Beta portlet under Settings — a two-column master/detail where an admin shapes the backend navigation by managing sections, choosing tools in each one via checkbox, ordering both by drag, and creating custom content tools. Ships as a route (
/#/c/tools-beta) withMenuGuardServicegating, opt-in through Add Portlet.Everything on the frontend is done and rendering against mocked service methods that mirror the endpoint contract pinned in #37353. When those endpoints land, the swap is a service body edit — no changes to the store, dialogs, drag-and-drop, confirmations, or models.
Draft because the backend wiring for the real write path (endpoints,
PortletID.TOOLSgate) is in-flight on #37353 and open questions remain in the spike #37352. Reachable via Add Portlet as of this PR.Commits
feat(tools): register tools-beta backend portlet—portlet.xmlentry +Language.propertiestitle +SerializationHelperTestassertion, mirroringusers-beta/roles-beta.feat(tools): scaffold Angular Tools portlet with dialogs, drag-drop and PrimeNG UI—libs/portlets/dot-tools/(shell → page → store), section dialog, tool dialog, CDK drag with custom preview/placeholder templates,p-confirmDialogwith count-driven copy,DotToolsServicewith WAITING FOR BACKEND stubs.i18n(tools): move every user-facing string to Language.properties— ~50tools.*keys wired throughDotMessagePipeandDotMessageService.feat(tools): loading, empty, error and no-selection states + aria labels—showLoading,showError,showEmptySectionscomputeds on the store; four distinct left-panel states plus right-panel "select a section"; aria labels on every icon-only button and drag handle.test(tools): store + dialog specs — 35 tests covering computeds, mutations, forms— store 96%, dialogs 93–100%.Backend blockers (not in this PR)
Every mock in
DotToolsServicemaps 1:1 to an endpoint in #37353. Swap point is the service body only.getSectionsGET /v1/layoutsgetCatalogGET /v1/portletcreateSection/updateSection/deleteSection/reorderSectionsPOST/PUT/DELETE/PUT _reorderunder/v1/layoutssetSectionToolsPUT /v1/layouts/{id}/portletscreateCustomTool/updateCustomToolPOST/PUT /v1/portlet/customdeleteCustomToolTwo additive requests posted on #37353:
isCustom: booleanonGET /v1/portletrows (already consumed by the client to gate the row menu on the Available Tools panel).GET /v1/portlet/custom/{portletId}for tool-edit prefill (component already accepts aprefill; today it falls back totool.title/tool.idfrom the catalog).Test plan
/#/c/tools-beta, confirm the two-column layout renders.tools.*key — swapLanguage.propertiesto a translated version and confirm nothing hardcodes.Related
Refs #37354
🤖 Generated with Claude Code