mirror of
https://github.com/umami-software/umami.git
synced 2026-02-11 16:17:13 +01:00
Updated grid layouts. Fixed chart tooltip.
This commit is contained in:
parent
96c2c32d14
commit
1d24e23a34
9 changed files with 64 additions and 79 deletions
|
|
@ -10,15 +10,17 @@ import { WebsiteMenu } from '@/app/(main)/websites/[websiteId]/WebsiteMenu';
|
|||
import { WebsiteCompareBar } from '@/app/(main)/websites/[websiteId]/WebsiteCompareBar';
|
||||
|
||||
export function WebsiteHeader({
|
||||
websiteId,
|
||||
showFilter = true,
|
||||
allowEdit = true,
|
||||
}: {
|
||||
websiteId: string;
|
||||
showFilter?: boolean;
|
||||
allowEdit?: boolean;
|
||||
compareMode?: boolean;
|
||||
}) {
|
||||
const website = useWebsite();
|
||||
const { id: websiteId, name, domain } = website || {};
|
||||
const { name, domain } = website || {};
|
||||
|
||||
return (
|
||||
<Column marginY="6" gap="6">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Grid } from '@umami/react-zen';
|
||||
import { GridRow } from '@/components/common/GridRow';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { PagesTable } from '@/components/metrics/PagesTable';
|
||||
import { ReferrersTable } from '@/components/metrics/ReferrersTable';
|
||||
|
|
@ -7,57 +8,37 @@ import { OSTable } from '@/components/metrics/OSTable';
|
|||
import { DevicesTable } from '@/components/metrics/DevicesTable';
|
||||
import { WorldMap } from '@/components/metrics/WorldMap';
|
||||
import { CountriesTable } from '@/components/metrics/CountriesTable';
|
||||
import { EventsTable } from '@/components/metrics/EventsTable';
|
||||
import { EventsChart } from '@/components/metrics/EventsChart';
|
||||
import { usePathname } from 'next/navigation';
|
||||
|
||||
export function WebsiteTableView({ websiteId }: { websiteId: string }) {
|
||||
const pathname = usePathname();
|
||||
const tableProps = {
|
||||
websiteId,
|
||||
limit: 10,
|
||||
};
|
||||
const isSharePage = pathname.includes('/share/');
|
||||
|
||||
return (
|
||||
<Grid gap="3">
|
||||
<Grid gap="3" columns="repeat(auto-fill, minmax(500px, 1fr))">
|
||||
<GridRow layout="two">
|
||||
<Panel>
|
||||
<PagesTable {...tableProps} />
|
||||
<PagesTable websiteId={websiteId} limit={10} />
|
||||
</Panel>
|
||||
<Panel>
|
||||
<ReferrersTable {...tableProps} />
|
||||
<ReferrersTable websiteId={websiteId} limit={10} />
|
||||
</Panel>
|
||||
</Grid>
|
||||
<Grid gap="3" columns="repeat(auto-fill, minmax(400px, 1fr))">
|
||||
</GridRow>
|
||||
<GridRow layout="three">
|
||||
<Panel>
|
||||
<BrowsersTable {...tableProps} />
|
||||
<BrowsersTable websiteId={websiteId} limit={10} />
|
||||
</Panel>
|
||||
<Panel>
|
||||
<OSTable {...tableProps} />
|
||||
<OSTable websiteId={websiteId} limit={10} />
|
||||
</Panel>
|
||||
<Panel>
|
||||
<DevicesTable {...tableProps} />
|
||||
<DevicesTable websiteId={websiteId} limit={10} />
|
||||
</Panel>
|
||||
</Grid>
|
||||
<Grid gap="3" columns="2fr 1fr">
|
||||
<Panel padding="0">
|
||||
</GridRow>
|
||||
<GridRow layout="two-one">
|
||||
<Panel padding="0" gridColumn="span 2">
|
||||
<WorldMap websiteId={websiteId} />
|
||||
</Panel>
|
||||
<Panel>
|
||||
<CountriesTable {...tableProps} />
|
||||
<CountriesTable websiteId={websiteId} limit={10} />
|
||||
</Panel>
|
||||
</Grid>
|
||||
{isSharePage && (
|
||||
<Grid gap="3">
|
||||
<Panel>
|
||||
<EventsTable {...tableProps} />
|
||||
</Panel>
|
||||
<Panel>
|
||||
<EventsChart websiteId={websiteId} />
|
||||
</Panel>
|
||||
</Grid>
|
||||
)}
|
||||
</GridRow>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,19 +82,19 @@ export function BarChart(props: BarChartProps) {
|
|||
const handleTooltip = ({ tooltip }: { tooltip: any }) => {
|
||||
const { opacity } = tooltip;
|
||||
|
||||
setTooltip(
|
||||
opacity ? <BarChartTooltip tooltip={tooltip} unit={unit} currency={currency} /> : null,
|
||||
);
|
||||
setTooltip(opacity ? tooltip : null);
|
||||
};
|
||||
|
||||
return (
|
||||
<Chart
|
||||
{...props}
|
||||
type="bar"
|
||||
chartOptions={options}
|
||||
tooltip={tooltip}
|
||||
onTooltip={handleTooltip}
|
||||
style={{ height: 400 }}
|
||||
/>
|
||||
<>
|
||||
<Chart
|
||||
{...props}
|
||||
type="bar"
|
||||
chartOptions={options}
|
||||
onTooltip={handleTooltip}
|
||||
style={{ height: 400 }}
|
||||
/>
|
||||
{tooltip && <BarChartTooltip tooltip={tooltip} unit={unit} currency={currency} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useRef, useEffect, useMemo, ReactNode, HTMLAttributes } from 'react';
|
||||
import { useState, useRef, useEffect, useMemo, HTMLAttributes } from 'react';
|
||||
import { Loading } from '@umami/react-zen';
|
||||
import ChartJS, { LegendItem, ChartOptions } from 'chart.js/auto';
|
||||
import { Legend } from '@/components/metrics/Legend';
|
||||
|
|
@ -14,7 +14,6 @@ export interface ChartProps extends HTMLAttributes<HTMLDivElement> {
|
|||
onUpdate?: (chart: any) => void;
|
||||
onTooltip?: (model: any) => void;
|
||||
chartOptions?: ChartOptions;
|
||||
tooltip?: ReactNode;
|
||||
}
|
||||
|
||||
export function Chart({
|
||||
|
|
@ -27,7 +26,6 @@ export function Chart({
|
|||
onUpdate,
|
||||
onTooltip,
|
||||
chartOptions,
|
||||
tooltip,
|
||||
...props
|
||||
}: ChartProps) {
|
||||
const canvas = useRef(null);
|
||||
|
|
@ -53,6 +51,7 @@ export function Chart({
|
|||
},
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
intersect: true,
|
||||
external: onTooltip,
|
||||
},
|
||||
},
|
||||
|
|
@ -139,7 +138,6 @@ export function Chart({
|
|||
<canvas ref={canvas} />
|
||||
</div>
|
||||
<Legend items={legendItems} onClick={handleLegendClick} />
|
||||
{tooltip}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,20 @@ import { Grid } from '@umami/react-zen';
|
|||
|
||||
const LAYOUTS = {
|
||||
one: { columns: '1fr' },
|
||||
two: { columns: { xs: '1fr', sm: '1fr', md: '1fr 1fr', lg: '1fr 1fr' } },
|
||||
three: { columns: { xs: '1fr', sm: '1fr', md: '1fr 1fr 1fr', lg: '1fr 2fr' } },
|
||||
'one-two': { columns: { xs: '1fr', sm: '1fr', md: '1fr 2fr', lg: '1fr 2fr' } },
|
||||
'two-one': { columns: { xs: '1fr', sm: '1fr', md: '2fr 1fr', lg: '2fr 1fr', xl: '2fr 1fr' } },
|
||||
two: {
|
||||
columns: {
|
||||
xs: '1fr',
|
||||
md: 'repeat(auto-fill, minmax(600px, 1fr))',
|
||||
},
|
||||
},
|
||||
three: {
|
||||
columns: {
|
||||
xs: '1fr',
|
||||
md: 'repeat(auto-fill, minmax(400px, 1fr))',
|
||||
},
|
||||
},
|
||||
'one-two': { columns: { xs: '1fr', lg: 'repeat(3, 1fr)' } },
|
||||
'two-one': { columns: { xs: '1fr', lg: 'repeat(3, 1fr)' } },
|
||||
};
|
||||
|
||||
export function GridRow(props: {
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ export function TypeIcon({
|
|||
return (
|
||||
<Row gap="3" alignItems="center">
|
||||
<img
|
||||
src={`${process.env.basePath || ''}/images/${type}/${value
|
||||
?.replaceAll(' ', '-')
|
||||
.toLowerCase()}.png`}
|
||||
src={`${process.env.basePath || ''}/images/${type}/${
|
||||
value?.replaceAll(' ', '-').toLowerCase() || 'xx'
|
||||
}.png`}
|
||||
onError={e => {
|
||||
e.currentTarget.src = `${process.env.basePath || ''}/images/${type}/unknown.png`;
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from 'react';
|
||||
import { Key } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import {
|
||||
Text,
|
||||
|
|
@ -30,16 +30,10 @@ export function TeamsButton({
|
|||
const { teamId } = useNavigation();
|
||||
const router = useRouter();
|
||||
const team = result?.data?.find(({ id }) => id === teamId);
|
||||
const [selectedKeys, setSelectedKeys] = useState<any>(new Set([teamId || user.id]));
|
||||
const selectedKeys = new Set([teamId || user.id]);
|
||||
|
||||
const handleSelect = (keys: Set<string>) => {
|
||||
if (keys.size > 0) {
|
||||
const [id] = [...keys];
|
||||
|
||||
router.push(id === user.id ? '/dashboard' : `/teams/${id}/dashboard`);
|
||||
|
||||
setSelectedKeys(keys);
|
||||
}
|
||||
const handleSelect = (id: Key) => {
|
||||
router.push(id === user.id ? '/dashboard' : `/teams/${id}/dashboard`);
|
||||
};
|
||||
|
||||
if (!result?.count) {
|
||||
|
|
@ -63,7 +57,7 @@ export function TeamsButton({
|
|||
selectionMode="single"
|
||||
selectedKeys={selectedKeys}
|
||||
autoFocus="last"
|
||||
onSelectionChange={keys => handleSelect(keys as Set<string>)}
|
||||
onAction={handleSelect}
|
||||
>
|
||||
<MenuSection title={formatMessage(labels.myAccount)}>
|
||||
<MenuItem id={user.id}>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue