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