dotCMS / dotCMS/core

Experiments Portlet — Screen 2: Create/Update (/experiments/new + /:id/configuration)

Open
#37,003 3 comments 0 reactions 1 assignee View on GitHub

@jcastro-dotcms is already working on this.

Since Sep 16, 2026.

  • #37306 by @oidacra — merged
dotCMS : Experiments Team : Falcon Type : New Functionality
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Description

Creation is a routed screen, not a dialog: /experiments/new is the Configure screen with an empty draft. This retires the current drawer (name + description only, page implied by the UVE route context) and lets a user create, configure and start an experiment end-to-end without opening the page editor.

Design: approved prototype, edit screen + Select A Page modal + Add Variant modal.

Routing and creation flow
  • /experiments/new and /experiments/:experimentId/configuration render the same component in new vs edit mode.
  • Autosave is the creation mechanism (design footer: "Changes are saved as you edit." — no Save button): in new mode, debounced autosave issues the POST as soon as name + page exist, then replaceUrl to /experiments/:id/configuration; every subsequent change is a debounced PATCH per field group. Hard dependency on #36988's PATCH fix — without it every autosave call creates an empty Rule.
  • Page preselection via query param: /experiments/new?pageId=<uuid> or /experiments/new?url=/index (path resolved by HTMLPAGE search on the current site) prefills the Page card and skips the picker. Invalid param → inline message, never a blank screen. (?page= avoided — collides with pagination; ?url= matches UVE.)
  • Locked state when status ∈ {RUNNING, ENDED, ARCHIVED}: banner per the design, every field disabled, add/delete variant hidden; RUNNING copy differs from generic read-only copy.
Layout

Fixed header (back · title falling back to "New Experiment" · status tag · subline {pageTitle} · {pagePath} or "No Page selected" · View Results / Stop when applicable) + scrolling card body (max-width 1040 centered) + pinned footer (hint · Back To Experiments · primary Start/Schedule). Header kebab with end / abort / cancelSchedule / pushPublish / addToBundle gated by AllowedActionsByExperimentStatus (parity with the current screen's menu).

The five cards
  1. Details — name (required) + description textarea.
  2. Goal — SET/REQUIRED chip; goal name; 4 types as radio cards (BOUNCE_RATE, EXIT_RATE, REACH_PAGE, URL_PARAMETER); condition sub-panels for REACH_PAGE (Parameter/Operator/Value) and URL_PARAMETER (Parameter Name/Operator incl. EXISTS/Value). Operator lists come from what the backend validates after #36988 — never offer an operator the backend silently ignores.
  3. Page — read-only summary + SelectSelect A Page dialog (900×560: folder tree + page table Page | Template | Modified | State + search, radio selection). A page may host any number of experiments, so the picker restricts nothing: ExperimentsAPIImpl.save puts no page-based condition on creating one. What cannot happen is two running on the same page at once, which start rejects — outright for an immediate start, and for a scheduled one unless the running experiment's window closes before the new one opens. Traffic allocation: slider 1–100 synced with number input.
  4. Variants — color dot, name + CONTROL chip, meta line, weight input, delete (non-control, unlocked). Ported parity behaviors: inplace variant rename, copy-variant-URL (dot-copy-button with &variantName=), n/max counter. Total + Split Evenly (even = floor(100/n), first absorbs remainder) + + Add Variant dialog (440px, Variant {n} fallback, re-splits evenly) + warning bar when weights ≠ 100. Edit Content/Preview out of scope here (UVE-integration issue) — render disabled with tooltip or omit until it lands. Cap: whatever #36988 enforces.
  5. Scheduling — start/end with time-of-day (p-datepicker [showTime]="true") and the min/max duration bounds from DotExperimentsConfigResolver (the design draws bare date inputs; dropping time + duration validation would be a parity regression). Note box + Clear Schedule.
Validation and transitions

The 8 rules (name, page, goal type, goal name, condition value, parameter name, ≥2 variants, weights = 100), revealed only after pressing Start — scroll to the first [data-error], count in the footer; Start never disabled. Start with date → SCHEDULED; without → RUNNING; Stop → ENDED. Toast per transition.

Store

Signal Store Events, same shape as #36989: experiments-form.events.ts, reducers per card, autosave in withEventHandlers (debounce + switchMap; failed PATCH → DotHttpErrorManagerService, state back to loaded).

Unhide from Screen 1

The New Experiment button and the Configure primary row action in #36989 route here.

Acceptance Criteria

  • /experiments/new renders the empty-draft Configure screen; typing a name and picking a page creates the experiment (one POST, no dialog) and the URL becomes /experiments/:id/configuration via replaceUrl.
  • Every field change persists via debounced PATCH; no PATCH creates a Rule/ConditionGroup (spec asserts untouched targetingConditions is omitted from the payload).
  • ?url=/index and ?pageId=<id> prefill the Page card; invalid values show a message.
  • All five cards match the design, including the ported behaviors: variant inplace rename, copy-variant-URL, n/max counter, scheduling time + duration bounds.
  • Select A Page: current-site browse, search, radio selection; selection updates the summary + traffic helper copy. No page is excluded or greyed — concurrency on a page is enforced at Start, not at the pick.
  • The 8 validation rules reveal on Start, scroll to the first error, count in the footer.
  • Start/Schedule/Stop transitions with toasts; locked states disable everything with the right banner copy.
  • Header kebab per AllowedActionsByExperimentStatus.
  • The old UVE configuration screen is untouched.
  • Jest specs per card + the autosave store (fake timers for debounce).

Priority

High.

Additional Context

  • Depends on: #36989 (base + list), #36988 (PATCH fix — hard blocker for autosave).
  • Out of scope: the variant Edit Content UVE round-trip (own issue); the Targeting card (current one is commented out Hide until is implemented — not a parity loss); autosave conflict resolution beyond last-write-wins.
  • Logic to lift (not the ComponentStore shape): validation, weight redistribution and action gating from dot-experiments-configuration/store/dot-experiments-configuration-store.ts.
  • E2E (create → configure → start) lives in the dedicated E2E issue.

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.