Skip to content

feat(apps): replace UVE configuration textarea with a Routes editor - #37898

Draft
rjvelazco wants to merge 16 commits into
mainfrom
issue-37897-replace-uve-app-configuration-textarea-with-a-routes-editor-and-validated-json
Draft

rjvelazco wants to merge 16 commits into
mainfrom
issue-37897-replace-uve-app-configuration-textarea-with-a-routes-editor-and-validated-json

Conversation

@rjvelazco

@rjvelazco rjvelazco commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Closes #37897

Proposed Changes

Frontend: Apps → UVE configuration

  • Replace the configuration textarea with a Routes editor: one card per config entry, with a path pattern (RegEx), a server URL and optional allowed dev URLs.
  • Routes can be added, removed and reordered with up/down buttons, since the first matching pattern wins.
  • Card titles say what each route does, e.g. /blogs/(.*) → myspa.blogs.com, with a #N order badge.
  • A .* route gets a Default tag. Any route after it gets a Never used warning.
  • Patterns must be valid RegEx and URLs must be http(s). Errors show after the user leaves a field, and Save stays disabled until they're fixed.
  • A JSON tab keeps a Monaco editor with live validation and Format JSON. It opens automatically when a saved value can't be shown as routes, and the long field hint now shows only there.
  • Keys the form doesn't edit are kept on save. The saved value is still the same JSON string in the same secret.
  • The UVE form is centered on the page.

Frontend: all Apps hints

  • Code blocks in app hints get a header with the language and a Copy button, plus JSON colors from the primary palette (DotAppsCodeBlocksDirective).
  • The global Prism text-shadow no longer blurs code in these blocks.

Backend

  • Add a new JSON app param type (com.dotcms.security.apps.Type), stored like STRING.
  • AppsUtil.isValidJson rejects malformed JSON, including trailing text after the JSON.
  • That check runs on save and import (AppsUtil.validateForSave), on update (AppsHelper.validateFormForUpdate) and when an app YAML is loaded (AppDescriptorHelper).
  • SecretView reports the descriptor's JSON type for configs that were saved as STRING, so existing UVE configs open in the new editor.
  • In dotema-config-v2.yml, configuration is now type: 'JSON'. Its hint is rewritten, and the old example, which had a trailing comma, is replaced with valid JSON.

Checklist

  • Tests: new Vitest specs for the JSON field, the Routes field and its parse/serialize helpers, and the code-block directive. All 283 Apps portlet tests pass.
  • Tests: no integration tests yet for the backend JSON validation.
  • Translations: new apps.uve.*, apps.json.field.* and apps.code.block.* keys in Language.properties.
  • Security Implications Contemplated: the code-block directive HTML-escapes everything before adding highlight spans. Hint content comes from system app YAML.

Additional Info

  • Behavior change: saving, updating or importing a UVE config whose value is invalid JSON now fails with "Param configuration is of type JSON but its value is not valid JSON." Such a config already broke the UVE at render time; this was agreed on Replace UVE app configuration textarea with a Routes editor and validated JSON #37897.
  • Checks run: pnpm nx build dotcms-ui, lint on the changed files and ./mvnw compile -pl :dotcms-core all pass, and openapi.yaml is unchanged.
  • Manual testing: the UI was tried against a stock trunk backend, using a temporary frontend shim that has been removed. It has not yet run end to end against a backend built from this branch.

Video

video.mov

🤖 Generated with Claude Code

…37897)

The UVE app asked for its configuration as raw JSON in a plain textarea,
with no validation, and the example in its hint was itself invalid JSON.

- Routes tab: one card per config entry (path pattern, server URL,
  allowed dev URLs) with add, remove and reorder, inline validation,
  and a warning for routes placed after a catch-all.
- JSON tab: Monaco editor with live validation and Format JSON, kept as
  a fallback; keys the form doesn't edit are preserved.
- New JSON app param type, validated on save, update, import and when
  the app YAML is loaded. Configs saved as STRING open in the new editor.
