Skip to content

Dojo to Angular: ES Search Portlet #34733

@fmontes

Description

@fmontes

Context

Migrate the ES Search developer-tool portlet from legacy Dojo/JSP to Angular (PrimeNG + Tailwind + NgRx Signals), following the modernization pattern established in Q1 by Categories (#34731 / PR #35146), Tags (#34552), and Plugins (#34732).

Scope: Feature parity with Dojo + UI/UX improvements that emerge during design.

Why now: #34733 is one of ~10 remaining Dojo portlets under the [PILLAR] #33458. ES Search is lower-risk than admin-critical portlets (only admin + STANDARD-licensed users access it), making it a good next step before larger pieces like Users Management (#34736) or Permissions (#34739).

Current State (Dojo)

Entry point: /dotAdmin/#/c/es-search → iframe loads JSP.

Files:

  • UI: dotCMS/src/main/webapp/WEB-INF/jsp/es-search/render.jsp (ACE editor, dijit widgets, XHR)
  • Help modal: dotCMS/src/main/webapp/WEB-INF/jsp/es-search/es-search-help.jsp
  • Not-licensed: dotCMS/src/main/webapp/WEB-INF/jsp/es-search/not_licensed.jsp
  • Resource: dotCMS/src/main/java/com/dotcms/rest/elasticsearch/ESContentResourcePortlet.java
  • Portlet registration: portlet.xml:345-348 (portlet class ESContentResourcePortlet)

Backend endpoints:

Method Path Purpose
GET/POST /api/es/search Run ES query → contentlets + raw ES metadata
POST /api/es/search POST variant with Swagger docs
GET/POST /api/es/raw Unprocessed SearchResponse
POST /api/portlet/es-search/render Legacy JSP form submit (to be removed)

⚠️ OpenAPI gap discovered: a live fetch of https://demo.dotcms.com/api/openapi.json confirms these endpoints are NOT in the OpenAPI spec — only the tag "Elasticsearch Content Search" ("Backend Elasticsearch search endpoints for portlet context") exists with zero paths attached. No schemas for ESSearchResults, ESSearchResponse, or related error shapes are defined. Fixing this is a mandatory deliverable in the BE audit sub-task.

Dojo features (catalog):

  • ACE JSON editor with syntax highlighting
  • Live vs working toggle
  • Admin user impersonation (userid param, admin-only)
  • Query timing (query time + population time)
  • Hit count + results table (title, inode, identifier, full printable map)
  • Aggregations table (buckets)
  • Term suggestions
  • Raw ES response JSON
  • Wrap code toggle
  • Help dialog with example queries, REST API docs, Velocity viewtool usage, geolocation examples

Gates:

  • License: requires LicenseLevel.STANDARD minimum (render.jsp:35-49)
  • Role: userid impersonation admin-only (render.jsp:73)

Target State (Angular)

  • New portlet at core-web/libs/portlets/dot-es-search/
  • Not a CRUD portlet — single page with query editor → results (tabs for hits / aggregations / raw). The standard dot-tags CRUD shape does not apply; the portlet needs a minimal shell + page + single SignalStore + 1 service. The FE spec sub-task formalizes this deviation.
  • Angular service in core-web/libs/data-access/src/lib/dot-es-search/ calling /api/es/search and /api/es/raw.
  • PrimeNG components for JSON editor, results tabs (TabView), help/examples dialog, Toast for errors.
  • All text via DotMessagePipe (i18n keys esSearch.*).
  • License-gated UI: render dot-not-licensed component (or equivalent) when license < STANDARD.
  • Admin-only controls (impersonation) gated via user role check.

Backend wiring (mirrors Categories PR #35146)

  • portlet.xml: switch es-search entry from ESContentResourcePortlet (JSP render) to PortletController route /es-search.
  • Add es-search-legacy portlet entry preserving the Dojo JSP view (displayed as "ES Search Legacy" in admin menu) — rollback escape hatch.
  • Add ES_SEARCH_LEGACY enum to PortletID.
  • Language.properties: add label com.dotcms.repackage.javax.portlet.title.es-search-legacy = ES Search Legacy.
  • New Angular route with MenuGuard + reuseRoute: false.

Definition of Done (Gherkin)

Feature: ES Search portlet migrated to Angular

Scenario: Admin with STANDARD license opens ES Search
  Given I am logged in as a user with the ES-Search portlet role
  And my license is STANDARD or higher
  When I navigate to /dotAdmin/#/c/es-search
  Then I see the Angular ES-Search portlet (no iframe, no Dojo)
  And I see the query editor, Run button, and examples link

Scenario: Run a valid ES query
  Given the Angular portlet is loaded
  When I paste a valid ES DSL JSON and click Run
  Then I see the hit count, query time, and results tab populated
  And the Aggregations tab is populated if aggregations were returned
  And the Raw Response tab shows the unprocessed ES response

Scenario: Run an invalid ES query
  Given the Angular portlet is loaded
  When I paste invalid JSON and click Run
  Then I see a toast error via DotHttpErrorManagerService
  And the previous results (if any) remain visible

Scenario: User without license
  Given my license is COMMUNITY
  When I navigate to /dotAdmin/#/c/es-search
  Then I see the not-licensed state (no query editor)

Scenario: Rollback available
  Given the new portlet is live
  When an admin navigates to the "ES Search Legacy" portlet in the menu
  Then the original Dojo JSP portlet loads and functions

Scenario: Live vs Working toggle
  Given I have the same contentlet in live and working states
  When I toggle "Live" and Run the same query
  Then the results reflect the live version
  And toggling off returns the working version

Scenario: Admin impersonation
  Given I am a CMS Admin
  When I enter a userid and Run a query
  Then the query executes as that user
  And a non-admin user does not see the impersonation input

Sub-tasks

Tracked as native GitHub sub-issues (see panel on the right):

  1. [Spike] Current-state audit + feature parity matrix
  2. [Spike] Backend API audit (includes OpenAPI annotation gap)
  3. [Task] UX/UI design (parity + improvements)
  4. [Task] Frontend implementation spec
  5. [Task] Backend wiring + rollback entry

References

Metadata

Metadata

Assignees

Type

Projects

Status

In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions