Skip to content

feat(37659): frontend limited-mode UI and analytics health gate (FE) - #37957

Open
freddyDOTCMS wants to merge 1 commit into
issue-37659-analytics-experiment-flag-gatesfrom
issue-37659-analytics-experiment-flag-gates-fe
Open

freddyDOTCMS wants to merge 1 commit into
issue-37659-analytics-experiment-flag-gatesfrom
issue-37659-analytics-experiment-flag-gates-fe

Conversation

@freddyDOTCMS

@freddyDOTCMS freddyDOTCMS commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Summary

Angular/TypeScript implementation of the limited-mode UI and analytics health response mapping. Depends on the BE PR: #37690.

Analytics portlet:

  • HealthEntity type updated — adds health field (OK|NOT_CONFIGURED|CONFIGURATION_ERROR); legacy available field preserved for rollback safety
  • DotAnalyticsService.healthCheck() maps health field first, falls back to available
  • analyticsHealthGuard allows on HealthStatusTypes.OK (was AVAILABLE)
  • Resolver extracts health field from full ExperimentsHealthResponse to preserve downstream contract

Experiments portlet:

  • ExperimentsHealthResponse interface — healthCheck() now returns tier, freeExperimentUsed, warning in addition to health
  • Store: three new computed signals — isLimitedMode, isSlotUsed, showAnalyticsWarning
  • List: non-closable limited-mode banner (info/warn based on slot state); closable analytics-warning banner; Archive/End/Cancel/Abort show info toast instead of disabled state (tooltip-invisible)
  • Configure scheduling: blocked by p-blockUI in limited mode with explanatory message; scheduling cleared by effect before _start so the BE sees no dates (prevents SCHEDULED instead of RUNNING)
  • Configure footer: Start button disabled when tier=LIMITED && freeExperimentUsed=true
  • Configure header + Results header: Stop Experiment shows info toast in limited mode

Test plan

  • pnpm nx test portlets-dot-analytics-data-access — 220 tests passing
  • pnpm nx test portlets-dot-analytics — 335 tests passing
  • pnpm nx test portlets-dot-experiments-portlet — 1407 tests passing
  • Manual: switch server to FEATURE_FLAG_EXPERIMENTS=false, verify limited-mode banners and blocked actions in the Experiments portlet
  • Manual: verify Analytics portlet health guard redirects correctly for NOT_CONFIGURED and CONFIGURATION_ERROR

🤖 Generated with Claude Code

This PR fixes: #37659

Angular/TypeScript implementation of the limited-mode UI and analytics health
response mapping, consuming the new BE gate fields from issue #37659.

Analytics portlet:
- HealthEntity type updated — adds health field (OK|NOT_CONFIGURED|CONFIGURATION_ERROR);
  legacy available field preserved for rollback safety
- DotAnalyticsService.healthCheck() maps health field first, falls back to available
- analyticsHealthGuard now allows on HealthStatusTypes.OK (was AVAILABLE)
- dot-analytics-health-check.resolver extracts health field from ExperimentsHealthResponse
- 220 tests passing in portlets-dot-analytics-data-access

Experiments portlet:
- ExperimentsHealthResponse interface added to dot-experiments.service; healthCheck()
  now returns the full response (tier, freeExperimentUsed, warning) rather than just health
- Store: healthResponse replaces healthStatus in state; new computed signals isLimitedMode,
  isSlotUsed, showAnalyticsWarning drive limited-mode UI
- List component: non-closable limited-mode info/warn banner; closable analytics-warning
  banner; Archive/End/Cancel/Abort show info toast in limited mode instead of disabled state
- Configure component: scheduling section blocked (p-blockUI) in limited mode with
  informational message; scheduling cleared via effect so autosave never sends dates that
  would cause _start to return SCHEDULED; Start button disabled when slot occupied
- Configure header + Results header: Stop Experiment shows info toast in limited mode
- 1407 tests passing in portlets-dot-experiments-portlet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude

claude Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @freddyDOTCMS's task in 1m 57s —— View job


Review — PR #37957 (limited-mode UI & analytics health gate, FE)

  • Read the full diff vs base branch
  • Analyze analytics service / health guard / resolver changes
  • Analyze experiments store + limited-mode UI changes
  • Check for bugs, test gaps, conventions
  • Post review

New Issues

  • 🟠 High: core-web/libs/portlets/dot-experiments/portlet/src/lib/dot-experiments-configure/dot-experiments-configure.component.html:83 — Stray o character prefixing the binding line: o [gated]="$isGated()". This is a copy/paste typo that leaks a bogus o attribute onto <dot-experiments-configure-scheduling>. Angular won't error (unknown attributes on components are tolerated), so it ships silently, but it's clearly unintended source and should not merge. Fix this →

  • 🟡 Medium: multiple independent healthCheck() subscriptions fire duplicate GET /api/v1/experiments/health requests on a single screen. toSignal(inject(DotExperimentsService).healthCheck()...) is created separately in dot-experiments-configure.component.ts:193, dot-experiments-configure-footer.component.ts:88, and dot-experiments-configure-header.component.ts — so opening the Configure screen issues three concurrent health requests; the Results screen issues two (dot-experiments-results-header.component.ts + dot-experiments-results.component.ts). healthCheck() is a plain http.get (no shareReplay), so each subscription is a real round-trip. Beyond the waste, three in-flight requests can resolve to different tier/slot values if the flag/slot changes mid-flight, giving an inconsistent screen. Consider resolving health once (route resolver or the Configure store) and passing tier/freeExperimentUsed down as inputs, mirroring how the List store already holds the single healthResponse.

  • 🟡 Medium: the limited-mode gate in DotExperimentsConfigureFooterComponent.$startDisabled and *ConfigureComponent.$isLimitedMode is a view-only guard. The Start button is disabled and scheduling is p-blockUI-blocked, but if the free slot is already used, nothing stops a _start dispatch that bypasses the button (e.g. the confirmStop/action paths, or a stale signal while the health request is still pending — initialValue: false means the UI renders as not limited for the first frame). Assumption: the BE PR (spec: Feature-flag gates for analytics and experiment endpoints (#37659) #37690) enforces the one-free-experiment limit server-side. What to verify: that the server rejects a second start in LIMITED tier regardless of FE state, so the FE gate is defense-in-depth and not the only check.

Notes (non-blocking)

  • The analytics health→HealthStatusTypes mapping (dot-analytics.service.ts:57) correctly prefers health and falls back to available, with unknown strings → ERROR. Legacy fallback and the resolver .pipe(map(r => r.health)) contract preservation look correct and are well covered by the new specs.
  • i18n keys (experiments.list.limited-mode.banner[.slot-used], .action.disabled, experiments.list.analytics.disabled.warning) all exist in Language.properties:6206-6209. ✅

Test coverage for the store computeds (isLimitedMode/isSlotUsed/showAnalyticsWarning), the guard OK transition, and the service mapping is thorough. The two Medium items are the real review points; the stray o is the one blocking fix.
· branch issue-37659-analytics-experiment-flag-gates-fe

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

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant