Repository navigation
feat: overview page comparing metrics and events across websites - #4514
CorCvusRamboChen wants to merge 4 commits into
Conversation
|
@RamboChenUnimelb is attempting to deploy a commit to the Umami Software Team on Vercel. A member of the Team first needs to authorize it. |
39c4921 to
197cedc
Compare
88e54f1 to
7ae00d5
Compare
[Medium impact] The PR adds a cross-website analytics view for users who can already access those sites. Fix the chart's timezone mismatch before merging. Findings
SummaryAdds an Overview page for comparing views, visitors, and custom events across websites.
The previous-review ancestry and merge-base checks did not pass, so this review used the full PR diff. All supplied previous threads were unnumbered; none require numbered ledger entries. CorCvusRamboChen acknowledged the website cap and pagination as open decisions. Reviews (2) · Last reviewed commit: "fix(overview): respect share sections an..." · Reviewed by Greptile |
Adds an Overview page (sidebar entry next to Websites) that shows several websites on one chart and one totals table: multi-select of the websites the user can view, a metric select covering Views, Visitors and any custom event name found in the data, a chart-type toggle (stacked bars, lines, stacked area), and the standard date filter including "All time" across the selected sites. Backend is a single endpoint, GET /api/websites/overview, that composes the existing getPageviewStats / getSessionStats / getEventStats / getWebsiteDateRange per website and is gated by canViewBatchWebsites, the same pattern as /api/websites/charts. No migrations, no new dependencies, no new i18n keys (reuses label.overview / label.chart); works on Prisma and ClickHouse alike.
`labels.metrics` was never defined, so the text above the metric picker fell back to the raw message id. `labels` is typed `Record<string, string>`, which is why nothing caught it: a missing key is not a type error, it is `undefined` reaching `t()` at runtime. The chart-type toggle showed only icons and carried its internal ids -- `bar`, `line`, `area` -- as aria-labels, so a screen reader read out the ids. They now have names of their own. The lookup sits inside the component because `labels` comes from the hook, not from module scope. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… once Addresses the review on umami-software#4514. API (/api/websites/overview): - A share token is now held to the sections it shares, as on the single-website routes: views and visitors need `overview`/`compare`, event counts need `events`. Previously any token that included the website got every custom event name and count. - Each website's filters go through setWebsiteDate, so the cloud plan's history limit and a website's reset date apply here too. The filters are built per website rather than shared across Promise.all. - Returns a period-wide `visitors` total from getWebsiteStats. Page: - The table's visitor total uses that figure. Summing the per-bucket `sessions` series counted a visitor once per hour/day they appeared in, and the total changed with the chart's time unit. - With All time selected, changing the website selection now follows the new websites' combined range instead of keeping the old dates. - Custom event metric ids carry an `event:` prefix, so events named `pageviews` or `visitors` no longer collide with the built-in metrics. Also: - The four new labels are added to every locale with the English text as a placeholder, so `check:messages` reports nothing missing. - getWebsiteStats was typed as returning an array, but every branch returns `result?.[0]`; the declared type now matches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7ae00d5 to
3b9f580
Compare
|
Thanks for the review. All six findings are addressed in 3b9f580 (replies on each thread):
Verified locally on the branch: @greptileai review |
useDateRange() defaulted to the browser's timezone while useDateParameters() builds the request in the user's saved timezone. When the two fall on different days, "Today" fetched one day's counts and drew another day's buckets, so the chart could be empty while the table had totals. Pass the saved timezone through, as the other report pages do. Addresses the follow-up review on umami-software#4514. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Refs #4513
What
Adds an Overview page that puts several websites on one chart and one table, so an instance that
hosts a family of related sites can answer "which site grew?" without opening each website page.
src/app/(main)/overview/— page + client component: website multi-select (defaults to everywebsite the user can view), metric select (Views / Visitors / any custom event name found in the
data), the standard
DateFilterwith an "All time" option, aBarChartwith a chart-type toggle(stacked bars / lines / stacked area, one colour per website), and a totals table (views,
visitors, one column per event name) with a column picker in the page header that is remembered
per browser.
src/app/api/websites/overview/route.ts—GET /api/websites/overview?ids=&startAt=&endAt=&unit=&timezone=.Composes the existing
getPageviewStats,getSessionStats,getEventStats,getWebsiteStatsand
getWebsiteDateRangeper website. Authorisation viacanViewBatchWebsites, mirroring/api/websites/charts, pluscanViewWebsiteSectionper website so a share token only gets thesections it shares (
overview/comparefor views and visitors,eventsfor event counts).Each website's dates go through
setWebsiteDate, like the single-website routes. Forbidden orunknown ids are dropped, not rejected.
SideNav.tsx/MobileNav.tsx— one entry each, reusing the existinglabel.overviewkey.Why
Dashboard and Boards give one widget per website: independent charts with independent axes and no
stacking or totals, and no way to switch all of them to the same custom event. The Websites list's
sparkline is fixed to visitors over seven days. Comparing sites day by day currently means opening
each website in its own tab. See the linked issue for the full use case.
Open questions
/api/websites/charts; fine, or should it page?Notes for review
@umami/react-zenandChart.js. Four newi18n keys:
label.metricsfor the metric picker, and names for the three chart types so theicon-only toggle is not read out as
bar/line/area. They are added to every locale withthe English text as a placeholder, so
check:messagesreports nothing missing.idsis capped at 20 like/api/websites/charts.needs configuring per instance.
getWebsiteStats, not a sum ofthe per-bucket
sessionsseries, so it matches a single website's stats and does not changewith the chart's time unit.
getWebsiteStatswas declared as returningWebsiteStatsData[], but every branch returnsresult?.[0]; the declared type is corrected toWebsiteStatsData.dev.tsc --noEmitand Biome are clean for the changed files;vitest runshows the same 3 failing tests on this branch as on
dev(none in files this PR touches).Screenshots
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.