Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions public/intl/messages/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"account": "Account",
"action": "Action",
"actions": "Actions",
"active": "Active",
"activity": "Activity",
"add": "Add",
"add-board": "Add board",
Expand Down Expand Up @@ -51,6 +52,7 @@
"cohorts": "Cohorts",
"compare": "Compare",
"compare-dates": "Compare dates",
"change": "Change",
"confirm": "Confirm",
"confirm-password": "Confirm password",
"contains": "Contains",
Expand Down Expand Up @@ -153,6 +155,7 @@
"insights-description": "Dive deeper into your data by using segments and filters.",
"inp": "INP",
"invalid-url": "Invalid URL",
"inactive": "Inactive",
"is": "Is",
"is-false": "Is false",
"is-not": "Is not",
Expand Down Expand Up @@ -309,7 +312,9 @@
"sms": "SMS",
"source": "Source",
"sources": "Sources",
"sort-by": "Sort by",
"start-step": "Start Step",
"status": "Status",
"steps": "Steps",
"sum": "Sum",
"support": "Support",
Expand Down Expand Up @@ -342,6 +347,7 @@
"toggle-charts": "Toggle charts",
"total": "Total",
"total-records": "Total records",
"results-per-page": "Results per page",
"tracking-code": "Tracking code",
"traffic": "Traffic",
"transactions": "Transactions",
Expand Down Expand Up @@ -384,6 +390,8 @@
"visit-duration": "Visit duration",
"visitors": "Visitors",
"visits": "Visits",
"most-visitors-today": "Most visitors today",
"most-views-today": "Most views today",
"website": "Website",
"website-id": "Website ID",
"websites": "Websites",
Expand Down
132 changes: 126 additions & 6 deletions src/app/(main)/websites/WebsitesDataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,164 @@
import { Icon, Row } from '@umami/react-zen';
import { Icon, ListItem, Row, Select, Text } from '@umami/react-zen';
import Link from '@/components/common/Link';
import { DataGrid } from '@/components/common/DataGrid';
import { useLoginQuery, useNavigation, useUserWebsitesQuery } from '@/components/hooks';
import {
useLoginQuery,
useMessages,
useNavigation,
useTimezone,
useUserWebsitesQuery,
} from '@/components/hooks';
import { Favicon } from '@/index';
import { DEFAULT_PAGE_SIZE } from '@/lib/constants';
import { WebsitesTable } from './WebsitesTable';

const PAGE_SIZE_OPTIONS = [20, 50, 100];
const SORT_OPTIONS = [
{
id: 'visitors',
orderBy: 'visitors',
sortDescending: true,
},
{
id: 'pageviews',
orderBy: 'pageviews',
sortDescending: true,
},
{
id: 'name',
orderBy: 'name',
sortDescending: false,
},
{
id: 'domain',
orderBy: 'domain',
sortDescending: false,
},
] as const;
const DEFAULT_SORT_ID = 'visitors';
const DEFAULT_SORT = SORT_OPTIONS.find(option => option.id === DEFAULT_SORT_ID) || SORT_OPTIONS[0];

function getSortById(id?: string) {
return SORT_OPTIONS.find(option => option.id === id) || DEFAULT_SORT;
}

function getSelectedSort(orderBy?: string, sortDescending?: boolean | string) {
const isDescending = sortDescending === true || sortDescending === 'true';

return (
SORT_OPTIONS.find(
option => option.orderBy === orderBy && option.sortDescending === isDescending,
) || DEFAULT_SORT
);
}

export function WebsitesDataTable({
userId,
teamId,
allowEdit = true,
allowView = true,
showActions = true,
showStats = false,
}: {
userId?: string;
teamId?: string;
allowEdit?: boolean;
allowView?: boolean;
showActions?: boolean;
showStats?: boolean;
}) {
const { user } = useLoginQuery();
const queryResult = useUserWebsitesQuery({ userId: userId || user?.id, teamId });
const { renderUrl } = useNavigation();
const { t, labels } = useMessages();
const { renderUrl, router, query, updateParams } = useNavigation();
const { timezone, canonicalizeTimezone } = useTimezone();
const pageSize = Number(query.pageSize) || DEFAULT_PAGE_SIZE;
const selectedSort = getSelectedSort(query.orderBy, query.sortDescending);
const queryResult = useUserWebsitesQuery(
{ userId: userId || user?.id, teamId },
{
pageSize,
orderBy: selectedSort.orderBy,
sortDescending: selectedSort.sortDescending,
timezone: canonicalizeTimezone(timezone),
includeMetrics: showStats || undefined,
},
);

const renderLink = (row: any) => (
<Row alignItems="center" gap="3">
<Icon size="md" color="muted">
<Favicon domain={row.domain} />
</Icon>
<Link href={renderUrl(`/websites/${row.id}`, false)}>{row.name}</Link>
<Text truncate>
<Link href={renderUrl(`/websites/${row.id}`, false)}>{row.name}</Link>
</Text>
</Row>
);

const handlePageSizeChange = (value: string) => {
router.push(updateParams({ page: 1, pageSize: value }));
};

const handleSortChange = (value: string) => {
const sort = getSortById(value);
const isDefault = sort.id === DEFAULT_SORT_ID;

router.push(
updateParams({
page: 1,
orderBy: isDefault ? undefined : sort.orderBy,
sortDescending: isDefault ? undefined : sort.sortDescending ? 'true' : 'false',
}),
);
Comment thread
Yashh56 marked this conversation as resolved.
};

const renderActions = () => (
<Row alignItems="center" gap="3" wrap="wrap">
<Row alignItems="center" gap="2">
<Text size="sm" color="muted">
{t(labels.sortBy)}
</Text>
<Select
value={selectedSort.id}
onChange={handleSortChange}
style={{ width: 220 }}
popoverProps={{ placement: 'bottom right' }}
>
<ListItem id="visitors">{t(labels.mostVisitorsToday)}</ListItem>
<ListItem id="pageviews">{t(labels.mostViewsToday)}</ListItem>
<ListItem id="name">{`${t(labels.name)} (A-Z)`}</ListItem>
<ListItem id="domain">{`${t(labels.domain)} (A-Z)`}</ListItem>
</Select>
</Row>
<Row alignItems="center" gap="2">
<Text size="sm" color="muted">
{t(labels.resultsPerPage)}
</Text>
<Select
value={pageSize.toString()}
onChange={handlePageSizeChange}
style={{ width: 120 }}
popoverProps={{ placement: 'bottom right' }}
>
{PAGE_SIZE_OPTIONS.map(value => (
<ListItem key={value} id={value.toString()}>
{value.toLocaleString()}
</ListItem>
))}
</Select>
</Row>
</Row>
);

return (
<DataGrid query={queryResult} allowSearch allowPaging>
<DataGrid query={queryResult} allowSearch allowPaging renderActions={renderActions}>
{({ data }) => (
<WebsitesTable
data={data}
showActions={showActions}
allowEdit={allowEdit}
allowView={allowView}
showStats={showStats}
renderLink={renderLink}
/>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/app/(main)/websites/WebsitesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function WebsitesPage() {
{showActions && <WebsiteAddButton teamId={teamId} />}
</PageHeader>
<Panel>
<WebsitesDataTable teamId={teamId} showActions={showActions} />
<WebsitesDataTable teamId={teamId} showActions={showActions} showStats />
</Panel>
</Column>
</PageBody>
Expand Down
Loading