Repository navigation
fix(plans): Plans page polish and run-now follow-ups - #1742
Conversation
The empty-plan-step refusal and the retry 409 are shown to users and named an internal issue number. Drop the suffix from both. Failure reasons already stored carry the old text, so the stored-note allowlist accepts both forms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep the empty-step Run now focusable with aria-disabled so keyboard users can read why it cannot run, let the plan name use available width, render empty numeric cells as one muted dash, add Plan and Scheduled Date column filters through the existing plans filter mechanism, and say the ramp step is a percent of the target. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A percentage max-width is ignored by auto table layout, so a long plan name widened the table; use a plain length. An empty step's Run now no longer reloads the list, which dropped keyboard focus. Key the Scheduled Date filter by the displayed day so same-day steps share one option. Cover the all-upfront $0 placeholder and add a Playwright width check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The filter keyed on formatDate text, which sorts alphabetically. Key by the local YYYY-MM-DD day so same-day steps still share one option and keys sort in date order; formatDate is only the option label. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@coderabbitai review |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 33 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Action not completed
|
Cold review: claude-ui-fix-1, verdict APPROVE at
|
cristim
left a comment
There was a problem hiding this comment.
APPROVE @ e214fc8 by claude-nibblets
Cold review of ecb118e...e214fc8 (4 commits), done in my own scratch clone; ecb118e is the current main tip. The PR body was treated as a claim. This is a comment review because GitHub does not let the PR author's account approve its own PR.
The 409 text and the stored-text matcher (#1708 item 1).
ErrPlanStepNoRecommendations(internal/purchase/execution.go) and theretryPurchase409 (handler_purchases.go) no longer end with "(platform#631: …)". The reference moves to a code comment.- No other user-facing error string in
internal/names aplatform#issue. - The
errnotes.goallowlist entry now makes the old suffix optional.serverNoteREis anchored (^…(?:; |$)), so text stored before this change passes only when the suffix matches in full, and the new text passes without it. Both are accepted bare and after theexecution <id>:prefix. TestSanitizeStoredError_AllowlistedNotesPassThroughVerbatimpins all four forms.
Run now on an empty step (#1708 item 2).
- The button is now
aria-disabled="true"with anis-disabledstyle instead ofdisabled, so it stays focusable and itsaria-labelandtitle("Run now: this step has no recommendations, so there is nothing to run") are reachable by keyboard and screen readers. - Activating it, by click, Enter or Space, which a button gets natively, runs the existing
has_recommendations === falseguard: an info toast, no confirm and no API call. runPlannedPurchaseNownow returnsfalsefor that case, sohandlePlannedPurchaseActionskips the reload and focus stays on the button.
The Plan and Scheduled Date filters (#1680).
- Both use the existing column-filter machinery: new
PlansColumnIdmembers, the categorical value, the label and the numeric and precision cases. - Scheduled Date is keyed by
localDayKey: a bareYYYY-MM-DDkey is kept, and a timestamp becomes its local calendar day. Same-day steps therefore share one option, and the keys sort chronologically. - Option labels go through
formatDate. ItsparseDateInputreads a bareYYYY-MM-DDas local midnight (utils.ts), so an option shows the same calendar day as the table cell in every time zone, with no off-by-one west of UTC.
The ramp "of target" label (#1680). The wording is accurate. RampSchedule.GetCurrentCoverage is baseCoverage * CumulativePercent / 100, and CumulativePercent is step * PercentPerStep capped at 100 (internal/config/types.go:303-321). Each step's percentage is therefore a share of the plan's target coverage, as the custom field ("Coverage per step (% of target)") and the preset descriptions now say. The computation is unchanged.
Placeholders and the name width (#1680).
- Empty Count, Upfront and Est. Savings cells render one muted
NO_VALUEin the right-alignedtd.num, including the all-upfront $0 case (upfrontCell === NO_VALUE). - The plan name moves from the narrow
cell-truncate--smto.plan-name-cell:max-width: 24remwith an ellipsis and the full name intitle.
The new tests fail on main.
- Go: with the three changed Go sources at the base,
TestHandler_retryPurchase_EmptyPlanStepMessageHasNoInternalRefandTestErrPlanStepNoRecommendations_NamesNoInternalIssuefail. The errnotes legacy-text cases pass at the base, as expected, since the base sentinel still carries the suffix. - jest: with
plans.ts,state.ts,index.htmlandtables.cssat the base, all 12 new tests fail: the filter triggers, narrowing, same-day collapse, chronological order, both ramp labels,aria-disabled, the placeholder style, the name not clamped, focus kept with no refetch, the $0 placeholder, and no API call. - Playwright:
plan-name-width.spec.tspasses against main's bundle, because main clamps the name narrowly and never overflows. It fails with only the new CSS reverted (Expected: <= 1641, Received: 2120), which is the intermediate regression the PR body names. The original "name cut off" bug is pinned by the jest test "the plan name is not clamped to the small truncate width".
Mutation probes (each run in my clone and reverted): 13 of 13 were killed.
| Mutation | Result |
|---|---|
| Stored old text no longer allowlisted | killed |
| New text no longer allowlisted | killed |
| Retry 409 names the issue again | killed |
disabled instead of aria-disabled |
killed (3) |
| An empty-step click reloads the list | killed |
| Date filter keyed by the raw timestamp | killed (same-day collapse) |
| Plan filter has a single empty value | killed |
| All-upfront $0 keeps the unstyled dash | killed |
| Ramp label reverted | killed |
Local verification at this SHA (macOS, under the review lock):
go build ./...andgo vetsucceed, andgo test -count=1 ./internal/api ./internal/purchasepasses;npm cisucceeds;- jest gives 187 suites, 4832 passed and 1 skipped;
- lint reports 0 errors (141 existing warnings), and typecheck and build succeed;
- Playwright
plan-name-widthandplans-column-filter-popoverwithCI=1: 3 passed.
CI at this SHA: 41 checks pass, CodeRabbit is NEUTRAL, and the merge state is CLEAN.
Not merging.
Cold review verdict: APPROVE at e214fc8Reviewer: claude-as-qa-lead. I didn't write this change. The 409 empty-step text
Run now on an empty step
Plan and Scheduled Date filters
Ramp wording"25% of target each week, 4 weeks" and "10% … each month, 10 months" both add up to 100%, and the computation is unchanged. Tests fail on main (current main 1a95098)
Gate at this head (scratch worktree)
The worktree's Note (not a blocker)
|
|
Merge gate at e214fc8:
|
Closes #1680
Closes #1708
Plans page polish (#1680) plus the follow-ups from the #1706 review (#1708). Both touch
frontend/src/plans.ts, so they are one PR.Changes
#1708: empty-step run-now follow-ups
ErrPlanStepNoRecommendations(internal/purchase/execution.go) and the retry refusal (internal/api/handler_purchases.go,retryPurchase) no longer end with "(platform#631: …)". The feat(plans): plan steps resolve real recommendations and show real counts and prices (tier B of #609) #631 reference moved to a code comment.internal/purchase/errnotes.goaccepts both the old and the new message, bare and after theexecution <id>:prefix. Tests cover both.aria-disabled="true"with anis-disabledstyle instead of thedisabledattribute. It stays focusable, so keyboard and screen-reader users can read its label: "Run now: this step has no recommendations, so there is nothing to run".#1680: Planned Purchases and plan form
.plan-name-cell(max-width: 24rem, ellipsis, full name intitle) instead of the narrowcell-truncate--sm. A 100-character name (the maximum) no longer widens the table past its wrapper. New Playwright specplan-name-width.spec.ts.aria-labelandtitle, as verified during QA.Tests
#) and errnotes tests (old text and new text).aria-disabled, no API call, no refetch and focus kept; placeholders including the $0 all-upfront branch; Plan and Scheduled Date filters including same-day collapse and chronological order; ramp labels.plan-name-width.spec.ts.plans.ts.has_recommendationsguard, restoring the reload after the empty-step click, and removing theNO_VALUEplaceholder branch each fail a test.Local verification (macOS, rebased on main ecb118e)
go build ./...: ok.go test ./internal/api ./internal/purchase: ok.tsc --noEmitclean; build compiled.plan-name-width,plans-column-filter-popover,narrow-width-layoutandmoney-columns: 17 passed (CI=1).Labels
The union of #1680 and #1708:
priority/p3,severity/low,urgency/eventually,effort/s,impact/many,impact/few,type/ux,type/bug,triaged.🤖 Generated with Claude Code