mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Fixed realtime page.
This commit is contained in:
parent
65ebd736b9
commit
c1d301ffdc
12 changed files with 83 additions and 450 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { Grid, Heading, Column } from '@umami/react-zen';
|
||||
import { Grid, Heading, Column, Row } from '@umami/react-zen';
|
||||
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
|
||||
import { SideBar } from '@/components/common/SideBar';
|
||||
import { BrowsersTable } from '@/components/metrics/BrowsersTable';
|
||||
|
|
@ -21,6 +21,7 @@ import { formatNumber } from '@/lib/format';
|
|||
import { useState } from 'react';
|
||||
import { useWebsites } from '@/store/websites';
|
||||
import { Panel } from '@/components/common/Panel';
|
||||
import { DateDisplay } from '@/components/common/DateDisplay';
|
||||
|
||||
const views = {
|
||||
url: PagesTable,
|
||||
|
|
@ -144,10 +145,13 @@ export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
|
|||
|
||||
return (
|
||||
<Panel>
|
||||
<Grid columns="200px 1fr 1fr" gap="6">
|
||||
<Grid columns={{ xs: '1fr', lg: '200px 1fr 1fr' }} gap="6">
|
||||
<SideBar items={items} selectedKey={view} />
|
||||
<Column>
|
||||
<Heading size="1">{formatMessage(labels.previous)}</Heading>
|
||||
<Column border="left" paddingLeft="6">
|
||||
<Row alignItems="center" justifyContent="space-between">
|
||||
<Heading size="1">{formatMessage(labels.previous)}</Heading>
|
||||
<DateDisplay startDate={startDate} endDate={endDate} />
|
||||
</Row>
|
||||
<Component
|
||||
websiteId={websiteId}
|
||||
limit={20}
|
||||
|
|
@ -157,7 +161,10 @@ export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
|
|||
/>
|
||||
</Column>
|
||||
<Column>
|
||||
<Heading size="1"> {formatMessage(labels.current)}</Heading>
|
||||
<Row alignItems="center" justifyContent="space-between">
|
||||
<Heading size="1"> {formatMessage(labels.current)}</Heading>
|
||||
<DateDisplay startDate={dateRange.startDate} endDate={dateRange.endDate} />
|
||||
</Row>
|
||||
<Component
|
||||
websiteId={websiteId}
|
||||
limit={20}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export function EventsPage({ websiteId }) {
|
|||
/>
|
||||
</Panel>
|
||||
</GridRow>
|
||||
<Panel marginY="6">
|
||||
<Panel>
|
||||
<Tabs selectedKey={tab} onSelectionChange={(value: any) => setTab(value)}>
|
||||
<TabList>
|
||||
<Tab id="activity">{formatMessage(labels.activity)}</Tab>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Key, useContext, useState } from 'react';
|
||||
import { useContext, useState } from 'react';
|
||||
import { Row } from '@umami/react-zen';
|
||||
import thenby from 'thenby';
|
||||
import { percentFilter } from '@/lib/filters';
|
||||
import { ListTable } from '@/components/metrics/ListTable';
|
||||
|
|
@ -12,19 +13,17 @@ export function RealtimeUrls({ data }: { data: RealtimeData }) {
|
|||
const website = useContext(WebsiteContext);
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { referrers, urls } = data || {};
|
||||
const [filter, setFilter] = useState<Key>(FILTER_REFERRERS);
|
||||
const [filter, setFilter] = useState(FILTER_REFERRERS);
|
||||
const limit = 15;
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
id: 1,
|
||||
id: FILTER_REFERRERS,
|
||||
label: formatMessage(labels.referrers),
|
||||
key: FILTER_REFERRERS,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
id: FILTER_PAGES,
|
||||
label: formatMessage(labels.pages),
|
||||
key: FILTER_PAGES,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -63,7 +62,9 @@ export function RealtimeUrls({ data }: { data: RealtimeData }) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<FilterButtons items={buttons} onSelect={setFilter} />
|
||||
<Row justifyContent="center">
|
||||
<FilterButtons items={buttons} value={filter} onChange={setFilter} />
|
||||
</Row>
|
||||
{filter === FILTER_REFERRERS && (
|
||||
<ListTable
|
||||
title={formatMessage(labels.referrers)}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export function WebsiteRealtimePage({ websiteId }: { websiteId: string }) {
|
|||
<Panel>
|
||||
<RealtimeChart data={data} unit="minute" />
|
||||
</Panel>
|
||||
<GridRow layout="one-two">
|
||||
<GridRow layout="two">
|
||||
<Panel>
|
||||
<RealtimeUrls data={data} />
|
||||
</Panel>
|
||||
|
|
@ -48,7 +48,7 @@ export function WebsiteRealtimePage({ websiteId }: { websiteId: string }) {
|
|||
<Panel>
|
||||
<RealtimeCountries data={countries} />
|
||||
</Panel>
|
||||
<Panel padding="0">
|
||||
<Panel padding="0" gridColumn="span 2">
|
||||
<WorldMap data={countries} />
|
||||
</Panel>
|
||||
</GridRow>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export function SessionsPage({ websiteId }) {
|
|||
<SessionsWeekly websiteId={websiteId} />
|
||||
</Panel>
|
||||
</GridRow>
|
||||
<Panel marginY="6">
|
||||
<Panel>
|
||||
<Tabs selectedKey={tab} onSelectionChange={(value: any) => setTab(value)}>
|
||||
<TabList>
|
||||
<Tab id="activity">{formatMessage(labels.activity)}</Tab>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export function BarChart(props: BarChartProps) {
|
|||
type: YAxisType,
|
||||
min: 0,
|
||||
beginAtZero: true,
|
||||
stacked,
|
||||
stacked: !!stacked,
|
||||
grid: {
|
||||
color: colors.chart.line,
|
||||
},
|
||||
|
|
|
|||
28
src/components/common/DateDisplay.tsx
Normal file
28
src/components/common/DateDisplay.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { Icon, Row, Text } from '@umami/react-zen';
|
||||
import { differenceInDays, isSameDay } from 'date-fns';
|
||||
import { useLocale } from '@/components/hooks';
|
||||
import { Icons } from '@/components/icons';
|
||||
import { formatDate } from '@/lib/date';
|
||||
|
||||
export function DateDisplay({ startDate, endDate }) {
|
||||
const { locale } = useLocale();
|
||||
const isSingleDate = differenceInDays(endDate, startDate) === 0;
|
||||
|
||||
return (
|
||||
<Row gap="3" alignItems="center" wrap="nowrap">
|
||||
<Icon>
|
||||
<Icons.Calendar />
|
||||
</Icon>
|
||||
<Text wrap="nowrap">
|
||||
{isSingleDate ? (
|
||||
<>{formatDate(startDate, 'PP', locale)}</>
|
||||
) : (
|
||||
<>
|
||||
{formatDate(startDate, 'PP', locale)}
|
||||
{!isSameDay(startDate, endDate) && ` — ${formatDate(endDate, 'PP', locale)}`}
|
||||
</>
|
||||
)}
|
||||
</Text>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from 'react';
|
||||
import { ToggleGroup, ToggleGroupItem } from '@umami/react-zen';
|
||||
import { ToggleGroup, ToggleGroupItem, Box } from '@umami/react-zen';
|
||||
|
||||
export interface FilterButtonsProps {
|
||||
items: { id: string; label: string }[];
|
||||
|
|
@ -16,12 +16,18 @@ export function FilterButtons({ items, value, onChange }: FilterButtonsProps) {
|
|||
};
|
||||
|
||||
return (
|
||||
<ToggleGroup value={[selected]} onChange={e => handleChange(e[0])}>
|
||||
{items.map(({ id, label }) => (
|
||||
<ToggleGroupItem key={id} id={id}>
|
||||
{label}
|
||||
</ToggleGroupItem>
|
||||
))}
|
||||
</ToggleGroup>
|
||||
<Box>
|
||||
<ToggleGroup
|
||||
value={[selected]}
|
||||
onChange={e => handleChange(e[0])}
|
||||
disallowEmptySelection={true}
|
||||
>
|
||||
{items.map(({ id, label }) => (
|
||||
<ToggleGroupItem key={id} id={id}>
|
||||
{label}
|
||||
</ToggleGroupItem>
|
||||
))}
|
||||
</ToggleGroup>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { useState, Key, Fragment } from 'react';
|
||||
import { Icon, Modal, Select, Text, Row, ListItem, ListSeparator, Dialog } from '@umami/react-zen';
|
||||
import { differenceInDays, endOfYear, isSameDay } from 'date-fns';
|
||||
import { Modal, Select, ListItem, ListSeparator, Dialog } from '@umami/react-zen';
|
||||
import { endOfYear } from 'date-fns';
|
||||
import { DatePickerForm } from '@/components/metrics/DatePickerForm';
|
||||
import { useLocale, useMessages } from '@/components/hooks';
|
||||
import { Icons } from '@/components/icons';
|
||||
import { formatDate } from '@/lib/date';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { DateDisplay } from '@/components/common/DateDisplay';
|
||||
|
||||
export interface DateFilterProps {
|
||||
value: string;
|
||||
|
|
@ -94,11 +93,7 @@ export function DateFilter({
|
|||
|
||||
const renderValue = ({ defaultChildren }) => {
|
||||
return value.startsWith('range') ? (
|
||||
<CustomRange
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
isSingleDate={differenceInDays(endDate, startDate) === 0}
|
||||
/>
|
||||
<DateDisplay startDate={startDate} endDate={endDate} />
|
||||
) : (
|
||||
defaultChildren
|
||||
);
|
||||
|
|
@ -139,25 +134,3 @@ export function DateFilter({
|
|||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const CustomRange = ({ startDate, endDate, isSingleDate }) => {
|
||||
const { locale } = useLocale();
|
||||
|
||||
return (
|
||||
<Row gap="3" alignItems="center" wrap="nowrap">
|
||||
<Icon>
|
||||
<Icons.Calendar />
|
||||
</Icon>
|
||||
<Text wrap="nowrap">
|
||||
{isSingleDate ? (
|
||||
<>{formatDate(startDate, 'PP', locale)}</>
|
||||
) : (
|
||||
<>
|
||||
{formatDate(startDate, 'PP', locale)}
|
||||
{!isSameDay(startDate, endDate) && ` — ${formatDate(endDate, 'PP', locale)}`}
|
||||
</>
|
||||
)}
|
||||
</Text>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,6 +62,6 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promis
|
|||
order by createdAt asc
|
||||
limit 100
|
||||
`,
|
||||
params,
|
||||
{ ...filters, ...params },
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue