Skip to content

feat(ui): analytics dashboard time-window selector (#2199) - #5268

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
RealDiligent:feat/ui-analytics-window-2199
Jul 12, 2026
Merged

feat(ui): analytics dashboard time-window selector (#2199)#5268
JSONbored merged 1 commit into
JSONbored:mainfrom
RealDiligent:feat/ui-analytics-window-2199

Conversation

@RealDiligent

Copy link
Copy Markdown
Contributor

Summary

  • Add 7d / 30d / 90d ToggleGroup to the /app/analytics header
  • Thread the selected window through useApiResource(operatorDashboardPath(days)) so usage summary + command-usefulness re-fetch on change
  • Persist the choice in local storage; restore on reload
  • Backend: honor ?days= on GET /v1/app/operator-dashboard and clamp to supported windows

Scope note: gate-precision, cycle-time, fleet, recommendation-quality, calibration, slop calibration, and MCP adoption keep their existing fixed lookbacks. Only usage summary metrics and command usefulness follow the selector.

Closes #2199

Test plan

UI Evidence

Page / Feature Before After
/app/analytics header
before: fixed window, no selector

after: 7d/30d/90d toggle drives usage fetch

@RealDiligent
RealDiligent requested a review from JSONbored as a code owner July 12, 2026 12:46
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.36%. Comparing base (864c52d) to head (53cd769).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5268      +/-   ##
==========================================
- Coverage   94.37%   94.36%   -0.01%     
==========================================
  Files         474      474              
  Lines       40114    40122       +8     
  Branches    14627    14629       +2     
==========================================
+ Hits        37856    37863       +7     
  Misses       1583     1583              
- Partials      675      676       +1     
Flag Coverage Δ
shard-1 46.28% <80.00%> (-0.14%) ⬇️
shard-2 34.73% <10.00%> (+<0.01%) ⬆️
shard-3 32.04% <10.00%> (-0.05%) ⬇️
shard-4 31.81% <10.00%> (-0.27%) ⬇️
shard-5 33.59% <10.00%> (-0.08%) ⬇️
shard-6 45.07% <100.00%> (+0.31%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/api/routes.ts 94.30% <100.00%> (+<0.01%) ⬆️
src/services/operator-dashboard.ts 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Add a persisted 7d/30d/90d toggle on /app/analytics that re-keys the
operator-dashboard fetch and threads days through the backend payload.

Closes JSONbored#2199

Co-authored-by: Cursor <cursoragent@cursor.com>
@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 12, 2026
@loopover-orb

loopover-orb Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-12 12:54:43 UTC

6 files · 1 AI reviewer · no blockers · readiness 100/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review: This PR changes guardrail-protected path(s): src/services/operator-dashboard.ts (matched src/services/**).

Review summary
This PR threads a user-selectable 7/30/90 day window through the analytics dashboard: a new ToggleGroup UI persisted to localStorage, a query param on the operator-dashboard route clamped server-side, and the window value flowing into usage-summary and command-usefulness while gate-precision/cycle-time/fleet/recommendation-quality intentionally stay pinned to a 90-day constant. The wiring is coherent end-to-end (route → clamp → payload → fetch path → localStorage restore) and is reasonably tested with both unit and integration coverage. One inconsistency: `weeklyValueReport`'s `days` field is silently switched from the fixed `USAGE_WINDOW_DAYS` to the user-selected `windowDays` even though the PR's own scope note says only usage-summary metrics and command usefulness should follow the selector — worth confirming `buildWeeklyValueReport` tolerates a non-7 'days' value without breaking its weekly framing.

Nits — 6 non-blocking
  • src/services/operator-dashboard.ts: `weeklyValueReport`'s `days: windowDays` change isn't mentioned in the PR's scope note (which lists only usage summary + command usefulness as window-driven) — confirm `buildWeeklyValueReport` handles days=30/90 correctly, since a 'weekly' report built on a 90-day window may misrepresent rates if it assumes ~7-day normalization internally.
  • test/unit/operator-dashboard.test.ts: the test titled 'keeps gate-precision and cycle-time cards on a fixed 90d lookback when windowDays is 7' only asserts empty gateEval/cycleTime output (because the test env has no data) — it doesn't actually verify `computeGateEval`/`computeCycleTimeAggregate` were called with `GATE_ANALYTICS_WINDOW_DAYS` rather than the passed-in `windowDays`; a spy or non-empty fixture would make this test meaningful.
  • src/services/operator-dashboard.ts:283-286: the 7/30/90 day-length arithmetic (`24*60*60*1000`) is repeated inline for both `usageSince` and `mcpSince` — consider a shared `daysToMs` helper to avoid magic-number drift.
  • apps/gittensory-ui/src/routes/app.analytics.tsx: the ToggleGroup is only rendered once `windowHydrated` is true, which can cause a layout shift/flash on first paint before localStorage resolves — consider a fixed-size skeleton placeholder instead of `null`.
  • Add a spy-based assertion (e.g. mock `computeGateEval`) in test/unit/operator-dashboard.test.ts to prove the 90d constant is actually what's passed, not just that outputs happen to be empty.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #2199
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 303 registered-repo PR(s), 143 merged, 23 issue(s).
Contributor context ✅ Confirmed Gittensor contributor RealDiligent; Gittensor profile; 303 PR(s), 23 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Improvement ✅ Minor risk: clean · value: minor — Code changes are accompanied by test evidence.
Review context
  • Author: RealDiligent
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 303 PR(s), 23 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
[BETA] Chat with Gittensory

Ask Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @gittensory ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @gittensory chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @gittensory mention with a real question is routed to the closest matching read-only command automatically -- no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/app/analytics desktop before /app/analytics after /app/analytics
/app/analytics mobile before /app/analytics (mobile) after /app/analytics (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@JSONbored JSONbored left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving forward, please use the AI skill found in the repo when including screenshots, as in the next day or so, screenshot/recording evidence will be enforced by gittensory-orb when submitting PRs that touch frontend code.

Your submitted screenshots are embedded as PNGs that need to be downloaded, which I don't do for security reasons.

Merging.

@JSONbored
JSONbored merged commit 96e1557 into JSONbored:main Jul 12, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

feat(ui): time-window selector for the analytics dashboard

2 participants