{renderTable('table')}
diff --git a/src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx b/src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx
index 048ac08d7..26ca581e2 100644
--- a/src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx
+++ b/src/app/(main)/websites/[websiteId]/session-data/SessionPropertyChart.tsx
@@ -1,12 +1,12 @@
'use client';
+import { Column, DataColumn, DataTable, Grid, Row, Text } from '@umami/react-zen';
+import { useMemo } from 'react';
import { DistributionBarChart } from '@/components/charts/DistributionBarChart';
import { Empty } from '@/components/common/Empty';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages, useMobile, useSessionDataActivityStatsQuery } from '@/components/hooks';
import { formatLongNumber } from '@/lib/format';
import type { PropertyFilter } from '@/lib/types';
-import { Column, DataColumn, DataTable, Grid, Row, Text } from '@umami/react-zen';
-import { useMemo } from 'react';
export function SessionPropertyChart({
websiteId,
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx
index dd9ce4690..26948b241 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx
@@ -34,7 +34,12 @@ export function SessionModal({ websiteId, ...props }: SessionModalProps) {
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx
index 9671c995e..7b05f07d7 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx
@@ -1,7 +1,4 @@
'use client';
-import { Avatar } from '@/components/common/Avatar';
-import { LoadingPanel } from '@/components/common/LoadingPanel';
-import { useMessages, useWebsiteSessionQuery } from '@/components/hooks';
import {
Button,
Column,
@@ -14,6 +11,9 @@ import {
TextField,
} from '@umami/react-zen';
import { X } from 'lucide-react';
+import { Avatar } from '@/components/common/Avatar';
+import { LoadingPanel } from '@/components/common/LoadingPanel';
+import { useMessages, useWebsiteSessionQuery } from '@/components/hooks';
import { SessionActivity } from './SessionActivity';
import { SessionData } from './SessionData';
import { SessionInfo } from './SessionInfo';
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx
index cfc6d4f76..5e1a7009f 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx
@@ -1,15 +1,19 @@
import { Column, ComboBox, Grid, Label, ListItem, Row } from '@umami/react-zen';
import { useMemo, useState } from 'react';
import { LoadingPanel } from '@/components/common/LoadingPanel';
-import { useMessages, usePropertyFieldsQuery, useSessionDataPropertiesQuery } from '@/components/hooks';
-import { DATA_TYPE } from '@/lib/constants';
-import type { PropertyFilter } from '@/lib/types';
+import { Panel } from '@/components/common/Panel';
+import {
+ useMessages,
+ usePropertyFieldsQuery,
+ useSessionDataPropertiesQuery,
+} from '@/components/hooks';
import { PropertyChart } from '@/components/property-data/PropertyChart';
import { PropertyDateChart } from '@/components/property-data/PropertyDateChart';
import { PropertyFilterBar } from '@/components/property-data/PropertyFilterBar';
import { PropertyFilterButton } from '@/components/property-data/PropertyFilterButton';
import { PropertyNumericChart } from '@/components/property-data/PropertyNumericChart';
-import { Panel } from '@/components/common/Panel';
+import { DATA_TYPE } from '@/lib/constants';
+import type { PropertyFilter } from '@/lib/types';
import { SessionDataPivotTable } from '../session-data/SessionDataPivotTable';
import { SessionPropertyChart } from '../session-data/SessionPropertyChart';
@@ -111,7 +115,9 @@ export function SessionProperties({ websiteId }: { websiteId: string }) {
)}
)}
- {propertyName &&
}
+ {propertyName && (
+
+ )}
{propertyName && selectedProperty?.dataType === DATA_TYPE.number && (
{(row: any) => (
-
+
)}
diff --git a/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx b/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx
index 3233a8585..b89e4e222 100644
--- a/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx
+++ b/src/app/(main)/websites/[websiteId]/settings/ShareEditForm.tsx
@@ -137,21 +137,21 @@ export function ShareEditForm({
-
- setValue('allowFilter', value, { shouldDirty: true })}
- >
- {t(labels.filtersEnabled)}
-
-
-
- setValue('theme', value, { shouldDirty: true })}
- />
-
+
+ setValue('allowFilter', value, { shouldDirty: true })}
+ >
+ {t(labels.filtersEnabled)}
+
+
+
+ setValue('theme', value, { shouldDirty: true })}
+ />
+
diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteReplaySettings.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteReplaySettings.tsx
index d7309affe..128ef106b 100644
--- a/src/app/(main)/websites/[websiteId]/settings/WebsiteReplaySettings.tsx
+++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteReplaySettings.tsx
@@ -93,14 +93,18 @@ export function WebsiteReplaySettings({ websiteId }: { websiteId: string }) {
const previous = replayEnabled;
setReplayEnabled(value);
- await saveRecorderConfig(getNextConfig({ replayEnabled: value }), () => setReplayEnabled(previous));
+ await saveRecorderConfig(getNextConfig({ replayEnabled: value }), () =>
+ setReplayEnabled(previous),
+ );
};
const handleHeatmapToggle = async (value: boolean) => {
const previous = heatmapEnabled;
setHeatmapEnabled(value);
- await saveRecorderConfig(getNextConfig({ heatmapEnabled: value }), () => setHeatmapEnabled(previous));
+ await saveRecorderConfig(getNextConfig({ heatmapEnabled: value }), () =>
+ setHeatmapEnabled(previous),
+ );
};
const handleSave = async () => {
diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx
index 42b968b5f..b96d3c6e7 100644
--- a/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx
+++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteSettingsHeader.tsx
@@ -1,6 +1,6 @@
import { Row } from '@umami/react-zen';
-import Link from '@/components/common/Link';
import { IconLabel } from '@/components/common/IconLabel';
+import Link from '@/components/common/Link';
import { PageHeader } from '@/components/common/PageHeader';
import { useMessages, useNavigation, useWebsite } from '@/components/hooks';
import { ArrowLeft, Globe } from '@/components/icons';
diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteTrackingCode.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteTrackingCode.tsx
index 9deb93f7f..7696161c9 100644
--- a/src/app/(main)/websites/[websiteId]/settings/WebsiteTrackingCode.tsx
+++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteTrackingCode.tsx
@@ -34,7 +34,14 @@ export function WebsiteTrackingCode({
{t(messages.trackingCode)}
-
+
);
}
diff --git a/src/app/api/boards/[boardId]/shares/route.ts b/src/app/api/boards/[boardId]/shares/route.ts
index 46e28e522..023189bd5 100644
--- a/src/app/api/boards/[boardId]/shares/route.ts
+++ b/src/app/api/boards/[boardId]/shares/route.ts
@@ -8,10 +8,7 @@ import { anyObjectParam, filterParams, pagingParams } from '@/lib/schema';
import { canUpdateBoard, canViewBoard } from '@/permissions';
import { createShare, getSharesByEntityId } from '@/queries/prisma';
-export async function GET(
- request: Request,
- { params }: { params: Promise<{ boardId: string }> },
-) {
+export async function GET(request: Request, { params }: { params: Promise<{ boardId: string }> }) {
const schema = z.object({
...filterParams,
...pagingParams,
@@ -39,10 +36,7 @@ export async function GET(
return json(data);
}
-export async function POST(
- request: Request,
- { params }: { params: Promise<{ boardId: string }> },
-) {
+export async function POST(request: Request, { params }: { params: Promise<{ boardId: string }> }) {
const schema = z.object({
name: z.string().max(200),
parameters: anyObjectParam.optional(),
diff --git a/src/app/api/dashboard/route.ts b/src/app/api/dashboard/route.ts
index 880057181..130c64e54 100644
--- a/src/app/api/dashboard/route.ts
+++ b/src/app/api/dashboard/route.ts
@@ -1,7 +1,7 @@
+import { z } from 'zod';
import { parseRequest } from '@/lib/request';
import { json, unauthorized } from '@/lib/response';
import { createBoard, getBoard, updateBoard } from '@/queries/prisma';
-import { z } from 'zod';
export async function GET(request: Request) {
const { auth, error } = await parseRequest(request);
diff --git a/src/app/api/links/[linkId]/shares/route.ts b/src/app/api/links/[linkId]/shares/route.ts
index f596bad85..554dbdd26 100644
--- a/src/app/api/links/[linkId]/shares/route.ts
+++ b/src/app/api/links/[linkId]/shares/route.ts
@@ -8,10 +8,7 @@ import { anyObjectParam, filterParams, pagingParams } from '@/lib/schema';
import { canUpdateLink, canViewLink } from '@/permissions';
import { createShare, getSharesByEntityId } from '@/queries/prisma';
-export async function GET(
- request: Request,
- { params }: { params: Promise<{ linkId: string }> },
-) {
+export async function GET(request: Request, { params }: { params: Promise<{ linkId: string }> }) {
const schema = z.object({
...filterParams,
...pagingParams,
@@ -39,10 +36,7 @@ export async function GET(
return json(data);
}
-export async function POST(
- request: Request,
- { params }: { params: Promise<{ linkId: string }> },
-) {
+export async function POST(request: Request, { params }: { params: Promise<{ linkId: string }> }) {
const schema = z.object({
name: z.string().max(200),
parameters: anyObjectParam.optional(),
diff --git a/src/app/api/pixels/[pixelId]/shares/route.ts b/src/app/api/pixels/[pixelId]/shares/route.ts
index a82b8ff7e..9ac539101 100644
--- a/src/app/api/pixels/[pixelId]/shares/route.ts
+++ b/src/app/api/pixels/[pixelId]/shares/route.ts
@@ -8,10 +8,7 @@ import { anyObjectParam, filterParams, pagingParams } from '@/lib/schema';
import { canUpdatePixel, canViewPixel } from '@/permissions';
import { createShare, getSharesByEntityId } from '@/queries/prisma';
-export async function GET(
- request: Request,
- { params }: { params: Promise<{ pixelId: string }> },
-) {
+export async function GET(request: Request, { params }: { params: Promise<{ pixelId: string }> }) {
const schema = z.object({
...filterParams,
...pagingParams,
@@ -39,10 +36,7 @@ export async function GET(
return json(data);
}
-export async function POST(
- request: Request,
- { params }: { params: Promise<{ pixelId: string }> },
-) {
+export async function POST(request: Request, { params }: { params: Promise<{ pixelId: string }> }) {
const schema = z.object({
name: z.string().max(200),
parameters: anyObjectParam.optional(),
diff --git a/src/app/api/realtime/[websiteId]/route.ts b/src/app/api/realtime/[websiteId]/route.ts
index da12e9b15..a709d87c3 100644
--- a/src/app/api/realtime/[websiteId]/route.ts
+++ b/src/app/api/realtime/[websiteId]/route.ts
@@ -3,8 +3,8 @@ import { z } from 'zod';
import { REALTIME_RANGE } from '@/lib/constants';
import { getQueryFilters, parseRequest } from '@/lib/request';
import { json, unauthorized } from '@/lib/response';
-import { canViewWebsiteSection } from '@/permissions';
import { filterParams, timezoneParam, unitParam } from '@/lib/schema';
+import { canViewWebsiteSection } from '@/permissions';
import { getRealtimeData } from '@/queries/sql';
export async function GET(
diff --git a/src/app/api/record/route.ts b/src/app/api/record/route.ts
index 91c2282dc..ad304a27c 100644
--- a/src/app/api/record/route.ts
+++ b/src/app/api/record/route.ts
@@ -1,11 +1,11 @@
import { isbot } from 'isbot';
import { serializeError } from 'serialize-error';
import { z } from 'zod';
+import { HEATMAP_EVENT_TYPE } from '@/lib/constants';
import { secret } from '@/lib/crypto';
import { getClientInfo, hasBlockedIp } from '@/lib/detect';
import { parseToken } from '@/lib/jwt';
import { fetchAccount, fetchTeam } from '@/lib/load';
-import { HEATMAP_EVENT_TYPE } from '@/lib/constants';
import { getRecorderConfig } from '@/lib/recorder';
import { parseRequest } from '@/lib/request';
import { badRequest, forbidden, json, serverError } from '@/lib/response';
@@ -185,15 +185,15 @@ export async function POST(request: Request) {
visitId,
eventType: event.type === 'click' ? HEATMAP_EVENT_TYPE.click : HEATMAP_EVENT_TYPE.scroll,
nodeId: null,
- x: event.type === 'click' ? event.x ?? null : null,
- y: event.type === 'click' ? event.y ?? null : null,
- pageX: event.type === 'click' ? event.pageX ?? null : null,
- pageY: event.type === 'click' ? event.pageY ?? null : null,
+ x: event.type === 'click' ? (event.x ?? null) : null,
+ y: event.type === 'click' ? (event.y ?? null) : null,
+ pageX: event.type === 'click' ? (event.pageX ?? null) : null,
+ pageY: event.type === 'click' ? (event.pageY ?? null) : null,
pageW: event.pageW ?? null,
viewportW: event.viewportW ?? null,
viewportH: event.viewportH ?? null,
pageH: event.pageH ?? null,
- scrollPct: event.type === 'scroll' ? event.scrollPct ?? null : null,
+ scrollPct: event.type === 'scroll' ? (event.scrollPct ?? null) : null,
urlPath: getUrlPath(event.url),
createdAt: new Date(event.timestamp ?? fallbackMs),
replayChunkIndex: null,
diff --git a/src/app/api/websites/[websiteId]/recorder/route.ts b/src/app/api/websites/[websiteId]/recorder/route.ts
index ef6307055..af8c42183 100644
--- a/src/app/api/websites/[websiteId]/recorder/route.ts
+++ b/src/app/api/websites/[websiteId]/recorder/route.ts
@@ -1,5 +1,5 @@
-import { parseRequest } from '@/lib/request';
import { getRecorderConfig } from '@/lib/recorder';
+import { parseRequest } from '@/lib/request';
import { getWebsite } from '@/queries/prisma';
export async function GET(
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 0cd4363b5..d313ba463 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,6 +1,6 @@
import type { Metadata } from 'next';
-import { headers } from 'next/headers';
import { Inter } from 'next/font/google';
+import { headers } from 'next/headers';
import { Suspense } from 'react';
import { getBaseUrl } from '@/lib/get-base-url';
import { Providers } from './Providers';
diff --git a/src/app/share/ShareProvider.tsx b/src/app/share/ShareProvider.tsx
index 806e1347a..790298bc6 100644
--- a/src/app/share/ShareProvider.tsx
+++ b/src/app/share/ShareProvider.tsx
@@ -1,10 +1,10 @@
'use client';
-import { useShareTokenQuery } from '@/components/hooks';
-import { ENTITY_TYPE } from '@/lib/constants';
-import type { ShareParameters, WhiteLabel } from '@/lib/types';
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 { ENTITY_TYPE } from '@/lib/constants';
+import type { ShareParameters, WhiteLabel } from '@/lib/types';
export interface ShareData {
shareId: string;
diff --git a/src/app/share/[slug]/[[...path]]/ShareBranding.tsx b/src/app/share/[slug]/[[...path]]/ShareBranding.tsx
index 89573b288..de45d1d33 100644
--- a/src/app/share/[slug]/[[...path]]/ShareBranding.tsx
+++ b/src/app/share/[slug]/[[...path]]/ShareBranding.tsx
@@ -1,7 +1,7 @@
'use client';
+import { Icon, Row, Text } from '@umami/react-zen';
import { useShare } from '@/components/hooks';
import { Logo } from '@/components/svg';
-import { Icon, Row, Text } from '@umami/react-zen';
const LOGO_SIZE = { sm: 24, md: 32, lg: 40 };
const TEXT_SIZE = { sm: 'sm', md: 'base', lg: 'lg' } as const;
diff --git a/src/app/share/[slug]/[[...path]]/ShareFooter.tsx b/src/app/share/[slug]/[[...path]]/ShareFooter.tsx
index 69177b34c..2b9e9d542 100644
--- a/src/app/share/[slug]/[[...path]]/ShareFooter.tsx
+++ b/src/app/share/[slug]/[[...path]]/ShareFooter.tsx
@@ -1,6 +1,6 @@
'use client';
-import { useShare } from '@/components/hooks';
import { Column, Row } from '@umami/react-zen';
+import { useShare } from '@/components/hooks';
import { ShareBranding } from './ShareBranding';
export function ShareFooter() {
diff --git a/src/app/share/[slug]/[[...path]]/ShareNav.tsx b/src/app/share/[slug]/[[...path]]/ShareNav.tsx
index 66899d256..a747f71b5 100644
--- a/src/app/share/[slug]/[[...path]]/ShareNav.tsx
+++ b/src/app/share/[slug]/[[...path]]/ShareNav.tsx
@@ -1,11 +1,3 @@
-import { IconLabel } from '@/components/common/IconLabel';
-import { useMessages, useNavigation, useShare } from '@/components/hooks';
-import { AlignEndHorizontal, Clock, Eye, PanelLeft, Sheet, Tag, User } from '@/components/icons';
-import { LanguageButton } from '@/components/input/LanguageButton';
-import { PreferencesButton } from '@/components/input/PreferencesButton';
-import { allowShareFilter, excludeShareFilterParam, getShareTheme } from '@/lib/share';
-import { Funnel, Gauge, Lightning, Magnet, Money, Network, Path, Target } from '@/components/svg';
-import { buildPath } from '@/lib/url';
import {
Button,
Column,
@@ -17,7 +9,15 @@ import {
Tooltip,
TooltipTrigger,
} from '@umami/react-zen';
+import { IconLabel } from '@/components/common/IconLabel';
import Link from '@/components/common/Link';
+import { useMessages, useNavigation, useShare } from '@/components/hooks';
+import { AlignEndHorizontal, Clock, Eye, PanelLeft, Sheet, Tag, User } from '@/components/icons';
+import { LanguageButton } from '@/components/input/LanguageButton';
+import { PreferencesButton } from '@/components/input/PreferencesButton';
+import { Funnel, Gauge, Lightning, Magnet, Money, Network, Path, Target } from '@/components/svg';
+import { allowShareFilter, excludeShareFilterParam, getShareTheme } from '@/lib/share';
+import { buildPath } from '@/lib/url';
import { ShareBranding } from './ShareBranding';
export function ShareNav({
diff --git a/src/app/share/[slug]/[[...path]]/SharePage.tsx b/src/app/share/[slug]/[[...path]]/SharePage.tsx
index d6660bd8a..87b76a71c 100644
--- a/src/app/share/[slug]/[[...path]]/SharePage.tsx
+++ b/src/app/share/[slug]/[[...path]]/SharePage.tsx
@@ -1,4 +1,7 @@
'use client';
+import { Column, Grid, Row, useTheme } from '@umami/react-zen';
+import { usePathname, useRouter } from 'next/navigation';
+import { useEffect, useState } from 'react';
import { BoardViewPage } from '@/app/(main)/boards/[boardId]/BoardViewPage';
import { LinkPage } from '@/app/(main)/links/[linkId]/LinkPage';
import { PixelPage } from '@/app/(main)/pixels/[pixelId]/PixelPage';
@@ -7,10 +10,10 @@ import { BreakdownPage } from '@/app/(main)/websites/[websiteId]/(reports)/break
import { FunnelsPage } from '@/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage';
import { GoalsPage } from '@/app/(main)/websites/[websiteId]/(reports)/goals/GoalsPage';
import { JourneysPage } from '@/app/(main)/websites/[websiteId]/(reports)/journeys/JourneysPage';
+import { PerformancePage } from '@/app/(main)/websites/[websiteId]/(reports)/performance/PerformancePage';
import { RetentionPage } from '@/app/(main)/websites/[websiteId]/(reports)/retention/RetentionPage';
import { RevenuePage } from '@/app/(main)/websites/[websiteId]/(reports)/revenue/RevenuePage';
import { UTMPage } from '@/app/(main)/websites/[websiteId]/(reports)/utm/UTMPage';
-import { PerformancePage } from '@/app/(main)/websites/[websiteId]/(reports)/performance/PerformancePage';
import { ComparePage } from '@/app/(main)/websites/[websiteId]/compare/ComparePage';
import { EventsPage } from '@/app/(main)/websites/[websiteId]/events/EventsPage';
import { RealtimePage } from '@/app/(main)/websites/[websiteId]/realtime/RealtimePage';
@@ -23,9 +26,6 @@ import { useShare } from '@/components/hooks';
import { MobileMenuButton } from '@/components/input/MobileMenuButton';
import { ENTITY_TYPE } from '@/lib/constants';
import { getShareTheme } from '@/lib/share';
-import { Column, Grid, Row, useTheme } from '@umami/react-zen';
-import { usePathname, useRouter } from 'next/navigation';
-import { useEffect, useState } from 'react';
import { ShareFooter } from './ShareFooter';
import { ShareNav } from './ShareNav';
diff --git a/src/components/charts/BarChart.tsx b/src/components/charts/BarChart.tsx
index db0cc1b60..9bf3f9fc0 100644
--- a/src/components/charts/BarChart.tsx
+++ b/src/components/charts/BarChart.tsx
@@ -1,3 +1,5 @@
+import { useTheme } from '@umami/react-zen';
+import { memo, useCallback, useMemo, useState } from 'react';
import { Chart, type ChartProps } from '@/components/charts/Chart';
import { ChartTooltip } from '@/components/charts/ChartTooltip';
import { useLocale } from '@/components/hooks';
@@ -5,8 +7,6 @@ import { renderNumberLabels } from '@/lib/charts';
import { getThemeColors } from '@/lib/colors';
import { DATE_FORMATS, formatDate } from '@/lib/date';
import { formatLongCurrency, formatLongNumber } from '@/lib/format';
-import { useTheme } from '@umami/react-zen';
-import { memo, useCallback, useMemo, useState } from 'react';
const MemoChart = memo(Chart);
diff --git a/src/components/charts/DistributionBarChart.tsx b/src/components/charts/DistributionBarChart.tsx
index 90a668c83..e315d745c 100644
--- a/src/components/charts/DistributionBarChart.tsx
+++ b/src/components/charts/DistributionBarChart.tsx
@@ -127,31 +127,38 @@ function DistributionBarChartComponent({
[chartData.labels, colors, horizontal, stacked],
);
- const handleTooltip = useCallback(({ tooltip }: { tooltip: any }) => {
- const { opacity, labelColors, dataPoints } = tooltip;
- const point = dataPoints?.[0];
- const nextTooltip = opacity
- ? {
- title: (point?.label ?? '').toString(),
- color: labelColors?.[0]?.backgroundColor,
- value: `${formatLongNumber(
- Number(horizontal ? point?.raw?.x ?? point?.raw ?? 0 : point?.raw?.y ?? point?.raw ?? 0),
- )}${point?.dataset?.label ? ` ${point.dataset.label}` : ''}`,
+ const handleTooltip = useCallback(
+ ({ tooltip }: { tooltip: any }) => {
+ const { opacity, labelColors, dataPoints } = tooltip;
+ const point = dataPoints?.[0];
+ const nextTooltip = opacity
+ ? {
+ title: (point?.label ?? '').toString(),
+ color: labelColors?.[0]?.backgroundColor,
+ value: `${formatLongNumber(
+ Number(
+ horizontal
+ ? (point?.raw?.x ?? point?.raw ?? 0)
+ : (point?.raw?.y ?? point?.raw ?? 0),
+ ),
+ )}${point?.dataset?.label ? ` ${point.dataset.label}` : ''}`,
+ }
+ : null;
+
+ setTooltip(prev => {
+ if (
+ prev?.title === nextTooltip?.title &&
+ prev?.color === nextTooltip?.color &&
+ prev?.value === nextTooltip?.value
+ ) {
+ return prev;
}
- : null;
- setTooltip(prev => {
- if (
- prev?.title === nextTooltip?.title &&
- prev?.color === nextTooltip?.color &&
- prev?.value === nextTooltip?.value
- ) {
- return prev;
- }
-
- return nextTooltip;
- });
- }, [horizontal]);
+ return nextTooltip;
+ });
+ },
+ [horizontal],
+ );
return (
<>
diff --git a/src/components/common/Badge.module.css b/src/components/common/Badge.module.css
index 216c9c2ae..c3c293141 100644
--- a/src/components/common/Badge.module.css
+++ b/src/components/common/Badge.module.css
@@ -54,29 +54,29 @@
background: var(--text-muted);
}
-:global([data-theme='dark']) .good {
+:global([data-theme="dark"]) .good {
color: #86efac;
background: rgba(22, 163, 74, 0.15);
}
-:global([data-theme='dark']) .good .dot {
+:global([data-theme="dark"]) .good .dot {
background: #4ade80;
}
-:global([data-theme='dark']) .warning {
+:global([data-theme="dark"]) .warning {
color: #fde047;
background: rgba(202, 138, 4, 0.15);
}
-:global([data-theme='dark']) .warning .dot {
+:global([data-theme="dark"]) .warning .dot {
background: #facc15;
}
-:global([data-theme='dark']) .danger {
+:global([data-theme="dark"]) .danger {
color: #fca5a5;
background: rgba(220, 38, 38, 0.15);
}
-:global([data-theme='dark']) .danger .dot {
+:global([data-theme="dark"]) .danger .dot {
background: #f87171;
}
diff --git a/src/components/common/CopyButton.tsx b/src/components/common/CopyButton.tsx
index d393cf77a..f719c229c 100644
--- a/src/components/common/CopyButton.tsx
+++ b/src/components/common/CopyButton.tsx
@@ -2,13 +2,7 @@ import { Button, Icon } from '@umami/react-zen';
import { useEffect, useRef, useState } from 'react';
import { Check, Copy } from '@/components/icons';
-export function CopyButton({
- value,
- label = 'Copy',
-}: {
- value: string;
- label?: string;
-}) {
+export function CopyButton({ value, label = 'Copy' }: { value: string; label?: string }) {
const [copied, setCopied] = useState(false);
const timeoutRef = useRef(null);
diff --git a/src/components/common/DataGrid.tsx b/src/components/common/DataGrid.tsx
index 3c9974572..f2c1cac99 100644
--- a/src/components/common/DataGrid.tsx
+++ b/src/components/common/DataGrid.tsx
@@ -62,7 +62,7 @@ export function DataGrid({
return stored === 'table' || stored === 'cards' ? stored : null;
});
- const displayMode: DisplayMode | undefined = isMobile ? 'cards' : userDisplayMode ?? undefined;
+ const displayMode: DisplayMode | undefined = isMobile ? 'cards' : (userDisplayMode ?? undefined);
const handleToggleDisplayMode = () => {
const next: DisplayMode = displayMode === 'cards' ? 'table' : 'cards';
diff --git a/src/components/common/ExternalLink.tsx b/src/components/common/ExternalLink.tsx
index 89e9e6cba..c5eb4219b 100644
--- a/src/components/common/ExternalLink.tsx
+++ b/src/components/common/ExternalLink.tsx
@@ -1,6 +1,6 @@
import { Icon, Row, Text } from '@umami/react-zen';
-import Link, { type LinkProps } from '@/components/common/Link';
import type { ReactNode } from 'react';
+import Link, { type LinkProps } from '@/components/common/Link';
import { ExternalLink as LinkIcon } from '@/components/icons';
export function ExternalLink({
diff --git a/src/components/common/FilterLink.tsx b/src/components/common/FilterLink.tsx
index f124706b9..ad5ea6722 100644
--- a/src/components/common/FilterLink.tsx
+++ b/src/components/common/FilterLink.tsx
@@ -1,6 +1,6 @@
import { Icon, Row, Text } from '@umami/react-zen';
-import Link from '@/components/common/Link';
import { type HTMLAttributes, type ReactNode, useState } from 'react';
+import Link from '@/components/common/Link';
import { useMessages, useNavigation } from '@/components/hooks';
import { ExternalLink } from '@/components/icons';
diff --git a/src/components/common/LinkButton.tsx b/src/components/common/LinkButton.tsx
index 826aedcf4..8486d6cf6 100644
--- a/src/components/common/LinkButton.tsx
+++ b/src/components/common/LinkButton.tsx
@@ -1,6 +1,6 @@
import { Button, type ButtonProps } from '@umami/react-zen';
-import Link from '@/components/common/Link';
import type { ReactNode } from 'react';
+import Link from '@/components/common/Link';
import { useLocale } from '@/components/hooks';
export interface LinkButtonProps extends ButtonProps {
diff --git a/src/components/common/NavMenu.tsx b/src/components/common/NavMenu.tsx
index 9442b2486..9bdc918a8 100644
--- a/src/components/common/NavMenu.tsx
+++ b/src/components/common/NavMenu.tsx
@@ -1,6 +1,6 @@
import { Column, Heading, Row, Text } from '@umami/react-zen';
-import Link from '@/components/common/Link';
import { IconLabel } from '@/components/common/IconLabel';
+import Link from '@/components/common/Link';
interface NavMenuData {
id: string;
diff --git a/src/components/common/Pager.tsx b/src/components/common/Pager.tsx
index f3d72fb47..7522770f8 100644
--- a/src/components/common/Pager.tsx
+++ b/src/components/common/Pager.tsx
@@ -11,13 +11,7 @@ export interface PagerProps {
className?: string;
}
-export function Pager({
- page,
- pageSize,
- count,
- isCapped,
- onPageChange,
-}: PagerProps) {
+export function Pager({ page, pageSize, count, isCapped, onPageChange }: PagerProps) {
const { t, labels } = useMessages();
const maxPage = pageSize && count ? Math.ceil(+count / +pageSize) : 0;
const lastPage = page === maxPage;
diff --git a/src/components/common/SortableLabel.tsx b/src/components/common/SortableLabel.tsx
index c45550c8c..99ca27691 100644
--- a/src/components/common/SortableLabel.tsx
+++ b/src/components/common/SortableLabel.tsx
@@ -1,9 +1,9 @@
'use client';
-import type { ReactNode } from 'react';
import { Icon } from '@umami/react-zen';
-import { ChevronDown, ChevronUp } from '@/components/icons';
+import type { ReactNode } from 'react';
import { useNavigation } from '@/components/hooks';
+import { ChevronDown, ChevronUp } from '@/components/icons';
type SortDirection = 'asc' | 'desc';
@@ -13,11 +13,7 @@ export interface SortableLabelProps {
defaultDirection?: SortDirection;
}
-export function SortableLabel({
- label,
- sortKey,
- defaultDirection = 'asc',
-}: SortableLabelProps) {
+export function SortableLabel({ label, sortKey, defaultDirection = 'asc' }: SortableLabelProps) {
const { router, query, updateParams } = useNavigation();
const isActive = query.orderBy === sortKey;
const isDescending = query.sortDescending === 'true';
diff --git a/src/components/hooks/index.ts b/src/components/hooks/index.ts
index 925b0a336..2db8d42e7 100644
--- a/src/components/hooks/index.ts
+++ b/src/components/hooks/index.ts
@@ -41,16 +41,16 @@ export * from './queries/useReplaysQuery';
export * from './queries/useReportQuery';
export * from './queries/useReportsQuery';
export * from './queries/useResultQuery';
-export * from './queries/useRevenueSessionsQuery';
-export * from './queries/useRevenueMetricsQuery';
export * from './queries/useRevenueChartQuery';
+export * from './queries/useRevenueMetricsQuery';
+export * from './queries/useRevenueSessionsQuery';
export * from './queries/useRevenueStatsQuery';
export * from './queries/useSavedReplaysQuery';
export * from './queries/useSessionActivityQuery';
-export * from './queries/useSessionDataPropertiesQuery';
-export * from './queries/useSessionDataPivotQuery';
-export * from './queries/useSessionDataQuery';
export * from './queries/useSessionDataActivityStatsQuery';
+export * from './queries/useSessionDataPivotQuery';
+export * from './queries/useSessionDataPropertiesQuery';
+export * from './queries/useSessionDataQuery';
export * from './queries/useSessionDataValuesQuery';
export * from './queries/useSessionReplaysQuery';
export * from './queries/useShareTokenQuery';
diff --git a/src/components/hooks/queries/useLinkSharesQuery.ts b/src/components/hooks/queries/useLinkSharesQuery.ts
index 990952d05..9245ea65b 100644
--- a/src/components/hooks/queries/useLinkSharesQuery.ts
+++ b/src/components/hooks/queries/useLinkSharesQuery.ts
@@ -3,10 +3,7 @@ import { useApi } from '../useApi';
import { useModified } from '../useModified';
import { usePagedQuery } from '../usePagedQuery';
-export function useLinkSharesQuery(
- { linkId }: { linkId: string },
- options?: ReactQueryOptions,
-) {
+export function useLinkSharesQuery({ linkId }: { linkId: string }, options?: ReactQueryOptions) {
const { modified } = useModified('shares');
const { get } = useApi();
diff --git a/src/components/hooks/queries/usePixelSharesQuery.ts b/src/components/hooks/queries/usePixelSharesQuery.ts
index aacd07a7a..3bb8c2486 100644
--- a/src/components/hooks/queries/usePixelSharesQuery.ts
+++ b/src/components/hooks/queries/usePixelSharesQuery.ts
@@ -3,10 +3,7 @@ import { useApi } from '../useApi';
import { useModified } from '../useModified';
import { usePagedQuery } from '../usePagedQuery';
-export function usePixelSharesQuery(
- { pixelId }: { pixelId: string },
- options?: ReactQueryOptions,
-) {
+export function usePixelSharesQuery({ pixelId }: { pixelId: string }, options?: ReactQueryOptions) {
const { modified } = useModified('shares');
const { get } = useApi();
diff --git a/src/components/hooks/queries/usePropertyArraySeriesQuery.ts b/src/components/hooks/queries/usePropertyArraySeriesQuery.ts
index fd4b8a42c..da79dfbbd 100644
--- a/src/components/hooks/queries/usePropertyArraySeriesQuery.ts
+++ b/src/components/hooks/queries/usePropertyArraySeriesQuery.ts
@@ -20,7 +20,17 @@ export function usePropertyArraySeriesQuery(
return useQuery({
queryKey: [
`websites:${source}-data:array-series`,
- { websiteId, propertyName, eventName, propertyFilters, startAt, endAt, unit, timezone, ...params },
+ {
+ websiteId,
+ propertyName,
+ eventName,
+ propertyFilters,
+ startAt,
+ endAt,
+ unit,
+ timezone,
+ ...params,
+ },
],
queryFn: () =>
get(
diff --git a/src/components/hooks/queries/usePropertyNumericSeriesQuery.ts b/src/components/hooks/queries/usePropertyNumericSeriesQuery.ts
index ffe5b18b7..8dff51742 100644
--- a/src/components/hooks/queries/usePropertyNumericSeriesQuery.ts
+++ b/src/components/hooks/queries/usePropertyNumericSeriesQuery.ts
@@ -21,7 +21,18 @@ export function usePropertyNumericSeriesQuery(
return useQuery({
queryKey: [
`websites:${source}-data:numeric-series`,
- { websiteId, propertyName, metric, eventName, propertyFilters, startAt, endAt, unit, timezone, ...params },
+ {
+ websiteId,
+ propertyName,
+ metric,
+ eventName,
+ propertyFilters,
+ startAt,
+ endAt,
+ unit,
+ timezone,
+ ...params,
+ },
],
queryFn: () =>
get(
diff --git a/src/components/hooks/queries/usePropertySeriesQuery.ts b/src/components/hooks/queries/usePropertySeriesQuery.ts
index 3df8af796..124e0abc4 100644
--- a/src/components/hooks/queries/usePropertySeriesQuery.ts
+++ b/src/components/hooks/queries/usePropertySeriesQuery.ts
@@ -20,7 +20,17 @@ export function usePropertySeriesQuery(
return useQuery({
queryKey: [
`websites:${source}-data:property-series`,
- { websiteId, propertyName, eventName, propertyFilters, startAt, endAt, unit, timezone, ...params },
+ {
+ websiteId,
+ propertyName,
+ eventName,
+ propertyFilters,
+ startAt,
+ endAt,
+ unit,
+ timezone,
+ ...params,
+ },
],
queryFn: () =>
get(
diff --git a/src/components/hooks/queries/usePropertyValuesQuery.ts b/src/components/hooks/queries/usePropertyValuesQuery.ts
index 131620fae..5c0ea227d 100644
--- a/src/components/hooks/queries/usePropertyValuesQuery.ts
+++ b/src/components/hooks/queries/usePropertyValuesQuery.ts
@@ -21,7 +21,18 @@ export function usePropertyValuesQuery(
return useQuery({
queryKey: [
`websites:${source}-data:values`,
- { websiteId, propertyName, dataType, eventName, propertyFilters, startAt, endAt, unit, timezone, ...params },
+ {
+ websiteId,
+ propertyName,
+ dataType,
+ eventName,
+ propertyFilters,
+ startAt,
+ endAt,
+ unit,
+ timezone,
+ ...params,
+ },
],
queryFn: () =>
get(
diff --git a/src/components/hooks/queries/useRevenueStatsQuery.ts b/src/components/hooks/queries/useRevenueStatsQuery.ts
index 42654889f..5dd638125 100644
--- a/src/components/hooks/queries/useRevenueStatsQuery.ts
+++ b/src/components/hooks/queries/useRevenueStatsQuery.ts
@@ -35,7 +35,10 @@ export function useRevenueStatsQuery(
const filters = useFilterParameters({ includePagination: false });
return useQuery({
- queryKey: ['websites:revenue:stats', { websiteId, currency, compare, startAt, endAt, ...filters }],
+ queryKey: [
+ 'websites:revenue:stats',
+ { websiteId, currency, compare, startAt, endAt, ...filters },
+ ],
queryFn: () =>
get(`/websites/${websiteId}/revenue/stats`, {
currency,
diff --git a/src/components/hooks/queries/useSessionDataPropertiesQuery.ts b/src/components/hooks/queries/useSessionDataPropertiesQuery.ts
index 7bd041a0f..275725b49 100644
--- a/src/components/hooks/queries/useSessionDataPropertiesQuery.ts
+++ b/src/components/hooks/queries/useSessionDataPropertiesQuery.ts
@@ -1,6 +1,5 @@
-import type { ReactQueryOptions } from '@/lib/types';
import { serializePropertyFilters } from '@/lib/params';
-import type { PropertyFilter } from '@/lib/types';
+import type { PropertyFilter, ReactQueryOptions } from '@/lib/types';
import { useApi } from '../useApi';
import { useDateParameters } from '../useDateParameters';
import { useFilterParameters } from '../useFilterParameters';
diff --git a/src/components/hooks/useFilterParameters.ts b/src/components/hooks/useFilterParameters.ts
index b5900d465..c49d1a6bb 100644
--- a/src/components/hooks/useFilterParameters.ts
+++ b/src/components/hooks/useFilterParameters.ts
@@ -3,7 +3,11 @@ import { FILTER_COLUMNS } from '@/lib/constants';
import { useShare } from './context/useShare';
import { useNavigation } from './useNavigation';
-export function useFilterParameters({ includePagination = true }: { includePagination?: boolean } = {}) {
+export function useFilterParameters({
+ includePagination = true,
+}: {
+ includePagination?: boolean;
+} = {}) {
const { query } = useNavigation();
const share = useShare();
const allowFilter = share?.parameters?.allowFilter !== false;
diff --git a/src/components/hooks/useSubscription.ts b/src/components/hooks/useSubscription.ts
index e596b35c5..8e77f5b48 100644
--- a/src/components/hooks/useSubscription.ts
+++ b/src/components/hooks/useSubscription.ts
@@ -27,7 +27,7 @@ export function useSubscription(teamId?: string | null) {
const ownSubscription: Subscription = user?.subscription || defaultSubscription;
const teamSubscription: Subscription | null = teamId
- ? user?.teams?.find((t: any) => t.id === teamId)?.subscription ?? null
+ ? (user?.teams?.find((t: any) => t.id === teamId)?.subscription ?? null)
: null;
const subscription: Subscription = teamSubscription || ownSubscription;
diff --git a/src/components/input/DialogButton.tsx b/src/components/input/DialogButton.tsx
index 98faf9d5d..76c5903ba 100644
--- a/src/components/input/DialogButton.tsx
+++ b/src/components/input/DialogButton.tsx
@@ -68,7 +68,12 @@ export function DialogButton({
if (isOpen !== undefined) {
return (
-
+
{dialog}
);
@@ -79,9 +84,7 @@ export function DialogButton({
-
- {dialog}
-
+ {dialog}
);
}
diff --git a/src/components/input/FilterBar.tsx b/src/components/input/FilterBar.tsx
index d8c121222..4b3c97eb7 100644
--- a/src/components/input/FilterBar.tsx
+++ b/src/components/input/FilterBar.tsx
@@ -163,7 +163,11 @@ const FilterItem = ({ name, label, operator, value, onRemove }) => {
theme="dark"
>
-
+
{label}
diff --git a/src/components/input/FilterEditForm.tsx b/src/components/input/FilterEditForm.tsx
index 81c198f97..247a698ca 100644
--- a/src/components/input/FilterEditForm.tsx
+++ b/src/components/input/FilterEditForm.tsx
@@ -115,7 +115,12 @@ export function FilterEditForm({ websiteId, onChange, onClose }: FilterEditFormP
-
+
diff --git a/src/components/input/LookupField.tsx b/src/components/input/LookupField.tsx
index daa95aa0c..ba17f18f4 100644
--- a/src/components/input/LookupField.tsx
+++ b/src/components/input/LookupField.tsx
@@ -1,8 +1,8 @@
-import { Empty } from '@/components/common/Empty';
-import { useMessages, useWebsiteValuesQuery } from '@/components/hooks';
import { ComboBox, type ComboBoxProps, ListItem, Loading, useDebounce } from '@umami/react-zen';
import { endOfDay, subMonths } from 'date-fns';
import { type SetStateAction, useMemo, useState } from 'react';
+import { Empty } from '@/components/common/Empty';
+import { useMessages, useWebsiteValuesQuery } from '@/components/hooks';
export interface LookupFieldProps extends Omit {
websiteId: string;
diff --git a/src/components/input/ThemeModeSelector.tsx b/src/components/input/ThemeModeSelector.tsx
index ad4d6a920..b90910672 100644
--- a/src/components/input/ThemeModeSelector.tsx
+++ b/src/components/input/ThemeModeSelector.tsx
@@ -1,5 +1,5 @@
-import type { ReactNode } from 'react';
import { Button, Icon, Row } from '@umami/react-zen';
+import type { ReactNode } from 'react';
import { Monitor, Moon, Sun } from '@/components/icons';
export type ThemeMode = 'light' | 'dark' | 'system';
diff --git a/src/components/metrics/ActiveUsers.tsx b/src/components/metrics/ActiveUsers.tsx
index 8f0a68c2a..d08aeaeae 100644
--- a/src/components/metrics/ActiveUsers.tsx
+++ b/src/components/metrics/ActiveUsers.tsx
@@ -42,4 +42,4 @@ export function ActiveUsers({
}
return {content};
-}
\ No newline at end of file
+}
diff --git a/src/components/metrics/PerformanceCard.module.css b/src/components/metrics/PerformanceCard.module.css
index 9e0d1f296..bf8399e64 100644
--- a/src/components/metrics/PerformanceCard.module.css
+++ b/src/components/metrics/PerformanceCard.module.css
@@ -9,4 +9,3 @@
.card.selected {
box-shadow: 0 0 0 1px var(--text-primary);
}
-
diff --git a/src/components/property-data/PropertyChart.tsx b/src/components/property-data/PropertyChart.tsx
index 0700ff1a7..886bd4775 100644
--- a/src/components/property-data/PropertyChart.tsx
+++ b/src/components/property-data/PropertyChart.tsx
@@ -37,7 +37,9 @@ export function PropertyChart({
}) {
const { t, labels } = useMessages();
const { timezone } = useTimezone();
- const { dateRange: { startDate, endDate, unit } } = useDateRange({ timezone });
+ const {
+ dateRange: { startDate, endDate, unit },
+ } = useDateRange({ timezone });
const { locale, dateLocale } = useLocale();
const propertySeriesQuery = usePropertySeriesQuery(
source,
diff --git a/src/components/property-data/PropertyDateChart.tsx b/src/components/property-data/PropertyDateChart.tsx
index 4eb83d6ea..6d2cc25f2 100644
--- a/src/components/property-data/PropertyDateChart.tsx
+++ b/src/components/property-data/PropertyDateChart.tsx
@@ -5,18 +5,23 @@ import {
format,
formatDistance,
isValid,
+ type Locale,
startOfDay,
startOfMonth,
startOfWeek,
startOfYear,
- type Locale,
} from 'date-fns';
import { toZonedTime } from 'date-fns-tz';
import { type ReactNode, useCallback, useMemo } from 'react';
import { BarChart } from '@/components/charts/BarChart';
import { PieChart } from '@/components/charts/PieChart';
import { LoadingPanel } from '@/components/common/LoadingPanel';
-import { useLocale, useMessages, usePropertyDateSeriesQuery, useTimezone } from '@/components/hooks';
+import {
+ useLocale,
+ useMessages,
+ usePropertyDateSeriesQuery,
+ useTimezone,
+} from '@/components/hooks';
import type { PropertyDataSource } from '@/components/hooks/queries/usePropertyFieldsQuery';
import { ListTable } from '@/components/metrics/ListTable';
import { MetricsBar } from '@/components/metrics/MetricsBar';
@@ -30,7 +35,11 @@ type DateChartUnit = 'day' | 'week' | 'month' | 'year';
type ParsedDateRow = EventDataDateSeriesPoint & { date: Date };
function parseDateValue(value: string) {
- const normalized = value?.trim().replace(' ', 'T').replace(/Z$/, '').replace(/\.\d+$/, '');
+ const normalized = value
+ ?.trim()
+ .replace(' ', 'T')
+ .replace(/Z$/, '')
+ .replace(/\.\d+$/, '');
const [datePart = '', timePart = '00:00:00'] = normalized.split('T');
const [year = 0, month = 1, day = 1] = datePart.split('-').map(Number);
const [hour = 0, minute = 0, second = 0] = timePart.split(':').map(Number);
@@ -52,9 +61,17 @@ function InsightCard({ label, value, hint }: { label: string; value: string; hin
height="100%"
style={{ minWidth: 0 }}
>
- {label}
- {value}
- {hint && {hint}}
+
+ {label}
+
+
+ {value}
+
+ {hint && (
+
+ {hint}
+
+ )}
);
}
@@ -98,7 +115,13 @@ export function PropertyDateChart({
const { locale, dateLocale } = useLocale();
const { timezone } = useTimezone();
const { colors } = useMemo(() => getThemeColors(theme), [theme]);
- const query = usePropertyDateSeriesQuery(source, websiteId, propertyName, propertyFilters, eventName);
+ const query = usePropertyDateSeriesQuery(
+ source,
+ websiteId,
+ propertyName,
+ propertyFilters,
+ eventName,
+ );
const rows = useMemo(() => query.data ?? [], [query.data]);
const total = useMemo(() => rows.reduce((sum, { y }) => sum + y, 0), [rows]);
@@ -119,7 +142,8 @@ export function PropertyDateChart({
const minPropertyDate = exactDateRows[0]?.date ?? null;
const maxPropertyDate = exactDateRows[exactDateRows.length - 1]?.date ?? null;
const chartUnit = useMemo(
- () => (minPropertyDate && maxPropertyDate ? getChartUnit(minPropertyDate, maxPropertyDate) : 'day'),
+ () =>
+ minPropertyDate && maxPropertyDate ? getChartUnit(minPropertyDate, maxPropertyDate) : 'day',
[maxPropertyDate, minPropertyDate],
);
@@ -216,17 +240,28 @@ export function PropertyDateChart({
},
{} as Record,
);
- return Object.values(dayTotals).sort((a, b) => b.count - a.count || b.date.getTime() - a.date.getTime())[0];
+ return Object.values(dayTotals).sort(
+ (a, b) => b.count - a.count || b.date.getTime() - a.date.getTime(),
+ )[0];
}, [exactDateRows, total]);
- const topWeekday = useMemo(() => [...weekdayTableData].sort((a, b) => b.count - a.count)[0], [weekdayTableData]);
- const weekdayLabels = useMemo(() => weekdayTableData.map(({ label }) => label), [weekdayTableData]);
+ const topWeekday = useMemo(
+ () => [...weekdayTableData].sort((a, b) => b.count - a.count)[0],
+ [weekdayTableData],
+ );
+ const weekdayLabels = useMemo(
+ () => weekdayTableData.map(({ label }) => label),
+ [weekdayTableData],
+ );
const weekdayColorMap = useMemo(
() =>
- weekdayLabels.reduce((obj, label, index) => {
- obj[label] = CHART_COLORS[index % CHART_COLORS.length];
- return obj;
- }, {} as Record),
+ weekdayLabels.reduce(
+ (obj, label, index) => {
+ obj[label] = CHART_COLORS[index % CHART_COLORS.length];
+ return obj;
+ },
+ {} as Record,
+ ),
[weekdayLabels],
);
@@ -246,27 +281,48 @@ export function PropertyDateChart({
return (
-
+
diff --git a/src/components/property-data/PropertyFilterButton.tsx b/src/components/property-data/PropertyFilterButton.tsx
index b5beb3de6..c8b671886 100644
--- a/src/components/property-data/PropertyFilterButton.tsx
+++ b/src/components/property-data/PropertyFilterButton.tsx
@@ -1,9 +1,9 @@
'use client';
import { useMessages } from '@/components/hooks';
+import type { PropertyDataSource } from '@/components/hooks/queries/usePropertyFieldsQuery';
import { ListFilter } from '@/components/icons';
import { DialogButton } from '@/components/input/DialogButton';
import type { PropertyFilter } from '@/lib/types';
-import type { PropertyDataSource } from '@/components/hooks/queries/usePropertyFieldsQuery';
import { PropertyFilterEditForm } from './PropertyFilterEditForm';
export function PropertyFilterButton({
diff --git a/src/components/property-data/PropertyFilterEditForm.tsx b/src/components/property-data/PropertyFilterEditForm.tsx
index 6f5e9bce6..8b3a996eb 100644
--- a/src/components/property-data/PropertyFilterEditForm.tsx
+++ b/src/components/property-data/PropertyFilterEditForm.tsx
@@ -1,13 +1,25 @@
'use client';
-import { Button, Column, Grid, Icon, List, ListItem, Menu, MenuItem, MenuTrigger, Popover, Row } from '@umami/react-zen';
+import {
+ Button,
+ Column,
+ Grid,
+ Icon,
+ List,
+ ListItem,
+ Menu,
+ MenuItem,
+ MenuTrigger,
+ Popover,
+ Row,
+} from '@umami/react-zen';
import { format } from 'date-fns';
import { useState } from 'react';
import { Empty } from '@/components/common/Empty';
import { useMessages, useMobile, usePropertyFieldsQuery } from '@/components/hooks';
+import type { PropertyDataSource } from '@/components/hooks/queries/usePropertyFieldsQuery';
import { Plus } from '@/components/icons';
import { DATA_TYPE, OPERATORS } from '@/lib/constants';
import type { PropertyFilter } from '@/lib/types';
-import type { PropertyDataSource } from '@/components/hooks/queries/usePropertyFieldsQuery';
import { PropertyFilterRecord } from './PropertyFilterRecord';
export function PropertyFilterEditForm({
@@ -76,7 +88,10 @@ export function PropertyFilterEditForm({
style={{ maxHeight: 'calc(100vh - 2rem)', overflowY: 'auto' }}
>
{(fields as any[]).map(field => (
-
-
- setValue('allowFilter', value, { shouldDirty: true })}
- >
- {t(labels.filtersEnabled)}
-
-
-
- setValue('theme', value, { shouldDirty: true })}
- />
-
+
+ setValue('allowFilter', value, { shouldDirty: true })}
+ >
+ {t(labels.filtersEnabled)}
+
+
+
+ setValue('theme', value, { shouldDirty: true })}
+ />
+
{onClose && (
diff --git a/src/components/share/SimpleSharesTable.tsx b/src/components/share/SimpleSharesTable.tsx
index 13313f7b9..7af3e946d 100644
--- a/src/components/share/SimpleSharesTable.tsx
+++ b/src/components/share/SimpleSharesTable.tsx
@@ -1,8 +1,8 @@
+import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
import { ShareDeleteButton } from '@/app/(main)/websites/[websiteId]/settings/ShareDeleteButton';
import { CopyButton } from '@/components/common/CopyButton';
import { ExternalLink } from '@/components/common/ExternalLink';
import { useConfig, useMessages, useMobile } from '@/components/hooks';
-import { DataColumn, DataTable, type DataTableProps, Row } from '@umami/react-zen';
import { SimpleShareEditButton } from './SimpleShareEditButton';
export function SimpleSharesTable(props: DataTableProps) {
diff --git a/src/lib/api-url.test.ts b/src/lib/api-url.test.ts
index 322315b00..be4720295 100644
--- a/src/lib/api-url.test.ts
+++ b/src/lib/api-url.test.ts
@@ -30,8 +30,6 @@ describe('getApiUrl', () => {
});
test('returns absolute input urls unchanged', () => {
- expect(getApiUrl('https://example.com/api/websites')).toBe(
- 'https://example.com/api/websites',
- );
+ expect(getApiUrl('https://example.com/api/websites')).toBe('https://example.com/api/websites');
});
});
diff --git a/src/lib/api-url.ts b/src/lib/api-url.ts
index 8cc790c1b..7d6e9d74d 100644
--- a/src/lib/api-url.ts
+++ b/src/lib/api-url.ts
@@ -3,10 +3,7 @@ type ApiUrlOptions = {
basePath?: string;
};
-const APP_ROUTE_PATTERNS: RegExp[] = [
- /^\/auth(\/|$)/,
- /^\/config(\/|$)/,
-];
+const APP_ROUTE_PATTERNS: RegExp[] = [/^\/auth(\/|$)/, /^\/config(\/|$)/];
function trimTrailingSlash(value: string) {
return value.replace(/\/+$/, '');
diff --git a/src/lib/boards.ts b/src/lib/boards.ts
index 77199fb88..c53865584 100644
--- a/src/lib/boards.ts
+++ b/src/lib/boards.ts
@@ -1,5 +1,5 @@
-import type { Board, BoardComponentConfig, BoardParameters } from './types';
import { isBoardComponentSupportedByEntityType } from './boardComponentCompatibility';
+import type { Board, BoardComponentConfig, BoardParameters } from './types';
export const BOARD_TYPES = {
dashboard: 'dashboard',
@@ -72,9 +72,7 @@ export function isOpenBoardType(type?: string) {
}
export function requiresBoardEntity(type?: string) {
- return (
- type === BOARD_TYPES.website || type === BOARD_TYPES.pixel || type === BOARD_TYPES.link
- );
+ return type === BOARD_TYPES.website || type === BOARD_TYPES.pixel || type === BOARD_TYPES.link;
}
export function getBoardEntity(board?: Pick | Partial): {
@@ -141,10 +139,7 @@ export function getResolvedComponentEntity(
return getComponentEntity(config);
}
-export function isBoardComponentSupported(
- componentType: string,
- entityType?: BoardEntityType,
-) {
+export function isBoardComponentSupported(componentType: string, entityType?: BoardEntityType) {
return isBoardComponentSupportedByEntityType(componentType, entityType);
}
diff --git a/src/lib/generate.ts b/src/lib/generate.ts
index 752c0b609..0d3a0de84 100644
--- a/src/lib/generate.ts
+++ b/src/lib/generate.ts
@@ -1,11 +1,8 @@
-import { uniformInt } from 'pure-rand/distribution/uniformInt';
-import { xoroshiro128plus } from 'pure-rand/generator/xoroshiro128plus';
-
-const seed = Date.now() ^ (Math.random() * 0x100000000);
-const rng = xoroshiro128plus(seed);
-
export function random(min: number, max: number) {
- return uniformInt(rng, min, max);
+ const range = max - min + 1;
+ const buf = new Uint32Array(1);
+ globalThis.crypto.getRandomValues(buf);
+ return min + (buf[0] % range);
}
export function getRandomChars(
diff --git a/src/lib/heatmap-r2.ts b/src/lib/heatmap-r2.ts
index 76c8b7343..4da5d06d6 100644
--- a/src/lib/heatmap-r2.ts
+++ b/src/lib/heatmap-r2.ts
@@ -52,11 +52,7 @@ function getClient() {
return client;
}
-export async function putHeatmapSnapshot(
- objectKey: string,
- imageData: Buffer,
- mimeType: string,
-) {
+export async function putHeatmapSnapshot(objectKey: string, imageData: Buffer, mimeType: string) {
await getClient().send(
new PutObjectCommand({
Bucket: getBucket(),
diff --git a/src/lib/params.ts b/src/lib/params.ts
index 50cb6db2d..17341fd53 100644
--- a/src/lib/params.ts
+++ b/src/lib/params.ts
@@ -108,42 +108,44 @@ export function parsePropertyFilters(
query: Record,
prefixes: string[] = ['pf'],
): PropertyFilter[] {
- return Object.entries(query)
- .flatMap(([key, val]) => {
- const prefix = getPropertyFilterPrefix(key, prefixes);
+ return Object.entries(query).flatMap(([key, val]) => {
+ const prefix = getPropertyFilterPrefix(key, prefixes);
- if (!prefix) {
- return [];
- }
+ if (!prefix) {
+ return [];
+ }
- const stringValue = String(val);
- const withoutPrefix = key.slice(prefix.length + 1);
- const propertyName = withoutPrefix.replace(/\d+$/, ''); // strip trailing index digits
- const prefixedDotMatch = stringValue.match(/^(\d+)\.([^.]+)\.(.*)$/);
- const untypedDotMatch = stringValue.match(/^([^.]+)\.(.*)$/);
- const explicitDataType = prefixedDotMatch ? Number(prefixedDotMatch[1]) : undefined;
- const rawOperator = prefixedDotMatch ? prefixedDotMatch[2] : untypedDotMatch?.[1];
- const operator = resolveOperator(rawOperator);
+ const stringValue = String(val);
+ const withoutPrefix = key.slice(prefix.length + 1);
+ const propertyName = withoutPrefix.replace(/\d+$/, ''); // strip trailing index digits
+ const prefixedDotMatch = stringValue.match(/^(\d+)\.([^.]+)\.(.*)$/);
+ const untypedDotMatch = stringValue.match(/^([^.]+)\.(.*)$/);
+ const explicitDataType = prefixedDotMatch ? Number(prefixedDotMatch[1]) : undefined;
+ const rawOperator = prefixedDotMatch ? prefixedDotMatch[2] : untypedDotMatch?.[1];
+ const operator = resolveOperator(rawOperator);
- if (!operator || (explicitDataType !== undefined && !VALID_EVENT_DATA_TYPES.includes(explicitDataType))) {
- return [];
- }
+ if (
+ !operator ||
+ (explicitDataType !== undefined && !VALID_EVENT_DATA_TYPES.includes(explicitDataType))
+ ) {
+ return [];
+ }
- const value = prefixedDotMatch ? prefixedDotMatch[3] : untypedDotMatch?.[2];
+ const value = prefixedDotMatch ? prefixedDotMatch[3] : untypedDotMatch?.[2];
- if (value === undefined) {
- return [];
- }
+ if (value === undefined) {
+ return [];
+ }
- return [
- {
- propertyName,
- dataType: explicitDataType ?? DATA_TYPE.string,
- operator,
- value,
- },
- ];
- });
+ return [
+ {
+ propertyName,
+ dataType: explicitDataType ?? DATA_TYPE.string,
+ operator,
+ value,
+ },
+ ];
+ });
}
export function parseEventPropertyFilters(query: Record) {
@@ -159,7 +161,10 @@ export function serializePropertyFilters(
filters.map(f => {
const n = counts[f.propertyName] ?? 0;
counts[f.propertyName] = n + 1;
- return [`${prefix}_${f.propertyName}${n > 0 ? n : ''}`, `${f.dataType}.${f.operator}.${f.value}`];
+ return [
+ `${prefix}_${f.propertyName}${n > 0 ? n : ''}`,
+ `${f.dataType}.${f.operator}.${f.value}`,
+ ];
}),
);
}
diff --git a/src/lib/request.ts b/src/lib/request.ts
index 87c4872ad..4aa2e8a7a 100644
--- a/src/lib/request.ts
+++ b/src/lib/request.ts
@@ -1,3 +1,5 @@
+import { startOfMonth, subMonths } from 'date-fns';
+import { z } from 'zod';
import { checkAuth } from '@/lib/auth';
import { DEFAULT_PAGE_SIZE, FILTER_COLUMNS, OPERATORS } from '@/lib/constants';
import { getAllowedUnits, getMinimumUnit, maxDate, parseDateRange } from '@/lib/date';
@@ -6,8 +8,6 @@ import { filtersArrayToObject } from '@/lib/params';
import { badRequest, unauthorized } from '@/lib/response';
import type { QueryFilters } from '@/lib/types';
import { getWebsiteSegment } from '@/queries/prisma';
-import { startOfMonth, subMonths } from 'date-fns';
-import { z } from 'zod';
export async function parseRequest(
request: Request,
diff --git a/src/permissions/link.ts b/src/permissions/link.ts
index f274c7b25..be6eef71a 100644
--- a/src/permissions/link.ts
+++ b/src/permissions/link.ts
@@ -8,7 +8,11 @@ export async function canViewLink({ user, shareToken }: Auth, linkId: string) {
return true;
}
- if (shareToken?.linkId === linkId || shareToken?.websiteId === linkId || shareToken?.linkIds?.includes(linkId)) {
+ if (
+ shareToken?.linkId === linkId ||
+ shareToken?.websiteId === linkId ||
+ shareToken?.linkIds?.includes(linkId)
+ ) {
return true;
}
diff --git a/src/permissions/pixel.ts b/src/permissions/pixel.ts
index 79b1b5976..061363063 100644
--- a/src/permissions/pixel.ts
+++ b/src/permissions/pixel.ts
@@ -8,7 +8,11 @@ export async function canViewPixel({ user, shareToken }: Auth, pixelId: string)
return true;
}
- if (shareToken?.pixelId === pixelId || shareToken?.websiteId === pixelId || shareToken?.pixelIds?.includes(pixelId)) {
+ if (
+ shareToken?.pixelId === pixelId ||
+ shareToken?.websiteId === pixelId ||
+ shareToken?.pixelIds?.includes(pixelId)
+ ) {
return true;
}
diff --git a/src/queries/prisma/user.ts b/src/queries/prisma/user.ts
index 905c3f6b2..99bb2f49e 100644
--- a/src/queries/prisma/user.ts
+++ b/src/queries/prisma/user.ts
@@ -130,9 +130,7 @@ export async function deleteUser(userId: string) {
const teamIds = teams.map(a => a.id);
- const ownedFilter = cloudMode
- ? { userId }
- : { OR: [{ userId }, { teamId: { in: teamIds } }] };
+ const ownedFilter = cloudMode ? { userId } : { OR: [{ userId }, { teamId: { in: teamIds } }] };
const [links, pixels, boards] = await Promise.all([
client.link.findMany({
diff --git a/src/queries/sql/events/getEventData.ts b/src/queries/sql/events/getEventData.ts
index 4a3fac860..ebd0df983 100644
--- a/src/queries/sql/events/getEventData.ts
+++ b/src/queries/sql/events/getEventData.ts
@@ -39,10 +39,9 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
group by website_event.event_id
`;
- const count = await rawQuery(
- `select count(*) as num from (${eventQuery}) t`,
- queryParams,
- ).then((res: any) => res[0].num);
+ const count = await rawQuery(`select count(*) as num from (${eventQuery}) t`, queryParams).then(
+ (res: any) => res[0].num,
+ );
const data = await rawQuery(
`
@@ -106,10 +105,9 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
group by event_data.event_id
`;
- const count = await rawQuery(
- `select count(*) as num from (${eventQuery}) t`,
- queryParams,
- ).then((res: any) => res[0].num);
+ const count = await rawQuery(`select count(*) as num from (${eventQuery}) t`, queryParams).then(
+ (res: any) => res[0].num,
+ );
const data = await rawQuery(
`
@@ -149,4 +147,4 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
);
return { data, count, page: +page, pageSize: size };
-}
\ No newline at end of file
+}
diff --git a/src/queries/sql/heatmap/ensureHeatmapSnapshot.ts b/src/queries/sql/heatmap/ensureHeatmapSnapshot.ts
index a194deb42..54e727e84 100644
--- a/src/queries/sql/heatmap/ensureHeatmapSnapshot.ts
+++ b/src/queries/sql/heatmap/ensureHeatmapSnapshot.ts
@@ -1,9 +1,9 @@
import { serializeError } from 'serialize-error';
import { getApiUrl } from '@/lib/api-url';
import clickhouse from '@/lib/clickhouse';
-import prisma from '@/lib/prisma';
import { uuid } from '@/lib/crypto';
import { getHeatmapSnapshot, putHeatmapSnapshot } from '@/lib/heatmap-r2';
+import prisma from '@/lib/prisma';
import { getWebsite } from '@/queries/prisma';
const SNAPSHOT_STATUS = {
@@ -78,7 +78,12 @@ async function measurePage(page: any) {
const rootClientWidth = root?.clientWidth || 0;
const docClientWidth = doc?.clientWidth || 0;
const bodyClientWidth = body?.clientWidth || 0;
- const visibleWidth = Math.max(window.innerWidth, rootClientWidth, docClientWidth, bodyClientWidth);
+ const visibleWidth = Math.max(
+ window.innerWidth,
+ rootClientWidth,
+ docClientWidth,
+ bodyClientWidth,
+ );
const rootScrollWidth = root?.scrollWidth || 0;
const docScrollWidth = doc?.scrollWidth || 0;
const bodyScrollWidth = body?.scrollWidth || 0;
@@ -299,7 +304,9 @@ async function findClickhouseSnapshot(
return null;
}
- const status = Object.entries(CLICKHOUSE_SNAPSHOT_STATUS).find(([, value]) => value === row.status)?.[0];
+ const status = Object.entries(CLICKHOUSE_SNAPSHOT_STATUS).find(
+ ([, value]) => value === row.status,
+ )?.[0];
if (!status) {
return null;
@@ -325,7 +332,10 @@ function getSnapshotImageUrl(websiteId: string, snapshotId: string) {
function mapSnapshot(websiteId: string, row: SnapshotRecord): HeatmapSnapshotImage {
return {
id: row.id,
- imageUrl: row.status === SNAPSHOT_STATUS.ready && row.hasImage ? getSnapshotImageUrl(websiteId, row.id) : null,
+ imageUrl:
+ row.status === SNAPSHOT_STATUS.ready && row.hasImage
+ ? getSnapshotImageUrl(websiteId, row.id)
+ : null,
status: row.status,
mimeType: row.mimeType,
pageW: Number(row.pageW),
@@ -566,7 +576,12 @@ async function insertClickhouseSnapshotRecord({
]);
}
-function getSnapshotObjectKey(websiteId: string, snapshotId: string, viewportW: number, viewportH: number) {
+function getSnapshotObjectKey(
+ websiteId: string,
+ snapshotId: string,
+ viewportW: number,
+ viewportH: number,
+) {
return `${websiteId}/${viewportW}x${viewportH}/${snapshotId}.png`;
}
@@ -624,7 +639,9 @@ async function captureSnapshot(
let dimensions = await measurePage(page);
let currentWidth = initialViewportW;
let captureWidth =
- dimensions.pageW > initialViewportW + 24 ? Math.max(initialViewportW, dimensions.pageW) : initialViewportW;
+ dimensions.pageW > initialViewportW + 24
+ ? Math.max(initialViewportW, dimensions.pageW)
+ : initialViewportW;
for (let i = 0; i < 3; i++) {
if (captureWidth <= currentWidth) {
@@ -684,17 +701,11 @@ export async function ensureHeatmapSnapshot({
const updatedAt = existing?.updatedAt ? new Date(existing.updatedAt) : null;
const ageMs = updatedAt ? Date.now() - updatedAt.getTime() : Number.POSITIVE_INFINITY;
- if (
- existing?.status === SNAPSHOT_STATUS.pending &&
- ageMs < SNAPSHOT_PENDING_WINDOW_MS
- ) {
+ if (existing?.status === SNAPSHOT_STATUS.pending && ageMs < SNAPSHOT_PENDING_WINDOW_MS) {
return mapSnapshot(websiteId, existing);
}
- if (
- existing?.status === SNAPSHOT_STATUS.failed &&
- ageMs < SNAPSHOT_RETRY_DELAY_MS
- ) {
+ if (existing?.status === SNAPSHOT_STATUS.failed && ageMs < SNAPSHOT_RETRY_DELAY_MS) {
return mapSnapshot(websiteId, existing);
}
@@ -738,10 +749,9 @@ export async function ensureHeatmapSnapshot({
try {
const capture = await captureSnapshot(captureUrl, viewportW, viewportH, pageW);
- const objectKey =
- clickhouse.enabled
- ? getSnapshotObjectKey(websiteId, snapshotId, viewportW, viewportH)
- : null;
+ const objectKey = clickhouse.enabled
+ ? getSnapshotObjectKey(websiteId, snapshotId, viewportW, viewportH)
+ : null;
if (objectKey) {
await putHeatmapSnapshot(objectKey, capture.imageData, capture.mimeType);
@@ -798,9 +808,7 @@ export async function getHeatmapSnapshotImage(
snapshotId: string,
): Promise<{ mimeType: string; imageData: Buffer } | null> {
if (clickhouse.enabled) {
- const rows = await clickhouse.rawQuery<
- { mimeType: string; objectKey: string }[]
- >(
+ const rows = await clickhouse.rawQuery<{ mimeType: string; objectKey: string }[]>(
`
select
mime_type as mimeType,
diff --git a/src/queries/sql/heatmap/getHeatmap.ts b/src/queries/sql/heatmap/getHeatmap.ts
index 1e4bd8b34..785956bcd 100644
--- a/src/queries/sql/heatmap/getHeatmap.ts
+++ b/src/queries/sql/heatmap/getHeatmap.ts
@@ -5,8 +5,8 @@ import { filtersObjectToArray } from '@/lib/params';
import prisma from '@/lib/prisma';
import type { QueryFilters } from '@/lib/types';
import {
- type HeatmapSnapshotImage,
ensureHeatmapSnapshot,
+ type HeatmapSnapshotImage,
shouldSkipSnapshot,
} from './ensureHeatmapSnapshot';
@@ -543,15 +543,13 @@ function pickSnapshotViewport(
}
}
- let bestViewport:
- | {
- width: number;
- height: number;
- count: number;
- maxPageW: number;
- maxPageH: number;
- }
- | null = null;
+ let bestViewport: {
+ width: number;
+ height: number;
+ count: number;
+ maxPageW: number;
+ maxPageH: number;
+ } | null = null;
for (const bucket of viewportBuckets.values()) {
if (!bestViewport || bucket.count > bestViewport.count) {
@@ -626,7 +624,9 @@ function getRelationalHeatmapPathFilterContext(filters: QueryFilters) {
);
const joinedClauses =
- filters.match === 'any' ? clauses.filter(Boolean).join('\n or ') : clauses.filter(Boolean).join('\n and ');
+ filters.match === 'any'
+ ? clauses.filter(Boolean).join('\n or ')
+ : clauses.filter(Boolean).join('\n and ');
return {
filterQuery:
@@ -680,7 +680,9 @@ function getClickhouseHeatmapPathFilterContext(filters: QueryFilters) {
);
const joinedClauses =
- filters.match === 'any' ? clauses.filter(Boolean).join('\n or ') : clauses.filter(Boolean).join('\n and ');
+ filters.match === 'any'
+ ? clauses.filter(Boolean).join('\n or ')
+ : clauses.filter(Boolean).join('\n and ');
return {
filterQuery:
diff --git a/src/queries/sql/index.ts b/src/queries/sql/index.ts
index a5bbb4193..bd0196e73 100644
--- a/src/queries/sql/index.ts
+++ b/src/queries/sql/index.ts
@@ -44,14 +44,14 @@ export * from './reports/getUTM';
export * from './sessions/createSession';
export * from './sessions/getSessionActivity';
export * from './sessions/getSessionData';
+export * from './sessions/getSessionDataActivityStats';
export * from './sessions/getSessionDataArraySeries';
export * from './sessions/getSessionDataDateSeries';
-export * from './sessions/getSessionDataProperties';
-export * from './sessions/getSessionDataPropertySeries';
export * from './sessions/getSessionDataNumericSeries';
export * from './sessions/getSessionDataNumericStats';
export * from './sessions/getSessionDataPivot';
-export * from './sessions/getSessionDataActivityStats';
+export * from './sessions/getSessionDataProperties';
+export * from './sessions/getSessionDataPropertySeries';
export * from './sessions/getSessionDataValues';
export * from './sessions/getSessionExpandedMetrics';
export * from './sessions/getSessionMetrics';
diff --git a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts
index c1ca8cd0c..2eeeeca5f 100644
--- a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts
+++ b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts
@@ -75,13 +75,15 @@ async function relationalQuery(
`;
}
- const selectColumn = type === 'fullPath'
- ? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
- : column;
+ const selectColumn =
+ type === 'fullPath'
+ ? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
+ : column;
- const groupByColumn = type === 'fullPath'
- ? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
- : column;
+ const groupByColumn =
+ type === 'fullPath'
+ ? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
+ : column;
return rawQuery(
`
diff --git a/src/queries/sql/pageviews/getPageviewMetrics.ts b/src/queries/sql/pageviews/getPageviewMetrics.ts
index cfc8d0c7f..8a78cb0d2 100644
--- a/src/queries/sql/pageviews/getPageviewMetrics.ts
+++ b/src/queries/sql/pageviews/getPageviewMetrics.ts
@@ -71,9 +71,10 @@ async function relationalQuery(
column = `x.${FILTER_COLUMNS[type] || type}`;
}
- const selectColumn = type === 'fullPath'
- ? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
- : column;
+ const selectColumn =
+ type === 'fullPath'
+ ? `case when website_event.url_query != '' then website_event.url_path || '?' || website_event.url_query else website_event.url_path end`
+ : column;
return rawQuery(
`
diff --git a/src/queries/sql/sessions/getSessionDataActivityStats.ts b/src/queries/sql/sessions/getSessionDataActivityStats.ts
index 939f437c0..724ba4844 100644
--- a/src/queries/sql/sessions/getSessionDataActivityStats.ts
+++ b/src/queries/sql/sessions/getSessionDataActivityStats.ts
@@ -7,7 +7,12 @@ import type { PropertyFilter, PropertyLeaderboardRow, QueryFilters } from '@/lib
const FUNCTION_NAME = 'getSessionDataActivityStats';
export async function getSessionDataActivityStats(
- ...args: [websiteId: string, propertyName: string, filters: QueryFilters, propertyFilters?: PropertyFilter[]]
+ ...args: [
+ websiteId: string,
+ propertyName: string,
+ filters: QueryFilters,
+ propertyFilters?: PropertyFilter[],
+ ]
): Promise {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
@@ -28,8 +33,12 @@ async function relationalQuery(
websiteId,
timezone,
});
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
-
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
+
return rawQuery(
`
with filtered_sessions as (
@@ -110,8 +119,16 @@ async function clickhouseQuery(
) {
const { timezone = 'UTC' } = filters;
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
diff --git a/src/queries/sql/sessions/getSessionDataArraySeries.ts b/src/queries/sql/sessions/getSessionDataArraySeries.ts
index 89e876d45..840d6b468 100644
--- a/src/queries/sql/sessions/getSessionDataArraySeries.ts
+++ b/src/queries/sql/sessions/getSessionDataArraySeries.ts
@@ -33,7 +33,11 @@ async function relationalQuery(
websiteId,
timezone,
});
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
@@ -71,8 +75,16 @@ async function clickhouseQuery(
): Promise {
const { timezone = 'UTC', unit = 'day' } = filters;
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
diff --git a/src/queries/sql/sessions/getSessionDataDateSeries.ts b/src/queries/sql/sessions/getSessionDataDateSeries.ts
index 15b762959..8c17bf929 100644
--- a/src/queries/sql/sessions/getSessionDataDateSeries.ts
+++ b/src/queries/sql/sessions/getSessionDataDateSeries.ts
@@ -33,7 +33,11 @@ async function relationalQuery(
websiteId,
timezone,
});
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
@@ -69,8 +73,16 @@ async function clickhouseQuery(
): Promise {
const { timezone = 'UTC' } = filters;
const { rawQuery, parseFilters, getDateStringSQL, getPropertyFilterQuery } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
diff --git a/src/queries/sql/sessions/getSessionDataNumericSeries.ts b/src/queries/sql/sessions/getSessionDataNumericSeries.ts
index e74ac8f56..64f74fc25 100644
--- a/src/queries/sql/sessions/getSessionDataNumericSeries.ts
+++ b/src/queries/sql/sessions/getSessionDataNumericSeries.ts
@@ -35,7 +35,11 @@ async function relationalQuery(
websiteId,
timezone,
});
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
const aggSql =
metric === 'avg'
? 'avg(cast(session_data.number_value as decimal))'
@@ -83,8 +87,16 @@ async function clickhouseQuery(
): Promise<{ t: string; y: number }[]> {
const { timezone = 'UTC', unit = 'day' } = filters;
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
const aggSql =
metric === 'avg'
? 'avg(session_data.number_value)'
diff --git a/src/queries/sql/sessions/getSessionDataNumericStats.ts b/src/queries/sql/sessions/getSessionDataNumericStats.ts
index 7f6ee775f..c7dfdad28 100644
--- a/src/queries/sql/sessions/getSessionDataNumericStats.ts
+++ b/src/queries/sql/sessions/getSessionDataNumericStats.ts
@@ -33,7 +33,11 @@ async function relationalQuery(
websiteId,
timezone,
});
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
@@ -75,8 +79,16 @@ async function clickhouseQuery(
): Promise {
const { timezone = 'UTC' } = filters;
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
diff --git a/src/queries/sql/sessions/getSessionDataPivot.ts b/src/queries/sql/sessions/getSessionDataPivot.ts
index 9e9445853..f8e313ba9 100644
--- a/src/queries/sql/sessions/getSessionDataPivot.ts
+++ b/src/queries/sql/sessions/getSessionDataPivot.ts
@@ -128,7 +128,11 @@ async function clickhouseQuery(
const { timezone = 'UTC' } = filters;
const { pagedRawQuery, parseFilters, getPropertyFilterQuery, getDateStringSQL } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
propertyFilters,
'session',
diff --git a/src/queries/sql/sessions/getSessionDataProperties.ts b/src/queries/sql/sessions/getSessionDataProperties.ts
index 38708b116..1d81c7bd0 100644
--- a/src/queries/sql/sessions/getSessionDataProperties.ts
+++ b/src/queries/sql/sessions/getSessionDataProperties.ts
@@ -85,7 +85,11 @@ async function clickhouseQuery(
): Promise<{ propertyName: string; dataType: number; total: number }[]> {
const { timezone = 'UTC' } = filters;
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
propertyFilters,
'session',
diff --git a/src/queries/sql/sessions/getSessionDataPropertySeries.ts b/src/queries/sql/sessions/getSessionDataPropertySeries.ts
index f66620b1e..f8ba5be1d 100644
--- a/src/queries/sql/sessions/getSessionDataPropertySeries.ts
+++ b/src/queries/sql/sessions/getSessionDataPropertySeries.ts
@@ -33,7 +33,11 @@ async function relationalQuery(
websiteId,
timezone,
});
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
@@ -70,8 +74,16 @@ async function clickhouseQuery(
): Promise {
const { timezone = 'UTC', unit = 'day' } = filters;
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
- const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
- const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
+ const { filterQuery, cohortQuery, queryParams } = parseFilters({
+ ...filters,
+ websiteId,
+ timezone,
+ });
+ const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
+ propertyFilters,
+ 'session',
+ timezone,
+ );
return rawQuery(
`
diff --git a/src/store/app.ts b/src/store/app.ts
index 0893c506a..851332e26 100644
--- a/src/store/app.ts
+++ b/src/store/app.ts
@@ -32,10 +32,7 @@ export function setLocale(locale: string) {
store.setState({ locale });
}
-export function setShareData(
- share: object | null,
- shareToken: { token?: string } | null,
-) {
+export function setShareData(share: object | null, shareToken: { token?: string } | null) {
store.setState({ share, shareToken });
}