Skip to content

fix(plans): label a plan's ramp the way Edit reads it - #1396

Merged
IAmJSD merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:ui/issue-1185
Oct 24, 2026
Merged

IAmJSD merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:ui/issue-1185

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

The Plans list picked the "Ramp Schedule" label from the stored ramp type alone, so a plan stored as weekly 20% every 7 days showed "Weekly 20%" while Edit opened it as Custom 20% / 7 days, and a weekly 25% every 14 days plan showed "Weekly 25%", hiding the interval. The auto-generated plan name also rounded custom step counts up ("(4 steps)" for a 3-step 30% schedule). This PR labels ramps with the same preset-equality rule Edit uses and counts steps the way the backend does.

Closes #1185

What changed

  • frontend/src/plans.ts:
    • formatBackendRampSchedule now uses rampRadioValue, the same preset-equality check Edit uses. It shows a preset name only when type, percent and interval all match PRESET_RAMPS, and otherwise "Custom N% every D days" ("day" when D is 1; "Custom N%" if no interval is stored). Unknown types still show the raw type. This is the only render site for the ramp label.
    • PRESET_RAMPS gains a label field so preset names and matching stay together.
    • generatePlanName uses Math.max(1, Math.floor(100 / pct)), matching internal/api/types.go buildCustomRampSchedule and plan-schedule-intent.ts, and says "1 step" in the singular.
  • New frontend/src/__tests__/plans-ramp-label.test.ts.

Why this approach

Reusing rampRadioValue means the list and the Edit dialog can't disagree again, which is the fix the issue proposes. The existing preset label text ("Weekly 25%", "Monthly 10%") is kept, so properly stored preset plans look exactly as before.

Screenshots

Before is main (a14dc8f2), after is this branch. Both are headless Chromium at 1440x900 against the repo's mocked e2e API, showing /plans with three mocked plans.

Before After
plan-list-ramp-labels before plan-list-ramp-labels after
  • Before: plans stored as weekly 20%/7d and weekly 25%/14d list as "Weekly 20%" and "Weekly 25%", the same label as the real 25%/7d preset, with the 14-day interval hidden. After: they read "Custom 20% every 7 days" and "Custom 25% every 14 days", matching what Edit opens, and the real preset still reads "Weekly 25%".

Verification

Run on this branch's head b98e8350 on top of main a14dc8f2:

  • Lint: 0 errors (142 existing warnings). Typecheck and build pass.
  • Jest: 110 suites, 3496 passed, 1 skipped. New tests (10): for stored weekly 25/7, monthly 10/30, weekly 20/7, weekly 25/14, custom 25/7, custom 50/1 and immediate, the list label and the radio Edit opens agree; the generated name for custom 30% says "(3 steps)", 25% "(4 steps)", 60% "(1 step)". On main a14dc8f2, 5 of the 10 fail (weekly 20/7, weekly 25/14, the "1 days" case, 30% naming and 60% naming). Randomized run: 10/10.
  • Playwright: 157 passed. No new spec (label text only; jest covers list/Edit agreement through the real index.html).
  • git-secrets scan clean (planted key flagged); allowlist test 137 pass.

Notes for review

  • Non-preset ramps read "Custom 20% every 7 days" even when stored with type weekly. That matches Edit, as the issue asks, but "Weekly 20%" for 7-day intervals is an alternative. The longer text wraps to two lines in the Ramp Schedule cell at 1440px (see the after shot).
  • Small extras beyond the issue: singular "1 day" and "1 step".

Overlaps

plans.ts is also touched by #18, #181, #37, #727, #737 and #739. Only #739 is close: it edits around lines 1037 and 1136-1140, next to formatBackendRampSchedule (1060-1070) and its call site at 1144. A textual conflict is unlikely, but the merge should be checked. Those PRs will be opened alongside this one and merged in sequence, with conflicts resolved on the later branch.

Note for the UI owner

This changes UI code that @cristim owns. IAmJSD reviewed the before/after screenshots and asked for it to be merged; any design point you disagree with can be a follow-up.

🤖 Generated with Claude Code

formatBackendRampSchedule picked the list label from the stored ramp type
alone. A weekly 20%/7d plan listed as "Weekly 20%" while Edit opened it as
Custom 20% / 7 days, and a weekly 25%/14d plan listed as "Weekly 25%",
hiding the 14-day interval.

The label now uses the same preset-equality rule as Edit (rampRadioValue).
It shows a preset name only when type, percent and interval all match, and
otherwise shows "Custom N% every D days" (singular "day" for 1). The preset
labels live next to PRESET_RAMPS so the two cannot drift.

generatePlanName counted custom steps with Math.ceil, so 30% was named
"(4 steps)" for a 3-step schedule. It now floors (minimum 1) like the
backend's buildCustomRampSchedule and the schedule preview, and says
"1 step" in the singular.

Refs LeanerCloud#1185

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@IAmJSD IAmJSD added triaged Item has been triaged priority/p3 Polish / idea / may never ship severity/low Minor harm urgency/this-quarter Within the quarter impact/few Limited audience effort/xs Trivial / one-liner type/bug Defect labels Oct 24, 2026
@IAmJSD

IAmJSD commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): APPROVE b98e8350411f00a85a36fb9b6282e32d53e2c921

Blocking:

  • none
    Non-blocking:
  • frontend/src/plans.ts:1147,1066: the label is still interpolated into innerHTML without escapeHtml, and the unknown-type branch returns raw ramp.type. This is pre-existing and low risk because the backend enforces ValidRampScheduleTypes, but wrapping the call in escapeHtml would be cheap.
    Attacked: Checked that the label now derives from rampRadioValue, the same function editPlan uses, so list and Edit cannot disagree. Checked that custom 25/7 (a type mismatch with the preset) reads Custom. Checked the new step count against buildCustomRampSchedule (int(100/stepPercent), minimum 1) and plan-schedule-intent.ts (floor), so they match. Checked that PRESET_RAMPS values mirror config.PresetRampSchedules. Closes fix(plans): plan list ramp label ignores percent/interval and disagrees with Edit #1185 is justified: both the label and the name items from the issue are covered.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 2 billable files and costs up to $0.50.

Or wait 59 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
Commits

Reviewing files that changed from the base of the PR and between 61be5b6 and b98e835.

Files selected for processing: 2
  • frontend/src/__tests__/plans-ramp-label.test.ts
  • frontend/src/plans.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@IAmJSD

IAmJSD commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

Local verification at b98e8350 merged onto current main (84b53f5a; merge-tree 68aba35f; Linux, Node, headless Chromium):

  • This branch's own checks passed at this head: lint, typecheck, build, the full jest suite, the full Playwright e2e suite, and the git-secrets checks (see Verification in the PR body).
  • The combined tree of every UI PR in this merge wave (tree 89dd34d8, main plus 46 PRs) passes npm ci, lint, typecheck, build, jest (1 skipped, 3914 passed, 3915 total), and the full Playwright suite (208 passed).
  • CI is green on b98e8350 (CI Success, Run pre-commit hooks).
  • The independent review above approves this exact head.
  • Nothing was applied to any cloud.

@IAmJSD
IAmJSD marked this pull request as ready for review October 24, 2026 17:40
@IAmJSD
IAmJSD merged commit 84b543d into LeanerCloud:main Oct 24, 2026
29 checks passed
@IAmJSD

IAmJSD commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

Marked ready and merged by IAmJSD's agent, at IAmJSD's request (IAmJSD reviewed the before/after screenshots; cristim is traveling), after the independent review and local verification above, all at b98e8350.

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

Labels

effort/xs Trivial / one-liner impact/few Limited audience priority/p3 Polish / idea / may never ship severity/low Minor harm triaged Item has been triaged type/bug Defect urgency/this-quarter Within the quarter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(plans): plan list ramp label ignores percent/interval and disagrees with Edit

1 participant