Repository navigation
fix(frontend): scope Home upcoming purchases to the provider chip - #1365
Merged
Merged
Conversation
The upcoming widget kept listing every provider's scheduled purchases
while the rest of Home followed the topbar chips, so it could disagree
with the page it sits on. GET /api/dashboard/upcoming takes no filter
parameters, but every row carries its plan's provider, so the provider
chip is applied client-side and an empty result names the filter
("No upcoming scheduled purchases for GCP"). Rows carry no account, so
the account chip cannot be applied here; a short note above the rows
says so instead of silently ignoring it. Both can move server-side once
the endpoint accepts the chip state.
The Retry path from the earlier error-state fix goes through the same
renderer, so it applies the same scope.
Refs LeanerCloud#713
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Conflicts: - frontend/src/dashboard.ts: import block. This branch added the lib/upcoming-scope import; main (LeanerCloud#1323) added formatTrendTooltipTitle to the chart-utils import. Kept both: the upcoming-scope import plus the widened chart-utils import. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No textual conflicts. Checked main's LeanerCloud#1397 (getUpcomingPurchases now typed as the { purchases } envelope; dashboard UpcomingPurchase is an alias of the API type): lib/upcoming-scope.ts and renderUpcomingPurchases still typecheck against it, and the provider scope applies to data?.purchases on both the initial load and the Retry path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts: - frontend/src/dashboard.ts: import block only. Kept this branch's lib/upcoming-scope import and took main's widened chart-utils import (formatSparseTrendMessage, MIN_TREND_POINTS from LeanerCloud#1334). renderUpcomingPurchases merged cleanly with main's LeanerCloud#1376 formatter changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No conflicts: main's LeanerCloud#1387 (ladder timeline) merged cleanly and touches no file this branch changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): APPROVE Blocking:
|
Collaborator
Author
|
Local verification at
|
IAmJSD
marked this pull request as ready for review
October 24, 2026 22:06
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 |
IAmJSD
added a commit
to IAmJSD/cloud-commitments-platform
that referenced
this pull request
Oct 24, 2026
Brings in LeanerCloud#1365, LeanerCloud#1381, LeanerCloud#1378 and LeanerCloud#1389. No conflicts; index.html auto-merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
IAmJSD
added a commit
to IAmJSD/cloud-commitments-platform
that referenced
this pull request
Oct 24, 2026
Conflicts: - frontend/src/dashboard.ts: import block only. Kept this branch's buildKpiTile import (lib/kpi-tile) and main's upcoming-scope import (LeanerCloud#1365) side by side. No body conflicts; main's onboarding, upcoming scope and chart a11y changes merged cleanly around the kpi-tile loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
IAmJSD
added a commit
to IAmJSD/cloud-commitments-platform
that referenced
this pull request
Oct 24, 2026
Conflicts:
- frontend/src/dashboard.ts:
- imports: kept this branch's filterByEnabledProviders import and all of
main's new imports (upcoming-scope LeanerCloud#1365, sparse-trend helpers LeanerCloud#1334,
chart-a11y LeanerCloud#1381, first-run empty state LeanerCloud#1389).
- loadDashboard Promise.allSettled: combined both sides into five
fetches; this branch's loadEnabledProviders() (LeanerCloud#180) plus main's
listAccountsMinimal() for the first-run onboarding card (LeanerCloud#1389).
- call site: kept renderDashboardSummary(summaryData, recs, recsCount)
and main's renderHomeOnboarding(...). The onboarding check uses the
Enabled-Providers-filtered recs, matching the Opportunities first-run
check, which also runs on the preference-filtered list.
- helpers: kept both loadEnabledProviders() and main's
renderHomeOnboarding(); renderDashboardSummary keeps this branch's
recsCount parameter.
- savings tile detail: this branch's filtered count with main's
NO_VALUE placeholder (LeanerCloud#1376): recsCount ?? total_recommendations ??
NO_VALUE; Active Commitments takes main's NO_VALUE.
- frontend/src/recommendations.ts: import block; main's NO_VALUE added to
the utils import, kept this branch's enabled-providers import.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The failed-fetch half of this issue was handled by #1186. The other half remained: the Home "Upcoming Scheduled Purchases" widget ignored the Provider and Account chips, so with Provider = AWS it still listed Azure purchases. This PR applies the provider chip client-side and adds a note that the account chip does not apply to this widget, since the rows carry no account and the endpoint takes no filter parameters.
Refs #713
Partial: account scoping needs filter parameters on
GET /api/dashboard/upcoming(backend), after which the frontend can pass the chip state and drop the note.What changed
frontend/src/lib/upcoming-scope.ts:scopeUpcomingToProvider()filters rows by the provider chip (empty or "all" keeps everything, case-insensitive).upcomingEmptyMessage()names the provider when the filter empties the list.UPCOMING_ACCOUNT_SCOPE_NOTE.frontend/src/dashboard.tsrenderUpcomingPurchases(): applies the provider scope (the Retry path goes through the same renderer), builds the empty state with DOM calls instead ofinnerHTML, and when an account chip is active and rows exist, shows a muted note above the cards. The View Details index is built from the scoped rows.src/__tests__/dashboard-upcoming-scope-713.test.ts.Why this approach
The API rows already carry
provider, so provider scoping is a correct, standalone frontend change. Account scoping cannot be done client-side, andgetUpcomingPurchases(internal/api/handler_dashboard.go) takes no filter parameters. Rather than send query params the backend ignores and guess the future contract, the widget says the account filter does not apply, which removes the silent disagreement. The new logic lives in a small lib module becausedashboard.tsis already about 1300 lines.Screenshots
Before is main (
a14dc8f2), after is this branch. Both are headless Chromium at 1440x900 against the repo's mocked e2e API. The chips are set via the URL (?provider=...&account=...); KPI tiles and charts are hidden in the shots only so the chips and the widget fit in one frame.Verification
Run on this branch's head
210de5c7on top of maina14dc8f2.npm run lint: 0 errors (142 pre-existing warnings, none in changed files). Typecheck and build pass.dashboard-upcoming-scope-713.test.ts: 9 tests (helpers, plus theloadDashboardrender path with no chips, provider chip, provider with no matches, account note, account plus empty, Retry applying the scope); also passes with--randomize.scripts/test-git-secrets-allowlist.sh: 137 PASS, 0 FAIL.Notes for review
GET /api/dashboard/upcoming(for exampleproviderandaccount_ids, as/dashboard/summarytakes), then pass the chip state from the frontend and remove the note.upcomingFromExecution), so a hypothetical multi-provider plan would be filtered by that one provider.Overlaps
getUpcomingPurchasescall sites indashboard.ts.git merge-treeshows a clean merge (it aliases theUpcomingPurchasetype thatlib/upcoming-scope.tsimports, which stays compatible), but they should land one after the other.dashboard.ts. fix(frontend): undefined button classes and grey default button break the button system #695's branch edits the Cancel button in the same renderer (trivial conflict). fix(frontend): impossible/placeholder values surfaced for scheduled and pending purchases #181's branch merges cleanly.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