mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Added menu options for cloud mode. Async fixes.
This commit is contained in:
parent
4df6f06485
commit
f639bb07f4
12 changed files with 47 additions and 27 deletions
|
|
@ -17,7 +17,7 @@ export function PixelDeleteButton({
|
||||||
const { mutateAsync, isPending, error } = useDeleteQuery(`/pixels/${pixelId}`);
|
const { mutateAsync, isPending, error } = useDeleteQuery(`/pixels/${pixelId}`);
|
||||||
const { touch } = useModified();
|
const { touch } = useModified();
|
||||||
|
|
||||||
const handleConfirm = (close: () => void) => {
|
const handleConfirm = async (close: () => void) => {
|
||||||
await mutateAsync(null, {
|
await mutateAsync(null, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
touch('pixels');
|
touch('pixels');
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export function PixelEditButton({ pixelId }: { pixelId: string }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActionButton title={formatMessage(labels.edit)} icon={<Edit />}>
|
<ActionButton title={formatMessage(labels.edit)} icon={<Edit />}>
|
||||||
<Dialog title={formatMessage(labels.pixel)} style={{ width: 800, minHeight: 300 }}>
|
<Dialog title={formatMessage(labels.pixel)} style={{ width: 600, minHeight: 300 }}>
|
||||||
{({ close }) => {
|
{({ close }) => {
|
||||||
return <PixelEditForm pixelId={pixelId} onClose={close} />;
|
return <PixelEditForm pixelId={pixelId} onClose={close} />;
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,7 @@ export function PixelEditForm({
|
||||||
allowCopy
|
allowCopy
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button onPress={() => setValue('slug', handleSlug(), { shouldDirty: true })}>
|
||||||
variant="quiet"
|
|
||||||
onPress={() => setValue('slug', handleSlug(), { shouldDirty: true })}
|
|
||||||
>
|
|
||||||
<Icon>
|
<Icon>
|
||||||
<RefreshCw />
|
<RefreshCw />
|
||||||
</Icon>
|
</Icon>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { usePixel, useMessages, useSlug } from '@/components/hooks';
|
import { usePixel, useMessages, useSlug } from '@/components/hooks';
|
||||||
import { PageHeader } from '@/components/common/PageHeader';
|
import { PageHeader } from '@/components/common/PageHeader';
|
||||||
import { Icon, Text } from '@umami/react-zen';
|
import { Icon, Text } from '@umami/react-zen';
|
||||||
import { ExternalLink, Pixel } from '@/components/icons';
|
import { ExternalLink, Grid2x2 } from '@/components/icons';
|
||||||
import { LinkButton } from '@/components/common/LinkButton';
|
import { LinkButton } from '@/components/common/LinkButton';
|
||||||
|
|
||||||
export function PixelHeader() {
|
export function PixelHeader() {
|
||||||
|
|
@ -10,7 +10,7 @@ export function PixelHeader() {
|
||||||
const pixel = usePixel();
|
const pixel = usePixel();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageHeader title={pixel.name} description={pixel.url} icon={<Pixel />}>
|
<PageHeader title={pixel.name} description={pixel.slug} icon={<Grid2x2 />}>
|
||||||
<LinkButton href={getSlugUrl(pixel.slug)} target="_blank">
|
<LinkButton href={getSlugUrl(pixel.slug)} target="_blank">
|
||||||
<Icon>
|
<Icon>
|
||||||
<ExternalLink />
|
<ExternalLink />
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { PixelPage } from './PixelPage';
|
import { PixelPage } from './PixelPage';
|
||||||
import { Metadata } from 'next';
|
import { Metadata } from 'next';
|
||||||
|
|
||||||
export default async function ({ params }: { params: Promise<{ pixelId: string }> }) {
|
export default function ({ params }: { params: { pixelId: string } }) {
|
||||||
const { pixelId } = await params;
|
const { pixelId } = params;
|
||||||
|
|
||||||
return <PixelPage pixelId={pixelId} />;
|
return <PixelPage pixelId={pixelId} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { Grid, Column } from '@umami/react-zen';
|
||||||
import { useMessages, useNavigation } from '@/components/hooks';
|
import { useMessages, useNavigation } from '@/components/hooks';
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
import { SideMenu } from '@/components/common/SideMenu';
|
import { SideMenu } from '@/components/common/SideMenu';
|
||||||
import { UserCircle, Users, Knobs } from '@/components/icons';
|
import { UserCircle, Users, Settings2 } from '@/components/icons';
|
||||||
|
|
||||||
export function SettingsLayout({ children }: { children: ReactNode }) {
|
export function SettingsLayout({ children }: { children: ReactNode }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
@ -18,7 +18,7 @@ export function SettingsLayout({ children }: { children: ReactNode }) {
|
||||||
id: 'preferences',
|
id: 'preferences',
|
||||||
label: formatMessage(labels.preferences),
|
label: formatMessage(labels.preferences),
|
||||||
path: renderUrl('/settings/preferences'),
|
path: renderUrl('/settings/preferences'),
|
||||||
icon: <Knobs />,
|
icon: <Settings2 />,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
Search,
|
Search,
|
||||||
Type,
|
Type,
|
||||||
SquareSlash,
|
SquareSlash,
|
||||||
SquareArrowRight,
|
Share2,
|
||||||
Megaphone,
|
Megaphone,
|
||||||
Earth,
|
Earth,
|
||||||
Globe,
|
Globe,
|
||||||
|
|
@ -20,7 +20,7 @@ import {
|
||||||
Monitor,
|
Monitor,
|
||||||
Cpu,
|
Cpu,
|
||||||
LightningSvg,
|
LightningSvg,
|
||||||
LucideCaseSensitive,
|
Network,
|
||||||
Tag,
|
Tag,
|
||||||
} from '@/components/icons';
|
} from '@/components/icons';
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ export function WebsiteExpandedView({
|
||||||
id: 'referrer',
|
id: 'referrer',
|
||||||
label: formatMessage(labels.referrer),
|
label: formatMessage(labels.referrer),
|
||||||
path: updateParams({ view: 'referrer' }),
|
path: updateParams({ view: 'referrer' }),
|
||||||
icon: <SquareArrowRight />,
|
icon: <Share2 />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'channel',
|
id: 'channel',
|
||||||
|
|
@ -167,7 +167,7 @@ export function WebsiteExpandedView({
|
||||||
id: 'hostname',
|
id: 'hostname',
|
||||||
label: formatMessage(labels.hostname),
|
label: formatMessage(labels.hostname),
|
||||||
path: updateParams({ view: 'hostname' }),
|
path: updateParams({ view: 'hostname' }),
|
||||||
icon: <LucideCaseSensitive />,
|
icon: <Network />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'tag',
|
id: 'tag',
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
MagnetSvg,
|
MagnetSvg,
|
||||||
Tag,
|
Tag,
|
||||||
MoneySvg,
|
MoneySvg,
|
||||||
Network,
|
NetworkSvg,
|
||||||
ChartPie,
|
ChartPie,
|
||||||
UserPlus,
|
UserPlus,
|
||||||
CompareSvg,
|
CompareSvg,
|
||||||
|
|
@ -137,7 +137,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
|
||||||
{
|
{
|
||||||
id: 'attribution',
|
id: 'attribution',
|
||||||
label: formatMessage(labels.attribution),
|
label: formatMessage(labels.attribution),
|
||||||
icon: <Network />,
|
icon: <NetworkSvg />,
|
||||||
path: renderPath('/attribution'),
|
path: renderPath('/attribution'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { List, ListItem } from '@umami/react-zen';
|
import { List, ListItem } from '@umami/react-zen';
|
||||||
import { useWebsiteSegmentsQuery } from '@/components/hooks';
|
import { useWebsiteSegmentsQuery } from '@/components/hooks';
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
|
import { Empty } from '@/components/common/Empty';
|
||||||
|
|
||||||
export interface SegmentFiltersProps {
|
export interface SegmentFiltersProps {
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
|
|
@ -23,6 +24,7 @@ export function SegmentFilters({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingPanel data={data} isLoading={isLoading} isFetching={isFetching} overflowY="auto">
|
<LoadingPanel data={data} isLoading={isLoading} isFetching={isFetching} overflowY="auto">
|
||||||
|
{data?.data?.length === 0 && <Empty />}
|
||||||
<List selectionMode="single" value={[segmentId]} onChange={id => handleChange(id[0])}>
|
<List selectionMode="single" value={[segmentId]} onChange={id => handleChange(id[0])}>
|
||||||
{data?.data?.map(item => {
|
{data?.data?.map(item => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -10,23 +10,27 @@ import {
|
||||||
MenuSection,
|
MenuSection,
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { useMessages, useLoginQuery, useNavigation, useConfig } from '@/components/hooks';
|
import { useMessages, useLoginQuery, useNavigation, useConfig } from '@/components/hooks';
|
||||||
import { LogOut, LockKeyhole, Settings, UserCircle } from '@/components/icons';
|
import { LogOut, LockKeyhole, Settings, UserCircle, LifeBuoy, BookText } from '@/components/icons';
|
||||||
|
import { DOCS_URL } from '@/lib/constants';
|
||||||
|
|
||||||
export function SettingsButton() {
|
export function SettingsButton() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const { user } = useLoginQuery();
|
const { user } = useLoginQuery();
|
||||||
const { router, renderUrl } = useNavigation();
|
const { router } = useNavigation();
|
||||||
const { cloudMode } = useConfig();
|
const { cloudMode } = useConfig();
|
||||||
|
|
||||||
const handleAction = (id: Key) => {
|
const handleAction = (id: Key) => {
|
||||||
const url = `/${id}`;
|
const url = id.toString();
|
||||||
|
|
||||||
if (cloudMode) {
|
if (cloudMode) {
|
||||||
window.location.href = url;
|
if (url === '/docs') {
|
||||||
return;
|
window.open(DOCS_URL, '_blank');
|
||||||
|
} else {
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
router.push(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
router.push(renderUrl(url));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -40,12 +44,26 @@ export function SettingsButton() {
|
||||||
<Menu autoFocus="last" onAction={handleAction}>
|
<Menu autoFocus="last" onAction={handleAction}>
|
||||||
<MenuSection title={user.username}>
|
<MenuSection title={user.username}>
|
||||||
<MenuSeparator />
|
<MenuSeparator />
|
||||||
<MenuItem id="settings" icon={<Settings />} label={formatMessage(labels.settings)} />
|
<MenuItem id="/settings" icon={<Settings />} label={formatMessage(labels.settings)} />
|
||||||
{!cloudMode && user.isAdmin && (
|
{!cloudMode && user.isAdmin && (
|
||||||
<MenuItem id="admin" icon={<LockKeyhole />} label={formatMessage(labels.admin)} />
|
<MenuItem id="admin" icon={<LockKeyhole />} label={formatMessage(labels.admin)} />
|
||||||
)}
|
)}
|
||||||
|
{cloudMode && (
|
||||||
|
<>
|
||||||
|
<MenuItem
|
||||||
|
id="/docs"
|
||||||
|
icon={<BookText />}
|
||||||
|
label={formatMessage(labels.documentation)}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
id="/settings/support"
|
||||||
|
icon={<LifeBuoy />}
|
||||||
|
label={formatMessage(labels.support)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<MenuSeparator />
|
<MenuSeparator />
|
||||||
<MenuItem id="logout" icon={<LogOut />} label={formatMessage(labels.logout)} />
|
<MenuItem id="/logout" icon={<LogOut />} label={formatMessage(labels.logout)} />
|
||||||
</MenuSection>
|
</MenuSection>
|
||||||
</Menu>
|
</Menu>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
|
||||||
|
|
@ -360,6 +360,8 @@ export const labels = defineMessages({
|
||||||
environment: { id: 'label.environment', defaultMessage: 'Environment' },
|
environment: { id: 'label.environment', defaultMessage: 'Environment' },
|
||||||
criteria: { id: 'label.criteria', defaultMessage: 'Criteria' },
|
criteria: { id: 'label.criteria', defaultMessage: 'Criteria' },
|
||||||
share: { id: 'label.share', defaultMessage: 'Share' },
|
share: { id: 'label.share', defaultMessage: 'Share' },
|
||||||
|
support: { id: 'label.support', defaultMessage: 'Support' },
|
||||||
|
documentation: { id: 'label.documentation', defaultMessage: 'Documentation' },
|
||||||
});
|
});
|
||||||
|
|
||||||
export const messages = defineMessages({
|
export const messages = defineMessages({
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ export const DASHBOARD_CONFIG = 'umami.dashboard';
|
||||||
export const VERSION_CHECK = 'umami.version-check';
|
export const VERSION_CHECK = 'umami.version-check';
|
||||||
export const SHARE_TOKEN_HEADER = 'x-umami-share-token';
|
export const SHARE_TOKEN_HEADER = 'x-umami-share-token';
|
||||||
export const HOMEPAGE_URL = 'https://umami.is';
|
export const HOMEPAGE_URL = 'https://umami.is';
|
||||||
|
export const DOCS_URL = 'https://umami.is/docs';
|
||||||
export const REPO_URL = 'https://github.com/umami-software/umami';
|
export const REPO_URL = 'https://github.com/umami-software/umami';
|
||||||
export const UPDATES_URL = 'https://api.umami.is/v1/updates';
|
export const UPDATES_URL = 'https://api.umami.is/v1/updates';
|
||||||
export const TELEMETRY_PIXEL = 'https://i.umami.is/a.png';
|
export const TELEMETRY_PIXEL = 'https://i.umami.is/a.png';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue