mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Responsive updates.
This commit is contained in:
parent
e4ce7c9071
commit
8aa4192576
14 changed files with 976 additions and 917 deletions
|
|
@ -78,7 +78,7 @@
|
||||||
"@react-spring/web": "^10.0.3",
|
"@react-spring/web": "^10.0.3",
|
||||||
"@svgr/cli": "^8.1.0",
|
"@svgr/cli": "^8.1.0",
|
||||||
"@tanstack/react-query": "^5.90.2",
|
"@tanstack/react-query": "^5.90.2",
|
||||||
"@umami/react-zen": "^0.187.0",
|
"@umami/react-zen": "^0.189.0",
|
||||||
"@umami/redis-client": "^0.29.0",
|
"@umami/redis-client": "^0.29.0",
|
||||||
"bcryptjs": "^3.0.2",
|
"bcryptjs": "^3.0.2",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
|
|
|
||||||
1774
pnpm-lock.yaml
generated
1774
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -55,7 +55,7 @@ export function LinkPanels({ linkId }: { linkId: string }) {
|
||||||
</Panel>
|
</Panel>
|
||||||
</GridRow>
|
</GridRow>
|
||||||
<GridRow layout="two" {...rowProps}>
|
<GridRow layout="two" {...rowProps}>
|
||||||
<Panel noPadding>
|
<Panel padding="0">
|
||||||
<WorldMap websiteId={linkId} />
|
<WorldMap websiteId={linkId} />
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel>
|
<Panel>
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export function PixelPanels({ pixelId }: { pixelId: string }) {
|
||||||
</Panel>
|
</Panel>
|
||||||
</GridRow>
|
</GridRow>
|
||||||
<GridRow layout="two" {...rowProps}>
|
<GridRow layout="two" {...rowProps}>
|
||||||
<Panel noPadding>
|
<Panel padding="0">
|
||||||
<WorldMap websiteId={pixelId} />
|
<WorldMap websiteId={pixelId} />
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel>
|
<Panel>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Column, Row } from '@umami/react-zen';
|
import { Column, Row, Grid } from '@umami/react-zen';
|
||||||
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
||||||
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
|
||||||
import { FilterBar } from '@/components/input/FilterBar';
|
import { FilterBar } from '@/components/input/FilterBar';
|
||||||
|
|
@ -22,12 +22,18 @@ export function WebsiteControls({
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Column gap>
|
<Column gap>
|
||||||
<Row alignItems="center" justifyContent="space-between" gap="3">
|
<Grid columns={{ xs: '1fr', md: 'auto 1fr' }} gap>
|
||||||
{allowFilter ? <WebsiteFilterButton websiteId={websiteId} /> : <div />}
|
<Row alignItems="center" justifyContent="flex-end">
|
||||||
{allowDateFilter && <WebsiteDateFilter websiteId={websiteId} allowCompare={allowCompare} />}
|
{allowFilter ? <WebsiteFilterButton websiteId={websiteId} /> : <div />}
|
||||||
{allowDownload && <ExportButton websiteId={websiteId} />}
|
</Row>
|
||||||
{allowMonthFilter && <MonthFilter />}
|
<Row alignItems="center" justifyContent="flex-end">
|
||||||
</Row>
|
{allowDateFilter && (
|
||||||
|
<WebsiteDateFilter websiteId={websiteId} allowCompare={allowCompare} />
|
||||||
|
)}
|
||||||
|
{allowDownload && <ExportButton websiteId={websiteId} />}
|
||||||
|
{allowMonthFilter && <MonthFilter />}
|
||||||
|
</Row>
|
||||||
|
</Grid>
|
||||||
{allowFilter && <FilterBar websiteId={websiteId} />}
|
{allowFilter && <FilterBar websiteId={websiteId} />}
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,11 @@ export function WebsiteHeader({ showActions }: { showActions?: boolean }) {
|
||||||
<ActiveUsers websiteId={website.id} />
|
<ActiveUsers websiteId={website.id} />
|
||||||
|
|
||||||
{showActions && (
|
{showActions && (
|
||||||
<Row alignItems="center" gap>
|
<Row
|
||||||
|
display={{ xs: 'none', sm: 'none', md: 'none', lg: 'flex', xl: 'flex' }}
|
||||||
|
alignItems="center"
|
||||||
|
gap
|
||||||
|
>
|
||||||
<ShareButton websiteId={website.id} shareId={website.shareId} />
|
<ShareButton websiteId={website.id} shareId={website.shareId} />
|
||||||
<LinkButton href={renderUrl(`/websites/${website.id}/settings`, false)}>
|
<LinkButton href={renderUrl(`/websites/${website.id}/settings`, false)}>
|
||||||
<Icon>
|
<Icon>
|
||||||
|
|
|
||||||
|
|
@ -2,24 +2,23 @@
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { Column, Grid } from '@umami/react-zen';
|
import { Column, Grid } from '@umami/react-zen';
|
||||||
import { WebsiteProvider } from '@/app/(main)/websites/WebsiteProvider';
|
import { WebsiteProvider } from '@/app/(main)/websites/WebsiteProvider';
|
||||||
import { useNavigation } from '@/components/hooks';
|
|
||||||
import { PageBody } from '@/components/common/PageBody';
|
import { PageBody } from '@/components/common/PageBody';
|
||||||
import { WebsiteHeader } from './WebsiteHeader';
|
import { WebsiteHeader } from './WebsiteHeader';
|
||||||
import { WebsiteNav } from './WebsiteNav';
|
import { WebsiteNav } from './WebsiteNav';
|
||||||
|
|
||||||
export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) {
|
export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) {
|
||||||
const { pathname } = useNavigation();
|
|
||||||
|
|
||||||
const isSettings = pathname.endsWith('/settings');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WebsiteProvider websiteId={websiteId}>
|
<WebsiteProvider websiteId={websiteId}>
|
||||||
<Grid columns={isSettings ? '1fr' : 'auto 1fr'} width="100%" height="100%">
|
<Grid columns={{ xs: '1fr', lg: 'auto 1fr' }} width="100%" height="100%">
|
||||||
{!isSettings && (
|
<Column
|
||||||
<Column height="100%" border="right" backgroundColor marginRight="2">
|
display={{ xs: 'none', lg: 'flex' }}
|
||||||
<WebsiteNav websiteId={websiteId} />
|
height="100%"
|
||||||
</Column>
|
border="right"
|
||||||
)}
|
backgroundColor
|
||||||
|
marginRight="2"
|
||||||
|
>
|
||||||
|
<WebsiteNav websiteId={websiteId} />
|
||||||
|
</Column>
|
||||||
<PageBody gap>
|
<PageBody gap>
|
||||||
<WebsiteHeader showActions />
|
<WebsiteHeader showActions />
|
||||||
<Column>{children}</Column>
|
<Column>{children}</Column>
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ export function WebsitePanels({ websiteId }: { websiteId: string }) {
|
||||||
</GridRow>
|
</GridRow>
|
||||||
|
|
||||||
<GridRow layout="two-one" {...rowProps}>
|
<GridRow layout="two-one" {...rowProps}>
|
||||||
<Panel gridColumn="span 2" noPadding>
|
<Panel gridColumn={{ xs: 'span 1', md: 'span 2' }} padding="0">
|
||||||
<WorldMap websiteId={websiteId} />
|
<WorldMap websiteId={websiteId} />
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
||||||
|
|
@ -130,7 +130,7 @@ export function WebsitePanels({ websiteId }: { websiteId: string }) {
|
||||||
filterLink={false}
|
filterLink={false}
|
||||||
/>
|
/>
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel gridColumn="span 2">
|
<Panel gridColumn={{ xs: 'span 1', md: 'span 2' }}>
|
||||||
<EventsChart websiteId={websiteId} />
|
<EventsChart websiteId={websiteId} />
|
||||||
</Panel>
|
</Panel>
|
||||||
</GridRow>
|
</GridRow>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ export function RealtimePage({ websiteId }: { websiteId: string }) {
|
||||||
<Panel>
|
<Panel>
|
||||||
<RealtimeCountries data={countries} />
|
<RealtimeCountries data={countries} />
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel gridColumn="span 2" noPadding>
|
<Panel gridColumn="span 2" padding="0">
|
||||||
<WorldMap data={countries} />
|
<WorldMap data={countries} />
|
||||||
</Panel>
|
</Panel>
|
||||||
</GridRow>
|
</GridRow>
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,11 @@ const LAYOUTS = {
|
||||||
md: 'repeat(auto-fill, minmax(360px, 1fr))',
|
md: 'repeat(auto-fill, minmax(360px, 1fr))',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'one-two': { columns: { xs: '1fr', lg: 'repeat(3, 1fr)' } },
|
'one-two': { columns: { xs: '1fr', md: 'repeat(3, 1fr)' } },
|
||||||
'two-one': { columns: { xs: '1fr', lg: 'repeat(3, 1fr)' } },
|
'two-one': { columns: { xs: '1fr', md: 'repeat(3, 1fr)' } },
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GridRow(props: {
|
export function GridRow(props: {
|
||||||
[x: string]: any;
|
|
||||||
layout?: 'one' | 'two' | 'three' | 'one-two' | 'two-one' | 'compare';
|
layout?: 'one' | 'two' | 'three' | 'one-two' | 'two-one' | 'compare';
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: any;
|
children?: any;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,14 @@ export function PageBody({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column {...props} width="100%" paddingBottom="9" style={{ margin: '0 auto', maxWidth }}>
|
<Column
|
||||||
|
{...props}
|
||||||
|
width="100%"
|
||||||
|
paddingBottom="9"
|
||||||
|
maxWidth={maxWidth}
|
||||||
|
paddingX="4"
|
||||||
|
style={{ margin: '0 auto' }}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import { useMessages } from '@/components/hooks';
|
||||||
export interface PanelProps extends ColumnProps {
|
export interface PanelProps extends ColumnProps {
|
||||||
title?: string;
|
title?: string;
|
||||||
allowFullscreen?: boolean;
|
allowFullscreen?: boolean;
|
||||||
noPadding?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullscreenStyles = {
|
const fullscreenStyles = {
|
||||||
|
|
@ -28,14 +27,7 @@ const fullscreenStyles = {
|
||||||
zIndex: 9999,
|
zIndex: 9999,
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
export function Panel({
|
export function Panel({ title, allowFullscreen, style, children, ...props }: PanelProps) {
|
||||||
title,
|
|
||||||
allowFullscreen,
|
|
||||||
noPadding,
|
|
||||||
style,
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: PanelProps) {
|
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
|
|
||||||
|
|
@ -45,7 +37,7 @@ export function Panel({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column
|
<Column
|
||||||
padding={!noPadding ? '6' : undefined}
|
padding={{ xs: '3', md: '6' }}
|
||||||
border
|
border
|
||||||
borderRadius="3"
|
borderRadius="3"
|
||||||
backgroundColor
|
backgroundColor
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export interface MetricsBarProps extends GridProps {
|
||||||
|
|
||||||
export function MetricsBar({ children, ...props }: MetricsBarProps) {
|
export function MetricsBar({ children, ...props }: MetricsBarProps) {
|
||||||
return (
|
return (
|
||||||
<Grid columns="repeat(auto-fit, minmax(200px, 1fr))" gap {...props}>
|
<Grid columns="repeat(auto-fit, minmax(170px, 1fr))" gap {...props}>
|
||||||
{children}
|
{children}
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
|
import { useEffect, useMemo } from 'react';
|
||||||
|
import { Icon, Text, Row, Grid } from '@umami/react-zen';
|
||||||
import { LinkButton } from '@/components/common/LinkButton';
|
import { LinkButton } from '@/components/common/LinkButton';
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
import { useMessages, useNavigation, useWebsiteMetricsQuery } from '@/components/hooks';
|
import { useMessages, useNavigation, useWebsiteMetricsQuery } from '@/components/hooks';
|
||||||
import { Maximize } from '@/components/icons';
|
import { Maximize } from '@/components/icons';
|
||||||
import { MetricLabel } from '@/components/metrics/MetricLabel';
|
import { MetricLabel } from '@/components/metrics/MetricLabel';
|
||||||
import { percentFilter } from '@/lib/filters';
|
import { percentFilter } from '@/lib/filters';
|
||||||
import { Icon, Row, Text } from '@umami/react-zen';
|
|
||||||
import { useEffect, useMemo } from 'react';
|
|
||||||
import { ListTable, ListTableProps } from './ListTable';
|
import { ListTable, ListTableProps } from './ListTable';
|
||||||
|
|
||||||
export interface MetricsTableProps extends ListTableProps {
|
export interface MetricsTableProps extends ListTableProps {
|
||||||
|
|
@ -77,21 +77,19 @@ export function MetricsTable({
|
||||||
error={error}
|
error={error}
|
||||||
minHeight="400px"
|
minHeight="400px"
|
||||||
>
|
>
|
||||||
<div style={{ display: 'grid', gridTemplateRows: '1fr auto', minHeight: '400px' }}>
|
<Grid>
|
||||||
<div>{data && <ListTable {...props} data={filteredData} renderLabel={renderLabel} />}</div>
|
{data && <ListTable {...props} data={filteredData} renderLabel={renderLabel} />}
|
||||||
<div>
|
{showMore && limit && (
|
||||||
{showMore && limit && (
|
<Row justifyContent="center" alignItems="flex-end">
|
||||||
<Row justifyContent="center" alignItems="flex-end">
|
<LinkButton href={updateParams({ view: type })} variant="quiet">
|
||||||
<LinkButton href={updateParams({ view: type })} variant="quiet">
|
<Icon size="sm">
|
||||||
<Icon size="sm">
|
<Maximize />
|
||||||
<Maximize />
|
</Icon>
|
||||||
</Icon>
|
<Text>{formatMessage(labels.more)}</Text>
|
||||||
<Text>{formatMessage(labels.more)}</Text>
|
</LinkButton>
|
||||||
</LinkButton>
|
</Row>
|
||||||
</Row>
|
)}
|
||||||
)}
|
</Grid>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</LoadingPanel>
|
</LoadingPanel>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue