diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
index df476e79..bbbb0614 100644
--- a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
+++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx
@@ -1,5 +1,14 @@
import { Text } from '@umami/react-zen';
-import { Eye, User, Clock, Ungroup, Tag, ChartPie, UserPlus, GitCompare } from '@/components/icons';
+import {
+ Eye,
+ User,
+ Clock,
+ Sheet,
+ Tag,
+ ChartPie,
+ UserPlus,
+ AlignEndHorizontal,
+} from '@/components/icons';
import { Lightning, Path, Money, Target, Funnel, Magnet, Network } from '@/components/svg';
import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu';
@@ -47,13 +56,13 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{
id: 'compare',
label: formatMessage(labels.compare),
- icon: ,
+ icon: ,
path: renderPath('/compare'),
},
{
id: 'breakdown',
label: formatMessage(labels.breakdown),
- icon: ,
+ icon: ,
path: renderPath('/breakdown'),
},
],
diff --git a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx
index 48e8b015..b918ec4d 100644
--- a/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx
+++ b/src/app/(main)/websites/[websiteId]/events/EventsPage.tsx
@@ -9,6 +9,7 @@ import { useMessages } from '@/components/hooks';
import { EventProperties } from './EventProperties';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { getItem, setItem } from '@/lib/storage';
+import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
const KEY_NAME = 'umami.events.tab';
@@ -52,6 +53,7 @@ export function EventsPage({ websiteId }) {
+
);
}
diff --git a/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx b/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx
index 31044982..c36ee5e7 100644
--- a/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx
+++ b/src/app/(main)/websites/[websiteId]/events/EventsTable.tsx
@@ -10,7 +10,7 @@ import { TypeIcon } from '@/components/common/TypeIcon';
export function EventsTable({ data = [] }) {
const { formatMessage, labels } = useMessages();
- const { renderUrl } = useNavigation();
+ const { updateParams } = useNavigation();
const { formatValue } = useFormat();
if (data.length === 0) {
@@ -23,7 +23,7 @@ export function EventsTable({ data = [] }) {
{(row: any) => {
return (
-
+
{row.eventName ? : }
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx
new file mode 100644
index 00000000..d2240d84
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionModal.tsx
@@ -0,0 +1,49 @@
+import { Dialog, Modal, ModalProps } from '@umami/react-zen';
+import { SessionProfile } from '@/app/(main)/websites/[websiteId]/sessions/SessionProfile';
+import { useNavigation } from '@/components/hooks';
+
+export interface SessionModalProps extends ModalProps {
+ websiteId: string;
+}
+
+export function SessionModal({ websiteId, ...props }: SessionModalProps) {
+ const {
+ router,
+ query: { session },
+ updateParams,
+ } = useNavigation();
+
+ const handleClose = (close: () => void) => {
+ router.push(updateParams({ session: undefined }));
+ close();
+ };
+
+ const handleOpenChange = (isOpen: boolean) => {
+ if (!isOpen) {
+ router.push(updateParams({ session: undefined }));
+ }
+ };
+
+ return (
+
+
+
+ );
+}
diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx
index ae0d4104..8a096aa7 100644
--- a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx
@@ -1,35 +1,19 @@
'use client';
import { Key, useState } from 'react';
-import { TabList, Tab, Tabs, TabPanel, Column, Modal, Dialog } from '@umami/react-zen';
+import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen';
import { SessionsDataTable } from './SessionsDataTable';
import { SessionProperties } from './SessionProperties';
-import { useMessages, useNavigation } from '@/components/hooks';
+import { useMessages } from '@/components/hooks';
import { Panel } from '@/components/common/Panel';
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
import { getItem, setItem } from '@/lib/storage';
-import { SessionProfile } from '@/app/(main)/websites/[websiteId]/sessions/SessionProfile';
+import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
const KEY_NAME = 'umami.sessions.tab';
export function SessionsPage({ websiteId }) {
const [tab, setTab] = useState(getItem(KEY_NAME) || 'activity');
const { formatMessage, labels } = useMessages();
- const {
- router,
- query: { session },
- updateParams,
- } = useNavigation();
-
- const handleClose = (close: () => void) => {
- router.push(updateParams({ session: undefined }));
- close();
- };
-
- const handleOpenChange = (isOpen: boolean) => {
- if (!isOpen) {
- router.push(updateParams({ session: undefined }));
- }
- };
const handleSelect = (value: Key) => {
setItem(KEY_NAME, value);
@@ -53,26 +37,7 @@ export function SessionsPage({ websiteId }) {
-
-
-
+
);
}
diff --git a/src/app/api/websites/route.ts b/src/app/api/websites/route.ts
index 776f23b0..994e22bd 100644
--- a/src/app/api/websites/route.ts
+++ b/src/app/api/websites/route.ts
@@ -1,4 +1,5 @@
import { z } from 'zod';
+import redis from '@/lib/redis';
import { canCreateTeamWebsite, canCreateWebsite } from '@/permissions';
import { json, unauthorized } from '@/lib/response';
import { uuid } from '@/lib/crypto';
@@ -50,11 +51,15 @@ export async function POST(request: Request) {
const { id, name, domain, shareId, teamId } = body;
- if (process.env.CLOUD_MODE && !teamId && !auth.user.hasSubscription) {
- const count = await getWebsiteCount(auth.user.id);
+ if (process.env.CLOUD_MODE && !teamId) {
+ const account = await redis.client.get(`account:${auth.user.id}`);
- if (count >= CLOUD_WEBSITE_LIMIT) {
- return unauthorized({ message: 'Website limit reached.' });
+ if (!account?.hasSubscription) {
+ const count = await getWebsiteCount(auth.user.id);
+
+ if (count >= CLOUD_WEBSITE_LIMIT) {
+ return unauthorized({ message: 'Website limit reached.' });
+ }
}
}
diff --git a/src/queries/prisma/website.ts b/src/queries/prisma/website.ts
index 315dca03..1c84f527 100644
--- a/src/queries/prisma/website.ts
+++ b/src/queries/prisma/website.ts
@@ -208,6 +208,7 @@ export async function getWebsiteCount(userId: string) {
return prisma.client.website.count({
where: {
userId,
+ deletedAt: null,
},
});
}