mirror of
https://github.com/umami-software/umami.git
synced 2025-12-08 05:12:36 +01:00
Updated date range handling.
This commit is contained in:
parent
6d1603fa28
commit
5ca51b3e8f
19 changed files with 101 additions and 99 deletions
|
|
@ -80,7 +80,7 @@
|
|||
"@react-spring/web": "^9.7.3",
|
||||
"@svgr/cli": "^8.1.0",
|
||||
"@tanstack/react-query": "^5.80.10",
|
||||
"@umami/react-zen": "^0.139.0",
|
||||
"@umami/react-zen": "^0.142.0",
|
||||
"@umami/redis-client": "^0.27.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"chalk": "^4.1.1",
|
||||
|
|
|
|||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
|
|
@ -45,8 +45,8 @@ importers:
|
|||
specifier: ^5.80.10
|
||||
version: 5.80.10(react@19.1.0)
|
||||
'@umami/react-zen':
|
||||
specifier: ^0.139.0
|
||||
version: 0.139.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))
|
||||
specifier: ^0.142.0
|
||||
version: 0.142.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))
|
||||
'@umami/redis-client':
|
||||
specifier: ^0.27.0
|
||||
version: 0.27.0
|
||||
|
|
@ -2549,8 +2549,8 @@ packages:
|
|||
resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@umami/react-zen@0.139.0':
|
||||
resolution: {integrity: sha512-NRf27+05z78DLFxK3aQUBfhZW7covl6qtS4OcaBUbZ71VZ7eeRVg7SU7Cn3NvkXlcI16t6bbLXGW4HjvfBhXsw==}
|
||||
'@umami/react-zen@0.142.0':
|
||||
resolution: {integrity: sha512-xD0O96c1AsztIbD8DZOszBeXAmEhVJ1isqsms+Nu/Kzf4vkWhEPpu7dbhntroHiA7JLK/uI1bgYHQMJFMM1f4w==}
|
||||
|
||||
'@umami/redis-client@0.27.0':
|
||||
resolution: {integrity: sha512-SbHTpxhgeZyTBUSp2zdZM+XUtpsaSL4Tad8QXIEhEtjWhvvfoornyT5kLuyYCVtzSAT4daALeGmOO1z6EE1KcA==}
|
||||
|
|
@ -9733,7 +9733,7 @@ snapshots:
|
|||
'@typescript-eslint/types': 8.34.1
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
'@umami/react-zen@0.139.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))':
|
||||
'@umami/react-zen@0.142.0(@babel/core@7.27.1)(@types/react@19.1.8)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@9.0.21)(use-sync-external-store@1.5.0(react@19.1.0))':
|
||||
dependencies:
|
||||
'@fontsource/jetbrains-mono': 5.2.6
|
||||
'@internationalized/date': 3.8.2
|
||||
|
|
|
|||
|
|
@ -19,32 +19,32 @@ export function SideNav(props: any) {
|
|||
const links = [
|
||||
{
|
||||
label: formatMessage(labels.websites),
|
||||
href: renderUrl('/websites'),
|
||||
href: '/websites',
|
||||
icon: <Globe />,
|
||||
},
|
||||
{
|
||||
label: formatMessage(labels.boards),
|
||||
href: renderUrl('/boards'),
|
||||
href: '/boards',
|
||||
icon: <LayoutDashboard />,
|
||||
},
|
||||
{
|
||||
label: formatMessage(labels.links),
|
||||
href: renderUrl('/links'),
|
||||
href: '/links',
|
||||
icon: <LinkIcon />,
|
||||
},
|
||||
{
|
||||
label: formatMessage(labels.pixels),
|
||||
href: renderUrl('/pixels'),
|
||||
href: '/pixels',
|
||||
icon: <Grid2X2 />,
|
||||
},
|
||||
{
|
||||
label: formatMessage(labels.settings),
|
||||
href: renderUrl('/settings'),
|
||||
href: '/settings',
|
||||
icon: <Settings />,
|
||||
},
|
||||
{
|
||||
label: formatMessage(labels.admin),
|
||||
href: renderUrl('/admin'),
|
||||
href: '/admin',
|
||||
icon: <LockKeyhole />,
|
||||
},
|
||||
].filter(n => n);
|
||||
|
|
@ -57,7 +57,7 @@ export function SideNav(props: any) {
|
|||
<SidebarSection>
|
||||
{links.map(({ href, label, icon }) => {
|
||||
return (
|
||||
<Link key={href} href={href} role="button">
|
||||
<Link key={href} href={renderUrl(href, false)} role="button">
|
||||
<SidebarItem label={label} icon={icon} isSelected={pathname.startsWith(href)} />
|
||||
</Link>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
import { DateFilter } from '@/components/input/DateFilter';
|
||||
import { Button, Row } from '@umami/react-zen';
|
||||
import { useDateRange, useMessages } from '@/components/hooks';
|
||||
import { DEFAULT_DATE_RANGE } from '@/lib/constants';
|
||||
import { DateRange } from '@/lib/types';
|
||||
import { DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
||||
|
||||
export function DateRangeSetting() {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { dateRange, saveDateRange } = useDateRange();
|
||||
const { value } = dateRange;
|
||||
|
||||
const handleChange = (value: string | DateRange) => saveDateRange(value);
|
||||
const handleReset = () => saveDateRange(DEFAULT_DATE_RANGE);
|
||||
const handleChange = (value: string) => saveDateRange(value);
|
||||
const handleReset = () => saveDateRange(DEFAULT_DATE_RANGE_VALUE);
|
||||
|
||||
return (
|
||||
<Row gap="3">
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export function ProfileSettings() {
|
|||
};
|
||||
|
||||
return (
|
||||
<Column gap="6">
|
||||
<Column width="400px" gap="6">
|
||||
<Column>
|
||||
<Label>{formatMessage(labels.username)}</Label>
|
||||
{username}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useMessages } from '@/components/hooks';
|
|||
import { Globe, Arrow } from '@/components/icons';
|
||||
import { SectionHeader } from '@/components/common/SectionHeader';
|
||||
import { WebsiteShareForm } from './WebsiteShareForm';
|
||||
import { TrackingCode } from './TrackingCode';
|
||||
import { WebsiteTrackingCode } from './WebsiteTrackingCode';
|
||||
import { WebsiteData } from './WebsiteData';
|
||||
import { WebsiteEditForm } from './WebsiteEditForm';
|
||||
import { LinkButton } from '@/components/common/LinkButton';
|
||||
|
|
@ -23,11 +23,7 @@ export function WebsiteSettings({
|
|||
return (
|
||||
<>
|
||||
<SectionHeader title={website?.name} icon={<Globe />}>
|
||||
<LinkButton
|
||||
variant="primary"
|
||||
href={`/websites/${websiteId}`}
|
||||
target={openExternal ? '_blank' : null}
|
||||
>
|
||||
<LinkButton href={`/websites/${websiteId}`} target={openExternal ? '_blank' : null}>
|
||||
<Icon>
|
||||
<Arrow />
|
||||
</Icon>
|
||||
|
|
@ -45,10 +41,10 @@ export function WebsiteSettings({
|
|||
<WebsiteEditForm websiteId={websiteId} />
|
||||
</TabPanel>
|
||||
<TabPanel id="tracking">
|
||||
<TrackingCode websiteId={websiteId} />
|
||||
<WebsiteTrackingCode websiteId={websiteId} />
|
||||
</TabPanel>
|
||||
<TabPanel id="share">
|
||||
<WebsiteShareForm />
|
||||
<WebsiteShareForm websiteId={websiteId} />
|
||||
</TabPanel>
|
||||
<TabPanel id="data">
|
||||
<WebsiteData websiteId={websiteId} />
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const generateId = () => getRandomChars(16);
|
|||
|
||||
export interface WebsiteShareFormProps {
|
||||
websiteId: string;
|
||||
shareId: string;
|
||||
shareId?: string;
|
||||
onSave?: () => void;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
import { TextField } from '@umami/react-zen';
|
||||
import { TextField, Text, Column } from '@umami/react-zen';
|
||||
import { useMessages, useConfig } from '@/components/hooks';
|
||||
|
||||
const SCRIPT_NAME = 'script.js';
|
||||
|
||||
export function TrackingCode({ websiteId, hostUrl }: { websiteId: string; hostUrl?: string }) {
|
||||
export function WebsiteTrackingCode({
|
||||
websiteId,
|
||||
hostUrl,
|
||||
}: {
|
||||
websiteId: string;
|
||||
hostUrl?: string;
|
||||
}) {
|
||||
const { formatMessage, messages } = useMessages();
|
||||
const config = useConfig();
|
||||
|
||||
|
|
@ -19,9 +25,9 @@ export function TrackingCode({ websiteId, hostUrl }: { websiteId: string; hostUr
|
|||
const code = `<script defer src="${url}" data-website-id="${websiteId}"></script>`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>{formatMessage(messages.trackingCode)}</p>
|
||||
<TextField value={code} isReadOnly allowCopy asTextArea />
|
||||
</>
|
||||
<Column gap>
|
||||
<Text>{formatMessage(messages.trackingCode)}</Text>
|
||||
<TextField value={code} isReadOnly allowCopy asTextArea resize="none" />
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
@ -5,22 +5,24 @@ import { Share, Edit } from '@/components/icons';
|
|||
import { Favicon } from '@/components/common/Favicon';
|
||||
import { ActiveUsers } from '@/components/metrics/ActiveUsers';
|
||||
import { WebsiteShareForm } from '@/app/(main)/settings/websites/[websiteId]/WebsiteShareForm';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { useMessages, useNavigation } from '@/components/hooks';
|
||||
import { LinkButton } from '@/components/common/LinkButton';
|
||||
|
||||
export function WebsiteHeader() {
|
||||
const website = useWebsite();
|
||||
const { renderUrl } = useNavigation();
|
||||
|
||||
return (
|
||||
<PageHeader title={website.name} icon={<Favicon domain={website.domain} />} showBorder={false}>
|
||||
<Row alignItems="center" gap>
|
||||
<ActiveUsers websiteId={website.id} />
|
||||
<ShareButton websiteId={website.id} shareId={website.shareId} />
|
||||
<Button>
|
||||
<LinkButton href={renderUrl(`/settings/websites/${website.id}`)}>
|
||||
<Icon>
|
||||
<Edit />
|
||||
</Icon>
|
||||
<Text>Edit</Text>
|
||||
</Button>
|
||||
</LinkButton>
|
||||
</Row>
|
||||
</PageHeader>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,55 +1,53 @@
|
|||
import { getMinimumUnit, parseDateRange } from '@/lib/date';
|
||||
import { getMinimumUnit, parseDateRange, getOffsetDateRange } from '@/lib/date';
|
||||
import { setItem } from '@/lib/storage';
|
||||
import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE } from '@/lib/constants';
|
||||
import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
||||
import { setWebsiteDateCompare, setWebsiteDateRange, useWebsites } from '@/store/websites';
|
||||
import { setDateRange, useApp } from '@/store/app';
|
||||
import { DateRange } from '@/lib/types';
|
||||
import { setDateRangeValue, useApp } from '@/store/app';
|
||||
import { useLocale } from './useLocale';
|
||||
import { useApi } from './useApi';
|
||||
import { useNavigation } from './useNavigation';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export function useDateRange(websiteId?: string) {
|
||||
const { get } = useApi();
|
||||
const { locale } = useLocale();
|
||||
const {
|
||||
query: { date },
|
||||
query: { date, offset = 0 },
|
||||
} = useNavigation();
|
||||
const websiteConfig = useWebsites(state => state[websiteId]?.dateRange);
|
||||
const globalConfig = useApp(state => state.dateRange);
|
||||
const dateRange = parseDateRange(
|
||||
date || websiteConfig || globalConfig || DEFAULT_DATE_RANGE,
|
||||
const globalConfig = useApp(state => state.dateRangeValue);
|
||||
const dateRangeObject = parseDateRange(
|
||||
date || websiteConfig?.value || globalConfig || DEFAULT_DATE_RANGE_VALUE,
|
||||
locale,
|
||||
);
|
||||
const dateRange = useMemo(
|
||||
() => (offset ? getOffsetDateRange(dateRangeObject, +offset) : dateRangeObject),
|
||||
[date, offset],
|
||||
);
|
||||
const dateCompare = useWebsites(state => state[websiteId]?.dateCompare || DEFAULT_DATE_COMPARE);
|
||||
|
||||
const saveDateRange = async (value: DateRange | string) => {
|
||||
const saveDateRange = async (value: string) => {
|
||||
if (websiteId) {
|
||||
let dateRange: DateRange | string = value;
|
||||
if (value === 'all') {
|
||||
const result: any = await get(`/websites/${websiteId}/daterange`);
|
||||
const { mindate, maxdate } = result;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (value === 'all') {
|
||||
const result: any = await get(`/websites/${websiteId}/daterange`);
|
||||
const { mindate, maxdate } = result;
|
||||
const startDate = new Date(mindate);
|
||||
const endDate = new Date(maxdate);
|
||||
const unit = getMinimumUnit(startDate, endDate);
|
||||
|
||||
const startDate = new Date(mindate);
|
||||
const endDate = new Date(maxdate);
|
||||
const unit = getMinimumUnit(startDate, endDate);
|
||||
|
||||
dateRange = {
|
||||
startDate,
|
||||
endDate,
|
||||
unit,
|
||||
value,
|
||||
};
|
||||
} else {
|
||||
dateRange = parseDateRange(value, locale);
|
||||
}
|
||||
setWebsiteDateRange(websiteId, {
|
||||
startDate,
|
||||
endDate,
|
||||
unit,
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
setWebsiteDateRange(websiteId, parseDateRange(value, locale));
|
||||
}
|
||||
|
||||
setWebsiteDateRange(websiteId, dateRange as DateRange);
|
||||
} else {
|
||||
setItem(DATE_RANGE_CONFIG, value);
|
||||
setDateRange(value);
|
||||
setDateRangeValue(value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export interface DateFilterProps {
|
|||
endDate: Date;
|
||||
onChange?: (value: string) => void;
|
||||
showAllTime?: boolean;
|
||||
renderDate?: boolean;
|
||||
}
|
||||
|
||||
export function DateFilter({
|
||||
|
|
@ -18,7 +19,8 @@ export function DateFilter({
|
|||
startDate,
|
||||
endDate,
|
||||
onChange,
|
||||
showAllTime = false,
|
||||
showAllTime,
|
||||
renderDate,
|
||||
}: DateFilterProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
|
|
@ -89,7 +91,7 @@ export function DateFilter({
|
|||
};
|
||||
|
||||
const renderValue = ({ defaultChildren }) => {
|
||||
return value?.startsWith('range') ? (
|
||||
return value?.startsWith('range') || renderDate ? (
|
||||
<DateDisplay startDate={startDate} endDate={endDate} />
|
||||
) : (
|
||||
defaultChildren
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import {
|
|||
import { isAfter } from 'date-fns';
|
||||
import { Chevron, Close, Compare } from '@/components/icons';
|
||||
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
|
||||
import { getOffsetDateRange } from '@/lib/date';
|
||||
import { DateFilter } from './DateFilter';
|
||||
|
||||
export function WebsiteDateFilter({
|
||||
|
|
@ -26,13 +25,13 @@ export function WebsiteDateFilter({
|
|||
showButtons?: boolean;
|
||||
allowCompare?: boolean;
|
||||
}) {
|
||||
const { dateRange, saveDateRange } = useDateRange(websiteId);
|
||||
const { value, startDate, endDate, offset } = dateRange;
|
||||
const { dateRange } = useDateRange(websiteId);
|
||||
const { value, startDate, endDate } = dateRange;
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const {
|
||||
router,
|
||||
updateParams,
|
||||
query: { compare },
|
||||
query: { compare, offset = 0 },
|
||||
} = useNavigation();
|
||||
const isAllTime = value === 'all';
|
||||
const isCustomRange = value.startsWith('range');
|
||||
|
|
@ -40,13 +39,11 @@ export function WebsiteDateFilter({
|
|||
const disableForward = value === 'all' || isAfter(endDate, new Date());
|
||||
|
||||
const handleChange = (date: string) => {
|
||||
router.push(updateParams({ date }));
|
||||
saveDateRange(date);
|
||||
router.push(updateParams({ date, offset: undefined }));
|
||||
};
|
||||
|
||||
const handleIncrement = (increment: number) => {
|
||||
router.push(updateParams({ offset: offset + increment }));
|
||||
saveDateRange(getOffsetDateRange(dateRange, increment));
|
||||
router.push(updateParams({ offset: +offset + increment }));
|
||||
};
|
||||
|
||||
const handleSelect = (compare: any) => {
|
||||
|
|
@ -79,6 +76,7 @@ export function WebsiteDateFilter({
|
|||
endDate={endDate}
|
||||
onChange={handleChange}
|
||||
showAllTime={showAllTime}
|
||||
renderDate={+offset !== 0}
|
||||
/>
|
||||
{!isAllTime && compare && (
|
||||
<Row alignItems="center" gap>
|
||||
|
|
|
|||
|
|
@ -330,6 +330,7 @@ export const labels = defineMessages({
|
|||
conversion: { id: 'label.conversion', defaultMessage: 'Conversion' },
|
||||
firstClick: { id: 'label.first-click', defaultMessage: 'First click' },
|
||||
lastClick: { id: 'label.last-click', defaultMessage: 'Last click' },
|
||||
online: { id: 'label.online', defaultMessage: 'Online' },
|
||||
});
|
||||
|
||||
export const messages = defineMessages({
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export function ActiveUsers({
|
|||
value?: number;
|
||||
refetchInterval?: number;
|
||||
}) {
|
||||
const { formatMessage, messages } = useMessages();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { data } = useActyiveUsersQuery(websiteId, { refetchInterval });
|
||||
|
||||
const count = useMemo(() => {
|
||||
|
|
@ -28,8 +28,8 @@ export function ActiveUsers({
|
|||
|
||||
return (
|
||||
<StatusLight variant="success">
|
||||
<Text size="2" weight="bold">
|
||||
{formatMessage(messages.numberOfUsers, { x: count })}
|
||||
<Text size="2" weight="medium">
|
||||
{count} {formatMessage(labels.online)}
|
||||
</Text>
|
||||
</StatusLight>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export * from '@/app/(main)/settings/teams/TeamsTable';
|
|||
export * from '@/app/(main)/settings/teams/WebsiteTags';
|
||||
|
||||
export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteShareForm';
|
||||
export * from '@/app/(main)/settings/websites/[websiteId]/TrackingCode';
|
||||
export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteTrackingCode';
|
||||
export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteData';
|
||||
export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteDeleteForm';
|
||||
export * from '@/app/(main)/settings/websites/[websiteId]/WebsiteEditForm';
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export const FAVICON_URL = 'https://icons.duckduckgo.com/ip3/{{domain}}.ico';
|
|||
export const DEFAULT_LOCALE = process.env.defaultLocale || 'en-US';
|
||||
export const DEFAULT_THEME = 'light';
|
||||
export const DEFAULT_ANIMATION_DURATION = 300;
|
||||
export const DEFAULT_DATE_RANGE = '24hour';
|
||||
export const DEFAULT_DATE_RANGE_VALUE = '24hour';
|
||||
export const DEFAULT_WEBSITE_LIMIT = 10;
|
||||
export const DEFAULT_RESET_DATE = '2000-01-01';
|
||||
export const DEFAULT_PAGE_SIZE = 10;
|
||||
|
|
|
|||
|
|
@ -126,9 +126,9 @@ export function parseDateValue(value: string) {
|
|||
return { num: +num, unit };
|
||||
}
|
||||
|
||||
export function parseDateRange(value: string | object, locale = 'en-US'): DateRange {
|
||||
export function parseDateRange(value: string, locale = 'en-US'): DateRange {
|
||||
if (typeof value !== 'string') {
|
||||
return value as DateRange;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value === 'all') {
|
||||
|
|
@ -151,14 +151,13 @@ export function parseDateRange(value: string | object, locale = 'en-US'): DateRa
|
|||
endDate,
|
||||
value,
|
||||
...parseDateValue(value),
|
||||
offset: 0,
|
||||
unit,
|
||||
};
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const dateLocale = getDateLocale(locale);
|
||||
const { num, unit } = parseDateValue(value);
|
||||
const { num = 1, unit } = parseDateValue(value);
|
||||
|
||||
switch (unit) {
|
||||
case 'hour':
|
||||
|
|
@ -211,10 +210,14 @@ export function parseDateRange(value: string | object, locale = 'en-US'): DateRa
|
|||
}
|
||||
}
|
||||
|
||||
export function getOffsetDateRange(dateRange: DateRange, increment: number) {
|
||||
const { startDate, endDate, unit, num, offset, value } = dateRange;
|
||||
export function getOffsetDateRange(dateRange: DateRange, offset: number) {
|
||||
if (offset === 0) {
|
||||
return dateRange;
|
||||
}
|
||||
|
||||
const change = num * increment;
|
||||
const { startDate, endDate, unit, num, value } = dateRange;
|
||||
|
||||
const change = num * offset;
|
||||
const { add } = DATE_FUNCTIONS[unit];
|
||||
const { unit: originalUnit } = parseDateValue(value) || {};
|
||||
|
||||
|
|
@ -224,28 +227,24 @@ export function getOffsetDateRange(dateRange: DateRange, increment: number) {
|
|||
...dateRange,
|
||||
startDate: addDays(startDate, change),
|
||||
endDate: addDays(endDate, change),
|
||||
offset: offset + increment,
|
||||
};
|
||||
case 'week':
|
||||
return {
|
||||
...dateRange,
|
||||
startDate: addWeeks(startDate, change),
|
||||
endDate: addWeeks(endDate, change),
|
||||
offset: offset + increment,
|
||||
};
|
||||
case 'month':
|
||||
return {
|
||||
...dateRange,
|
||||
startDate: addMonths(startDate, change),
|
||||
endDate: addMonths(endDate, change),
|
||||
offset: offset + increment,
|
||||
};
|
||||
case 'year':
|
||||
return {
|
||||
...dateRange,
|
||||
startDate: addYears(startDate, change),
|
||||
endDate: addYears(endDate, change),
|
||||
offset: offset + increment,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
|
|
@ -254,7 +253,6 @@ export function getOffsetDateRange(dateRange: DateRange, increment: number) {
|
|||
value,
|
||||
unit,
|
||||
num,
|
||||
offset: offset + increment,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export async function getActiveVisitors(...args: [websiteId: string]) {
|
|||
|
||||
async function relationalQuery(websiteId: string) {
|
||||
const { rawQuery } = prisma;
|
||||
const startDate = subMinutes(new Date(), 5);
|
||||
|
||||
const result = await rawQuery(
|
||||
`
|
||||
|
|
@ -20,7 +21,7 @@ async function relationalQuery(websiteId: string) {
|
|||
where website_id = {{websiteId::uuid}}
|
||||
and created_at >= {{startDate}}
|
||||
`,
|
||||
{ websiteId, startDate: subMinutes(new Date(), 5) },
|
||||
{ websiteId, startDate },
|
||||
);
|
||||
|
||||
return result[0] ?? null;
|
||||
|
|
@ -28,6 +29,7 @@ async function relationalQuery(websiteId: string) {
|
|||
|
||||
async function clickhouseQuery(websiteId: string): Promise<{ x: number }> {
|
||||
const { rawQuery } = clickhouse;
|
||||
const startDate = subMinutes(new Date(), 5);
|
||||
|
||||
const result = await rawQuery(
|
||||
`
|
||||
|
|
@ -37,7 +39,7 @@ async function clickhouseQuery(websiteId: string): Promise<{ x: number }> {
|
|||
where website_id = {websiteId:UUID}
|
||||
and created_at >= {startDate:DateTime64}
|
||||
`,
|
||||
{ websiteId, startDate: subMinutes(new Date(), 5) },
|
||||
{ websiteId, startDate },
|
||||
);
|
||||
|
||||
return result[0] ?? null;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { create } from 'zustand';
|
||||
import {
|
||||
DATE_RANGE_CONFIG,
|
||||
DEFAULT_DATE_RANGE,
|
||||
DEFAULT_DATE_RANGE_VALUE,
|
||||
DEFAULT_LOCALE,
|
||||
DEFAULT_THEME,
|
||||
LOCALE_CONFIG,
|
||||
|
|
@ -23,7 +23,7 @@ const initialState = {
|
|||
locale: getItem(LOCALE_CONFIG) || DEFAULT_LOCALE,
|
||||
theme: getItem(THEME_CONFIG) || getDefaultTheme() || DEFAULT_THEME,
|
||||
timezone: getItem(TIMEZONE_CONFIG) || getTimezone(),
|
||||
dateRange: getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE,
|
||||
dateRangeValue: getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE,
|
||||
shareToken: null,
|
||||
user: null,
|
||||
config: null,
|
||||
|
|
@ -51,8 +51,8 @@ export function setConfig(config: object) {
|
|||
store.setState({ config });
|
||||
}
|
||||
|
||||
export function setDateRange(dateRange: string | object) {
|
||||
store.setState({ dateRange });
|
||||
export function setDateRangeValue(dateRangeValue: string) {
|
||||
store.setState({ dateRangeValue });
|
||||
}
|
||||
|
||||
export const useApp = store;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue