mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Responsive everything.
This commit is contained in:
parent
9df012084d
commit
4d2a7ea947
23 changed files with 286 additions and 287 deletions
|
|
@ -1,22 +1,11 @@
|
|||
import {
|
||||
Row,
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
Button,
|
||||
Icon,
|
||||
Modal,
|
||||
NavMenu,
|
||||
NavMenuItem,
|
||||
IconLabel,
|
||||
Text,
|
||||
Grid,
|
||||
} from '@umami/react-zen';
|
||||
import { Globe, Grid2x2, LinkIcon, Menu } from '@/components/icons';
|
||||
import { Row, NavMenu, NavMenuItem, IconLabel, Text, Grid } from '@umami/react-zen';
|
||||
import { Globe, Grid2x2, LinkIcon } from '@/components/icons';
|
||||
import { useMessages, useNavigation } from '@/components/hooks';
|
||||
import Link from 'next/link';
|
||||
import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav';
|
||||
import { Logo } from '@/components/svg';
|
||||
import { NavButton } from '@/components/input/NavButton';
|
||||
import { MobileMenu } from '@/components/common/MobileMenu';
|
||||
|
||||
export function MobileNav() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
@ -45,30 +34,27 @@ export function MobileNav() {
|
|||
|
||||
return (
|
||||
<Grid columns="auto 1fr" flexGrow={1}>
|
||||
<DialogTrigger>
|
||||
<Button>
|
||||
<Icon>
|
||||
<Menu />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Modal position="left" offset="80px">
|
||||
<Dialog variant="sheet">
|
||||
<NavMenu padding="3">
|
||||
<NavButton />
|
||||
{links.map(link => {
|
||||
return (
|
||||
<Link key={link.id} href={link.path}>
|
||||
<NavMenuItem>
|
||||
<IconLabel icon={link.icon} label={link.label} />
|
||||
</NavMenuItem>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</NavMenu>
|
||||
{websiteId && <WebsiteNav websiteId={websiteId} />}
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</DialogTrigger>
|
||||
<MobileMenu>
|
||||
{({ close }) => {
|
||||
return (
|
||||
<>
|
||||
<NavMenu padding="3" onItemClick={close} border="bottom">
|
||||
<NavButton />
|
||||
{links.map(link => {
|
||||
return (
|
||||
<Link key={link.id} href={link.path}>
|
||||
<NavMenuItem>
|
||||
<IconLabel icon={link.icon} label={link.label} />
|
||||
</NavMenuItem>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</NavMenu>
|
||||
{websiteId && <WebsiteNav websiteId={websiteId} onItemClick={close} />}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</MobileMenu>
|
||||
<Row alignItems="center" justifyContent="center" flexGrow={1}>
|
||||
<IconLabel icon={<Logo />} style={{ width: 'auto' }}>
|
||||
<Text weight="bold">umami</Text>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Dialog, Modal } from '@umami/react-zen';
|
||||
import { Dialog, Modal, useBreakpoint } from '@umami/react-zen';
|
||||
import { WebsiteExpandedView } from '@/app/(main)/websites/[websiteId]/WebsiteExpandedView';
|
||||
import { useNavigation } from '@/components/hooks';
|
||||
|
||||
|
|
@ -14,6 +14,8 @@ export function ExpandedViewModal({
|
|||
query: { view },
|
||||
updateParams,
|
||||
} = useNavigation();
|
||||
const breakpoint = useBreakpoint();
|
||||
const isMobile = ['xs', 'sm', 'md'].includes(breakpoint);
|
||||
|
||||
const handleClose = (close: () => void) => {
|
||||
router.push(updateParams({ view: undefined }));
|
||||
|
|
@ -28,7 +30,13 @@ export function ExpandedViewModal({
|
|||
|
||||
return (
|
||||
<Modal isOpen={!!view} onOpenChange={handleOpenChange} isDismissable>
|
||||
<Dialog style={{ maxWidth: 1320, width: '100vw', height: 'calc(100vh - 40px)' }}>
|
||||
<Dialog
|
||||
style={{
|
||||
maxWidth: 1320,
|
||||
width: '100vw',
|
||||
height: isMobile ? '100dvh' : 'calc(100dvh - 40px)',
|
||||
}}
|
||||
>
|
||||
{({ close }) => {
|
||||
return (
|
||||
<WebsiteExpandedView
|
||||
|
|
|
|||
|
|
@ -22,7 +22,13 @@ import {
|
|||
} from '@/components/icons';
|
||||
import { Lightning } from '@/components/svg';
|
||||
|
||||
export function WebsiteExpandedMenu({ excludedIds = [] }: { excludedIds?: string[] }) {
|
||||
export function WebsiteExpandedMenu({
|
||||
excludedIds = [],
|
||||
onItemClick,
|
||||
}: {
|
||||
excludedIds?: string[];
|
||||
onItemClick?: () => void;
|
||||
}) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const {
|
||||
updateParams,
|
||||
|
|
@ -173,5 +179,5 @@ export function WebsiteExpandedMenu({ excludedIds = [] }: { excludedIds?: string
|
|||
},
|
||||
];
|
||||
|
||||
return <SideMenu items={items} selectedKey={view} />;
|
||||
return <SideMenu items={items} selectedKey={view} onItemClick={onItemClick} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { Grid, Column } from '@umami/react-zen';
|
||||
import { Grid, Column, Row } from '@umami/react-zen';
|
||||
import { useMessages, useNavigation } from '@/components/hooks';
|
||||
import { MetricsExpandedTable } from '@/components/metrics/MetricsExpandedTable';
|
||||
import { WebsiteExpandedMenu } from '@/app/(main)/websites/[websiteId]/WebsiteExpandedMenu';
|
||||
import { MobileMenu } from '@/components/common/MobileMenu';
|
||||
|
||||
export function WebsiteExpandedView({
|
||||
websiteId,
|
||||
|
|
@ -18,24 +19,33 @@ export function WebsiteExpandedView({
|
|||
} = useNavigation();
|
||||
|
||||
return (
|
||||
<Grid columns={{ xs: '1fr', md: 'auto 1fr' }} gap="6" height="100%" overflow="hidden">
|
||||
<Column
|
||||
display={{ xs: 'none', md: 'flex' }}
|
||||
gap="6"
|
||||
border="right"
|
||||
paddingRight="3"
|
||||
overflowY="auto"
|
||||
>
|
||||
<WebsiteExpandedMenu excludedIds={excludedIds} />
|
||||
</Column>
|
||||
<Column overflow="hidden">
|
||||
<MetricsExpandedTable
|
||||
title={formatMessage(labels[view])}
|
||||
type={view}
|
||||
websiteId={websiteId}
|
||||
onClose={onClose}
|
||||
/>
|
||||
</Column>
|
||||
</Grid>
|
||||
<Column gap>
|
||||
<Row display={{ xs: 'flex', md: 'none' }}>
|
||||
<MobileMenu>
|
||||
{({ close }) => {
|
||||
return <WebsiteExpandedMenu excludedIds={excludedIds} onItemClick={close} />;
|
||||
}}
|
||||
</MobileMenu>
|
||||
</Row>
|
||||
<Grid columns={{ xs: '1fr', md: 'auto 1fr' }} gap="6" height="100%" overflow="hidden">
|
||||
<Column
|
||||
display={{ xs: 'none', md: 'flex' }}
|
||||
gap="6"
|
||||
border="right"
|
||||
paddingRight="3"
|
||||
overflow="auto"
|
||||
>
|
||||
<WebsiteExpandedMenu excludedIds={excludedIds} />
|
||||
</Column>
|
||||
<Column overflow="hidden">
|
||||
<MetricsExpandedTable
|
||||
title={formatMessage(labels[view])}
|
||||
type={view}
|
||||
websiteId={websiteId}
|
||||
onClose={onClose}
|
||||
/>
|
||||
</Column>
|
||||
</Grid>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Text } from '@umami/react-zen';
|
||||
import { Text, Column } from '@umami/react-zen';
|
||||
import {
|
||||
Eye,
|
||||
User,
|
||||
|
|
@ -14,7 +14,13 @@ import { useMessages, useNavigation } from '@/components/hooks';
|
|||
import { SideMenu } from '@/components/common/SideMenu';
|
||||
import { WebsiteSelect } from '@/components/input/WebsiteSelect';
|
||||
|
||||
export function WebsiteNav({ websiteId }: { websiteId: string }) {
|
||||
export function WebsiteNav({
|
||||
websiteId,
|
||||
onItemClick,
|
||||
}: {
|
||||
websiteId: string;
|
||||
onItemClick?: () => void;
|
||||
}) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { pathname, renderUrl, teamId, router } = useNavigation();
|
||||
|
||||
|
|
@ -155,7 +161,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
|
|||
.find(({ path }) => path && pathname.endsWith(path.split('?')[0]))?.id;
|
||||
|
||||
return (
|
||||
<SideMenu items={items} selectedKey={selectedKey} allowMinimize={false}>
|
||||
<Column padding="3" gap>
|
||||
<WebsiteSelect
|
||||
websiteId={websiteId}
|
||||
teamId={teamId}
|
||||
|
|
@ -163,6 +169,12 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
|
|||
renderValue={renderValue}
|
||||
buttonProps={{ style: { outline: 'none' } }}
|
||||
/>
|
||||
</SideMenu>
|
||||
<SideMenu
|
||||
items={items}
|
||||
selectedKey={selectedKey}
|
||||
allowMinimize={false}
|
||||
onItemClick={onItemClick}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Icon, TextField, Column, Row, Label } from '@umami/react-zen';
|
||||
import { Icon, Grid, Column, Row, Label } from '@umami/react-zen';
|
||||
import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks';
|
||||
import { TypeIcon } from '@/components/common/TypeIcon';
|
||||
import { KeyRound, Calendar } from '@/components/icons';
|
||||
import { Location } from '@/components/svg';
|
||||
import { KeyRound, Calendar, MapPin, Landmark } from '@/components/icons';
|
||||
import { DateDistance } from '@/components/common/DateDistance';
|
||||
|
||||
export function SessionInfo({ data }) {
|
||||
|
|
@ -13,11 +12,7 @@ export function SessionInfo({ data }) {
|
|||
const { getRegionName } = useRegionNames(locale);
|
||||
|
||||
return (
|
||||
<Column gap="6">
|
||||
<Info label="ID">
|
||||
<TextField value={data?.id} style={{ width: '100%' }} allowCopy />
|
||||
</Info>
|
||||
|
||||
<Grid columns="repeat(auto-fit, minmax(200px, 1fr)" gap>
|
||||
<Info label={formatMessage(labels.distinctId)} icon={<KeyRound />}>
|
||||
{data?.distinctId}
|
||||
</Info>
|
||||
|
|
@ -37,11 +32,11 @@ export function SessionInfo({ data }) {
|
|||
{formatValue(data?.country, 'country')}
|
||||
</Info>
|
||||
|
||||
<Info label={formatMessage(labels.region)} icon={<Location />}>
|
||||
<Info label={formatMessage(labels.region)} icon={<MapPin />}>
|
||||
{getRegionName(data?.region)}
|
||||
</Info>
|
||||
|
||||
<Info label={formatMessage(labels.city)} icon={<Location />}>
|
||||
<Info label={formatMessage(labels.city)} icon={<Landmark />}>
|
||||
{data?.city}
|
||||
</Info>
|
||||
|
||||
|
|
@ -65,7 +60,7 @@ export function SessionInfo({ data }) {
|
|||
>
|
||||
{formatValue(data?.device, 'device')}
|
||||
</Info>
|
||||
</Column>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
import { Grid, Row, Column, Tabs, TabList, Tab, TabPanel, Icon, Button } from '@umami/react-zen';
|
||||
import {
|
||||
TextField,
|
||||
Row,
|
||||
Column,
|
||||
Tabs,
|
||||
TabList,
|
||||
Tab,
|
||||
TabPanel,
|
||||
Icon,
|
||||
Button,
|
||||
} from '@umami/react-zen';
|
||||
import { Avatar } from '@/components/common/Avatar';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { X } from '@/components/icons';
|
||||
|
|
@ -37,35 +47,34 @@ export function SessionProfile({
|
|||
</Icon>
|
||||
</Button>
|
||||
</Row>
|
||||
<Grid columns="340px 1fr" gap="6">
|
||||
<Column gap="6">
|
||||
<Row justifyContent="center">
|
||||
<Avatar seed={data?.id} size={128} />
|
||||
</Row>
|
||||
<SessionInfo data={data} />
|
||||
</Column>
|
||||
<Column gap>
|
||||
<SessionStats data={data} />
|
||||
<Column gap="6">
|
||||
<Row justifyContent="center" alignItems="center" gap="6">
|
||||
<Avatar seed={data?.id} size={128} />
|
||||
<Column width="360px">
|
||||
<TextField label="ID" value={data?.id} allowCopy />
|
||||
</Column>
|
||||
</Row>
|
||||
<SessionStats data={data} />
|
||||
<SessionInfo data={data} />
|
||||
|
||||
<Tabs>
|
||||
<TabList>
|
||||
<Tab id="activity">{formatMessage(labels.activity)}</Tab>
|
||||
<Tab id="properties">{formatMessage(labels.properties)}</Tab>
|
||||
</TabList>
|
||||
<TabPanel id="activity">
|
||||
<SessionActivity
|
||||
websiteId={websiteId}
|
||||
sessionId={sessionId}
|
||||
startDate={data?.firstAt}
|
||||
endDate={data?.lastAt}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel id="properties">
|
||||
<SessionData sessionId={sessionId} websiteId={websiteId} />
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</Column>
|
||||
</Grid>
|
||||
<Tabs>
|
||||
<TabList>
|
||||
<Tab id="activity">{formatMessage(labels.activity)}</Tab>
|
||||
<Tab id="properties">{formatMessage(labels.properties)}</Tab>
|
||||
</TabList>
|
||||
<TabPanel id="activity">
|
||||
<SessionActivity
|
||||
websiteId={websiteId}
|
||||
sessionId={sessionId}
|
||||
startDate={data?.firstAt}
|
||||
endDate={data?.lastAt}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel id="properties">
|
||||
<SessionData sessionId={sessionId} websiteId={websiteId} />
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</Column>
|
||||
</Column>
|
||||
)}
|
||||
</LoadingPanel>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue