Skip to content

Commit 554054d

Browse files
committed
Merged nav menus.
1 parent 2f5e692 commit 554054d

File tree

12 files changed

+164
-47
lines changed

12 files changed

+164
-47
lines changed

next.config.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import pkg from './package.json' assert { type: 'json' };
33

44
const TRACKER_SCRIPT = '/script.js';
55

6-
const basePath = process.env.BASE_PATH;
7-
const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT;
8-
const cloudMode = !!process.env.CLOUD_MODE;
9-
const corsMaxAge = process.env.CORS_MAX_AGE;
10-
const defaultLocale = process.env.DEFAULT_LOCALE;
11-
const forceSSL = process.env.FORCE_SSL;
12-
const frameAncestors = process.env.ALLOWED_FRAME_URLS ?? '';
13-
const trackerScriptName = process.env.TRACKER_SCRIPT_NAME;
14-
const trackerScriptURL = process.env.TRACKER_SCRIPT_URL;
6+
const basePath = process.env.BASE_PATH || '';
7+
const cloudMode = process.env.CLOUD_MODE || '';
8+
const cloudUrl = process.env.CLOUD_URL || '';
9+
const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT || '';
10+
const corsMaxAge = process.env.CORS_MAX_AGE || '';
11+
const defaultLocale = process.env.DEFAULT_LOCALE || '';
12+
const forceSSL = process.env.FORCE_SSL || '';
13+
const frameAncestors = process.env.ALLOWED_FRAME_URLS || '';
14+
const trackerScriptName = process.env.TRACKER_SCRIPT_NAME || '';
15+
const trackerScriptURL = process.env.TRACKER_SCRIPT_URL || '';
1516

1617
const contentSecurityPolicy = [
1718
`default-src 'self'`,
@@ -163,6 +164,7 @@ export default {
163164
env: {
164165
basePath,
165166
cloudMode,
167+
cloudUrl,
166168
currentVersion: pkg.version,
167169
defaultLocale,
168170
},

pnpm-lock.yaml

Lines changed: 47 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/(main)/App.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
'use client';
22
import { Grid, Loading, Column } from '@umami/react-zen';
33
import Script from 'next/script';
4-
import { usePathname } from 'next/navigation';
54
import { UpdateNotice } from './UpdateNotice';
65
import { SideNav } from '@/app/(main)/SideNav';
7-
import { useLoginQuery, useConfig } from '@/components/hooks';
6+
import { useLoginQuery, useConfig, useNavigation } from '@/components/hooks';
87

98
export function App({ children }) {
109
const { user, isLoading, error } = useLoginQuery();
1110
const config = useConfig();
12-
const pathname = usePathname();
11+
const { pathname, router } = useNavigation();
1312

1413
if (isLoading || !config) {
1514
return <Loading placement="absolute" />;
1615
}
1716

1817
if (error) {
19-
window.location.href = `${process.env.basePath || ''}/login`;
18+
if (process.env.cloudMode) {
19+
window.location.href = '/login';
20+
} else {
21+
router.push('/login');
22+
}
2023
return null;
2124
}
2225

src/app/(main)/SideNav.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Key } from 'react';
12
import Link from 'next/link';
23
import {
34
Sidebar,
@@ -12,8 +13,7 @@ import { Globe, LinkIcon, LogoSvg, Grid2x2, PanelLeft } from '@/components/icons
1213
import { useMessages, useNavigation, useGlobalState } from '@/components/hooks';
1314
import { NavButton } from '@/components/input/NavButton';
1415
import { PanelButton } from '@/components/input/PanelButton';
15-
import { Key } from 'react';
16-
import { SettingsButton } from '@/components/input/SettingsButton';
16+
import { LanguageButton } from '@/components/input/LanguageButton';
1717

1818
export function SideNav(props: SidebarProps) {
1919
const { formatMessage, labels } = useMessages();
@@ -77,9 +77,9 @@ export function SideNav(props: SidebarProps) {
7777
})}
7878
</SidebarSection>
7979
<SidebarSection justifyContent="flex-start">
80-
<Row>
81-
<SettingsButton />
82-
{!isCollapsed && !hasNav && <ThemeButton />}
80+
<Row wrap="wrap">
81+
<LanguageButton />
82+
<ThemeButton />
8383
</Row>
8484
</SidebarSection>
8585
</Sidebar>

src/assets/switch.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/icons.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
export * from 'lucide-react';
22
export {
3-
Logo as LogoSvg,
43
Compare as CompareSvg,
54
Funnel as FunnelSvg,
65
Lightning as LightningSvg,
76
Location as LocationSvg,
7+
Logo as LogoSvg,
88
Magnet as MagnetSvg,
99
Money as MoneySvg,
1010
Network as NetworkSvg,
1111
Path as PathSvg,
12+
Switch as SwitchSvg,
1213
Target as TargetSvg,
13-
AddUser as AddUserSvg,
1414
} from '@/components/svg';

src/components/input/NavButton.tsx

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ import {
2424
Settings,
2525
User,
2626
Users,
27+
SwitchSvg,
2728
} from '@/components/icons';
2829
import { DOCS_URL } from '@/lib/constants';
29-
import * as url from 'node:url';
30+
import { ArrowRight } from 'lucide-react';
3031

3132
export interface TeamsButtonProps {
3233
showText?: boolean;
@@ -43,7 +44,7 @@ export function NavButton({ showText = true }: TeamsButtonProps) {
4344
const label = teamId ? team?.name : user.username;
4445

4546
const getUrl = (url: string) => {
46-
return cloudMode ? `${process.env.cloudUrl}/${url}` : url;
47+
return cloudMode ? `${process.env.cloudUrl}${url}` : url;
4748
};
4849

4950
const handleAction = async () => {};
@@ -75,42 +76,52 @@ export function NavButton({ showText = true }: TeamsButtonProps) {
7576
</Pressable>
7677
<Popover placement="bottom start">
7778
<Column minWidth="300px">
78-
<Menu
79-
selectionMode="single"
80-
selectedKeys={selectedKeys}
81-
autoFocus="last"
82-
onAction={handleAction}
83-
>
84-
<MenuSection title={formatMessage(labels.myAccount)}>
85-
<MenuItem id="user">
86-
<IconLabel icon={<User />} label={user.username} />
87-
</MenuItem>
88-
</MenuSection>
89-
<MenuSeparator />
79+
<Menu autoFocus="last" onAction={handleAction}>
9080
<SubmenuTrigger>
9181
<MenuItem id="teams" showChecked={false} showSubMenuIcon>
92-
<IconLabel icon={<Users />} label={formatMessage(labels.teams)} />
82+
<IconLabel icon={<SwitchSvg />} label={formatMessage(labels.switchAccount)} />
9383
</MenuItem>
9484
<Popover placement="right top">
9585
<Column minWidth="300px">
96-
<Menu>
86+
<Menu selectionMode="single" selectedKeys={selectedKeys}>
87+
<MenuSection title={formatMessage(labels.myAccount)}>
88+
<MenuItem id="user" href={getUrl('/')}>
89+
<IconLabel icon={<User />} label={user.username} />
90+
</MenuItem>
91+
</MenuSection>
92+
<MenuSeparator />
9793
<MenuSection title={formatMessage(labels.teams)}>
9894
{user?.teams?.map(({ id, name }) => (
99-
<MenuItem key={id} id={id}>
100-
<Row alignItems="center" gap>
101-
<Icon size="sm">
102-
<Users />
103-
</Icon>
95+
<MenuItem key={id} id={id} href={getUrl(`/teams/${id}`)}>
96+
<IconLabel icon={<Users />}>
10497
<Text wrap="nowrap">{name}</Text>
105-
</Row>
98+
</IconLabel>
10699
</MenuItem>
107100
))}
101+
{user?.teams?.length === 0 && (
102+
<MenuItem id="manage-teams">
103+
<a href="/settings/teams" style={{ width: '100%' }}>
104+
<Row alignItems="center" justifyContent="space-between" gap>
105+
<Text align="center">Manage teams</Text>
106+
<Icon>
107+
<ArrowRight />
108+
</Icon>
109+
</Row>
110+
</a>
111+
</MenuItem>
112+
)}
108113
</MenuSection>
109114
</Menu>
110115
</Column>
111116
</Popover>
112117
</SubmenuTrigger>
113-
<MenuItem id="settings" icon={<Settings />} label={formatMessage(labels.settings)} />
118+
<MenuSeparator />
119+
<MenuItem
120+
id="settings"
121+
href={getUrl('/settings')}
122+
icon={<Settings />}
123+
label={formatMessage(labels.settings)}
124+
/>
114125
{cloudMode && (
115126
<>
116127
<MenuItem
@@ -132,14 +143,24 @@ export function NavButton({ showText = true }: TeamsButtonProps) {
132143
/>
133144
</>
134145
)}
135-
{user.isAdmin && (
146+
{!cloudMode && user.isAdmin && (
136147
<>
137148
<MenuSeparator />
138-
<MenuItem id="/admin" icon={<LockKeyhole />} label={formatMessage(labels.admin)} />
149+
<MenuItem
150+
id="/admin"
151+
href="/admin"
152+
icon={<LockKeyhole />}
153+
label={formatMessage(labels.admin)}
154+
/>
139155
</>
140156
)}
141157
<MenuSeparator />
142-
<MenuItem id="/logout" icon={<LogOut />} label={formatMessage(labels.logout)} />
158+
<MenuItem
159+
id="logout"
160+
href={getUrl('/logout')}
161+
icon={<LogOut />}
162+
label={formatMessage(labels.logout)}
163+
/>
143164
</Menu>
144165
</Column>
145166
</Popover>

src/components/messages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ export const labels = defineMessages({
362362
share: { id: 'label.share', defaultMessage: 'Share' },
363363
support: { id: 'label.support', defaultMessage: 'Support' },
364364
documentation: { id: 'label.documentation', defaultMessage: 'Documentation' },
365+
switchAccount: { id: 'label.switch-account', defaultMessage: 'Switch account' },
365366
});
366367

367368
export const messages = defineMessages({

src/components/svg/Download.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as React from 'react';
2+
import type { SVGProps } from 'react';
3+
const SvgDownload = (props: SVGProps<SVGSVGElement>) => (
4+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" {...props}>
5+
<path d="M97.5 82.656V71.357a3.545 3.545 0 0 0-3.545-3.544H89.17a3.545 3.545 0 0 0-3.545 3.544v11.3c0 1.639-1.33 2.968-2.969 2.968H17.344a2.97 2.97 0 0 1-2.969-2.969V71.357a3.545 3.545 0 0 0-3.545-3.545H6.045A3.545 3.545 0 0 0 2.5 71.357v11.3C2.5 90.853 9.146 97.5 17.344 97.5h65.312c8.198 0 14.844-6.646 14.844-14.844" />
6+
<path d="m29.68 44.105-3.387 3.388a3.545 3.545 0 0 0 0 5.014l19.506 19.506a5.94 5.94 0 0 0 8.397.005l.005-.005 19.506-19.506a3.545 3.545 0 0 0 0-5.014l-3.388-3.388a3.545 3.545 0 0 0-5.013 0l-9.368 9.368V6.045A3.545 3.545 0 0 0 52.393 2.5h-4.786a3.545 3.545 0 0 0-3.544 3.545v47.428l-9.369-9.368a3.545 3.545 0 0 0-5.013 0" />
7+
</svg>
8+
);
9+
export default SvgDownload;

src/components/svg/Export.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as React from 'react';
2+
import type { SVGProps } from 'react';
3+
const SvgExport = (props: SVGProps<SVGSVGElement>) => (
4+
<svg xmlns="http://www.w3.org/2000/svg" width={512} height={512} viewBox="0 0 24 24" {...props}>
5+
<switch>
6+
<g>
7+
<path d="M8.7 7.7 11 5.4V15c0 .6.4 1 1 1s1-.4 1-1V5.4l2.3 2.3c.4.4 1 .4 1.4 0s.4-1 0-1.4l-4-4c-.1-.1-.2-.2-.3-.2-.2-.1-.5-.1-.8 0-.1 0-.2.1-.3.2l-4 4c-.4.4-.4 1 0 1.4s1 .4 1.4 0M21 14c-.6 0-1 .4-1 1v4c0 .6-.4 1-1 1H5c-.6 0-1-.4-1-1v-4c0-.6-.4-1-1-1s-1 .4-1 1v4c0 1.7 1.3 3 3 3h14c1.7 0 3-1.3 3-3v-4c0-.6-.4-1-1-1" />
8+
</g>
9+
</switch>
10+
</svg>
11+
);
12+
export default SvgExport;

0 commit comments

Comments
 (0)