mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
Compare commits
3 commits
3f173889ea
...
355fa1e9a9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
355fa1e9a9 | ||
|
|
a2f0066c42 | ||
|
|
e73432dd26 |
17 changed files with 144 additions and 61 deletions
|
|
@ -21,30 +21,28 @@ export function WebsiteChart({
|
||||||
const { pageviews, sessions, compare } = (data || {}) as any;
|
const { pageviews, sessions, compare } = (data || {}) as any;
|
||||||
|
|
||||||
const chartData = useMemo(() => {
|
const chartData = useMemo(() => {
|
||||||
if (data) {
|
if (!data) {
|
||||||
const result = {
|
return { pageviews: [], sessions: [] };
|
||||||
pageviews,
|
}
|
||||||
sessions,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (compare) {
|
return {
|
||||||
result.compare = {
|
pageviews,
|
||||||
pageviews: result.pageviews.map(({ x }, i) => ({
|
sessions,
|
||||||
|
...(compare && {
|
||||||
|
compare: {
|
||||||
|
pageviews: pageviews.map(({ x }, i) => ({
|
||||||
x,
|
x,
|
||||||
y: compare.pageviews[i]?.y,
|
y: compare.pageviews[i]?.y,
|
||||||
d: compare.pageviews[i]?.x,
|
d: compare.pageviews[i]?.x,
|
||||||
})),
|
})),
|
||||||
sessions: result.sessions.map(({ x }, i) => ({
|
sessions: sessions.map(({ x }, i) => ({
|
||||||
x,
|
x,
|
||||||
y: compare.sessions[i]?.y,
|
y: compare.sessions[i]?.y,
|
||||||
d: compare.sessions[i]?.x,
|
d: compare.sessions[i]?.x,
|
||||||
})),
|
})),
|
||||||
};
|
},
|
||||||
}
|
}),
|
||||||
|
};
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return { pageviews: [], sessions: [] };
|
|
||||||
}, [data, startDate, endDate, unit]);
|
}, [data, startDate, endDate, unit]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from '@umami/react-zen';
|
} from '@umami/react-zen';
|
||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
import { useMessages, useNavigation } from '@/components/hooks';
|
import { useMessages, useNavigation } from '@/components/hooks';
|
||||||
import { Edit, More, Share } from '@/components/icons';
|
import { Edit, MoreHorizontal, Share } from '@/components/icons';
|
||||||
|
|
||||||
export function WebsiteMenu({ websiteId }: { websiteId: string }) {
|
export function WebsiteMenu({ websiteId }: { websiteId: string }) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
@ -33,7 +33,7 @@ export function WebsiteMenu({ websiteId }: { websiteId: string }) {
|
||||||
<MenuTrigger>
|
<MenuTrigger>
|
||||||
<Button variant="quiet">
|
<Button variant="quiet">
|
||||||
<Icon>
|
<Icon>
|
||||||
<More />
|
<MoreHorizontal />
|
||||||
</Icon>
|
</Icon>
|
||||||
</Button>
|
</Button>
|
||||||
<Popover placement="bottom">
|
<Popover placement="bottom">
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,18 @@ import { formatLongNumber, formatShortTime } from '@/lib/format';
|
||||||
|
|
||||||
export function WebsiteMetricsBar({
|
export function WebsiteMetricsBar({
|
||||||
websiteId,
|
websiteId,
|
||||||
|
compareMode,
|
||||||
}: {
|
}: {
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
showChange?: boolean;
|
showChange?: boolean;
|
||||||
compareMode?: boolean;
|
compareMode?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { isAllTime } = useDateRange();
|
const { isAllTime, dateCompare } = useDateRange();
|
||||||
const { formatMessage, labels, getErrorMessage } = useMessages();
|
const { formatMessage, labels, getErrorMessage } = useMessages();
|
||||||
const { data, isLoading, isFetching, error } = useWebsiteStatsQuery(websiteId);
|
const { data, isLoading, isFetching, error } = useWebsiteStatsQuery({
|
||||||
|
websiteId,
|
||||||
|
compare: compareMode ? dateCompare?.compare : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
const { pageviews, visitors, visits, bounces, totaltime, comparison } = data || {};
|
const { pageviews, visitors, visits, bounces, totaltime, comparison } = data || {};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ export function WebsiteNav({
|
||||||
event: undefined,
|
event: undefined,
|
||||||
compare: undefined,
|
compare: undefined,
|
||||||
view: undefined,
|
view: undefined,
|
||||||
|
unit: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Column } from '@umami/react-zen';
|
import { Column, Row } from '@umami/react-zen';
|
||||||
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
|
import { ExpandedViewModal } from '@/app/(main)/websites/[websiteId]/ExpandedViewModal';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
|
import { UnitFilter } from '@/components/input/UnitFilter';
|
||||||
import { WebsiteChart } from './WebsiteChart';
|
import { WebsiteChart } from './WebsiteChart';
|
||||||
import { WebsiteControls } from './WebsiteControls';
|
import { WebsiteControls } from './WebsiteControls';
|
||||||
import { WebsiteMetricsBar } from './WebsiteMetricsBar';
|
import { WebsiteMetricsBar } from './WebsiteMetricsBar';
|
||||||
|
|
@ -13,6 +14,9 @@ export function WebsitePage({ websiteId }: { websiteId: string }) {
|
||||||
<WebsiteControls websiteId={websiteId} />
|
<WebsiteControls websiteId={websiteId} />
|
||||||
<WebsiteMetricsBar websiteId={websiteId} showChange={true} />
|
<WebsiteMetricsBar websiteId={websiteId} showChange={true} />
|
||||||
<Panel minHeight="520px">
|
<Panel minHeight="520px">
|
||||||
|
<Row justifyContent="end">
|
||||||
|
<UnitFilter />
|
||||||
|
</Row>
|
||||||
<WebsiteChart websiteId={websiteId} />
|
<WebsiteChart websiteId={websiteId} />
|
||||||
</Panel>
|
</Panel>
|
||||||
<WebsitePanels websiteId={websiteId} />
|
<WebsitePanels websiteId={websiteId} />
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ export function ComparePage({ websiteId }: { websiteId: string }) {
|
||||||
return (
|
return (
|
||||||
<Column gap>
|
<Column gap>
|
||||||
<WebsiteControls websiteId={websiteId} allowCompare={true} />
|
<WebsiteControls websiteId={websiteId} allowCompare={true} />
|
||||||
<WebsiteMetricsBar websiteId={websiteId} showChange={true} />
|
<WebsiteMetricsBar websiteId={websiteId} compareMode={true} showChange={true} />
|
||||||
<Panel minHeight="520px">
|
<Panel minHeight="520px">
|
||||||
<WebsiteChart websiteId={websiteId} compareMode={true} />
|
<WebsiteChart websiteId={websiteId} compareMode={true} />
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,11 @@ export async function GET(
|
||||||
|
|
||||||
const data = await getWebsiteStats(websiteId, filters);
|
const data = await getWebsiteStats(websiteId, filters);
|
||||||
|
|
||||||
const compare = filters.compare ?? 'prev';
|
const { startDate, endDate } = getCompareDate(
|
||||||
|
filters.compare ?? 'prev',
|
||||||
const { startDate, endDate } = getCompareDate(compare, filters.startDate, filters.endDate);
|
filters.startDate,
|
||||||
|
filters.endDate,
|
||||||
|
);
|
||||||
|
|
||||||
const comparison = await getWebsiteStats(websiteId, {
|
const comparison = await getWebsiteStats(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export function useWebsiteExpandedMetricsQuery(
|
||||||
options?: ReactQueryOptions<WebsiteExpandedMetricsData>,
|
options?: ReactQueryOptions<WebsiteExpandedMetricsData>,
|
||||||
) {
|
) {
|
||||||
const { get, useQuery } = useApi();
|
const { get, useQuery } = useApi();
|
||||||
const { startAt, endAt, unit, timezone } = useDateParameters();
|
const { startAt, endAt } = useDateParameters();
|
||||||
const filters = useFilterParameters();
|
const filters = useFilterParameters();
|
||||||
|
|
||||||
return useQuery<WebsiteExpandedMetricsData>({
|
return useQuery<WebsiteExpandedMetricsData>({
|
||||||
|
|
@ -29,8 +29,6 @@ export function useWebsiteExpandedMetricsQuery(
|
||||||
websiteId,
|
websiteId,
|
||||||
startAt,
|
startAt,
|
||||||
endAt,
|
endAt,
|
||||||
unit,
|
|
||||||
timezone,
|
|
||||||
...filters,
|
...filters,
|
||||||
...params,
|
...params,
|
||||||
},
|
},
|
||||||
|
|
@ -39,8 +37,6 @@ export function useWebsiteExpandedMetricsQuery(
|
||||||
get(`/websites/${websiteId}/metrics/expanded`, {
|
get(`/websites/${websiteId}/metrics/expanded`, {
|
||||||
startAt,
|
startAt,
|
||||||
endAt,
|
endAt,
|
||||||
unit,
|
|
||||||
timezone,
|
|
||||||
...filters,
|
...filters,
|
||||||
...params,
|
...params,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export function useWebsiteMetricsQuery(
|
||||||
options?: ReactQueryOptions<WebsiteMetricsData>,
|
options?: ReactQueryOptions<WebsiteMetricsData>,
|
||||||
) {
|
) {
|
||||||
const { get, useQuery } = useApi();
|
const { get, useQuery } = useApi();
|
||||||
const { startAt, endAt, unit, timezone } = useDateParameters();
|
const { startAt, endAt } = useDateParameters();
|
||||||
const filters = useFilterParameters();
|
const filters = useFilterParameters();
|
||||||
|
|
||||||
return useQuery<WebsiteMetricsData>({
|
return useQuery<WebsiteMetricsData>({
|
||||||
|
|
@ -25,8 +25,6 @@ export function useWebsiteMetricsQuery(
|
||||||
websiteId,
|
websiteId,
|
||||||
startAt,
|
startAt,
|
||||||
endAt,
|
endAt,
|
||||||
unit,
|
|
||||||
timezone,
|
|
||||||
...filters,
|
...filters,
|
||||||
...params,
|
...params,
|
||||||
},
|
},
|
||||||
|
|
@ -35,8 +33,6 @@ export function useWebsiteMetricsQuery(
|
||||||
get(`/websites/${websiteId}/metrics`, {
|
get(`/websites/${websiteId}/metrics`, {
|
||||||
startAt,
|
startAt,
|
||||||
endAt,
|
endAt,
|
||||||
unit,
|
|
||||||
timezone,
|
|
||||||
...filters,
|
...filters,
|
||||||
...params,
|
...params,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import type { UseQueryOptions } from '@tanstack/react-query';
|
import type { UseQueryOptions } from '@tanstack/react-query';
|
||||||
import { useDateParameters } from '@/components/hooks/useDateParameters';
|
import { useDateParameters } from '@/components/hooks/useDateParameters';
|
||||||
import { useDateRange } from '@/components/hooks/useDateRange';
|
|
||||||
import { useApi } from '../useApi';
|
import { useApi } from '../useApi';
|
||||||
import { useFilterParameters } from '../useFilterParameters';
|
import { useFilterParameters } from '../useFilterParameters';
|
||||||
|
|
||||||
|
|
@ -20,21 +19,16 @@ export interface WebsiteStatsData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useWebsiteStatsQuery(
|
export function useWebsiteStatsQuery(
|
||||||
websiteId: string,
|
{ websiteId, compare }: { websiteId: string; compare?: string },
|
||||||
options?: UseQueryOptions<WebsiteStatsData, Error, WebsiteStatsData>,
|
options?: UseQueryOptions<WebsiteStatsData, Error, WebsiteStatsData>,
|
||||||
) {
|
) {
|
||||||
const { get, useQuery } = useApi();
|
const { get, useQuery } = useApi();
|
||||||
const { startAt, endAt, unit, timezone } = useDateParameters();
|
const { startAt, endAt } = useDateParameters();
|
||||||
const { compare } = useDateRange();
|
|
||||||
const filters = useFilterParameters();
|
const filters = useFilterParameters();
|
||||||
|
|
||||||
return useQuery<WebsiteStatsData>({
|
return useQuery<WebsiteStatsData>({
|
||||||
queryKey: [
|
queryKey: ['websites:stats', { websiteId, compare, startAt, endAt, ...filters }],
|
||||||
'websites:stats',
|
queryFn: () => get(`/websites/${websiteId}/stats`, { compare, startAt, endAt, ...filters }),
|
||||||
{ websiteId, startAt, endAt, unit, timezone, compare, ...filters },
|
|
||||||
],
|
|
||||||
queryFn: () =>
|
|
||||||
get(`/websites/${websiteId}/stats`, { startAt, endAt, unit, timezone, compare, ...filters }),
|
|
||||||
enabled: !!websiteId,
|
enabled: !!websiteId,
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,12 @@ export function useWeeklyTrafficQuery(websiteId: string, params?: Record<string,
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: [
|
queryKey: [
|
||||||
'sessions',
|
'sessions',
|
||||||
{ websiteId, modified, startAt, endAt, unit, timezone, ...params, ...filters },
|
{ websiteId, modified, startAt, endAt, timezone, ...params, ...filters },
|
||||||
],
|
],
|
||||||
queryFn: () => {
|
queryFn: () => {
|
||||||
return get(`/websites/${websiteId}/sessions/weekly`, {
|
return get(`/websites/${websiteId}/sessions/weekly`, {
|
||||||
startAt,
|
startAt,
|
||||||
endAt,
|
endAt,
|
||||||
unit,
|
|
||||||
timezone,
|
timezone,
|
||||||
...params,
|
...params,
|
||||||
...filters,
|
...filters,
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@ import { getItem } from '@/lib/storage';
|
||||||
|
|
||||||
export function useDateRange(options: { ignoreOffset?: boolean; timezone?: string } = {}) {
|
export function useDateRange(options: { ignoreOffset?: boolean; timezone?: string } = {}) {
|
||||||
const {
|
const {
|
||||||
query: { date = '', offset = 0, compare = 'prev' },
|
query: { date = '', unit = '', offset = 0, compare = 'prev' },
|
||||||
} = useNavigation();
|
} = useNavigation();
|
||||||
const { locale } = useLocale();
|
const { locale } = useLocale();
|
||||||
|
|
||||||
const dateRange = useMemo(() => {
|
const dateRange = useMemo(() => {
|
||||||
const dateRangeObject = parseDateRange(
|
const dateRangeObject = parseDateRange(
|
||||||
date || getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE,
|
date || getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE,
|
||||||
|
unit,
|
||||||
locale,
|
locale,
|
||||||
options.timezone,
|
options.timezone,
|
||||||
);
|
);
|
||||||
|
|
@ -21,12 +21,13 @@ export function useDateRange(options: { ignoreOffset?: boolean; timezone?: strin
|
||||||
return !options.ignoreOffset && offset
|
return !options.ignoreOffset && offset
|
||||||
? getOffsetDateRange(dateRangeObject, +offset)
|
? getOffsetDateRange(dateRangeObject, +offset)
|
||||||
: dateRangeObject;
|
: dateRangeObject;
|
||||||
}, [date, offset, options]);
|
}, [date, unit, offset, options]);
|
||||||
|
|
||||||
const dateCompare = getCompareDate(compare, dateRange.startDate, dateRange.endDate);
|
const dateCompare = getCompareDate(compare, dateRange.startDate, dateRange.endDate);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
date,
|
date,
|
||||||
|
unit,
|
||||||
offset,
|
offset,
|
||||||
compare,
|
compare,
|
||||||
isAllTime: date.endsWith(`:all`),
|
isAllTime: date.endsWith(`:all`),
|
||||||
|
|
|
||||||
71
src/components/input/UnitFilter.tsx
Normal file
71
src/components/input/UnitFilter.tsx
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { ListItem, Row, Select } from '@umami/react-zen';
|
||||||
|
import { useMessages, useNavigation } from '@/components/hooks';
|
||||||
|
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
||||||
|
import { getItem } from '@/lib/storage';
|
||||||
|
|
||||||
|
export function UnitFilter() {
|
||||||
|
const { formatMessage, labels } = useMessages();
|
||||||
|
const { router, query, updateParams } = useNavigation();
|
||||||
|
|
||||||
|
const DATE_RANGE_UNIT_CONFIG = {
|
||||||
|
'0week': {
|
||||||
|
defaultUnit: 'day',
|
||||||
|
availableUnits: ['day', 'hour'],
|
||||||
|
},
|
||||||
|
'7day': {
|
||||||
|
defaultUnit: 'day',
|
||||||
|
availableUnits: ['day', 'hour'],
|
||||||
|
},
|
||||||
|
'0month': {
|
||||||
|
defaultUnit: 'day',
|
||||||
|
availableUnits: ['day', 'hour'],
|
||||||
|
},
|
||||||
|
'30day': {
|
||||||
|
defaultUnit: 'day',
|
||||||
|
availableUnits: ['day', 'hour'],
|
||||||
|
},
|
||||||
|
'90day': {
|
||||||
|
defaultUnit: 'day',
|
||||||
|
availableUnits: ['day', 'month'],
|
||||||
|
},
|
||||||
|
'6month': {
|
||||||
|
defaultUnit: 'month',
|
||||||
|
availableUnits: ['month', 'day'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const unitConfig =
|
||||||
|
DATE_RANGE_UNIT_CONFIG[query.date || getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE];
|
||||||
|
|
||||||
|
if (!unitConfig) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChange = (value: string) => {
|
||||||
|
router.push(updateParams({ unit: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = unitConfig.availableUnits.map(unit => ({
|
||||||
|
id: unit,
|
||||||
|
label: formatMessage(labels[unit]),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const selectedUnit = query.unit ?? unitConfig.defaultUnit;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Select
|
||||||
|
value={selectedUnit}
|
||||||
|
onChange={handleChange}
|
||||||
|
popoverProps={{ placement: 'bottom right' }}
|
||||||
|
style={{ width: 100 }}
|
||||||
|
>
|
||||||
|
{options.map(({ id, label }) => (
|
||||||
|
<ListItem key={id} id={id}>
|
||||||
|
{label}
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -41,7 +41,7 @@ export function WebsiteDateFilter({
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
router.push(updateParams({ date, offset: undefined }));
|
router.push(updateParams({ date, offset: undefined, unit: undefined }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,10 @@ export const labels = defineMessages({
|
||||||
tag: { id: 'label.tag', defaultMessage: 'Tag' },
|
tag: { id: 'label.tag', defaultMessage: 'Tag' },
|
||||||
segment: { id: 'label.segment', defaultMessage: 'Segment' },
|
segment: { id: 'label.segment', defaultMessage: 'Segment' },
|
||||||
cohort: { id: 'label.cohort', defaultMessage: 'Cohort' },
|
cohort: { id: 'label.cohort', defaultMessage: 'Cohort' },
|
||||||
|
minute: { id: 'label.minute', defaultMessage: 'Minute' },
|
||||||
|
hour: { id: 'label.hour', defaultMessage: 'Hour' },
|
||||||
day: { id: 'label.day', defaultMessage: 'Day' },
|
day: { id: 'label.day', defaultMessage: 'Day' },
|
||||||
|
month: { id: 'label.month', defaultMessage: 'Month' },
|
||||||
date: { id: 'label.date', defaultMessage: 'Date' },
|
date: { id: 'label.date', defaultMessage: 'Date' },
|
||||||
pageOf: { id: 'label.page-of', defaultMessage: 'Page {current} of {total}' },
|
pageOf: { id: 'label.page-of', defaultMessage: 'Page {current} of {total}' },
|
||||||
create: { id: 'label.create', defaultMessage: 'Create' },
|
create: { id: 'label.create', defaultMessage: 'Create' },
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export const MetricCard = ({
|
||||||
showChange = false,
|
showChange = false,
|
||||||
}: MetricCardProps) => {
|
}: MetricCardProps) => {
|
||||||
const diff = value - change;
|
const diff = value - change;
|
||||||
const pct = ((value - diff) / diff) * 100;
|
const pct = diff !== 0 ? ((value - diff) / diff) * 100 : value !== 0 ? 100 : 0;
|
||||||
const props = useSpring({ x: Number(value) || 0, from: { x: 0 } });
|
const props = useSpring({ x: Number(value) || 0, from: { x: 0 } });
|
||||||
const changeProps = useSpring({ x: Number(pct) || 0, from: { x: 0 } });
|
const changeProps = useSpring({ x: Number(pct) || 0, from: { x: 0 } });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
differenceInCalendarMonths,
|
differenceInCalendarMonths,
|
||||||
differenceInCalendarWeeks,
|
differenceInCalendarWeeks,
|
||||||
differenceInCalendarYears,
|
differenceInCalendarYears,
|
||||||
|
differenceInDays,
|
||||||
differenceInHours,
|
differenceInHours,
|
||||||
differenceInMinutes,
|
differenceInMinutes,
|
||||||
endOfDay,
|
endOfDay,
|
||||||
|
|
@ -136,7 +137,12 @@ export function parseDateValue(value: string) {
|
||||||
return { num: +num, unit };
|
return { num: +num, unit };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDateRange(value: string, locale = 'en-US', timezone?: string): DateRange {
|
export function parseDateRange(
|
||||||
|
value: string,
|
||||||
|
unitValue?: string,
|
||||||
|
locale = 'en-US',
|
||||||
|
timezone?: string,
|
||||||
|
): DateRange {
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +152,7 @@ export function parseDateRange(value: string, locale = 'en-US', timezone?: strin
|
||||||
|
|
||||||
const startDate = new Date(+startTime);
|
const startDate = new Date(+startTime);
|
||||||
const endDate = new Date(+endTime);
|
const endDate = new Date(+endTime);
|
||||||
const unit = getMinimumUnit(startDate, endDate);
|
const unit = getMinimumUnit(startDate, endDate, true);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
startDate,
|
startDate,
|
||||||
|
|
@ -169,14 +175,14 @@ export function parseDateRange(value: string, locale = 'en-US', timezone?: strin
|
||||||
endDate: endOfHour(now),
|
endDate: endOfHour(now),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
num: num || 1,
|
num: num || 1,
|
||||||
unit,
|
unit: unitValue || unit,
|
||||||
value,
|
value,
|
||||||
};
|
};
|
||||||
case 'day':
|
case 'day':
|
||||||
return {
|
return {
|
||||||
startDate: num ? subDays(startOfDay(now), num) : startOfDay(now),
|
startDate: num ? subDays(startOfDay(now), num) : startOfDay(now),
|
||||||
endDate: endOfDay(now),
|
endDate: endOfDay(now),
|
||||||
unit: num ? 'day' : 'hour',
|
unit: unitValue ? unitValue : num ? 'day' : 'hour',
|
||||||
offset: 0,
|
offset: 0,
|
||||||
num: num || 1,
|
num: num || 1,
|
||||||
value,
|
value,
|
||||||
|
|
@ -187,7 +193,7 @@ export function parseDateRange(value: string, locale = 'en-US', timezone?: strin
|
||||||
? subWeeks(startOfWeek(now, { locale: dateLocale }), num)
|
? subWeeks(startOfWeek(now, { locale: dateLocale }), num)
|
||||||
: startOfWeek(now, { locale: dateLocale }),
|
: startOfWeek(now, { locale: dateLocale }),
|
||||||
endDate: endOfWeek(now, { locale: dateLocale }),
|
endDate: endOfWeek(now, { locale: dateLocale }),
|
||||||
unit: 'day',
|
unit: unitValue || 'day',
|
||||||
offset: 0,
|
offset: 0,
|
||||||
num: num || 1,
|
num: num || 1,
|
||||||
value,
|
value,
|
||||||
|
|
@ -196,7 +202,7 @@ export function parseDateRange(value: string, locale = 'en-US', timezone?: strin
|
||||||
return {
|
return {
|
||||||
startDate: num ? subMonths(startOfMonth(now), num) : startOfMonth(now),
|
startDate: num ? subMonths(startOfMonth(now), num) : startOfMonth(now),
|
||||||
endDate: endOfMonth(now),
|
endDate: endOfMonth(now),
|
||||||
unit: num ? 'month' : 'day',
|
unit: unitValue ? unitValue : num ? 'month' : 'day',
|
||||||
offset: 0,
|
offset: 0,
|
||||||
num: num || 1,
|
num: num || 1,
|
||||||
value,
|
value,
|
||||||
|
|
@ -205,7 +211,7 @@ export function parseDateRange(value: string, locale = 'en-US', timezone?: strin
|
||||||
return {
|
return {
|
||||||
startDate: num ? subYears(startOfYear(now), num) : startOfYear(now),
|
startDate: num ? subYears(startOfYear(now), num) : startOfYear(now),
|
||||||
endDate: endOfYear(now),
|
endDate: endOfYear(now),
|
||||||
unit: 'month',
|
unit: unitValue || 'month',
|
||||||
offset: 0,
|
offset: 0,
|
||||||
num: num || 1,
|
num: num || 1,
|
||||||
value,
|
value,
|
||||||
|
|
@ -273,12 +279,20 @@ export function getAllowedUnits(startDate: Date, endDate: Date) {
|
||||||
return index >= 0 ? units.splice(index) : [];
|
return index >= 0 ? units.splice(index) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMinimumUnit(startDate: number | Date, endDate: number | Date) {
|
export function getMinimumUnit(
|
||||||
|
startDate: number | Date,
|
||||||
|
endDate: number | Date,
|
||||||
|
isDateRange: boolean = false,
|
||||||
|
) {
|
||||||
if (differenceInMinutes(endDate, startDate) <= 60) {
|
if (differenceInMinutes(endDate, startDate) <= 60) {
|
||||||
return 'minute';
|
return 'minute';
|
||||||
} else if (differenceInHours(endDate, startDate) <= 48) {
|
} else if (
|
||||||
|
isDateRange
|
||||||
|
? differenceInHours(endDate, startDate) <= 48
|
||||||
|
: differenceInDays(endDate, startDate) <= 30
|
||||||
|
) {
|
||||||
return 'hour';
|
return 'hour';
|
||||||
} else if (differenceInCalendarMonths(endDate, startDate) <= 6) {
|
} else if (differenceInCalendarMonths(endDate, startDate) <= 7) {
|
||||||
return 'day';
|
return 'day';
|
||||||
} else if (differenceInCalendarMonths(endDate, startDate) <= 24) {
|
} else if (differenceInCalendarMonths(endDate, startDate) <= 24) {
|
||||||
return 'month';
|
return 'month';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue