Updated edit forms and icons.

This commit is contained in:
Mike Cao
2025-09-26 01:46:36 -07:00
parent 554054d3a1
commit 257050f749
20 changed files with 120 additions and 123 deletions
+3 -2
View File
@@ -9,7 +9,8 @@ import {
SidebarProps, SidebarProps,
ThemeButton, ThemeButton,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { Globe, LinkIcon, LogoSvg, Grid2x2, PanelLeft } from '@/components/icons'; import { Globe, LinkIcon, Grid2x2, PanelLeft } from '@/components/icons';
import { Logo } from '@/components/svg';
import { useMessages, useNavigation, useGlobalState } from '@/components/hooks'; import { useMessages, useNavigation, useGlobalState } from '@/components/hooks';
import { NavButton } from '@/components/input/NavButton'; import { NavButton } from '@/components/input/NavButton';
import { PanelButton } from '@/components/input/PanelButton'; import { PanelButton } from '@/components/input/PanelButton';
@@ -53,7 +54,7 @@ export function SideNav(props: SidebarProps) {
<SidebarSection onClick={() => setIsCollapsed(false)}> <SidebarSection onClick={() => setIsCollapsed(false)}>
<SidebarHeader <SidebarHeader
label="umami" label="umami"
icon={isCollapsed && !hasNav ? <PanelLeft /> : <LogoSvg />} icon={isCollapsed && !hasNav ? <PanelLeft /> : <Logo />}
style={{ maxHeight: 40 }} style={{ maxHeight: 40 }}
> >
{!isCollapsed && !hasNav && <PanelButton />} {!isCollapsed && !hasNav && <PanelButton />}
+1 -1
View File
@@ -3,7 +3,7 @@ import { SettingsLayout } from './SettingsLayout';
export default function ({ children }) { export default function ({ children }) {
if (process.env.cloudMode) { if (process.env.cloudMode) {
return null; //return null;
} }
return <SettingsLayout>{children}</SettingsLayout>; return <SettingsLayout>{children}</SettingsLayout>;
+20 -7
View File
@@ -5,9 +5,12 @@ import {
FormSubmitButton, FormSubmitButton,
TextField, TextField,
Button, Button,
IconLabel,
Row,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { getRandomChars } from '@/lib/generate'; import { getRandomChars } from '@/lib/generate';
import { useMessages, useTeam, useUpdateQuery } from '@/components/hooks'; import { useMessages, useTeam, useUpdateQuery } from '@/components/hooks';
import { RefreshCw } from '@/components/icons';
const generateId = () => `team_${getRandomChars(16)}`; const generateId = () => `team_${getRandomChars(16)}`;
@@ -54,15 +57,25 @@ export function TeamEditForm({
<TextField isReadOnly={!allowEdit} /> <TextField isReadOnly={!allowEdit} />
</FormField> </FormField>
{showAccessCode && ( {showAccessCode && (
<FormField name="accessCode" label={formatMessage(labels.accessCode)}> <Row alignItems="flex-end" gap>
<TextField isReadOnly allowCopy /> <FormField
</FormField> name="accessCode"
label={formatMessage(labels.accessCode)}
style={{ flex: 1 }}
>
<TextField isReadOnly allowCopy />
</FormField>
{allowEdit && (
<Button
onPress={() => setValue('accessCode', generateId(), { shouldDirty: true })}
>
<IconLabel icon={<RefreshCw />} label={formatMessage(labels.regenerate)} />
</Button>
)}
</Row>
)} )}
{allowEdit && ( {allowEdit && (
<FormButtons justifyContent="space-between"> <FormButtons justifyContent="flex-end">
<Button onPress={() => setValue('accessCode', generateId(), { shouldDirty: true })}>
{formatMessage(labels.regenerate)}
</Button>
<FormSubmitButton variant="primary" isPending={isPending}> <FormSubmitButton variant="primary" isPending={isPending}>
{formatMessage(labels.save)} {formatMessage(labels.save)}
</FormSubmitButton> </FormSubmitButton>
+17 -30
View File
@@ -1,8 +1,7 @@
import Link from 'next/link'; import { Column } from '@umami/react-zen';
import { Column, Icon, Text, Row } from '@umami/react-zen'; import { useLoginQuery, useNavigation, useTeam } from '@/components/hooks';
import { useLoginQuery, useMessages, useNavigation, useTeam } from '@/components/hooks';
import { ROLES } from '@/lib/constants'; import { ROLES } from '@/lib/constants';
import { Users, ArrowRight } from '@/components/icons'; import { Users } from '@/components/icons';
import { TeamLeaveButton } from '@/app/(main)/teams/TeamLeaveButton'; import { TeamLeaveButton } from '@/app/(main)/teams/TeamLeaveButton';
import { TeamManage } from './TeamManage'; import { TeamManage } from './TeamManage';
import { TeamEditForm } from './TeamEditForm'; import { TeamEditForm } from './TeamEditForm';
@@ -13,7 +12,6 @@ import { Panel } from '@/components/common/Panel';
export function TeamSettings({ teamId }: { teamId: string }) { export function TeamSettings({ teamId }: { teamId: string }) {
const team: any = useTeam(); const team: any = useTeam();
const { user } = useLoginQuery(); const { user } = useLoginQuery();
const { formatMessage, labels } = useMessages();
const { pathname } = useNavigation(); const { pathname } = useNavigation();
const isAdmin = pathname.includes('/admin'); const isAdmin = pathname.includes('/admin');
@@ -31,32 +29,21 @@ export function TeamSettings({ teamId }: { teamId: string }) {
user.role !== ROLES.viewOnly); user.role !== ROLES.viewOnly);
return ( return (
<> <Column gap="6">
<Link href="/settings/teams"> <PageHeader title={team?.name} icon={<Users />}>
<Row marginTop="2" alignItems="center" gap> {!isTeamOwner && !isAdmin && <TeamLeaveButton teamId={team.id} teamName={team.name} />}
<Icon rotate={180}> </PageHeader>
<ArrowRight /> <Panel>
</Icon> <TeamEditForm teamId={teamId} allowEdit={canEdit} showAccessCode={canEdit} />
<Text>{formatMessage(labels.teams)}</Text> </Panel>
</Row> <Panel>
</Link> <TeamMembersDataTable teamId={teamId} allowEdit={canEdit} />
</Panel>
<Column gap="6"> {isTeamOwner && (
<PageHeader title={team?.name} icon={<Users />}>
{!isTeamOwner && !isAdmin && <TeamLeaveButton teamId={team.id} teamName={team.name} />}
</PageHeader>
<Panel> <Panel>
<TeamEditForm teamId={teamId} allowEdit={canEdit} showAccessCode={canEdit} /> <TeamManage teamId={teamId} />
</Panel> </Panel>
<Panel> )}
<TeamMembersDataTable teamId={teamId} allowEdit={canEdit} /> </Column>
</Panel>
{isTeamOwner && (
<Panel>
<TeamManage teamId={teamId} />
</Panel>
)}
</Column>
</>
); );
} }
@@ -1,7 +1,8 @@
import { Grid, Column, Row, Text, Icon, ProgressBar, Dialog, Box } from '@umami/react-zen'; import { Grid, Column, Row, Text, Icon, ProgressBar, Dialog, Box } from '@umami/react-zen';
import { useMessages, useResultQuery } from '@/components/hooks'; import { useMessages, useResultQuery } from '@/components/hooks';
import { LoadingPanel } from '@/components/common/LoadingPanel'; import { LoadingPanel } from '@/components/common/LoadingPanel';
import { File, LightningSvg, User } from '@/components/icons'; import { File, User } from '@/components/icons';
import { Lightning } from '@/components/svg';
import { formatLongNumber } from '@/lib/format'; import { formatLongNumber } from '@/lib/format';
import { ReportEditButton } from '@/components/input/ReportEditButton'; import { ReportEditButton } from '@/components/input/ReportEditButton';
import { FunnelEditForm } from './FunnelEditForm'; import { FunnelEditForm } from './FunnelEditForm';
@@ -92,7 +93,7 @@ export function Funnel({ id, name, type, parameters, websiteId }) {
</Row> </Row>
<Row alignItems="center" justifyContent="space-between" gap> <Row alignItems="center" justifyContent="space-between" gap>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon>{type === 'path' ? <File /> : <LightningSvg />}</Icon> <Icon>{type === 'path' ? <File /> : <Lightning />}</Icon>
<Text>{value}</Text> <Text>{value}</Text>
</Row> </Row>
<Row alignItems="center" gap> <Row alignItems="center" gap>
@@ -1,7 +1,7 @@
import { Grid, Row, Column, Text, Icon, ProgressBar, Dialog } from '@umami/react-zen'; import { Grid, Row, Column, Text, Icon, ProgressBar, Dialog } from '@umami/react-zen';
import { ReportEditButton } from '@/components/input/ReportEditButton'; import { ReportEditButton } from '@/components/input/ReportEditButton';
import { useMessages, useResultQuery } from '@/components/hooks'; import { useMessages, useResultQuery } from '@/components/hooks';
import { File, LightningSvg, User } from '@/components/icons'; import { File, Lightning, User } from '@/components/icons';
import { LoadingPanel } from '@/components/common/LoadingPanel'; import { LoadingPanel } from '@/components/common/LoadingPanel';
import { formatLongNumber } from '@/lib/format'; import { formatLongNumber } from '@/lib/format';
import { GoalEditForm } from './GoalEditForm'; import { GoalEditForm } from './GoalEditForm';
@@ -68,7 +68,7 @@ export function Goal({ id, name, type, parameters, websiteId, startDate, endDate
</Row> </Row>
<Row alignItems="center" justifyContent="space-between" gap> <Row alignItems="center" justifyContent="space-between" gap>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon>{parameters.type === 'path' ? <File /> : <LightningSvg />}</Icon> <Icon>{parameters.type === 'path' ? <File /> : <Lightning />}</Icon>
<Text>{parameters.value}</Text> <Text>{parameters.value}</Text>
</Row> </Row>
<Row alignItems="center" gap> <Row alignItems="center" gap>
@@ -3,7 +3,7 @@ import { TooltipTrigger, Tooltip, Focusable, Icon, Text, Row, Column } from '@um
import { firstBy } from 'thenby'; import { firstBy } from 'thenby';
import classNames from 'classnames'; import classNames from 'classnames';
import { useEscapeKey, useMessages, useResultQuery } from '@/components/hooks'; import { useEscapeKey, useMessages, useResultQuery } from '@/components/hooks';
import { File, LightningSvg } from '@/components/icons'; import { File, Lightning } from '@/components/icons';
import { objectToArray } from '@/lib/data'; import { objectToArray } from '@/lib/data';
import { formatLongNumber } from '@/lib/format'; import { formatLongNumber } from '@/lib/format';
import { LoadingPanel } from '@/components/common/LoadingPanel'; import { LoadingPanel } from '@/components/common/LoadingPanel';
@@ -215,7 +215,7 @@ export function Journey({ websiteId, steps, startStep, endStep }: JourneyProps)
onClick={() => handleClick(name, columnIndex, paths)} onClick={() => handleClick(name, columnIndex, paths)}
> >
<Row alignItems="center" className={styles.name} title={name} gap> <Row alignItems="center" className={styles.name} title={name} gap>
<Icon>{name.startsWith('/') ? <File /> : <LightningSvg />}</Icon> <Icon>{name.startsWith('/') ? <File /> : <Lightning />}</Icon>
<Text truncate>{name}</Text> <Text truncate>{name}</Text>
</Row> </Row>
<div className={styles.count} title={nodeCount}> <div className={styles.count} title={nodeCount}>
@@ -19,10 +19,10 @@ import {
Languages, Languages,
Monitor, Monitor,
Cpu, Cpu,
LightningSvg,
Network, Network,
Tag, Tag,
} from '@/components/icons'; } from '@/components/icons';
import { Lightning } from '@/components/svg';
export function WebsiteExpandedView({ export function WebsiteExpandedView({
websiteId, websiteId,
@@ -161,7 +161,7 @@ export function WebsiteExpandedView({
id: 'event', id: 'event',
label: formatMessage(labels.event), label: formatMessage(labels.event),
path: updateParams({ view: 'event' }), path: updateParams({ view: 'event' }),
icon: <LightningSvg />, icon: <Lightning />,
}, },
{ {
id: 'hostname', id: 'hostname',
@@ -46,7 +46,7 @@ const ShareButton = ({ websiteId, shareId }) => {
<Text>Share</Text> <Text>Share</Text>
</Button> </Button>
<Modal> <Modal>
<Dialog title={formatMessage(labels.share)} style={{ width: 600 }}> <Dialog title={formatMessage(labels.share)} style={{ width: 800 }}>
{({ close }) => { {({ close }) => {
return <WebsiteShareForm websiteId={websiteId} shareId={shareId} onClose={close} />; return <WebsiteShareForm websiteId={websiteId} shareId={shareId} onClose={close} />;
}} }}
@@ -1,20 +1,5 @@
import { import { Eye, User, Clock, Sheet, Tag, ChartPie, UserPlus } from '@/components/icons';
Eye, import { Lightning, Path, Money, Compare, Target, Funnel, Magnet, Network } from '@/components/svg';
LightningSvg,
User,
Clock,
Sheet,
TargetSvg,
FunnelSvg,
PathSvg,
MagnetSvg,
Tag,
MoneySvg,
NetworkSvg,
ChartPie,
UserPlus,
CompareSvg,
} from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu'; import { SideMenu } from '@/components/common/SideMenu';
import { WebsiteSelect } from '@/components/input/WebsiteSelect'; import { WebsiteSelect } from '@/components/input/WebsiteSelect';
@@ -44,7 +29,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'events', id: 'events',
label: formatMessage(labels.events), label: formatMessage(labels.events),
icon: <LightningSvg />, icon: <Lightning />,
path: renderPath('/events'), path: renderPath('/events'),
}, },
{ {
@@ -62,7 +47,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'compare', id: 'compare',
label: formatMessage(labels.compare), label: formatMessage(labels.compare),
icon: <CompareSvg />, icon: <Compare />,
path: renderPath('/compare'), path: renderPath('/compare'),
}, },
{ {
@@ -79,25 +64,25 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'goals', id: 'goals',
label: formatMessage(labels.goals), label: formatMessage(labels.goals),
icon: <TargetSvg />, icon: <Target />,
path: renderPath('/goals'), path: renderPath('/goals'),
}, },
{ {
id: 'funnel', id: 'funnel',
label: formatMessage(labels.funnels), label: formatMessage(labels.funnels),
icon: <FunnelSvg />, icon: <Funnel />,
path: renderPath('/funnels'), path: renderPath('/funnels'),
}, },
{ {
id: 'journeys', id: 'journeys',
label: formatMessage(labels.journeys), label: formatMessage(labels.journeys),
icon: <PathSvg />, icon: <Path />,
path: renderPath('/journeys'), path: renderPath('/journeys'),
}, },
{ {
id: 'retention', id: 'retention',
label: formatMessage(labels.retention), label: formatMessage(labels.retention),
icon: <MagnetSvg />, icon: <Magnet />,
path: renderPath('/retention'), path: renderPath('/retention'),
}, },
], ],
@@ -131,13 +116,13 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'revenue', id: 'revenue',
label: formatMessage(labels.revenue), label: formatMessage(labels.revenue),
icon: <MoneySvg />, icon: <Money />,
path: renderPath('/revenue'), path: renderPath('/revenue'),
}, },
{ {
id: 'attribution', id: 'attribution',
label: formatMessage(labels.attribution), label: formatMessage(labels.attribution),
icon: <NetworkSvg />, icon: <Network />,
path: renderPath('/attribution'), path: renderPath('/attribution'),
}, },
], ],
@@ -3,7 +3,8 @@ import { useFormat, useMessages, useNavigation } from '@/components/hooks';
import { Empty } from '@/components/common/Empty'; import { Empty } from '@/components/common/Empty';
import { Avatar } from '@/components/common/Avatar'; import { Avatar } from '@/components/common/Avatar';
import Link from 'next/link'; import Link from 'next/link';
import { LightningSvg, Eye } from '@/components/icons'; import { Eye } from '@/components/icons';
import { Lightning } from '@/components/svg';
import { DateDistance } from '@/components/common/DateDistance'; import { DateDistance } from '@/components/common/DateDistance';
import { TypeIcon } from '@/components/common/TypeIcon'; import { TypeIcon } from '@/components/common/TypeIcon';
@@ -25,7 +26,7 @@ export function EventsTable({ data = [] }) {
<Link href={renderUrl(`/websites/${row.websiteId}/sessions/${row.sessionId}`)}> <Link href={renderUrl(`/websites/${row.websiteId}/sessions/${row.sessionId}`)}>
<Avatar seed={row.sessionId} size={32} /> <Avatar seed={row.sessionId} size={32} />
</Link> </Link>
<Icon>{row.eventName ? <LightningSvg /> : <Eye />}</Icon> <Icon>{row.eventName ? <Lightning /> : <Eye />}</Icon>
<Text> <Text>
{formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)} {formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)}
</Text> </Text>
@@ -8,7 +8,7 @@ import {
useTimezone, useTimezone,
useWebsite, useWebsite,
} from '@/components/hooks'; } from '@/components/hooks';
import { Eye, User, LightningSvg } from '@/components/icons'; import { Eye, User, Lightning } from '@/components/icons';
import { BROWSERS, OS_NAMES } from '@/lib/constants'; import { BROWSERS, OS_NAMES } from '@/lib/constants';
import { stringToColor } from '@/lib/format'; import { stringToColor } from '@/lib/format';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
@@ -24,7 +24,7 @@ const TYPE_EVENT = 'event';
const icons = { const icons = {
[TYPE_PAGEVIEW]: <Eye />, [TYPE_PAGEVIEW]: <Eye />,
[TYPE_SESSION]: <User />, [TYPE_SESSION]: <User />,
[TYPE_EVENT]: <LightningSvg />, [TYPE_EVENT]: <Lightning />,
}; };
export function RealtimeLog({ data }: { data: any }) { export function RealtimeLog({ data }: { data: any }) {
@@ -12,7 +12,7 @@ import {
Dialog, Dialog,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel'; import { LoadingPanel } from '@/components/common/LoadingPanel';
import { LightningSvg, Eye, FileText } from '@/components/icons'; import { Lightning, Eye, FileText } from '@/components/icons';
import { useMessages, useSessionActivityQuery, useTimezone } from '@/components/hooks'; import { useMessages, useSessionActivityQuery, useTimezone } from '@/components/hooks';
import { EventData } from '@/components/metrics/EventData'; import { EventData } from '@/components/metrics/EventData';
@@ -52,7 +52,7 @@ export function SessionActivity({
{formatTimezoneDate(createdAt, 'pp')} {formatTimezoneDate(createdAt, 'pp')}
</StatusLight> </StatusLight>
<Row alignItems="center" gap="2"> <Row alignItems="center" gap="2">
<Icon>{eventName ? <LightningSvg /> : <Eye />}</Icon> <Icon>{eventName ? <Lightning /> : <Eye />}</Icon>
<Text> <Text>
{eventName {eventName
? formatMessage(labels.triggeredEvent) ? formatMessage(labels.triggeredEvent)
@@ -2,7 +2,8 @@ import { ReactNode } from 'react';
import { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen'; import { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen';
import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks'; import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks';
import { TypeIcon } from '@/components/common/TypeIcon'; import { TypeIcon } from '@/components/common/TypeIcon';
import { LocationSvg, KeyRound, Calendar } from '@/components/icons'; import { KeyRound, Calendar } from '@/components/icons';
import { Location } from '@/components/svg';
import { DateDistance } from '@/components/common/DateDistance'; import { DateDistance } from '@/components/common/DateDistance';
export function SessionInfo({ data }) { export function SessionInfo({ data }) {
@@ -36,11 +37,11 @@ export function SessionInfo({ data }) {
{formatValue(data?.country, 'country')} {formatValue(data?.country, 'country')}
</Info> </Info>
<Info label={formatMessage(labels.region)} icon={<LocationSvg />}> <Info label={formatMessage(labels.region)} icon={<Location />}>
{getRegionName(data?.region)} {getRegionName(data?.region)}
</Info> </Info>
<Info label={formatMessage(labels.city)} icon={<LocationSvg />}> <Info label={formatMessage(labels.city)} icon={<Location />}>
{data?.city} {data?.city}
</Info> </Info>
@@ -8,10 +8,12 @@ import {
Column, Column,
Label, Label,
Row, Row,
IconLabel,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { useState } from 'react'; import { useState } from 'react';
import { getRandomChars } from '@/lib/generate'; import { getRandomChars } from '@/lib/generate';
import { useMessages, useUpdateQuery } from '@/components/hooks'; import { useMessages, useUpdateQuery, useConfig } from '@/components/hooks';
import { RefreshCcw } from 'lucide-react';
const generateId = () => getRandomChars(16); const generateId = () => getRandomChars(16);
@@ -24,22 +26,31 @@ export interface WebsiteShareFormProps {
export function WebsiteShareForm({ websiteId, shareId, onSave, onClose }: WebsiteShareFormProps) { export function WebsiteShareForm({ websiteId, shareId, onSave, onClose }: WebsiteShareFormProps) {
const { formatMessage, labels, messages, getErrorMessage } = useMessages(); const { formatMessage, labels, messages, getErrorMessage } = useMessages();
const [id, setId] = useState(shareId); const [currentId, setCurrentId] = useState(shareId);
const { mutateAsync, error, touch, toast } = useUpdateQuery(`/websites/${websiteId}`); const { mutateAsync, error, touch, toast } = useUpdateQuery(`/websites/${websiteId}`);
const { cloudMode } = useConfig();
const url = `${window?.location.origin || ''}${process.env.basePath || ''}/share/${id}`; const getUrl = (shareId: string) => {
if (cloudMode) {
return `${process.env.cloudUrl}/share/${shareId}`;
}
return `${window?.location.origin}${process.env.basePath || ''}/share/${shareId}`;
};
const url = getUrl(currentId);
const handleGenerate = () => { const handleGenerate = () => {
setId(generateId()); setCurrentId(generateId());
}; };
const handleSwitch = () => { const handleSwitch = () => {
setId(id ? null : generateId()); setCurrentId(currentId ? null : generateId());
}; };
const handleSave = async () => { const handleSave = async () => {
const data = { const data = {
shareId: id, shareId: currentId,
}; };
await mutateAsync(data, { await mutateAsync(data, {
onSuccess: async () => { onSuccess: async () => {
@@ -54,19 +65,23 @@ export function WebsiteShareForm({ websiteId, shareId, onSave, onClose }: Websit
return ( return (
<Form onSubmit={handleSave} error={getErrorMessage(error)} values={{ url }}> <Form onSubmit={handleSave} error={getErrorMessage(error)} values={{ url }}>
<Column gap> <Column gap>
<Switch isSelected={!!id} onChange={handleSwitch}> <Switch isSelected={!!currentId} onChange={handleSwitch}>
{formatMessage(labels.enableShareUrl)} {formatMessage(labels.enableShareUrl)}
</Switch> </Switch>
{id && ( {currentId && (
<Column> <Row alignItems="flex-end" gap>
<Label>{formatMessage(labels.shareUrl)}</Label> <Column flexGrow={1}>
<TextField value={url} isReadOnly allowCopy /> <Label>{formatMessage(labels.shareUrl)}</Label>
</Column> <TextField value={url} isReadOnly allowCopy />
)} </Column>
<FormButtons justifyContent="space-between"> <Column>
<Row> <Button onPress={handleGenerate}>
{id && <Button onPress={handleGenerate}>{formatMessage(labels.regenerate)}</Button>} <IconLabel icon={<RefreshCcw />} label={formatMessage(labels.regenerate)} />
</Button>
</Column>
</Row> </Row>
)}
<FormButtons justifyContent="flex-end">
<Row alignItems="center" gap> <Row alignItems="center" gap>
{onClose && <Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>} {onClose && <Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>}
<FormSubmitButton isDisabled={false}>{formatMessage(labels.save)}</FormSubmitButton> <FormSubmitButton isDisabled={false}>{formatMessage(labels.save)}</FormSubmitButton>
@@ -16,11 +16,17 @@ export function WebsiteTrackingCode({
const trackerScriptName = const trackerScriptName =
config?.trackerScriptName?.split(',')?.map((n: string) => n.trim())?.[0] || SCRIPT_NAME; config?.trackerScriptName?.split(',')?.map((n: string) => n.trim())?.[0] || SCRIPT_NAME;
const url = trackerScriptName?.startsWith('http') const getUrl = () => {
? trackerScriptName if (config?.cloudMode) {
: `${hostUrl || window?.location.origin || ''}${ return `${process.env.cloudUrl}/${trackerScriptName}`;
process.env.basePath || '' }
}/${trackerScriptName}`;
return `${hostUrl || window?.location?.origin || ''}${
process.env.basePath || ''
}/${trackerScriptName}`;
};
const url = trackerScriptName?.startsWith('http') ? trackerScriptName : getUrl();
const code = `<script defer src="${url}" data-website-id="${websiteId}"></script>`; const code = `<script defer src="${url}" data-website-id="${websiteId}"></script>`;
+2 -2
View File
@@ -13,7 +13,7 @@ import { useRouter } from 'next/navigation';
import { useMessages, useUpdateQuery } from '@/components/hooks'; import { useMessages, useUpdateQuery } from '@/components/hooks';
import { setUser } from '@/store/app'; import { setUser } from '@/store/app';
import { setClientAuthToken } from '@/lib/client'; import { setClientAuthToken } from '@/lib/client';
import { LogoSvg } from '@/components/icons'; import { Logo } from '@/components/svg';
export function LoginForm() { export function LoginForm() {
const { formatMessage, labels, getErrorMessage } = useMessages(); const { formatMessage, labels, getErrorMessage } = useMessages();
@@ -34,7 +34,7 @@ export function LoginForm() {
return ( return (
<Column justifyContent="center" alignItems="center" gap="6"> <Column justifyContent="center" alignItems="center" gap="6">
<Icon size="lg"> <Icon size="lg">
<LogoSvg /> <Logo />
</Icon> </Icon>
<Heading>umami</Heading> <Heading>umami</Heading>
<Form onSubmit={handleSubmit} error={getErrorMessage(error)}> <Form onSubmit={handleSubmit} error={getErrorMessage(error)}>
+2 -2
View File
@@ -1,7 +1,7 @@
import { Row, Icon, Text, ThemeButton } from '@umami/react-zen'; import { Row, Icon, Text, ThemeButton } from '@umami/react-zen';
import { LanguageButton } from '@/components/input/LanguageButton'; import { LanguageButton } from '@/components/input/LanguageButton';
import { PreferencesButton } from '@/components/input/PreferencesButton'; import { PreferencesButton } from '@/components/input/PreferencesButton';
import { LogoSvg } from '@/components/icons'; import { Logo } from '@/components/svg';
export function Header() { export function Header() {
return ( return (
@@ -9,7 +9,7 @@ export function Header() {
<a href="https://umami.is" target="_blank"> <a href="https://umami.is" target="_blank">
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<LogoSvg /> <Logo />
</Icon> </Icon>
<Text weight="bold">umami</Text> <Text weight="bold">umami</Text>
</Row> </Row>
-13
View File
@@ -1,14 +1 @@
export * from 'lucide-react'; export * from 'lucide-react';
export {
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,
} from '@/components/svg';
+2 -2
View File
@@ -24,8 +24,8 @@ import {
Settings, Settings,
User, User,
Users, Users,
SwitchSvg,
} from '@/components/icons'; } from '@/components/icons';
import { Switch } from '@/components/svg';
import { DOCS_URL } from '@/lib/constants'; import { DOCS_URL } from '@/lib/constants';
import { ArrowRight } from 'lucide-react'; import { ArrowRight } from 'lucide-react';
@@ -79,7 +79,7 @@ export function NavButton({ showText = true }: TeamsButtonProps) {
<Menu autoFocus="last" onAction={handleAction}> <Menu autoFocus="last" onAction={handleAction}>
<SubmenuTrigger> <SubmenuTrigger>
<MenuItem id="teams" showChecked={false} showSubMenuIcon> <MenuItem id="teams" showChecked={false} showSubMenuIcon>
<IconLabel icon={<SwitchSvg />} label={formatMessage(labels.switchAccount)} /> <IconLabel icon={<Switch />} label={formatMessage(labels.switchAccount)} />
</MenuItem> </MenuItem>
<Popover placement="right top"> <Popover placement="right top">
<Column minWidth="300px"> <Column minWidth="300px">