diff --git a/next.config.ts b/next.config.ts
index 17705dc20..eac6f327a 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -3,16 +3,15 @@ import pkg from './package.json' assert { type: 'json' };
const TRACKER_SCRIPT = '/script.js';
-const basePath = process.env.BASE_PATH || '';
-const cloudMode = process.env.CLOUD_MODE || '';
-const cloudUrl = process.env.CLOUD_URL || '';
-const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT || '';
-const corsMaxAge = process.env.CORS_MAX_AGE || '';
-const defaultLocale = process.env.DEFAULT_LOCALE || '';
-const forceSSL = process.env.FORCE_SSL || '';
-const frameAncestors = process.env.ALLOWED_FRAME_URLS || '';
-const trackerScriptName = process.env.TRACKER_SCRIPT_NAME || '';
-const trackerScriptURL = process.env.TRACKER_SCRIPT_URL || '';
+const basePath = process.env.BASE_PATH;
+const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT;
+const cloudMode = !!process.env.CLOUD_MODE;
+const corsMaxAge = process.env.CORS_MAX_AGE;
+const defaultLocale = process.env.DEFAULT_LOCALE;
+const forceSSL = process.env.FORCE_SSL;
+const frameAncestors = process.env.ALLOWED_FRAME_URLS ?? '';
+const trackerScriptName = process.env.TRACKER_SCRIPT_NAME;
+const trackerScriptURL = process.env.TRACKER_SCRIPT_URL;
const contentSecurityPolicy = [
`default-src 'self'`,
@@ -164,7 +163,6 @@ export default {
env: {
basePath,
cloudMode,
- cloudUrl,
currentVersion: pkg.version,
defaultLocale,
},
diff --git a/package.json b/package.json
index 3328c5c71..44ec9f088 100644
--- a/package.json
+++ b/package.json
@@ -82,7 +82,7 @@
"@react-spring/web": "^10.0.1",
"@svgr/cli": "^8.1.0",
"@tanstack/react-query": "^5.85.5",
- "@umami/react-zen": "^0.187.0",
+ "@umami/react-zen": "^0.186.0",
"@umami/redis-client": "^0.29.0",
"bcryptjs": "^3.0.2",
"chalk": "^5.6.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 949928622..1f3fdc90c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,8 +45,8 @@ importers:
specifier: ^5.85.5
version: 5.85.5(react@19.1.1)
'@umami/react-zen':
- specifier: ^0.187.0
- version: 0.187.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
+ specifier: ^0.186.0
+ version: 0.186.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
'@umami/redis-client':
specifier: ^0.29.0
version: 0.29.0
@@ -367,44 +367,7 @@ importers:
specifier: ^5.9.2
version: 5.9.2
- dist:
- dependencies:
- chart.js:
- specifier: ^4.5.0
- version: 4.5.0
- chartjs-adapter-date-fns:
- specifier: ^3.0.0
- version: 3.0.0(chart.js@4.5.0)(date-fns@2.30.0)
- colord:
- specifier: ^2.9.2
- version: 2.9.3
- jsonwebtoken:
- specifier: ^9.0.2
- version: 9.0.2
- lucide-react:
- specifier: ^0.542.0
- version: 0.542.0(react@19.1.1)
- pure-rand:
- specifier: ^7.0.1
- version: 7.0.1
- react-simple-maps:
- specifier: ^2.3.0
- version: 2.3.0(prop-types@15.8.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
- react-use-measure:
- specifier: ^2.0.4
- version: 2.1.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
- react-window:
- specifier: ^1.8.6
- version: 1.8.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
- serialize-error:
- specifier: ^12.0.0
- version: 12.0.0
- thenby:
- specifier: ^1.3.4
- version: 1.3.4
- uuid:
- specifier: ^11.1.0
- version: 11.1.0
+ dist: {}
packages:
@@ -2775,8 +2738,8 @@ packages:
'@prisma/client': ^6.1.0
'@prisma/extension-read-replicas': ^0.4.1
- '@umami/react-zen@0.187.0':
- resolution: {integrity: sha512-CiTGBqEvN/dcZ1Tq4R+mj9ynN1opZF81iukUzElChJ5XF/Ec9HhPR+KM2r8PXt+uWeVVe1aZtjyVOdwUR/ndXg==}
+ '@umami/react-zen@0.186.0':
+ resolution: {integrity: sha512-s+x4cJK5UTHQ0l2TTUb3zX8P2U6bMw35NRjIqG+OJvljJf5NNdRo6WChZOvnh/08XxGI30jntFhUYdup255rFg==}
'@umami/redis-client@0.29.0':
resolution: {integrity: sha512-Jaqh++jskqDB7ny75pfC02OvKp1JTS4asGDsFrRL3qy8sxL3PAl9+/mybCJe4/6vWrXDJKqpgkSfUDJq2bFjyw==}
@@ -5283,11 +5246,6 @@ packages:
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
- lucide-react@0.542.0:
- resolution: {integrity: sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw==}
- peerDependencies:
- react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
-
lucide-react@0.543.0:
resolution: {integrity: sha512-fpVfuOQO0V3HBaOA1stIiP/A2fPCXHIleRZL16Mx3HmjTYwNSbimhnFBygs2CAfU1geexMX5ItUcWBGUaqw5CA==}
peerDependencies:
@@ -10385,7 +10343,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@umami/react-zen@0.187.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
+ '@umami/react-zen@0.186.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
dependencies:
'@fontsource/jetbrains-mono': 5.2.8
'@internationalized/date': 3.9.0
@@ -13418,10 +13376,6 @@ snapshots:
dependencies:
react: 19.1.1
- lucide-react@0.542.0(react@19.1.1):
- dependencies:
- react: 19.1.1
-
lucide-react@0.543.0(react@19.1.1):
dependencies:
react: 19.1.1
diff --git a/src/app/(main)/App.tsx b/src/app/(main)/App.tsx
index c3f88c5b0..6c14a484a 100644
--- a/src/app/(main)/App.tsx
+++ b/src/app/(main)/App.tsx
@@ -1,25 +1,22 @@
'use client';
import { Grid, Loading, Column } from '@umami/react-zen';
import Script from 'next/script';
+import { usePathname } from 'next/navigation';
import { UpdateNotice } from './UpdateNotice';
import { SideNav } from '@/app/(main)/SideNav';
-import { useLoginQuery, useConfig, useNavigation } from '@/components/hooks';
+import { useLoginQuery, useConfig } from '@/components/hooks';
export function App({ children }) {
const { user, isLoading, error } = useLoginQuery();
const config = useConfig();
- const { pathname, router } = useNavigation();
+ const pathname = usePathname();
if (isLoading || !config) {
return ;
}
if (error) {
- if (process.env.cloudMode) {
- window.location.href = '/login';
- } else {
- router.push('/login');
- }
+ window.location.href = `${process.env.basePath || ''}/login`;
return null;
}
diff --git a/src/app/(main)/SideNav.tsx b/src/app/(main)/SideNav.tsx
index 4398009e6..a50f0c1f1 100644
--- a/src/app/(main)/SideNav.tsx
+++ b/src/app/(main)/SideNav.tsx
@@ -1,4 +1,3 @@
-import { Key } from 'react';
import Link from 'next/link';
import {
Sidebar,
@@ -13,7 +12,8 @@ import { Globe, LinkIcon, LogoSvg, Grid2x2, PanelLeft } from '@/components/icons
import { useMessages, useNavigation, useGlobalState } from '@/components/hooks';
import { NavButton } from '@/components/input/NavButton';
import { PanelButton } from '@/components/input/PanelButton';
-import { LanguageButton } from '@/components/input/LanguageButton';
+import { Key } from 'react';
+import { SettingsButton } from '@/components/input/SettingsButton';
export function SideNav(props: SidebarProps) {
const { formatMessage, labels } = useMessages();
@@ -77,9 +77,9 @@ export function SideNav(props: SidebarProps) {
})}
-
-
-
+
+
+ {!isCollapsed && !hasNav && }
diff --git a/src/app/Providers.tsx b/src/app/Providers.tsx
index b8898e884..77be52016 100644
--- a/src/app/Providers.tsx
+++ b/src/app/Providers.tsx
@@ -36,21 +36,9 @@ function MessagesProvider({ children }) {
export function Providers({ children }) {
const router = useRouter();
- function navigate(url: string) {
- if (shouldUseNativeLink(url)) {
- window.location.href = url;
- } else {
- router.push(url);
- }
- }
-
- function shouldUseNativeLink(url: string) {
- return url.startsWith('http');
- }
-
return (
-
+
{children}
diff --git a/src/assets/switch.svg b/src/assets/switch.svg
deleted file mode 100644
index 86166cc5c..000000000
--- a/src/assets/switch.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/components/icons.ts b/src/components/icons.ts
index e0e7c6787..ddcda3b66 100644
--- a/src/components/icons.ts
+++ b/src/components/icons.ts
@@ -1,14 +1,14 @@
export * from 'lucide-react';
export {
+ Logo as LogoSvg,
Compare as CompareSvg,
Funnel as FunnelSvg,
Lightning as LightningSvg,
Location as LocationSvg,
- Logo as LogoSvg,
Magnet as MagnetSvg,
Money as MoneySvg,
Network as NetworkSvg,
Path as PathSvg,
- Switch as SwitchSvg,
Target as TargetSvg,
+ AddUser as AddUserSvg,
} from '@/components/svg';
diff --git a/src/components/input/NavButton.tsx b/src/components/input/NavButton.tsx
index 240c67351..ebe1a19a6 100644
--- a/src/components/input/NavButton.tsx
+++ b/src/components/input/NavButton.tsx
@@ -6,49 +6,27 @@ import {
MenuTrigger,
MenuSection,
MenuSeparator,
- SubmenuTrigger,
Popover,
Row,
Column,
Pressable,
- IconLabel,
} from '@umami/react-zen';
-import { useConfig, useLoginQuery, useMessages, useNavigation } from '@/components/hooks';
-import {
- BookText,
- ChevronRight,
- ExternalLink,
- LifeBuoy,
- LockKeyhole,
- LogOut,
- Settings,
- User,
- Users,
- SwitchSvg,
-} from '@/components/icons';
-import { DOCS_URL } from '@/lib/constants';
-import { ArrowRight } from 'lucide-react';
+import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks';
+import { ChevronRight, User, Users } from '@/components/icons';
export interface TeamsButtonProps {
showText?: boolean;
onAction?: (id: any) => void;
}
-export function NavButton({ showText = true }: TeamsButtonProps) {
+export function NavButton({ showText = true, onAction }: TeamsButtonProps) {
const { user } = useLoginQuery();
- const { cloudMode } = useConfig();
const { formatMessage, labels } = useMessages();
const { teamId } = useNavigation();
const team = user?.teams?.find(({ id }) => id === teamId);
const selectedKeys = new Set([teamId || 'user']);
const label = teamId ? team?.name : user.username;
- const getUrl = (url: string) => {
- return cloudMode ? `${process.env.cloudUrl}${url}` : url;
- };
-
- const handleAction = async () => {};
-
return (
@@ -76,91 +54,35 @@ export function NavButton({ showText = true }: TeamsButtonProps) {
-
diff --git a/src/components/messages.ts b/src/components/messages.ts
index 0438c06e6..c40a3b05f 100644
--- a/src/components/messages.ts
+++ b/src/components/messages.ts
@@ -362,7 +362,6 @@ export const labels = defineMessages({
share: { id: 'label.share', defaultMessage: 'Share' },
support: { id: 'label.support', defaultMessage: 'Support' },
documentation: { id: 'label.documentation', defaultMessage: 'Documentation' },
- switchAccount: { id: 'label.switch-account', defaultMessage: 'Switch account' },
});
export const messages = defineMessages({
diff --git a/src/components/svg/Download.tsx b/src/components/svg/Download.tsx
deleted file mode 100644
index 56d4d683c..000000000
--- a/src/components/svg/Download.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import * as React from 'react';
-import type { SVGProps } from 'react';
-const SvgDownload = (props: SVGProps) => (
-
-);
-export default SvgDownload;
diff --git a/src/components/svg/Export.tsx b/src/components/svg/Export.tsx
deleted file mode 100644
index 355321cf1..000000000
--- a/src/components/svg/Export.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import * as React from 'react';
-import type { SVGProps } from 'react';
-const SvgExport = (props: SVGProps) => (
-
-);
-export default SvgExport;
diff --git a/src/components/svg/Switch.tsx b/src/components/svg/Switch.tsx
deleted file mode 100644
index 2a12f3936..000000000
--- a/src/components/svg/Switch.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import * as React from 'react';
-import type { SVGProps } from 'react';
-const SvgSwitch = (props: SVGProps) => (
-
-);
-export default SvgSwitch;
diff --git a/src/components/svg/index.ts b/src/components/svg/index.ts
index 1bfc728a8..86c3ea947 100644
--- a/src/components/svg/index.ts
+++ b/src/components/svg/index.ts
@@ -6,9 +6,7 @@ export { default as Bookmark } from './Bookmark';
export { default as Change } from './Change';
export { default as Compare } from './Compare';
export { default as Dashboard } from './Dashboard';
-export { default as Download } from './Download';
export { default as Expand } from './Expand';
-export { default as Export } from './Export';
export { default as Flag } from './Flag';
export { default as Funnel } from './Funnel';
export { default as Gear } from './Gear';
@@ -30,7 +28,6 @@ export { default as Redo } from './Redo';
export { default as Reports } from './Reports';
export { default as Security } from './Security';
export { default as Speaker } from './Speaker';
-export { default as Switch } from './Switch';
export { default as Tag } from './Tag';
export { default as Target } from './Target';
export { default as Visitor } from './Visitor';