- Code blocks in app hints get a Copy button and themed JSON colors.

The saved value is unchanged: the same JSON string in the same secret.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added Area : Backend PR changes Java/Maven backend code Area : Frontend PR changes Angular/TypeScript frontend code labels Oct 5, 2026
@claude

claude Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @rjvelazco's task in 3m 27s —— View job


Code Review

  • Read backend Java changes (Type, AppsUtil, AppsHelper, SecretView, AppDescriptorHelper)
  • Read frontend changes (UVE field, JSON field, utils, code-block directive, form)
  • Analyze for bugs, security, conventions, test gaps
  • Post review

I reviewed the diff against the branch state (16 commits). All of @oidacra's earlier findings are addressed in the follow-up commits; I verified the fixes rather than taking the replies at face value.

New Issues

No blocking issues found. One minor accessibility note below.

  • 🟡 Medium: core-web/.../dot-apps-configuration-detail-form.component.html:76 — for the JSON case the shared labelField still renders <label [for]="field.name">, and field.name is the id handed to the UVE/JSON wrapper <div> ([fieldId]="field.name"). A <label for> can't associate with a <div>, so clicking the visible label focuses nothing. Functionally the control is still named — the fix in ba541634 added role="group" + aria-label and Monaco's ariaLabel, so this is a redundant/non-functional label rather than an unnamed control. Non-blocking; could point the label at a real focusable element or drop for for these two types.

Verified correct (spot-checks worth recording)

  • AppsUtil.isValidJson (AppsUtil.java:484) rejects blank/MissingNode and trailing-token input (FAIL_ON_TRAILING_TOKENS), and the JSON branch is guarded by isSet in all three call sites (validateForSave, AppsHelper.validateFormForUpdate:657, AppDescriptorHelper:262) — no NPE on null/empty char[].
  • Rollback safety: storedType() maps JSON → STRING before persisting (AppsUtil.java:726) and SecretView.mergeSecretAndParam re-reports JSON from the descriptor (SecretView.java:205), so an older release never meets an unknown "type":"JSON" enum value in a stored secret. This matches the Type.JSON Javadoc.
  • highlightJson HTML-escapes every slice before building spans (dot-apps-code-block.directive.ts:35-49); input is system-YAML hint text, so no XSS exposure via innerHTML.
  • The DotCopyButtonComponent change (treating a resolved false as an error — dot-copy-button.component.ts:102) is safe for its ~31 other call sites: DotClipboardUtil.copy only resolves false when both the modern API and the execCommand fallback fail, i.e. a genuine copy failure, so no false error states in normal use.
  • parseUveConfig/serializeUveConfig preserve unknown top-level and options keys via extra/extraOptions, and validate()/writeValue correctly fall back to the JSON tab ($formBlocked) when the saved value isn't the { config: [...] } shape.

Test coverage

Backend AppsUtilJsonTypeTest (surefire) plus the AppsResourceTest additions (registered via MainSuite3a, per 8be5998a) cover isValidJson, validateForSave, the descriptor default check, storedType, and the PUT/read paths. Frontend specs cover the route actions, the mode toggle, reactive-form wiring, and error messages by test id. This closes the gaps the earlier review flagged.
· branch issue-37897-replace-uve-app-configuration-textarea-with-a-routes-editor-and-validated-json

@rjvelazco rjvelazco changed the title feat(apps): replace UVE configuration textarea with a Routes editor (#37897) feat(apps): replace UVE configuration textarea with a Routes editor Oct 5, 2026
@rjvelazco rjvelazco added the PR: docker image Build & push a per-PR test image to dotcms/dotcms-test label Oct 5, 2026
@rjvelazco
rjvelazco marked this pull request as ready for review October 5, 2026 16:49
rjvelazco and others added 3 commits October 5, 2026 12:49
…xtarea-with-a-routes-editor-and-validated-json
…-a-routes-editor-and-validated-json' of https://github.com/dotCMS/core into issue-37897-replace-uve-app-configuration-textarea-with-a-routes-editor-and-validated-json
…yout (#37897)

$isUveApp picks the UVE route editor. $shouldCenterForm reads a list of
app keys, so other redesigned apps can opt into the centered layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

🐳 PR Docker test image

Latest build for commit 8be5998 pushed to dotcms/dotcms-test:

docker pull dotcms/dotcms-test:pr-37898-issue-37897-replace-uve-app-configuration-textarea-with-a-routes-editor-and-validated-json
docker pull dotcms/dotcms-test:pr-37898-issue-37897-replace-uve-app-configuration-textarea-with-a-routes-editor-and-validated-json_8be5998

rjvelazco and others added 4 commits October 5, 2026 14:31
The ngx-monaco-editor and markdown stubs must keep the real selectors,
so they opt out of the dot- prefix rule like other specs in this portlet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Narrow nullable DOM queries, type the onChange spy and parsed output,
and read the index-signature 'config' key with bracket access.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#37897)

A fieldset defaults to min-inline-size: min-content, so the route list
widened to the full length of a long title and the title never truncated.
The fieldset now gets min-w-0, the title container no longer wraps, and
the badge, tags and action buttons keep their size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…arately (#37897)

A long pattern hid the server, or the reverse. Each half now starts from
an equal share but never grows past its own text, so a short half gives
its spare room to the other and the tags sit right after the text. Each
half truncates on its own; the arrow never shrinks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread dotCMS/src/main/java/com/dotcms/security/apps/Type.java
Comment thread dotCMS/src/main/java/com/dotcms/security/apps/AppsUtil.java
rjvelazco and others added 6 commits October 5, 2026 17:04
…xtarea-with-a-routes-editor-and-validated-json
…hem (#37897)

A stored "type":"JSON" can not be deserialized by a release that predates
Type.JSON, which would leave that site's App secrets unreadable after a
rollback. JSON params are now persisted as STRING; SecretView still reports
JSON from the app descriptor at read time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Use the global .field wrapper with plain labels, and p-field-error /
  p-field-hint instead of the dead .p-error class, so errors render red.
- Center the form with mx-auto instead of a custom modifier.
- Flatten the hint and code-block SCSS to at most three levels.
- Mount the shared DotCopyButtonComponent in code blocks, and make it show
  its error state when DotClipboardUtil reports a refused copy.
- Add specs for remove, move up, dev URL removal, the Routes/JSON toggle,
  the disabled state, error messages by test id, and the reactive-form
  wiring of both fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Unit tests for validateForSave rejecting malformed JSON, the app descriptor
check on JSON defaults, and isValidJson with scalars.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…E editor (#37897)

- Give the JSON editor and the route editor accessible names: a <label for>
  can't name their <div> wrappers, so pass the field label to Monaco's
  ariaLabel and to role=group wrappers.
- Use # private fields to match the TypeScript standards.
- Replace $any($event.target) with template refs to keep template
  type-checking on.
- Replace raw SCSS values with spacing and font tokens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…width (#37897)

Replaces the custom max-width: 64.25rem with the shared --container-content
token (70rem), so the form layout needs no component SCSS. All Apps
configuration forms get slightly wider.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rjvelazco
rjvelazco marked this pull request as draft October 6, 2026 15:48
…ad (#37897)

Covers what the unit tests can't reach: AppsHelper.validateFormForUpdate
rejecting malformed JSON on the PUT path, the secret being stored as STRING,
and SecretView still reporting JSON from the descriptor. Added to
AppsResourceTest, which MainSuite3a already runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area : Backend PR changes Java/Maven backend code Area : Frontend PR changes Angular/TypeScript frontend code PR: docker image Build & push a per-PR test image to dotcms/dotcms-test Team : Scout

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Replace UVE app configuration textarea with a Routes editor and validated JSON

2 participants