mirror of
https://github.com/umami-software/umami.git
synced 2025-12-08 05:12:36 +01:00
Separated query string date handling. Fixed all time date.
This commit is contained in:
parent
1def80ba42
commit
b36cd48b4a
7 changed files with 86 additions and 66 deletions
|
|
@ -1,21 +1,24 @@
|
||||||
|
import { useState } from 'react';
|
||||||
import { DateFilter } from '@/components/input/DateFilter';
|
import { DateFilter } from '@/components/input/DateFilter';
|
||||||
import { Button, Row } from '@umami/react-zen';
|
import { Button, Row } from '@umami/react-zen';
|
||||||
import { useDateRange, useMessages } from '@/components/hooks';
|
import { useMessages } from '@/components/hooks';
|
||||||
import { DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
||||||
|
import { setItem, getItem } from '@/lib/storage';
|
||||||
|
|
||||||
export function DateRangeSetting() {
|
export function DateRangeSetting() {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const { dateRange, saveDateRange } = useDateRange();
|
const [date, setDate] = useState(getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE);
|
||||||
const { value } = dateRange;
|
|
||||||
|
|
||||||
const handleChange = (value: string) => {
|
const handleChange = (value: string) => {
|
||||||
saveDateRange(value);
|
setItem(DATE_RANGE_CONFIG, value);
|
||||||
|
setDate(value);
|
||||||
};
|
};
|
||||||
const handleReset = () => saveDateRange(DEFAULT_DATE_RANGE_VALUE);
|
|
||||||
|
const handleReset = () => setItem(DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gap="3">
|
<Row gap="3">
|
||||||
<DateFilter value={value} onChange={handleChange} placement="bottom start" />
|
<DateFilter value={date} onChange={handleChange} placement="bottom start" />
|
||||||
<Button onPress={handleReset}>{formatMessage(labels.reset)}</Button>
|
<Button onPress={handleReset}>{formatMessage(labels.reset)}</Button>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export function WebsiteChart({
|
||||||
const { startDate, endDate, unit, value } = dateRange;
|
const { startDate, endDate, unit, value } = dateRange;
|
||||||
const { data, isLoading, isFetching, error } = useWebsitePageviewsQuery({
|
const { data, isLoading, isFetching, error } = useWebsitePageviewsQuery({
|
||||||
websiteId,
|
websiteId,
|
||||||
compare: compareMode ? dateCompare : undefined,
|
compare: compareMode ? dateCompare?.['value'] : undefined,
|
||||||
});
|
});
|
||||||
const { pageviews, sessions, compare } = (data || {}) as any;
|
const { pageviews, sessions, compare } = (data || {}) as any;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export * from './context/useWebsite';
|
||||||
|
|
||||||
// Query hooks
|
// Query hooks
|
||||||
export * from './queries/useActiveUsersQuery';
|
export * from './queries/useActiveUsersQuery';
|
||||||
|
export * from './queries/useDateRangeQuery';
|
||||||
export * from './queries/useDeleteQuery';
|
export * from './queries/useDeleteQuery';
|
||||||
export * from './queries/useEventDataEventsQuery';
|
export * from './queries/useEventDataEventsQuery';
|
||||||
export * from './queries/useEventDataPropertiesQuery';
|
export * from './queries/useEventDataPropertiesQuery';
|
||||||
|
|
@ -76,6 +77,7 @@ export * from './useModified';
|
||||||
export * from './useNavigation';
|
export * from './useNavigation';
|
||||||
export * from './usePagedQuery';
|
export * from './usePagedQuery';
|
||||||
export * from './usePageParameters';
|
export * from './usePageParameters';
|
||||||
|
export * from './useQueryStringDate';
|
||||||
export * from './useRegionNames';
|
export * from './useRegionNames';
|
||||||
export * from './useSlug';
|
export * from './useSlug';
|
||||||
export * from './useSticky';
|
export * from './useSticky';
|
||||||
|
|
|
||||||
12
src/components/hooks/queries/useDateRangeQuery.ts
Normal file
12
src/components/hooks/queries/useDateRangeQuery.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { useApi } from '../useApi';
|
||||||
|
import { ReactQueryOptions } from '@/lib/types';
|
||||||
|
|
||||||
|
export function useDateRangeQuery(websiteId: string, options?: ReactQueryOptions) {
|
||||||
|
const { get, useQuery } = useApi();
|
||||||
|
return useQuery<any>({
|
||||||
|
queryKey: ['date-range', websiteId],
|
||||||
|
queryFn: () => get(`/websites/${websiteId}/daterange`),
|
||||||
|
enabled: !!websiteId,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,65 +1,35 @@
|
||||||
import { useMemo } from 'react';
|
import { getMinimumUnit, parseDateRange } from '@/lib/date';
|
||||||
import { getMinimumUnit, parseDateRange, getOffsetDateRange } from '@/lib/date';
|
import { useLocale } from '@/components/hooks/useLocale';
|
||||||
import { setItem } from '@/lib/storage';
|
import { useApi } from '@/components/hooks//useApi';
|
||||||
import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
import { useQueryStringDate } from '@/components/hooks/useQueryStringDate';
|
||||||
import { setWebsiteDateCompare, setWebsiteDateRange, useWebsites } from '@/store/websites';
|
import { useGlobalState } from '@/components/hooks/useGlobalState';
|
||||||
import { setDateRangeValue, useApp } from '@/store/app';
|
|
||||||
import { useLocale } from './useLocale';
|
|
||||||
import { useApi } from './useApi';
|
|
||||||
import { useNavigation } from './useNavigation';
|
|
||||||
|
|
||||||
export interface UseDateRangeOptions {
|
export function useDateRange(websiteId: string) {
|
||||||
ignoreOffset?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDateRange(websiteId?: string, options: UseDateRangeOptions = {}) {
|
|
||||||
const { get } = useApi();
|
const { get } = useApi();
|
||||||
const { locale } = useLocale();
|
const { locale } = useLocale();
|
||||||
const {
|
const { dateRange: defaultDateRange, dateCompare } = useQueryStringDate();
|
||||||
query: { date, offset = 0 },
|
|
||||||
} = useNavigation();
|
|
||||||
const websiteConfig = useWebsites(state => state[websiteId]?.dateRange);
|
|
||||||
const globalConfig = useApp(state => state.dateRangeValue);
|
|
||||||
const dateValue = websiteConfig?.value || date || globalConfig || DEFAULT_DATE_RANGE_VALUE;
|
|
||||||
|
|
||||||
const dateRange = useMemo(() => {
|
const [dateRange, setDateRange] = useGlobalState(`date-range:${websiteId}`, defaultDateRange);
|
||||||
const dateRangeObject = parseDateRange(dateValue, locale);
|
|
||||||
|
|
||||||
return !options.ignoreOffset && offset
|
const setDateRangeValue = async (value: string) => {
|
||||||
? getOffsetDateRange(dateRangeObject, +offset)
|
if (value === 'all') {
|
||||||
: dateRangeObject;
|
const result = await get(`/websites/${websiteId}/daterange`);
|
||||||
}, [date, offset, dateValue, options]);
|
const { mindate, maxdate } = result;
|
||||||
|
|
||||||
const dateCompare = useWebsites(state => state[websiteId]?.dateCompare || DEFAULT_DATE_COMPARE);
|
const startDate = new Date(mindate);
|
||||||
|
const endDate = new Date(maxdate);
|
||||||
|
const unit = getMinimumUnit(startDate, endDate);
|
||||||
|
|
||||||
const saveDateRange = async (value: string) => {
|
setDateRange({
|
||||||
if (websiteId) {
|
startDate,
|
||||||
if (value === 'all') {
|
endDate,
|
||||||
const result: any = await get(`/websites/${websiteId}/daterange`);
|
unit,
|
||||||
const { mindate, maxdate } = result;
|
value,
|
||||||
|
});
|
||||||
const startDate = new Date(mindate);
|
|
||||||
const endDate = new Date(maxdate);
|
|
||||||
const unit = getMinimumUnit(startDate, endDate);
|
|
||||||
|
|
||||||
setWebsiteDateRange(websiteId, {
|
|
||||||
startDate,
|
|
||||||
endDate,
|
|
||||||
unit,
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setWebsiteDateRange(websiteId, parseDateRange(value, locale));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setItem(DATE_RANGE_CONFIG, value);
|
setDateRange(parseDateRange(value, locale));
|
||||||
setDateRangeValue(value);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveDateCompare = (value: string) => {
|
return { dateRange, dateCompare, setDateRange, setDateRangeValue };
|
||||||
setWebsiteDateCompare(websiteId, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
return { dateRange, saveDateRange, dateCompare, saveDateCompare };
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
src/components/hooks/useQueryStringDate.ts
Normal file
24
src/components/hooks/useQueryStringDate.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { useNavigation } from '@/components/hooks/useNavigation';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { getCompareDate, getOffsetDateRange, parseDateRange } from '@/lib/date';
|
||||||
|
import { useLocale } from '@/components/hooks/useLocale';
|
||||||
|
import { DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
||||||
|
|
||||||
|
export function useQueryStringDate(options: { ignoreOffset?: boolean } = {}) {
|
||||||
|
const {
|
||||||
|
query: { date = DEFAULT_DATE_RANGE_VALUE, offset = 0, compare = 'prev' },
|
||||||
|
} = useNavigation();
|
||||||
|
const { locale } = useLocale();
|
||||||
|
|
||||||
|
const dateRange = useMemo(() => {
|
||||||
|
const dateRangeObject = parseDateRange(date, locale);
|
||||||
|
|
||||||
|
return !options.ignoreOffset && offset
|
||||||
|
? getOffsetDateRange(dateRangeObject, +offset)
|
||||||
|
: dateRangeObject;
|
||||||
|
}, [date, offset, options]);
|
||||||
|
|
||||||
|
const dateCompare = getCompareDate(compare, dateRange.startDate, dateRange.endDate);
|
||||||
|
|
||||||
|
return { date, offset, dateRange, dateCompare };
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,8 @@ import { isAfter } from 'date-fns';
|
||||||
import { ChevronRight } from '@/components/icons';
|
import { ChevronRight } from '@/components/icons';
|
||||||
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
|
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
|
||||||
import { DateFilter } from './DateFilter';
|
import { DateFilter } from './DateFilter';
|
||||||
|
import { getOffsetDateRange } from '@/lib/date';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
export interface WebsiteDateFilterProps {
|
export interface WebsiteDateFilterProps {
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
|
|
@ -18,7 +20,7 @@ export function WebsiteDateFilter({
|
||||||
showButtons = true,
|
showButtons = true,
|
||||||
allowCompare,
|
allowCompare,
|
||||||
}: WebsiteDateFilterProps) {
|
}: WebsiteDateFilterProps) {
|
||||||
const { dateRange, saveDateRange } = useDateRange(websiteId);
|
const { dateRange, setDateRange, setDateRangeValue } = useDateRange(websiteId);
|
||||||
const { value, endDate } = dateRange;
|
const { value, endDate } = dateRange;
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const {
|
const {
|
||||||
|
|
@ -27,18 +29,25 @@ export function WebsiteDateFilter({
|
||||||
query: { compare = 'prev', offset = 0 },
|
query: { compare = 'prev', offset = 0 },
|
||||||
} = useNavigation();
|
} = useNavigation();
|
||||||
const isAllTime = value === 'all';
|
const isAllTime = value === 'all';
|
||||||
|
|
||||||
const isCustomRange = value.startsWith('range');
|
const isCustomRange = value.startsWith('range');
|
||||||
|
|
||||||
const disableForward = value === 'all' || isAfter(endDate, new Date());
|
const disableForward = value === 'all' || isAfter(endDate, new Date());
|
||||||
|
|
||||||
const handleChange = (date: string) => {
|
const handleChange = (date: string) => {
|
||||||
saveDateRange(date);
|
setDateRangeValue(date);
|
||||||
router.push(updateParams({ date, offset: undefined }));
|
router.push(updateParams({ date, offset: undefined }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleIncrement = (increment: number) => {
|
const handleIncrement = useCallback(
|
||||||
router.push(updateParams({ offset: +offset + increment }));
|
(increment: number) => {
|
||||||
};
|
const offsetDate = getOffsetDateRange(dateRange, +offset + increment);
|
||||||
|
|
||||||
|
setDateRange(offsetDate);
|
||||||
|
router.push(updateParams({ offset: +offset + increment }));
|
||||||
|
},
|
||||||
|
[offset],
|
||||||
|
);
|
||||||
|
|
||||||
const handleSelect = (compare: any) => {
|
const handleSelect = (compare: any) => {
|
||||||
router.push(updateParams({ compare }));
|
router.push(updateParams({ compare }));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue