dotCMS / dotCMS/core

[Task] Tools: Angular implementation + backend wiring

Open
#37,354 1 comment 0 reactions 1 assignee View on GitHub

@hmoreras is already working on this.

Since Sep 2, 2026.

dotCMS : Admin Tools Team : Modernization Type : Task
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 SECTIONS header with a New Section button.
  • 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 in edit-ema's dot-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 through p-confirmDialog at 500px before removing the section.
  • Hovering a tool row reveals its drag handle and a remove control with a Remove from section tooltip. 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-tooltip explains 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 TOOLS card header with a New Tool button.
  • A search field (pInputText with a search icon) filtering the list client-side by tool name.
  • One p-checkbox row 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 DialogService at 700px with closable: true and closeOnEscape: true.
  • Fields: Name (required) and Icon, the latter a p-select over 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 DotToolsStore NgRx 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/layouts and tools-catalog endpoints plus the /v1/portlet/custom writes.
  • All HTTP errors route through DotHttpErrorManagerService.handle(error); a failed write returns the status to loaded so the screen stays usable.
  • Extend DotToolGroup in libs/dotcms-models with a typed icon field, and add a DotTool model for the catalog entries.
  • All user-facing text goes through DotMessagePipe with tools.* i18n keys. data-testid on 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 name tools-beta, display name Tools (Beta), class com.dotcms.spring.portlet.PortletController, <portlet-url>/tools-beta</portlet-url>.
  • dotCMS/src/main/webapp/WEB-INF/messages/Language.properties — add com.dotcms.repackage.javax.portlet.title.tools-beta=Tools (Beta) plus the tools.* keys the portlet uses.
  • core-web/apps/dotcms-ui/src/app/app.routes.ts — add a tools-beta route lazy-loading @dotcms/portlets/dot-tools/portlet. The route path must equal the portlet id, since MenuGuardService matches the first URL segment against /api/v1/menu.
  • core-web/tsconfig.base.json — add the @dotcms/portlets/dot-tools/portlet alias.
  • dotCMS/src/test/java/com/dotmarketing/business/portal/SerializationHelperTest.java — pin tools-beta in testFromXmlFile, alongside the existing roles-beta assertion.
  • 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 roles and roles-beta entries in portlet.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 page
  • core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-palette/components/dot-row-reorder/ for the drag-drop pattern
  • core-web/libs/portlets/CLAUDE.md and docs/frontend/*

QA

  • Tools (Beta) shows up in Add Portlet and can be added to a layout.
  • The portlet loads at /#/c/tools-beta and 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 Section creates 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 Tool creates 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/main and pnpm nx format:check --base=origin/main are clean.
  • pnpm nx build dotcms-ui --configuration=production succeeds.

Refs #37351

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.