[WIP]: feat(usage-dashboard): usage dashboard prototype: show every state on fixture data - #8192
[WIP]: feat(usage-dashboard): usage dashboard prototype: show every state on fixture data#8192talissoncosta wants to merge 33 commits into
Conversation
Reframes OrganisationUsagePage with a "usage vs plan limit" summary: % of plan consumed, a meter, and a cumulative-vs-limit chart, all wired to the existing usage-data + max_api_calls (no backend change). Everything the API cannot feed yet is marked TODO(BE) and listed in the component so the diff doubles as the backend ask: reset date / billing period boundaries, the current-billing-period date-range bug, projection, grace-period status, and cost in currency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expands the prototype to the full v0.2 layout for the global view: billing-period strip, hero meter with Notify markers, stat tiles, cumulative usage-vs-limit chart (Area + plan-limit ReferenceLine + today dot), and the request-type breakdown. Global view now renders this in place of the old totals + bar chart; By SDK view is unchanged. Still wired only to existing data; reset date, projection and cost remain TODO(BE). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Swaps the hardcoded hex (accent/danger/success/warning + panel/border/ text/track) for the --color-* semantic tokens via common/theme/tokens, so the prototype flips correctly under .dark. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`_get_start_date_and_stop_date_for_subscribed_organisation` derived the current period start from relativedelta(...).months only, dropping the years component, so terms that started >12 months ago (annual plans) resolved to the wrong year. Add years*12, mirroring the existing PREVIOUS_BILLING_PERIOD branch, and cover the annual case with a test. Note: api env (uv) not available locally; needs CI to run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The reframed design drops the left "By Endpoint / By SDK" sidebar (SDK becomes a breakdown-dimension option instead), so remove the sidebar and the global/user-agents toggle from the page. Keep the Period/Project/Environment filters. Per the agreed behaviour, the plan limit is org-level, so the meter + cumulative chart use an org-wide query (period only) while Project/Environment filter a second query that feeds only the request-type breakdown. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Environment is a drill-down within a project and too granular for org-level usage; project is the meaningful pivot. Remove the environment select from UsageChartFilters and the page's filtered query. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the design: Usage title on the left, Period + Project selects on the right of the page header (dropping the separate labelled filter row). Give the surface a max-width and centre it instead of the left-aligned, narrow app-container layout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Recharts auto-scaled the y-axis to usage, so with tiny usage against a large limit the plan-limit ceiling fell off-screen and the "usage vs limit" comparison was lost. Fix the domain to [0, max(limit, usage)] so the ceiling is always visible (and over-limit usage still shows above it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The end marker's label was centred on the far-right point and half of it overflowed the panel; right-align it so it stays within bounds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a scenario switch backed by fixtures so the over-limit, restricted and grace states can be shown on demand, fills in the tiles that were printing "needs BE", and adds the notifications screen. Restores the existing usage page and puts the prototype behind the usage_billing_prototype flag, so nothing changes until the flag is on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe change fixes annual billing-period date calculation and adds a regression test. It extends Estimated code review effort: 5 (Critical) | ~120 minutes ✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8192 +/- ##
==========================================
+ Coverage 98.71% 98.73% +0.02%
==========================================
Files 1531 1556 +25
Lines 61234 61903 +669
==========================================
+ Hits 60446 61120 +674
+ Misses 788 783 -5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The branch is never merged, so gating it behind a flag only means creating one in Flagsmith before anyone can look at it. Check the branch out and the prototype is there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Swaps the hand-rolled pieces for what already exists: StatItem for the tiles, Chip for the grace status, BareButton for the state and screen switches, and Format.shortenNumber instead of a local copy. Adds progressbar semantics to the meter and group labels to the switches. The tile badges go with this: StatItem has no badge slot, so the state now reads from the meter colour, the banner and the chart. Whether StatItem should grow one is a question for #8185. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
StatItem and Chip pulled the page away from the design: the tiles lost their badge and sub-label and grew icon blocks, and the grace chip read as a flat pill. Both are back to the designed layout. Badges now follow the dot-and-label pattern from experiments/StatusBadge, which looks like where the app is heading. That component is typed to experiment statuses, so this is a local copy with a tone prop rather than a change to shared code. Generalising it is a question for #8185. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
StatItem was a label, a value and an icon block, so anything richer got hand-rolled next to it: the admin metrics cards render their sub-line in a <small> outside the component, and the usage prototype had its own tiles. It now carries its own card: label and optional badge on one line, the value, then an optional sub-line. The icon is optional, since dense rows of figures read better without one. Call sites: the admin metrics cards drop their external <small>, Billing loses the panel that was wrapping the limit cards, and the usage prototype uses StatItem instead of its own tiles. Stories cover the new slots. Lives on the prototype branch by choice, so it needs porting when this becomes real work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
One model for everyone: every org has a period, so the reset date, days remaining and the projection work the same way regardless of plan, and the selector offers billing periods to everybody. This is the target state, not what we enforce today. Free limits are still enforced on a rolling 30 days, so the backend change has to land with this or before it, otherwise the page shows a period nobody is measured against. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
55c386c moved everyone onto billing periods as the target state, on the assumption the backend change would land with it. It is not landing yet: Matt is still costing it, and free orgs have no Chargebee subscription at all, so there is no billing term to read. Until then the page has to describe what is actually enforced. Free plans are measured over a trailing 30 days (api/organisations/task_helpers.py), which has no start, no reset and no end to project to. So for a rolling window: - The period carries no reset date, no days remaining, and the selector offers the rolling options rather than billing periods. - The chart is daily volume rather than cumulative. Cumulative against a ceiling only reads correctly when the total resets; on a trailing window it can fall as old days drop off the back. Daily values come from the same cumulative series, so no second shape is needed from the API. - No projection, which is the part that misleads hardest. - The projection tile becomes "If you reach 100%", since free plans are restricted rather than charged. Paid is untouched. Cancelled subscriptions take the same rolling branch in the backend and have no fixture here yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Standardising the tiles: a trailing window has no end to run to, so the slot is left empty rather than filled with a substitute. Free plans get a shorter row. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every free fixture was over its limit, so the two states most free orgs are actually in could not be viewed, and those are the ones where the row is shortest. Adds free-healthy and free-approaching. The sub-line was doing six different jobs across the row: a denominator, a period, a date, a method, a consequence and a remedy. It now states the scope or boundary the value applies to, and nothing else. Method is what the Estimate badge is for, and advice belongs in the banner. - Projected: "by 17 Aug 2026" rather than "at the current run rate" - Overage: "for this billing period" rather than "charged at the end of it" - Restricted: "until usage drops or you upgrade". The banner already said service returns when usage falls back under the limit; the tile claimed only upgrading would do it. Rolling windows say allowance, not plan limit, matching the headline and the strip, and "last 30 days" rather than "this window". Drops resumesAt from free-restricted-now. It read "the period resets", which a trailing window never does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The banner said "flag serving pauses in N days". Nothing in the API can produce that number. The 7 day lag runs from the qualifying usage notification (organisations/tasks.py:303), and that date is not exposed, so the countdown was invented. Without a date the banner now says serving may be paused if usage stays over, which is what we can actually stand behind. free-countdown-dated keeps the version with a number, so the gap between what we can say today and what we want to say stays visible in the picker. Adds the state we never modelled: over the limit with grace already spent. That org has no countdown at all and can be cut off on the next task run, which is the most urgent message on the page, and we were jumping straight from countdown to restricted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The comment claimed the API only breaks usage down by request type. It does not. Every row of events_list carries labels.user_agent, so grouping by SDK needs no second request and no backend work. Project and environment are genuinely different: usage-data takes them as filters (project_id, environment_id) rather than as a grouping, so they need one request per key or a group_by parameter. That is an optimisation rather than a blocker, and the comment now says so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
usage-data takes project_id and environment_id as filters, so the data was always reachable, just one key at a time. The panel claimed the API could not break usage down this way, which was wrong. Both dimensions now fetch per key and sum. Only the visible dimension is fetched, so the dimension moved up to the page next to the other query state. Environments belong to projects, so with no project selected this would fan out to every project times every environment. The panel asks for a project instead of doing that. A group_by on usage-data would turn each of these into one request. That is an optimisation now rather than the thing blocking the feature. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The page showed 75 and 100. The backend notifies on 75, 90, 100, 120, 200, 300, 400 and 500 (api/organisations/constants.py). Two of eight. That matters more now notifications are scoped to a page that states what we do rather than one that configures it. A read-only page listing two thresholds would be wrong on its only job. The meter draws the ones at or below 100, since above the limit it is already full and they would stack at the far end. The notifications list carries all eight. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The prototype had the same plan-name inference as the shipped page, so fixing one and not the other left the branch that is meant to show the target behaviour doing the wrong thing. Also drops the 90 day default on a rolling window. The prototype says "last 30 days" everywhere while asking the API for 90, so the picture and the copy were describing different windows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
organisations/{id}/api-usage-notification/ already returns percent_usage
and notified_at for the current period, and nothing in the frontend was
calling it. We had written off "days over limit" and the grace countdown
as needing new API work; they did not.
The earliest crossing at or above 100% is when the organisation went over,
so days over limit comes from it and the free grace window runs 7 days
from the same date.
Still missing, and still #8256: whether grace has already been spent. So
an organisation over the limit gets the countdown rather than the "grace
already used" state, which is the one that matters most.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Thanks for submitting a PR! Please check the boxes below:
docs/if required so people know about the feature.Changes
Contributes to #8184
Prototype, not for merge. It replaces the usage page on this branch so the v0.2 designs can be reviewed before we commit to building them. The production work is tracked under #8183.
The page runs on fixtures, so every designed state can be shown without depending on what an organisation has actually used:
A "Live data" option uses the real usage endpoints.
On the page: billing period with reset date and grace chip, "% of plan consumed" meter with notification markers, tiles that change per state, cumulative usage against the plan limit with a shaded overage zone and a dashed projection, request-type breakdown, and the notifications screen.
Reset date, grace state and cost are faked here. The API work that would make them real is in #8183.
Also included: the fix for #6099, current billing period ignoring terms longer than a year. One line and a test, no dependency on the prototype, and it can be split out to merge on its own.
How did you test this code?
Type checking and linting only. The page has not been rendered yet, I had no local API running to load it against.
To try it: check out the branch, run the frontend against an API, and open Organisation Settings, then Usage. The state switch at the top moves between the six fixtures, and the tabs move between the usage and notifications screens. Only "Live data" needs the API to return anything.