mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Skip domain-like segments (containing dots) when parsing the share path.
e.g., /share/slug/aol.com is treated as /share/slug
/share/slug/aol.com/events is treated as /share/slug/events
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
77 lines
1.9 KiB
TypeScript
77 lines
1.9 KiB
TypeScript
'use client';
|
|
import { Loading } from '@umami/react-zen';
|
|
import { usePathname, useRouter } from 'next/navigation';
|
|
import { createContext, type ReactNode, useEffect } from 'react';
|
|
import { useShareTokenQuery } from '@/components/hooks';
|
|
import type { WhiteLabel } from '@/lib/types';
|
|
|
|
export interface ShareData {
|
|
shareId: string;
|
|
slug: string;
|
|
websiteId: string;
|
|
parameters: any;
|
|
token: string;
|
|
whiteLabel?: WhiteLabel;
|
|
}
|
|
|
|
export const ShareContext = createContext<ShareData>(null);
|
|
|
|
const ALL_SECTION_IDS = [
|
|
'overview',
|
|
'events',
|
|
'sessions',
|
|
'realtime',
|
|
'compare',
|
|
'breakdown',
|
|
'goals',
|
|
'funnels',
|
|
'journeys',
|
|
'retention',
|
|
'utm',
|
|
'revenue',
|
|
'attribution',
|
|
];
|
|
|
|
function getSharePath(pathname: string) {
|
|
const segments = pathname.split('/');
|
|
const firstSegment = segments[3];
|
|
|
|
// If first segment looks like a domain name, skip it
|
|
if (firstSegment?.includes('.')) {
|
|
return segments[4];
|
|
}
|
|
|
|
return firstSegment;
|
|
}
|
|
|
|
export function ShareProvider({ slug, children }: { slug: string; children: ReactNode }) {
|
|
const { share, isLoading, isFetching } = useShareTokenQuery(slug);
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
const path = getSharePath(pathname);
|
|
|
|
const allowedSections = share?.parameters
|
|
? ALL_SECTION_IDS.filter(id => share.parameters[id] !== false)
|
|
: [];
|
|
|
|
const shouldRedirect =
|
|
allowedSections.length === 1 &&
|
|
allowedSections[0] !== 'overview' &&
|
|
(path === undefined || path === '' || path === 'overview');
|
|
|
|
useEffect(() => {
|
|
if (shouldRedirect) {
|
|
router.replace(`/share/${slug}/${allowedSections[0]}`);
|
|
}
|
|
}, [shouldRedirect, slug, allowedSections, router]);
|
|
|
|
if (isFetching && isLoading) {
|
|
return <Loading placement="absolute" />;
|
|
}
|
|
|
|
if (!share || shouldRedirect) {
|
|
return null;
|
|
}
|
|
|
|
return <ShareContext.Provider value={{ ...share, slug }}>{children}</ShareContext.Provider>;
|
|
}
|