diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
index 3696b786..df476e79 100644
--- a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
+++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
@@ -1,14 +1,5 @@
import { Text } from '@umami/react-zen';
-import {
- Eye,
- User,
- Clock,
- Sheet,
- Tag,
- ChartPie,
- UserPlus,
- GitCompareArrows,
-} from '@/components/icons';
+import { Eye, User, Clock, Ungroup, Tag, ChartPie, UserPlus, GitCompare } from '@/components/icons';
import { Lightning, Path, Money, Target, Funnel, Magnet, Network } from '@/components/svg';
import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu';
@@ -56,13 +47,13 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{
id: 'compare',
label: formatMessage(labels.compare),
- icon: ,
+ icon: ,
path: renderPath('/compare'),
},
{
id: 'breakdown',
label: formatMessage(labels.breakdown),
- icon: ,
+ icon: ,
path: renderPath('/breakdown'),
},
],
diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx
similarity index 97%
rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx
rename to src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx
index 4ed55427..4dcf08b4 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx
@@ -47,7 +47,7 @@ export function SessionActivity({
return (
- {showHeader && {formatTimezoneDate(createdAt, 'PPPP')}}
+ {showHeader && {formatTimezoneDate(createdAt, 'PPPP')}}
{formatTimezoneDate(createdAt, 'pp')}
diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionData.tsx
similarity index 100%
rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx
rename to src/app/(main)/websites/[websiteId]/sessions/SessionData.tsx
diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionInfo.tsx
similarity index 93%
rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx
rename to src/app/(main)/websites/[websiteId]/sessions/SessionInfo.tsx
index 4ebb462c..c2127cf5 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionInfo.tsx
@@ -1,5 +1,5 @@
import { ReactNode } from 'react';
-import { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen';
+import { Icon, TextField, Column, Row, Label } from '@umami/react-zen';
import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks';
import { TypeIcon } from '@/components/common/TypeIcon';
import { KeyRound, Calendar } from '@/components/icons';
@@ -15,7 +15,7 @@ export function SessionInfo({ data }) {
return (
-
+
}>
@@ -83,7 +83,7 @@ const Info = ({
{icon && {icon}}
- {children || '—'}
+ {children || '—'}
);
diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx
similarity index 58%
rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx
rename to src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx
index 86e3cdbf..bdbfbc58 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx
@@ -1,37 +1,52 @@
-'use client';
-import { Grid, Row, Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen';
+import { Grid, Row, Column, Tabs, TabList, Tab, TabPanel, Icon, Button } from '@umami/react-zen';
import { Avatar } from '@/components/common/Avatar';
import { LoadingPanel } from '@/components/common/LoadingPanel';
+import { X } from '@/components/icons';
import { useMessages, useWebsiteSessionQuery } from '@/components/hooks';
import { SessionActivity } from './SessionActivity';
import { SessionData } from './SessionData';
import { SessionInfo } from './SessionInfo';
import { SessionStats } from './SessionStats';
-import { Panel } from '@/components/common/Panel';
-export function SessionDetailsPage({
+export function SessionProfile({
websiteId,
sessionId,
+ onClose,
}: {
websiteId: string;
sessionId: string;
+ onClose?: () => void;
}) {
const { data, isLoading, error } = useWebsiteSessionQuery(websiteId, sessionId);
const { formatMessage, labels } = useMessages();
return (
-
+
{data && (
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{formatMessage(labels.activity)}
@@ -49,9 +64,9 @@ export function SessionDetailsPage({
-
-
-
+
+
+
)}
);
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx
index ea4b5f03..e66302ad 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx
@@ -1,5 +1,5 @@
import { useMemo, useState } from 'react';
-import { Select, ListItem, Grid } from '@umami/react-zen';
+import { Select, ListItem, Grid, Column } from '@umami/react-zen';
import {
useMessages,
useSessionDataPropertiesQuery,
@@ -24,25 +24,26 @@ export function SessionProperties({ websiteId }: { websiteId: string }) {
data={data}
error={error}
minHeight="300px"
- gap="6"
>
- {data && (
-
-
-
- )}
- {propertyName && }
+
+ {data && (
+
+
+
+ )}
+ {propertyName && }
+
);
}
@@ -84,7 +85,6 @@ const SessionValues = ({ websiteId, propertyName }) => {
data={data}
error={error}
minHeight="300px"
- gap="6"
>
{data && (
diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionStats.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionStats.tsx
similarity index 100%
rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionStats.tsx
rename to src/app/(main)/websites/[websiteId]/sessions/SessionStats.tsx
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx
index 68eef29c..ae0d4104 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx
@@ -1,18 +1,35 @@
'use client';
import { Key, useState } from 'react';
-import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen';
+import { TabList, Tab, Tabs, TabPanel, Column, Modal, Dialog } from '@umami/react-zen';
import { SessionsDataTable } from './SessionsDataTable';
import { SessionProperties } from './SessionProperties';
-import { useMessages } from '@/components/hooks';
+import { useMessages, useNavigation } from '@/components/hooks';
import { Panel } from '@/components/common/Panel';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { getItem, setItem } from '@/lib/storage';
+import { SessionProfile } from '@/app/(main)/websites/[websiteId]/sessions/SessionProfile';
const KEY_NAME = 'umami.sessions.tab';
export function SessionsPage({ websiteId }) {
const [tab, setTab] = useState(getItem(KEY_NAME) || 'activity');
const { formatMessage, labels } = useMessages();
+ const {
+ router,
+ query: { session },
+ updateParams,
+ } = useNavigation();
+
+ const handleClose = (close: () => void) => {
+ router.push(updateParams({ session: undefined }));
+ close();
+ };
+
+ const handleOpenChange = (isOpen: boolean) => {
+ if (!isOpen) {
+ router.push(updateParams({ session: undefined }));
+ }
+ };
const handleSelect = (value: Key) => {
setItem(KEY_NAME, value);
@@ -36,6 +53,26 @@ export function SessionsPage({ websiteId }) {
+
+
+
);
}
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx
index fa3be6c7..391c57f4 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx
@@ -1,6 +1,6 @@
import Link from 'next/link';
import { DataColumn, DataTable } from '@umami/react-zen';
-import { useFormat, useMessages } from '@/components/hooks';
+import { useFormat, useMessages, useNavigation } from '@/components/hooks';
import { Avatar } from '@/components/common/Avatar';
import { TypeIcon } from '@/components/common/TypeIcon';
import { DateDistance } from '@/components/common/DateDistance';
@@ -8,12 +8,13 @@ import { DateDistance } from '@/components/common/DateDistance';
export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean }) {
const { formatMessage, labels } = useMessages();
const { formatValue } = useFormat();
+ const { updateParams } = useNavigation();
return (
{(row: any) => (
-
+
)}
diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/page.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/page.tsx
deleted file mode 100644
index 8d85a7c7..00000000
--- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/page.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { SessionDetailsPage } from './SessionDetailsPage';
-import { Metadata } from 'next';
-
-export default async function WebsitePage({
- params,
-}: {
- params: Promise<{ websiteId: string; sessionId: string }>;
-}) {
- const { websiteId, sessionId } = await params;
-
- return ;
-}
-
-export const metadata: Metadata = {
- title: 'Websites',
-};
diff --git a/src/components/common/LoadingPanel.tsx b/src/components/common/LoadingPanel.tsx
index a0159a02..b3ff7a09 100644
--- a/src/components/common/LoadingPanel.tsx
+++ b/src/components/common/LoadingPanel.tsx
@@ -29,25 +29,31 @@ export function LoadingPanel({
}: LoadingPanelProps) {
const empty = isEmpty ?? checkEmpty(data);
- return (
- <>
- {/* Show loading spinner only if no data exists */}
- {(isLoading || isFetching) && (
-
-
-
- )}
+ // Show loading spinner only if no data exists
+ if (isLoading || isFetching) {
+ return (
+
+
+
+ );
+ }
- {/* Show error */}
- {error && }
+ // Show error
+ if (error) {
+ return ;
+ }
- {/* Show empty state (once loaded) */}
- {!error && !isLoading && !isFetching && empty && renderEmpty()}
+ // Show empty state (once loaded)
+ if (!error && !isLoading && !isFetching && empty) {
+ return renderEmpty();
+ }
- {/* Show main content when data exists */}
- {!isLoading && !isFetching && !error && !empty && children}
- >
- );
+ // Show main content when data exists
+ if (!isLoading && !isFetching && !error && !empty) {
+ return children;
+ }
+
+ return null;
}
function checkEmpty(data: any) {
diff --git a/src/components/hooks/queries/useWebsiteSessionQuery.ts b/src/components/hooks/queries/useWebsiteSessionQuery.ts
index 053dae31..21e94911 100644
--- a/src/components/hooks/queries/useWebsiteSessionQuery.ts
+++ b/src/components/hooks/queries/useWebsiteSessionQuery.ts
@@ -8,5 +8,6 @@ export function useWebsiteSessionQuery(websiteId: string, sessionId: string) {
queryFn: () => {
return get(`/websites/${websiteId}/sessions/${sessionId}`);
},
+ enabled: Boolean(websiteId && sessionId),
});
}
diff --git a/src/components/hooks/useDateRange.ts b/src/components/hooks/useDateRange.ts
index 0b8db7ce..b5d967ed 100644
--- a/src/components/hooks/useDateRange.ts
+++ b/src/components/hooks/useDateRange.ts
@@ -6,7 +6,7 @@ import { DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
export function useDateRange(options: { ignoreOffset?: boolean } = {}) {
const {
- query: { date = DEFAULT_DATE_RANGE_VALUE, offset = 0, compare = 'prev', all },
+ query: { date = DEFAULT_DATE_RANGE_VALUE, offset = 0, compare = 'prev' },
} = useNavigation();
const { locale } = useLocale();
@@ -24,7 +24,7 @@ export function useDateRange(options: { ignoreOffset?: boolean } = {}) {
date,
offset,
compare,
- isAllTime: !!all,
+ isAllTime: date.endsWith(`:all`),
isCustomRange: date.startsWith('range:'),
dateRange,
dateCompare,
diff --git a/src/components/input/DateFilter.tsx b/src/components/input/DateFilter.tsx
index cd016491..44c725cf 100644
--- a/src/components/input/DateFilter.tsx
+++ b/src/components/input/DateFilter.tsx
@@ -99,11 +99,13 @@ export function DateFilter({
);
};
+ const selectedValue = value.endsWith(':all') ? 'all' : value;
+
return (
<>