Context
The Velocity Playground portlet (developer/admin tool for evaluating ad-hoc Velocity / VTL snippets against the live engine) currently ships as a Dojo + Ace JSP. This epic migrates it to Angular + PrimeNG. The scope is intentionally small — single endpoint, split-pane developer view — so the work is decomposed into a consolidated spike, a single FE + BE implementation task, and a docs task.
Current State (Dojo)
| Aspect |
Value |
| Entry point |
Portlet velocity_playground registered in dotCMS/src/main/webapp/WEB-INF/portlet.xml |
| JSP |
dotCMS/src/main/webapp/WEB-INF/jsp/velocity_playground/render.jsp |
| Portlet class |
com.dotcms.rest.JSPPortlet |
| Backend endpoint |
POST /api/vtl/dynamic/ (com.dotcms.rest.api.v1.vtl.VTLResource#dynamicPost) |
| Editor |
Ace 1.2.3 with Velocity mode |
| Input |
Raw Velocity / VTL source (text/plain or JSON body) |
| Output |
text/plain, application/json, or application/xml — content type determined by what the VTL emits |
| Extras |
Resizable split-pane, "Wrap Code" toggle, history dropdown (last 10 entries persisted in localStorage), auto-wrapped timing metric using $dotTimer + $math.sub |
| Gates |
License STANDARD+ (confirmed in the spike's API audit) + admin role |
Target State (Angular)
- Path:
core-web/libs/portlets/dot-velocity-playground/
- Shell + page + SignalStore + data-access service
- PrimeNG:
p-splitter, Monaco editor (Velocity / VTL language mode), output panel with JSON / XML / plain-text rendering
- History persisted client-side (size + storage location finalized in the spike)
- License + role gating preserved from the current portlet; any gap surfaced in the spike's API audit is filed as a separate security task and linked here.
Backend Wiring
dotCMS/src/main/webapp/WEB-INF/portlet.xml: velocity_playground points at the new Angular shell; a new velocity_playground-legacy entry points at the existing JSP for rollback.
- Corresponding
PortletID enum entry and i18n key added (or existing velocity_playground key reused).
- Live-toggle rollback so admins can revert to the JSP without redeploy.
Definition of Done
Scenario: Admin runs valid Velocity code
Given I am logged in as an admin
When I open the Velocity Playground portlet
And I enter a valid Velocity snippet
And I click Run
Then the rendered output appears in the output panel
And I see the execution timing
Scenario: Output renders JSON, XML, and plain text
Given a snippet that emits JSON
When I run it
Then the output panel renders the JSON content
And the same flow works for XML and plain-text snippets
Scenario: Velocity error surfaces inline
Given I submit a malformed Velocity snippet
Then I see an inline error explaining the failure
And the editor content is unchanged
Scenario: History recall
Given I have run several snippets in this session
When I pick a previous entry from the history control
Then the editor loads that snippet
Scenario: Resizable split-pane
Given the editor and output panels are visible
When I drag the splitter
Then editor and output resize accordingly
Scenario: Non-admin role is blocked
Given I am logged in as a non-admin user
When I try to open the Velocity Playground portlet
Then access is denied per the existing gating
Scenario: Unlicensed instance blocks the portlet
Given the instance does not meet the STANDARD license level
When I try to open the Velocity Playground portlet
Then access is blocked per the existing license gate
Scenario: Rollback to legacy JSP
Given the Angular portlet is enabled
When an admin switches the toggle to legacy
Then the original Dojo JSP renders without redeploy
Sub-tasks
Context
The Velocity Playground portlet (developer/admin tool for evaluating ad-hoc Velocity / VTL snippets against the live engine) currently ships as a Dojo + Ace JSP. This epic migrates it to Angular + PrimeNG. The scope is intentionally small — single endpoint, split-pane developer view — so the work is decomposed into a consolidated spike, a single FE + BE implementation task, and a docs task.
Current State (Dojo)
velocity_playgroundregistered indotCMS/src/main/webapp/WEB-INF/portlet.xmldotCMS/src/main/webapp/WEB-INF/jsp/velocity_playground/render.jspcom.dotcms.rest.JSPPortletPOST /api/vtl/dynamic/(com.dotcms.rest.api.v1.vtl.VTLResource#dynamicPost)text/plainor JSON body)text/plain,application/json, orapplication/xml— content type determined by what the VTL emitslocalStorage), auto-wrapped timing metric using$dotTimer+$math.subSTANDARD+(confirmed in the spike's API audit) + admin roleTarget State (Angular)
core-web/libs/portlets/dot-velocity-playground/p-splitter, Monaco editor (Velocity / VTL language mode), output panel with JSON / XML / plain-text renderingBackend Wiring
dotCMS/src/main/webapp/WEB-INF/portlet.xml:velocity_playgroundpoints at the new Angular shell; a newvelocity_playground-legacyentry points at the existing JSP for rollback.PortletIDenum entry and i18n key added (or existingvelocity_playgroundkey reused).Definition of Done
Sub-tasks