Skip to content

feat(websites): add sorting and results-per-page controls to website list#4118

Open
Yashh56 wants to merge 13 commits intoumami-software:devfrom
Yashh56:sorting-pagination
Open

feat(websites): add sorting and results-per-page controls to website list#4118
Yashh56 wants to merge 13 commits intoumami-software:devfrom
Yashh56:sorting-pagination

Conversation

@Yashh56
Copy link
Copy Markdown
Contributor

@Yashh56 Yashh56 commented Mar 30, 2026

This pull request introduces sorting and paging enhancements to the websites data table, enabling users to sort websites by visitors, pageviews, name, or domain, and to select the number of results per page. It also updates the backend API and query logic to support these new features, including activity-based sorting (by visitors or pageviews) that uses recent statistics. Additionally, internationalization labels and schema definitions have been updated to accommodate these UI changes.

Frontend: Table Sorting & Paging UI

  • Added sorting and results-per-page selectors to the WebsitesDataTable, allowing users to sort by visitors, pageviews, name, or domain, and to choose how many results are displayed per page. These selections update the URL parameters and trigger new queries. (src/app/(main)/websites/WebsitesDataTable.tsx, [1] [2] [3] [4]

Backend: API & Schema Updates

  • Enhanced API endpoints for websites to accept new query parameters for sorting (orderBy, sortDescending) and paging, and to handle timezone-aware queries. The schema was updated to parse and validate these parameters. (src/app/api/websites/route.ts, src/app/api/me/websites/route.ts, src/app/api/users/[userId]/websites/route.ts, src/app/api/teams/[teamId]/websites/route.ts, src/lib/schema.tsR84-R87)

Backend: Activity-based Sorting Logic

  • Implemented logic in the Prisma website query layer to support sorting websites by activity (visitors or pageviews) over the current day, using timezone-aware date ranges. This includes a new helper to fetch and sort by recent activity stats. (src/queries/prisma/website.ts, [1] [2] [3] [4]

Backend: Website List Stats Query

  • Added a new SQL query (getWebsiteListStats) to efficiently aggregate pageview and visitor counts per website for a given date range, supporting both relational and ClickHouse backends. (src/queries/sql/getWebsiteListStats.ts, [1] [2]

Internationalization

  • Added new i18n labels for sorting, results per page, and activity-based sorting options to support the enhanced UI. (public/intl/messages/en-US.json, src/components/messages.ts, [1] [2] [3] [4]

Close : #4102

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 30, 2026

@Yashh56 is attempting to deploy a commit to the Umami Software Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 30, 2026

Greptile Summary

This PR adds sorting (by visitors, pageviews, name, domain) and results-per-page controls to the website list, backed by new Prisma query logic and three new SQL helpers. Of the six concerns raised in previous threads, five are now addressed: startDate/endDate are validated by the typed WebsiteListStatsFilters interface, orderBy is constrained to an enum, the default-sort fallback uses an explicit DEFAULT_SORT_ID constant, the visitors subquery is properly scoped to the user's websites via websiteFilterWhereClause, and the null return for ClickHouse+pageviews is now explicit rather than implicit. The one remaining concern from prior threads — getWebsitesByActivityFallback loading every matching website into Node memory before sorting and slicing, which runs for every ClickHouse deployment when sorting by pageviews — is still unresolved.

Confidence Score: 4/5

Safe to merge for PostgreSQL deployments; ClickHouse+pageviews sort still falls back to a full in-memory load of all matching websites.

Five of six prior P1 concerns are resolved, showing strong convergence. The remaining issue — in-memory pagination for ClickHouse pageviews sort via getWebsitesByActivityFallback — is a production reliability risk on ClickHouse deployments with large website counts and keeps the score at 4 rather than 5.

src/queries/prisma/website.ts — specifically getWebsitesByActivityFallback and its interaction with getActivityOrderQuery returning null for ClickHouse+pageviews.

Important Files Changed

Filename Overview
src/queries/prisma/website.ts Most complex file in the PR; adds activity-sorted pagination via raw SQL (fetchActivitySortedWebsitePage) and a metrics decoration layer. The primary path (PostgreSQL + visitors/pageviews) is correctly scoped with WHERE website_id IN (...). The fallback path (getWebsitesByActivityFallback) still loads all website rows into Node memory before sorting, which is triggered on every ClickHouse deployment when orderBy='pageviews'.
src/queries/sql/getWebsiteListStats.ts New SQL helper that aggregates pageviews/visitors/visits/bounces per website for a date range. Both Postgres and ClickHouse variants are present; dates are validated with getRequiredDateRange (addresses the prior thread concern about undefined dates).
src/queries/sql/getWebsiteListActivity.ts New SQL helper returning 7-day bucket activity per website. getRequiredDateRange throws on invalid dates; formatResults assembles the fixed-length 7-bucket array which aligns with WebsiteActivitySparkline on the frontend.
src/queries/sql/getWebsiteListActiveVisitors.ts New SQL helper counting distinct sessions active in the last 5 minutes per website; both relational and ClickHouse variants look correct.
src/app/(main)/websites/WebsitesDataTable.tsx Adds sort selector and results-per-page control. Default sort is now expressed as an explicit DEFAULT_SORT_ID constant, resolving the prior array-index fallback concern. Sort/pageSize changes update URL params correctly.
src/app/(main)/websites/WebsitesTable.tsx Adds optional metrics columns (visitors, pageviews, bounce rate, change, sparkline, status) behind the showStats prop. New sub-components are self-contained and correct.
src/lib/schema.ts Adds websiteOrderByParam (an explicit enum) and websiteSortingParams, addressing the prior concern about unconstrained orderBy strings. Also adds sortDescending parsing to sortingParams.
src/app/api/me/websites/route.ts Routes updated to accept websiteSortingParams, timezoneParam, and includeMetrics; all are passed through to the query layer.
src/app/api/websites/route.ts Same route augmentation pattern as /me/websites; consistent and correct.
src/app/api/teams/[teamId]/websites/route.ts Same route augmentation pattern; consistent and correct.
src/app/api/users/[userId]/websites/route.ts Same route augmentation pattern; consistent and correct.
public/intl/messages/en-US.json Adds labels for sort-by, results-per-page, most-visitors-today, most-views-today, active, inactive, change, status; all referenced in the updated components.
src/components/messages.ts Maps new label keys used in WebsitesDataTable and WebsitesTable; entries are consistent with en-US.json additions.
src/queries/sql/index.ts Re-exports the three new SQL helpers; no issues.
src/app/(main)/websites/WebsitesPage.tsx Passes showStats to WebsitesDataTable, enabling metrics columns on the main websites page.

Sequence Diagram

sequenceDiagram
    participant UI as WebsitesDataTable
    participant API as /me/websites (GET)
    participant GW as getWebsites()
    participant ACT as fetchActivitySortedWebsitePage()
    participant FB as getWebsitesByActivityFallback()
    participant DEC as decorateWebsiteList()
    participant SQL as SQL helpers

    UI->>API: orderBy, sortDescending, pageSize, timezone, includeMetrics
    API->>GW: filters (parsed + validated)
    alt orderBy is visitors or pageviews
        GW->>ACT: criteria, filters
        alt PostgreSQL (or ClickHouse + visitors)
            ACT->>SQL: rawQuery — COUNT + activity LEFT JOIN, LIMIT/OFFSET
            ACT-->>GW: {ids[], count, page, pageSize}
            GW->>SQL: findMany WHERE id IN (ids[])
        else ClickHouse + pageviews
            ACT-->>GW: null
            GW->>FB: criteria, filters
            FB->>SQL: findMany (ALL websites, no pagination)
            FB->>SQL: getWebsiteListStats (sort key)
            FB-->>GW: sorted + sliced page
        end
        alt includeMetrics = true
            GW->>DEC: attachMetricsToWebsites
            DEC->>SQL: getWebsiteListStats (today)
            DEC->>SQL: getWebsiteListStats (yesterday)
            DEC->>SQL: getWebsiteListActivity (7 days)
            DEC->>SQL: getWebsiteListActiveVisitors (last 5 min)
        end
    else orderBy is name or domain (or absent)
        GW->>SQL: pagedQuery (DB-level ORDER BY + LIMIT/OFFSET)
        opt includeMetrics = true
            GW->>DEC: attachMetricsToWebsites (4 parallel queries)
        end
    end
    GW-->>API: {data[], count, page, pageSize, metrics?}
    API-->>UI: JSON response
Loading

Reviews (7): Last reviewed commit: "fix(websites): validate website list sor..." | Re-trigger Greptile

Comment thread src/queries/prisma/website.ts Outdated
Comment thread src/queries/sql/getWebsiteListStats.ts Outdated
Comment thread src/app/(main)/websites/WebsitesDataTable.tsx
Comment thread src/lib/schema.ts
@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Mar 30, 2026

@greptileai

Comment thread src/queries/prisma/website.ts
@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Mar 30, 2026

@greptileai

@boutterudy
Copy link
Copy Markdown
Contributor

@Yashh56 That looks like a really cool feature! Well done and thanks for all your hard work! 💪🤩

Just out of curiosity, could you please add a demo video or some screenshots? I’d love to see what the end result looks like 👀

@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Apr 3, 2026

@greptileai

Comment thread src/queries/prisma/website.ts
@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Apr 3, 2026

@greptileai

@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Apr 3, 2026

@greptileai

@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Apr 3, 2026

@greptileai

@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Apr 3, 2026

Screenshot 2026-04-03 184255

@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Apr 3, 2026

Hi @franciscao633 and @mikecao, could you please take a look and share your feedback?

@Yashh56
Copy link
Copy Markdown
Contributor Author

Yashh56 commented Apr 18, 2026

@franciscao633, @mikecao

@God-2077
Copy link
Copy Markdown
Contributor

God-2077 commented Apr 20, 2026

This PR looks really nice. I’ve noticed that many PRs just sit around without getting reviewed these days. I submitted a translation PR two months ago, and it’s still waiting for a review with no one taking a look at it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants