diff --git a/.gitignore b/.gitignore
index 8b543f6b9..de893d0f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,48 +1,46 @@
-# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-
-# dependencies
-node_modules
-.pnp
-.pnp.js
-.pnpm-store
-package-lock.json
-
-# testing
-/coverage
-
-# next.js
-/.next
-/out
-
-# production
-/build
-/public/script.js
-/geo
-/dist
-/generated
-/src/generated
-pm2.yml
-
-# misc
-.DS_Store
-.idea
-.yarn
-*.iml
-*.log
-.vscode
-.tool-versions
-.claude
-nul
-
-# debug
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# local env files
-.env
-.env.*
-*.env.*
-
-*.dev.yml
-
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+node_modules
+.pnp
+.pnp.js
+.pnpm-store
+package-lock.json
+
+# testing
+/coverage
+
+# next.js
+/.next
+/out
+
+# production
+/build
+/public/script.js
+/geo
+/dist
+/generated
+/src/generated
+pm2.yml
+
+# misc
+.DS_Store
+.idea
+.yarn
+*.iml
+*.log
+.vscode
+.tool-versions
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env
+.env.*
+*.env.*
+
+*.dev.yml
+
diff --git a/package.json b/package.json
index ee22a9eed..ac2ea36c2 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
},
"type": "module",
"scripts": {
- "dev": "next dev -p 3002 --turbo",
+ "dev": "next dev -p 3001 --turbo",
"build": "npm-run-all check-env build-db check-db build-tracker build-geo build-app",
"start": "next start",
"build-docker": "npm-run-all build-db build-tracker build-geo build-app",
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel.tsx b/src/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel.tsx
index d81519d76..e336a3db6 100644
--- a/src/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel.tsx
+++ b/src/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel.tsx
@@ -1,6 +1,6 @@
import { Box, Column, Dialog, Grid, Icon, ProgressBar, Row, Text } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
-import { useMessages, useNavigation, useResultQuery } from '@/components/hooks';
+import { useMessages, useResultQuery } from '@/components/hooks';
import { File, User } from '@/components/icons';
import { ReportEditButton } from '@/components/input/ReportEditButton';
import { ChangeLabel } from '@/components/metrics/ChangeLabel';
@@ -20,8 +20,6 @@ type FunnelResult = {
export function Funnel({ id, name, type, parameters, websiteId }) {
const { formatMessage, labels } = useMessages();
- const { pathname } = useNavigation();
- const isSharePage = pathname.includes('/share/');
const { data, error, isLoading } = useResultQuery(type, {
websiteId,
...parameters,
@@ -38,22 +36,21 @@ export function Funnel({ id, name, type, parameters, websiteId }) {
- {!isSharePage && (
-
-
- {({ close }) => {
- return (
-
- );
- }}
-
-
- )}
+
+
+ {({ close }) => {
+ return (
+
+ );
+ }}
+
+
{data?.map(
(
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage.tsx b/src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage.tsx
index a56917b76..57bce52f8 100644
--- a/src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage.tsx
+++ b/src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage.tsx
@@ -4,7 +4,7 @@ import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteContro
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
import { SectionHeader } from '@/components/common/SectionHeader';
-import { useDateRange, useNavigation, useReportsQuery } from '@/components/hooks';
+import { useDateRange, useReportsQuery } from '@/components/hooks';
import { Funnel } from './Funnel';
import { FunnelAddButton } from './FunnelAddButton';
@@ -13,17 +13,13 @@ export function FunnelsPage({ websiteId }: { websiteId: string }) {
const {
dateRange: { startDate, endDate },
} = useDateRange();
- const { pathname } = useNavigation();
- const isSharePage = pathname.includes('/share/');
return (
- {!isSharePage && (
-
-
-
- )}
+
+
+
{data && (
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/goals/Goal.tsx b/src/app/(main)/websites/[websiteId]/(reports)/goals/Goal.tsx
index 1d0b96e50..b6c4a11d6 100644
--- a/src/app/(main)/websites/[websiteId]/(reports)/goals/Goal.tsx
+++ b/src/app/(main)/websites/[websiteId]/(reports)/goals/Goal.tsx
@@ -1,6 +1,6 @@
import { Column, Dialog, Grid, Icon, ProgressBar, Row, Text } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
-import { useMessages, useNavigation, useResultQuery } from '@/components/hooks';
+import { useMessages, useResultQuery } from '@/components/hooks';
import { File, User } from '@/components/icons';
import { ReportEditButton } from '@/components/input/ReportEditButton';
import { Lightning } from '@/components/svg';
@@ -25,8 +25,6 @@ export type GoalData = { num: number; total: number };
export function Goal({ id, name, type, parameters, websiteId, startDate, endDate }: GoalProps) {
const { formatMessage, labels } = useMessages();
- const { pathname } = useNavigation();
- const isSharePage = pathname.includes('/share/');
const { data, error, isLoading, isFetching } = useResultQuery(type, {
websiteId,
startDate,
@@ -47,23 +45,21 @@ export function Goal({ id, name, type, parameters, websiteId, startDate, endDate
- {!isSharePage && (
-
-
- {({ close }) => {
- return (
-
- );
- }}
-
-
- )}
+
+
+ {({ close }) => {
+ return (
+
+ );
+ }}
+
+
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/goals/GoalsPage.tsx b/src/app/(main)/websites/[websiteId]/(reports)/goals/GoalsPage.tsx
index fe4550d6e..ff7b49fbd 100644
--- a/src/app/(main)/websites/[websiteId]/(reports)/goals/GoalsPage.tsx
+++ b/src/app/(main)/websites/[websiteId]/(reports)/goals/GoalsPage.tsx
@@ -4,7 +4,7 @@ import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteContro
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Panel } from '@/components/common/Panel';
import { SectionHeader } from '@/components/common/SectionHeader';
-import { useDateRange, useNavigation, useReportsQuery } from '@/components/hooks';
+import { useDateRange, useReportsQuery } from '@/components/hooks';
import { Goal } from './Goal';
import { GoalAddButton } from './GoalAddButton';
@@ -13,17 +13,13 @@ export function GoalsPage({ websiteId }: { websiteId: string }) {
const {
dateRange: { startDate, endDate },
} = useDateRange();
- const { pathname } = useNavigation();
- const isSharePage = pathname.includes('/share/');
return (
- {!isSharePage && (
-
-
-
- )}
+
+
+
{data && (
diff --git a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx
index 1dee80220..e79576dd3 100644
--- a/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx
+++ b/src/app/(main)/websites/[websiteId]/WebsiteHeader.tsx
@@ -6,13 +6,7 @@ import { useMessages, useNavigation, useWebsite } from '@/components/hooks';
import { Edit } from '@/components/icons';
import { ActiveUsers } from '@/components/metrics/ActiveUsers';
-export function WebsiteHeader({
- showActions,
- allowLink = true,
-}: {
- showActions?: boolean;
- allowLink?: boolean;
-}) {
+export function WebsiteHeader({ showActions }: { showActions?: boolean }) {
const website = useWebsite();
const { renderUrl, pathname } = useNavigation();
const isSettings = pathname.endsWith('/settings');
@@ -27,7 +21,7 @@ export function WebsiteHeader({
}
- titleHref={allowLink ? renderUrl(`/websites/${website.id}`, false) : undefined}
+ titleHref={renderUrl(`/websites/${website.id}`, false)}
>
diff --git a/src/app/(main)/websites/[websiteId]/settings/ShareCreateForm.tsx b/src/app/(main)/websites/[websiteId]/settings/ShareCreateForm.tsx
new file mode 100644
index 000000000..a16f2dc54
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/settings/ShareCreateForm.tsx
@@ -0,0 +1,81 @@
+import {
+ Button,
+ Checkbox,
+ Column,
+ Form,
+ FormField,
+ FormSubmitButton,
+ Row,
+ Text,
+} from '@umami/react-zen';
+import { useState } from 'react';
+import { useApi, useMessages, useModified } from '@/components/hooks';
+import { SHARE_NAV_ITEMS } from './constants';
+
+export interface ShareCreateFormProps {
+ websiteId: string;
+ onSave?: () => void;
+ onClose?: () => void;
+}
+
+export function ShareCreateForm({ websiteId, onSave, onClose }: ShareCreateFormProps) {
+ const { formatMessage, labels } = useMessages();
+ const { post } = useApi();
+ const { touch } = useModified();
+ const [isPending, setIsPending] = useState(false);
+
+ // Build default values - only overview and events enabled by default
+ const defaultValues: Record = {};
+ SHARE_NAV_ITEMS.forEach(section => {
+ section.items.forEach(item => {
+ defaultValues[item.id] = item.id === 'overview' || item.id === 'events';
+ });
+ });
+
+ const handleSubmit = async (data: any) => {
+ setIsPending(true);
+ try {
+ const parameters: Record = {};
+ SHARE_NAV_ITEMS.forEach(section => {
+ section.items.forEach(item => {
+ parameters[item.id] = data[item.id] ?? false;
+ });
+ });
+ await post(`/websites/${websiteId}/shares`, { parameters });
+ touch('shares');
+ onSave?.();
+ onClose?.();
+ } finally {
+ setIsPending(false);
+ }
+ };
+
+ return (
+
+ );
+}
diff --git a/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx b/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx
index 4b86247ac..c5bd85a60 100644
--- a/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx
+++ b/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx
@@ -5,7 +5,6 @@ import {
Form,
FormField,
FormSubmitButton,
- Grid,
Label,
Loading,
Row,
@@ -14,30 +13,25 @@ import {
} from '@umami/react-zen';
import { useEffect, useState } from 'react';
import { useApi, useConfig, useMessages, useModified } from '@/components/hooks';
+import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
import { SHARE_NAV_ITEMS } from './constants';
export function ShareEditForm({
shareId,
- websiteId,
onSave,
onClose,
}: {
- shareId?: string;
- websiteId?: string;
+ shareId: string;
onSave?: () => void;
onClose?: () => void;
}) {
- const { formatMessage, labels, getErrorMessage } = useMessages();
+ const { formatMessage, labels, messages, getErrorMessage } = useMessages();
+ const { mutateAsync, error, isPending, touch, toast } = useUpdateQuery(`/share/id/${shareId}`);
const { cloudMode } = useConfig();
- const { get, post } = useApi();
- const { touch } = useModified();
+ const { get } = useApi();
const { modified } = useModified('shares');
const [share, setShare] = useState(null);
- const [isLoading, setIsLoading] = useState(!!shareId);
- const [isPending, setIsPending] = useState(false);
- const [error, setError] = useState(null);
-
- const isEditing = !!shareId;
+ const [isLoading, setIsLoading] = useState(true);
const getUrl = (slug: string) => {
if (cloudMode) {
@@ -47,8 +41,6 @@ export function ShareEditForm({
};
useEffect(() => {
- if (!shareId) return;
-
const loadShare = async () => {
setIsLoading(true);
try {
@@ -69,35 +61,27 @@ export function ShareEditForm({
});
});
- setIsPending(true);
- setError(null);
-
- try {
- if (isEditing) {
- await post(`/share/id/${shareId}`, { name: data.name, slug: share.slug, parameters });
- } else {
- await post(`/websites/${websiteId}/shares`, { name: data.name, parameters });
- }
- touch('shares');
- onSave?.();
- onClose?.();
- } catch (e) {
- setError(e);
- } finally {
- setIsPending(false);
- }
+ await mutateAsync(
+ { slug: share.slug, parameters },
+ {
+ onSuccess: async () => {
+ toast(formatMessage(messages.saved));
+ touch('shares');
+ onSave?.();
+ onClose?.();
+ },
+ },
+ );
};
if (isLoading) {
return ;
}
- const url = isEditing ? getUrl(share?.slug || '') : null;
+ const url = getUrl(share?.slug || '');
// Build default values from share parameters
- const defaultValues: Record = {
- name: share?.name || '',
- };
+ const defaultValues: Record = {};
SHARE_NAV_ITEMS.forEach(section => {
section.items.forEach(item => {
const defaultSelected = item.id === 'overview' || item.id === 'events';
@@ -105,60 +89,34 @@ export function ShareEditForm({
});
});
- // Get all item ids for validation
- const allItemIds = SHARE_NAV_ITEMS.flatMap(section => section.items.map(item => item.id));
-
return (
- );
- }}
+ ))}
+
+ {onClose && (
+
+ )}
+ {formatMessage(labels.save)}
+
+
);
}
diff --git a/src/app/(main)/websites/[websiteId]/settings/SharesTable.tsx b/src/app/(main)/websites/[websiteId]/settings/SharesTable.tsx
index 57701ac67..05e8b357b 100644
--- a/src/app/(main)/websites/[websiteId]/settings/SharesTable.tsx
+++ b/src/app/(main)/websites/[websiteId]/settings/SharesTable.tsx
@@ -10,14 +10,14 @@ export function SharesTable(props: DataTableProps) {
const { cloudMode } = useConfig();
const getUrl = (slug: string) => {
- return `${cloudMode ? process.env.cloudUrl : window?.location.origin}${process.env.basePath || ''}/share/${slug}`;
+ if (cloudMode) {
+ return `${process.env.cloudUrl}/share/${slug}`;
+ }
+ return `${window?.location.origin}${process.env.basePath || ''}/share/${slug}`;
};
return (
-
- {({ name }: any) => name}
-
{({ slug }: any) => {
const url = getUrl(slug);
diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx
index 8472ca977..7453b4028 100644
--- a/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx
+++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx
@@ -2,7 +2,7 @@ import { Column, Heading, Row, Text } from '@umami/react-zen';
import { Plus } from 'lucide-react';
import { useMessages, useWebsiteSharesQuery } from '@/components/hooks';
import { DialogButton } from '@/components/input/DialogButton';
-import { ShareEditForm } from './ShareEditForm';
+import { ShareCreateForm } from './ShareCreateForm';
import { SharesTable } from './SharesTable';
export interface WebsiteShareFormProps {
@@ -25,9 +25,9 @@ export function WebsiteShareForm({ websiteId }: WebsiteShareFormProps) {
label={formatMessage(labels.add)}
title={formatMessage(labels.share)}
variant="primary"
- width="600px"
+ width="400px"
>
- {({ close }) => }
+ {({ close }) => }
{hasShares ? (
diff --git a/src/app/api/share/[slug]/route.ts b/src/app/api/share/[slug]/route.ts
index e7d5372fe..ed3271eab 100644
--- a/src/app/api/share/[slug]/route.ts
+++ b/src/app/api/share/[slug]/route.ts
@@ -1,47 +1,7 @@
-import { ROLES } from '@/lib/constants';
import { secret } from '@/lib/crypto';
import { createToken } from '@/lib/jwt';
-import prisma from '@/lib/prisma';
-import redis from '@/lib/redis';
import { json, notFound } from '@/lib/response';
-import type { WhiteLabel } from '@/lib/types';
-import { getShareByCode, getWebsite } from '@/queries/prisma';
-
-async function getAccountId(website: { userId?: string; teamId?: string }): Promise {
- if (website.userId) {
- return website.userId;
- }
-
- if (website.teamId) {
- const teamOwner = await prisma.client.teamUser.findFirst({
- where: {
- teamId: website.teamId,
- role: ROLES.teamOwner,
- },
- select: {
- userId: true,
- },
- });
-
- return teamOwner?.userId || null;
- }
-
- return null;
-}
-
-async function getWhiteLabel(accountId: string): Promise {
- if (!redis.enabled) {
- return null;
- }
-
- const data = await redis.client.get(`white-label:${accountId}`);
-
- if (data) {
- return data as WhiteLabel;
- }
-
- return null;
-}
+import { getShareByCode } from '@/queries/prisma';
export async function GET(_request: Request, { params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
@@ -52,25 +12,12 @@ export async function GET(_request: Request, { params }: { params: Promise<{ slu
return notFound();
}
- const website = await getWebsite(share.entityId);
-
- const data: Record = {
+ const data = {
shareId: share.id,
websiteId: share.entityId,
parameters: share.parameters,
};
+ const token = createToken(data, secret());
- data.token = createToken(data, secret());
-
- const accountId = await getAccountId(website);
-
- if (accountId) {
- const whiteLabel = await getWhiteLabel(accountId);
-
- if (whiteLabel) {
- data.whiteLabel = whiteLabel;
- }
- }
-
- return json(data);
+ return json({ ...data, token });
}
diff --git a/src/app/api/share/id/[shareId]/route.ts b/src/app/api/share/id/[shareId]/route.ts
index 80da17b80..da7dcf562 100644
--- a/src/app/api/share/id/[shareId]/route.ts
+++ b/src/app/api/share/id/[shareId]/route.ts
@@ -25,7 +25,6 @@ export async function GET(request: Request, { params }: { params: Promise<{ shar
export async function POST(request: Request, { params }: { params: Promise<{ shareId: string }> }) {
const schema = z.object({
- name: z.string().max(200),
slug: z.string().max(100),
parameters: anyObjectParam,
});
@@ -37,7 +36,7 @@ export async function POST(request: Request, { params }: { params: Promise<{ sha
}
const { shareId } = await params;
- const { name, slug, parameters } = body;
+ const { slug, parameters } = body;
const share = await getShare(shareId);
@@ -50,7 +49,6 @@ export async function POST(request: Request, { params }: { params: Promise<{ sha
}
const result = await updateShare(shareId, {
- name,
slug,
parameters,
} as any);
diff --git a/src/app/api/websites/[websiteId]/shares/route.ts b/src/app/api/websites/[websiteId]/shares/route.ts
index 65d53771d..db079d497 100644
--- a/src/app/api/websites/[websiteId]/shares/route.ts
+++ b/src/app/api/websites/[websiteId]/shares/route.ts
@@ -44,7 +44,6 @@ export async function POST(
{ params }: { params: Promise<{ websiteId: string }> },
) {
const schema = z.object({
- name: z.string().max(200),
parameters: anyObjectParam.optional(),
});
@@ -55,8 +54,7 @@ export async function POST(
}
const { websiteId } = await params;
- const { name, parameters } = body;
- const shareParameters = parameters ?? {};
+ const { parameters = {} } = body;
if (!(await canUpdateWebsite(auth, websiteId))) {
return unauthorized();
@@ -68,9 +66,8 @@ export async function POST(
id: uuid(),
entityId: websiteId,
shareType: ENTITY_TYPE.website,
- name,
slug,
- parameters: shareParameters,
+ parameters,
});
return json(share);
diff --git a/src/app/share/[...shareId]/Footer.tsx b/src/app/share/[...shareId]/Footer.tsx
new file mode 100644
index 000000000..f29486286
--- /dev/null
+++ b/src/app/share/[...shareId]/Footer.tsx
@@ -0,0 +1,12 @@
+import { Row, Text } from '@umami/react-zen';
+import { CURRENT_VERSION, HOMEPAGE_URL } from '@/lib/constants';
+
+export function Footer() {
+ return (
+
+
+ umami {`v${CURRENT_VERSION}`}
+
+
+ );
+}
diff --git a/src/app/share/[...shareId]/Header.tsx b/src/app/share/[...shareId]/Header.tsx
new file mode 100644
index 000000000..d7b7dcb42
--- /dev/null
+++ b/src/app/share/[...shareId]/Header.tsx
@@ -0,0 +1,24 @@
+import { Icon, Row, Text, ThemeButton } from '@umami/react-zen';
+import { LanguageButton } from '@/components/input/LanguageButton';
+import { PreferencesButton } from '@/components/input/PreferencesButton';
+import { Logo } from '@/components/svg';
+
+export function Header() {
+ return (
+
+
+
+
+
+
+ umami
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/share/[...shareId]/ShareFooter.tsx b/src/app/share/[...shareId]/ShareFooter.tsx
deleted file mode 100644
index 5348ac63c..000000000
--- a/src/app/share/[...shareId]/ShareFooter.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Row, Text } from '@umami/react-zen';
-import { CURRENT_VERSION, HOMEPAGE_URL } from '@/lib/constants';
-import type { WhiteLabel } from '@/lib/types';
-
-export function ShareFooter({ whiteLabel }: { whiteLabel?: WhiteLabel }) {
- if (whiteLabel) {
- return (
-
-
- {whiteLabel.name}
-
-
- );
- }
-
- return (
-
-
- umami {`v${CURRENT_VERSION}`}
-
-
- );
-}
diff --git a/src/app/share/[...shareId]/ShareHeader.tsx b/src/app/share/[...shareId]/ShareHeader.tsx
deleted file mode 100644
index abd8511df..000000000
--- a/src/app/share/[...shareId]/ShareHeader.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Icon, Row, Text, ThemeButton } from '@umami/react-zen';
-import { LanguageButton } from '@/components/input/LanguageButton';
-import { PreferencesButton } from '@/components/input/PreferencesButton';
-import { Logo } from '@/components/svg';
-import type { WhiteLabel } from '@/lib/types';
-
-export function ShareHeader({ whiteLabel }: { whiteLabel?: WhiteLabel }) {
- const logoUrl = whiteLabel?.url || 'https://umami.is';
- const logoName = whiteLabel?.name || 'umami';
- const logoImage = whiteLabel?.image;
-
- return (
-
-
-
- {logoImage ? (
-
- ) : (
-
-
-
- )}
- {logoName}
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/app/share/[...shareId]/SharePage.tsx b/src/app/share/[...shareId]/SharePage.tsx
index 91a8b298c..3e1cedc06 100644
--- a/src/app/share/[...shareId]/SharePage.tsx
+++ b/src/app/share/[...shareId]/SharePage.tsx
@@ -1,7 +1,6 @@
'use client';
-import { Column, Grid, Row, useTheme } from '@umami/react-zen';
-import { useRouter } from 'next/navigation';
-import { useEffect, useMemo } from 'react';
+import { Column, Grid, useTheme } from '@umami/react-zen';
+import { useEffect } from 'react';
import { AttributionPage } from '@/app/(main)/websites/[websiteId]/(reports)/attribution/AttributionPage';
import { BreakdownPage } from '@/app/(main)/websites/[websiteId]/(reports)/breakdown/BreakdownPage';
import { FunnelsPage } from '@/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage';
@@ -19,9 +18,8 @@ import { WebsitePage } from '@/app/(main)/websites/[websiteId]/WebsitePage';
import { WebsiteProvider } from '@/app/(main)/websites/WebsiteProvider';
import { PageBody } from '@/components/common/PageBody';
import { useShareTokenQuery } from '@/components/hooks';
-import { MobileMenuButton } from '@/components/input/MobileMenuButton';
-import { ShareFooter } from './ShareFooter';
-import { ShareHeader } from './ShareHeader';
+import { Footer } from './Footer';
+import { Header } from './Header';
import { ShareNav } from './ShareNav';
const PAGE_COMPONENTS: Record> = {
@@ -41,34 +39,9 @@ const PAGE_COMPONENTS: Record
attribution: AttributionPage,
};
-// All section IDs that can be enabled/disabled via parameters
-const ALL_SECTION_IDS = [
- 'overview',
- 'events',
- 'sessions',
- 'realtime',
- 'compare',
- 'breakdown',
- 'goals',
- 'funnels',
- 'journeys',
- 'retention',
- 'utm',
- 'revenue',
- 'attribution',
-];
-
export function SharePage({ shareId, path = '' }: { shareId: string; path?: string }) {
const { shareToken, isLoading } = useShareTokenQuery(shareId);
const { setTheme } = useTheme();
- const router = useRouter();
-
- // Calculate allowed sections
- const allowedSections = useMemo(() => {
- if (!shareToken?.parameters) return [];
- const params = shareToken.parameters;
- return ALL_SECTION_IDS.filter(id => params[id] !== false);
- }, [shareToken?.parameters]);
useEffect(() => {
const url = new URL(window?.location?.href);
@@ -79,31 +52,11 @@ export function SharePage({ shareId, path = '' }: { shareId: string; path?: stri
}
}, []);
- // Redirect to the only allowed section if there's just one and we're on the base path
- useEffect(() => {
- if (
- allowedSections.length === 1 &&
- allowedSections[0] !== 'overview' &&
- (path === '' || path === 'overview')
- ) {
- router.replace(`/share/${shareId}/${allowedSections[0]}`);
- }
- }, [allowedSections, shareId, path, router]);
-
if (isLoading || !shareToken) {
return null;
}
- const { websiteId, parameters = {}, whiteLabel } = shareToken;
-
- // Redirect to only allowed section - return null while redirecting
- if (
- allowedSections.length === 1 &&
- allowedSections[0] !== 'overview' &&
- (path === '' || path === 'overview')
- ) {
- return null;
- }
+ const { websiteId, parameters = {} } = shareToken;
// Check if the requested path is allowed
const pageKey = path || '';
@@ -117,16 +70,8 @@ export function SharePage({ shareId, path = '' }: { shareId: string; path?: stri
return (
+
-
-
-
- {({ close }) => {
- return ;
- }}
-
-
-
-
-
-
+
-
+
-
-
+
);
}
diff --git a/src/components/common/PageBody.tsx b/src/components/common/PageBody.tsx
index c70b9dfec..f07e589ba 100644
--- a/src/components/common/PageBody.tsx
+++ b/src/components/common/PageBody.tsx
@@ -31,7 +31,6 @@ export function PageBody({