[Task] Tools: Angular implementation + backend wiring
@hmoreras is already working on this.
Since Sep 2, 2026.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Goal
Build the Tools portlet in Angular and register it as an opt-in Beta: a two-column screen where an admin shapes the backend navigation by managing sections, choosing the tools inside each one, ordering both by drag, and creating custom content tools.
Frontend scope
New Nx library core-web/libs/portlets/dot-tools/, following the structure in core-web/libs/portlets/CLAUDE.md. dot-tags is the reference for the dialog and store patterns; dot-roles is the reference for a master/detail page.
Layout
Two columns. The left column is the sections panel at a fixed width; the right column is the available-tools panel and fills the rest. The page header carries the portlet title.
Left panel — sections
- A
SECTIONSheader with aNew Sectionbutton. - One row per section, showing its icon and name, in navigation order. Clicking a row selects it, which drives the right panel.
- The selected section expands to list the tools it contains, in their stored order, indented under it.
- Rows are drag-ordered with
@angular/cdk/drag-drop(CdkDropList+moveItemInArray), matching the existing use inedit-ema'sdot-row-reorder. Sections reorder among themselves; tools reorder within their section. Dropping persists the new order. - Hovering a section row reveals an overflow menu (
p-menu) with Edit, which opens the section dialog prefilled, and Delete, which asks for confirmation throughp-confirmDialogat 500px before removing the section. - Hovering a tool row reveals its drag handle and a remove control with a
Remove from sectiontooltip. Removing takes the tool out of the section and unchecks it on the right. - A footer line explains that dragging sets the order of the navigation.
Right panel — available tools
- A header with the selected section's icon and name, plus an info icon whose
p-tooltipexplains that this is the master list and that granting a tool to a role happens in Roles & Tools. - An instruction line under the header explaining that checking a tool adds it to the section, and that the section list on the left is where its order and removal live.
- An
AVAILABLE TOOLScard header with aNew Toolbutton. - A search field (
pInputTextwith a search icon) filtering the list client-side by tool name. - One
p-checkboxrow per tool in the catalog, sorted by name, checked when the tool is in the selected section. Toggling a checkbox adds or removes the tool from the selected section and the left panel updates in step. - Custom content tools whose title resolves to a raw
com.dotcms.repackage.javax.portlet.title.c_*key render as a readable label, not as the key.
New Section / Edit Section dialog
- Opened through
DialogServiceat 700px withclosable: trueandcloseOnEscape: true. - Fields: Name (required) and Icon, the latter a
p-selectover a curated Material Symbols list rendering each option with its glyph and name. There is no free-text icon field and no numeric order field. - A footer note states that order is set by dragging in the sections panel.
- Cancel and Create — Save in edit mode. A duplicate name surfaces the API's message inline rather than as a generic error.
New Tool dialog
- Same dialog conventions, 700px.
- A subtitle explaining that a tool is a filtered content list which lands in Available Tools and is added to a section from there.
- Fields: Name (required); Id, defaulted from the name, editable, with help text saying to change it only when an integration depends on a specific id; Content to display, a multi-select over base types and content types rendering selections as removable chips and defaulting to all content types; Data view mode, a two-option toggle of List and Card.
- On create the tool appears in Available Tools unchecked, ready to be added to any section.
Store and data access
- A
DotToolsStoreNgRx signal store holding the sections, the tools catalog, the selected section id, the search term, and the loading and saving flags. Data only — dialogs and confirmations are opened by the components, never by the store. - Data access in
core-web/libs/data-access/src/lib/dot-tools/wrapping the/v1/layoutsand tools-catalog endpoints plus the/v1/portlet/customwrites. - All HTTP errors route through
DotHttpErrorManagerService.handle(error); a failed write returns the status to loaded so the screen stays usable. - Extend
DotToolGroupinlibs/dotcms-modelswith a typed icon field, and add aDotToolmodel for the catalog entries. - All user-facing text goes through
DotMessagePipewithtools.*i18n keys.data-testidon every interactive element,[attr.aria-label]on inputs and icon-only buttons.
Backend wiring
dotCMS/src/main/webapp/WEB-INF/portlet.xml— add a new entry: portlet nametools-beta, display nameTools (Beta), classcom.dotcms.spring.portlet.PortletController,<portlet-url>/tools-beta</portlet-url>.dotCMS/src/main/webapp/WEB-INF/messages/Language.properties— addcom.dotcms.repackage.javax.portlet.title.tools-beta=Tools (Beta)plus thetools.*keys the portlet uses.core-web/apps/dotcms-ui/src/app/app.routes.ts— add atools-betaroute lazy-loading@dotcms/portlets/dot-tools/portlet. The route path must equal the portlet id, sinceMenuGuardServicematches the first URL segment against/api/v1/menu.core-web/tsconfig.base.json— add the@dotcms/portlets/dot-tools/portletalias.dotCMS/src/test/java/com/dotmarketing/business/portal/SerializationHelperTest.java— pintools-betaintestFromXmlFile, alongside the existingroles-betaassertion.- Not added to any default layout and no
UpgradeTask— admins opt in through Add Portlet.
Untouched files
dotCMS/src/main/webapp/html/portlet/ext/roleadmin/*— every Dojo JSP stays as it is.- The
rolesandroles-betaentries inportlet.xml, and their i18n title keys. com.dotmarketing.business.ajax.RoleAjax— the DWR methods stay so the Dojo screen keeps working.- The Tools tab inside the Roles portlet, which owns granting and is out of scope here.
Inputs
- The spike's target UI mapping and destructive-action findings
- The endpoints delivered by the backend task
- Design: https://claude.ai/design/p/879ff4e6-1b23-486d-9926-327709e91953?via=share&file=Tools.dc.html (internal — auth required)
core-web/libs/portlets/dot-tags/for the CRUD and dialog patterns,core-web/libs/portlets/dot-roles/for the master/detail pagecore-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-palette/components/dot-row-reorder/for the drag-drop patterncore-web/libs/portlets/CLAUDE.mdanddocs/frontend/*
QA
-
Tools (Beta)shows up in Add Portlet and can be added to a layout. - The portlet loads at
/#/c/tools-betaand lists every section in navigation order with its icon. - Selecting a section expands its tools on the left and checks them on the right.
- Dragging a section persists its new position; reloading the admin shows the navigation in that order.
- Dragging a tool inside a section persists the order of the tools in that section.
-
New Sectioncreates a section from a name and an icon and it appears in the panel immediately; submitting a name that already exists shows a readable message and no section is created. - The overflow menu's Edit reopens the dialog prefilled; changing the name and icon persists both.
- The overflow menu's Delete asks for confirmation, and cancelling leaves the section intact.
- Checking a tool adds it to the selected section and it appears on the left; unchecking it removes it; the remove control on the tool row does the same and unchecks the box.
- The search field filters the catalog and clearing it restores the full list.
-
New Toolcreates a custom content tool with each data view mode; the tool appears in Available Tools and can then be added to a section. - A custom tool's name renders readably, not as a
com.dotcms.repackage.javax.portlet.title.c_*key. - Signed in as a backend user without the tools portlet, the route is unreachable and the API returns 403.
- Removing
Tools (Beta)from the layout restores the previous navigation with no code change. - Every dialog closes with its X button and with Escape.
Definition of Done
- Every acceptance criterion on epic #37351 that this task owns is met.
- Jest specs cover the store's loads and writes, the two dialogs in both create and edit modes, the drag reordering, the search filter, and the error paths.
pnpm nx affected -t lint --base=origin/main,pnpm nx affected -t test --base=origin/mainandpnpm nx format:check --base=origin/mainare clean.pnpm nx build dotcms-ui --configuration=productionsucceeds.
Refs #37351
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.