This commit is contained in:
Mike Cao
2026-03-31 18:56:00 -04:00
8 changed files with 34 additions and 21 deletions
@@ -1,13 +1,14 @@
'use client'; 'use client';
import { Column } from '@umami/react-zen'; import { Column } from '@umami/react-zen';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls'; import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { useDateRange } from '@/components/hooks'; import { useDateRange, useTimezone } from '@/components/hooks';
import { Revenue } from './Revenue'; import { Revenue } from './Revenue';
export function RevenuePage({ websiteId }: { websiteId: string }) { export function RevenuePage({ websiteId }: { websiteId: string }) {
const { timezone } = useTimezone();
const { const {
dateRange: { startDate, endDate, unit }, dateRange: { startDate, endDate, unit },
} = useDateRange(); } = useDateRange({ timezone });
return ( return (
<Column gap> <Column gap>
@@ -10,9 +10,11 @@ export interface SessionModalProps extends ModalProps {
export function SessionModal({ websiteId, ...props }: SessionModalProps) { export function SessionModal({ websiteId, ...props }: SessionModalProps) {
const { const {
router, router,
pathname,
query: { session }, query: { session },
updateParams, updateParams,
} = useNavigation(); } = useNavigation();
const isSharePage = pathname.includes('/share/');
const handleOpenChange = (isOpen: boolean) => { const handleOpenChange = (isOpen: boolean) => {
if (!isOpen) { if (!isOpen) {
router.push(updateParams({ session: undefined })); router.push(updateParams({ session: undefined }));
@@ -32,7 +34,7 @@ export function SessionModal({ websiteId, ...props }: SessionModalProps) {
<Dialog variant="sheet" className="rounded-lg"> <Dialog variant="sheet" className="rounded-lg">
{({ close }) => ( {({ close }) => (
<Column padding="10"> <Column padding="10">
<SessionProfile websiteId={websiteId} sessionId={session} onClose={() => close()} /> <SessionProfile websiteId={websiteId} sessionId={session} showReplays={!isSharePage} onClose={() => close()} />
</Column> </Column>
)} )}
</Dialog> </Dialog>
@@ -23,10 +23,12 @@ import { SessionStats } from './SessionStats';
export function SessionProfile({ export function SessionProfile({
websiteId, websiteId,
sessionId, sessionId,
showReplays = true,
onClose, onClose,
}: { }: {
websiteId: string; websiteId: string;
sessionId: string; sessionId: string;
showReplays?: boolean;
onClose?: () => void; onClose?: () => void;
}) { }) {
const { data, isLoading, error } = useWebsiteSessionQuery(websiteId, sessionId); const { data, isLoading, error } = useWebsiteSessionQuery(websiteId, sessionId);
@@ -65,7 +67,7 @@ export function SessionProfile({
<TabList> <TabList>
<Tab id="activity">{t(labels.activity)}</Tab> <Tab id="activity">{t(labels.activity)}</Tab>
<Tab id="properties">{t(labels.properties)}</Tab> <Tab id="properties">{t(labels.properties)}</Tab>
<Tab id="replays">{t(labels.replays)}</Tab> {showReplays && <Tab id="replays">{t(labels.replays)}</Tab>}
</TabList> </TabList>
<TabPanel id="activity"> <TabPanel id="activity">
<SessionActivity <SessionActivity
@@ -78,9 +80,11 @@ export function SessionProfile({
<TabPanel id="properties"> <TabPanel id="properties">
<SessionData sessionId={sessionId} websiteId={websiteId} /> <SessionData sessionId={sessionId} websiteId={websiteId} />
</TabPanel> </TabPanel>
<TabPanel id="replays"> {showReplays && (
<SessionReplaysDataTable websiteId={websiteId} sessionId={sessionId} /> <TabPanel id="replays">
</TabPanel> <SessionReplaysDataTable websiteId={websiteId} sessionId={sessionId} />
</TabPanel>
)}
</Tabs> </Tabs>
</Column> </Column>
</Column> </Column>
@@ -1,15 +1,20 @@
import { DataGrid } from '@/components/common/DataGrid'; import { DataGrid } from '@/components/common/DataGrid';
import { useWebsiteSessionsQuery } from '@/components/hooks'; import { useNavigation, useWebsiteSessionsQuery } from '@/components/hooks';
import { SessionsTable } from './SessionsTable'; import { SessionsTable } from './SessionsTable';
export function SessionsDataTable({ websiteId }: { websiteId: string }) { export function SessionsDataTable({ websiteId }: { websiteId: string }) {
const queryResult = useWebsiteSessionsQuery(websiteId); const queryResult = useWebsiteSessionsQuery(websiteId);
const { updateParams } = useNavigation();
return ( return (
<DataGrid query={queryResult} allowPaging allowSearch> <DataGrid query={queryResult} allowPaging allowSearch>
{({ data }) => { {({ data }) => (
return <SessionsTable data={data} websiteId={websiteId} />; <SessionsTable
}} data={data}
websiteId={websiteId}
getSessionHref={row => updateParams({ session: row.id })}
/>
)}
</DataGrid> </DataGrid>
); );
} }
@@ -5,6 +5,7 @@ import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteContro
import { Panel } from '@/components/common/Panel'; import { Panel } from '@/components/common/Panel';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { getItem, setItem } from '@/lib/storage'; import { getItem, setItem } from '@/lib/storage';
import { SessionModal } from './SessionModal';
import { SessionProperties } from './SessionProperties'; import { SessionProperties } from './SessionProperties';
import { SessionsDataTable } from './SessionsDataTable'; import { SessionsDataTable } from './SessionsDataTable';
@@ -22,6 +23,7 @@ export function SessionsPage({ websiteId }) {
return ( return (
<Column gap="3"> <Column gap="3">
<WebsiteControls websiteId={websiteId} /> <WebsiteControls websiteId={websiteId} />
<SessionModal websiteId={websiteId} />
<Panel> <Panel>
<Tabs selectedKey={tab} onSelectionChange={handleSelect}> <Tabs selectedKey={tab} onSelectionChange={handleSelect}>
<TabList> <TabList>
@@ -17,11 +17,7 @@ export function SessionsTable({
<DataTable {...props}> <DataTable {...props}>
<DataColumn id="id" label={t(labels.session)} width="100px"> <DataColumn id="id" label={t(labels.session)} width="100px">
{(row: any) => ( {(row: any) => (
<Link <Link href={getSessionHref ? getSessionHref(row) : `/websites/${websiteId}/sessions/${row.id}`}>
href={
getSessionHref ? getSessionHref(row) : `/websites/${websiteId}/sessions/${row.id}`
}
>
<Avatar seed={row.id} size={32} /> <Avatar seed={row.id} size={32} />
</Link> </Link>
)} )}
+2 -1
View File
@@ -27,6 +27,7 @@ const ALL_SECTION_IDS = [
'events', 'events',
'sessions', 'sessions',
'realtime', 'realtime',
'performance',
'compare', 'compare',
'breakdown', 'breakdown',
'goals', 'goals',
@@ -59,7 +60,7 @@ export function ShareProvider({ slug, children }: { slug: string; children: Reac
const isWebsiteShare = share?.shareType === ENTITY_TYPE.website; const isWebsiteShare = share?.shareType === ENTITY_TYPE.website;
const allowedSections = isWebsiteShare && share?.parameters const allowedSections = isWebsiteShare && share?.parameters
? ALL_SECTION_IDS.filter(id => share.parameters[id] !== false) ? ALL_SECTION_IDS.filter(id => share.parameters[id] === true)
: []; : [];
const shouldRedirect = isWebsiteShare && const shouldRedirect = isWebsiteShare &&
@@ -23,7 +23,7 @@ import { useShare } from '@/components/hooks';
import { MobileMenuButton } from '@/components/input/MobileMenuButton'; import { MobileMenuButton } from '@/components/input/MobileMenuButton';
import { ENTITY_TYPE } from '@/lib/constants'; import { ENTITY_TYPE } from '@/lib/constants';
import { Column, Grid, Row, useTheme } from '@umami/react-zen'; import { Column, Grid, Row, useTheme } from '@umami/react-zen';
import { usePathname } from 'next/navigation'; import { usePathname, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { ShareFooter } from './ShareFooter'; import { ShareFooter } from './ShareFooter';
import { ShareNav } from './ShareNav'; import { ShareNav } from './ShareNav';
@@ -69,9 +69,10 @@ export function SharePage() {
}; };
const share = useShare(); const share = useShare();
const { setTheme } = useTheme(); const { setTheme } = useTheme();
const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
const path = getSharePath(pathname); const path = getSharePath(pathname);
const { websiteId, boardId, pixelId, linkId, parameters = {}, shareType } = share; const { slug, websiteId, boardId, pixelId, linkId, parameters = {}, shareType } = share;
useEffect(() => { useEffect(() => {
const url = new URL(window?.location?.href); const url = new URL(window?.location?.href);
@@ -102,9 +103,10 @@ export function SharePage() {
// Check if the requested path is allowed // Check if the requested path is allowed
const pageKey = path || ''; const pageKey = path || '';
const isAllowed = pageKey === '' || pageKey === 'overview' || parameters[pageKey] !== false; const isAllowed = pageKey === '' || parameters[pageKey] === true;
if (!isAllowed) { if (!isAllowed) {
router.replace(`/share/${slug}`);
return null; return null;
} }
@@ -125,7 +127,7 @@ export function SharePage() {
<PageBody gap> <PageBody gap>
<WebsiteProvider websiteId={websiteId}> <WebsiteProvider websiteId={websiteId}>
<Column> <Column>
<WebsiteHeader showActions={false} /> <WebsiteHeader showActions={false} allowLink={false} />
<PageComponent websiteId={websiteId} /> <PageComponent websiteId={websiteId} />
</Column> </Column>
</WebsiteProvider> </WebsiteProvider>