mirror of
https://github.com/umami-software/umami.git
synced 2026-02-19 20:15:41 +01:00
Compare commits
No commits in common. "6751bf88bbc610de8d7f3bda11abb1aeb11e25b0" and "9fbcec46af355034a4c072dbe9018bef2d8a61b7" have entirely different histories.
6751bf88bb
...
9fbcec46af
11 changed files with 81 additions and 151 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
import { useDateRange, useTimezone } from '@/components/hooks';
|
import { useDateRange } from '@/components/hooks';
|
||||||
import { useWebsitePageviewsQuery } from '@/components/hooks/queries/useWebsitePageviewsQuery';
|
import { useWebsitePageviewsQuery } from '@/components/hooks/queries/useWebsitePageviewsQuery';
|
||||||
import { PageviewsChart } from '@/components/metrics/PageviewsChart';
|
import { PageviewsChart } from '@/components/metrics/PageviewsChart';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
@ -11,8 +11,7 @@ export function WebsiteChart({
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
compareMode?: boolean;
|
compareMode?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { timezone } = useTimezone();
|
const { dateRange, dateCompare } = useDateRange();
|
||||||
const { dateRange, dateCompare } = useDateRange({ timezone: timezone });
|
|
||||||
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,
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ export function useDateParameters() {
|
||||||
const {
|
const {
|
||||||
dateRange: { startDate, endDate, unit },
|
dateRange: { startDate, endDate, unit },
|
||||||
} = useDateRange();
|
} = useDateRange();
|
||||||
const { timezone, localToUtc, canonicalizeTimezone } = useTimezone();
|
const { timezone, toUtc, canonicalizeTimezone } = useTimezone();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
startAt: +localToUtc(startDate),
|
startAt: +toUtc(startDate),
|
||||||
endAt: +localToUtc(endDate),
|
endAt: +toUtc(endDate),
|
||||||
startDate: localToUtc(startDate).toISOString(),
|
startDate: toUtc(startDate).toISOString(),
|
||||||
endDate: localToUtc(endDate).toISOString(),
|
endDate: toUtc(endDate).toISOString(),
|
||||||
unit,
|
unit,
|
||||||
timezone: canonicalizeTimezone(timezone),
|
timezone: canonicalizeTimezone(timezone),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { useLocale } from '@/components/hooks/useLocale';
|
||||||
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
|
||||||
import { getItem } from '@/lib/storage';
|
import { getItem } from '@/lib/storage';
|
||||||
|
|
||||||
export function useDateRange(options: { ignoreOffset?: boolean; timezone?: string } = {}) {
|
export function useDateRange(options: { ignoreOffset?: boolean } = {}) {
|
||||||
const {
|
const {
|
||||||
query: { date = '', offset = 0, compare = 'prev' },
|
query: { date = '', offset = 0, compare = 'prev' },
|
||||||
} = useNavigation();
|
} = useNavigation();
|
||||||
|
|
@ -15,7 +15,6 @@ export function useDateRange(options: { ignoreOffset?: boolean; timezone?: strin
|
||||||
const dateRangeObject = parseDateRange(
|
const dateRangeObject = parseDateRange(
|
||||||
date || getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE,
|
date || getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE,
|
||||||
locale,
|
locale,
|
||||||
options.timezone,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return !options.ignoreOffset && offset
|
return !options.ignoreOffset && offset
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,11 @@ import { TIMEZONE_CONFIG, TIMEZONE_LEGACY } from '@/lib/constants';
|
||||||
import { formatInTimeZone, zonedTimeToUtc, utcToZonedTime } from 'date-fns-tz';
|
import { formatInTimeZone, zonedTimeToUtc, utcToZonedTime } from 'date-fns-tz';
|
||||||
import { useApp, setTimezone } from '@/store/app';
|
import { useApp, setTimezone } from '@/store/app';
|
||||||
import { useLocale } from './useLocale';
|
import { useLocale } from './useLocale';
|
||||||
import { getTimezone } from '@/lib/date';
|
|
||||||
|
|
||||||
const selector = (state: { timezone: string }) => state.timezone;
|
const selector = (state: { timezone: string }) => state.timezone;
|
||||||
|
|
||||||
export function useTimezone() {
|
export function useTimezone() {
|
||||||
const timezone = useApp(selector);
|
const timezone = useApp(selector);
|
||||||
const localTimeZone = getTimezone();
|
|
||||||
const { dateLocale } = useLocale();
|
const { dateLocale } = useLocale();
|
||||||
|
|
||||||
const saveTimezone = (value: string) => {
|
const saveTimezone = (value: string) => {
|
||||||
|
|
@ -28,38 +26,6 @@ export function useTimezone() {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatSeriesTimezone = (data: any, column: string, timezone: string) => {
|
|
||||||
return data.map(item => {
|
|
||||||
const date = new Date(item[column]);
|
|
||||||
|
|
||||||
const format = new Intl.DateTimeFormat('en-US', {
|
|
||||||
timeZone: timezone,
|
|
||||||
hour12: false,
|
|
||||||
year: 'numeric',
|
|
||||||
month: '2-digit',
|
|
||||||
day: '2-digit',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit',
|
|
||||||
});
|
|
||||||
|
|
||||||
const parts = format.formatToParts(date);
|
|
||||||
const get = type => parts.find(p => p.type === type)?.value;
|
|
||||||
|
|
||||||
const year = get('year');
|
|
||||||
const month = get('month');
|
|
||||||
const day = get('day');
|
|
||||||
const hour = get('hour');
|
|
||||||
const minute = get('minute');
|
|
||||||
const second = get('second');
|
|
||||||
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
[column]: `${year}-${month}-${day} ${hour}:${minute}:${second}`,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const toUtc = (date: Date | string | number) => {
|
const toUtc = (date: Date | string | number) => {
|
||||||
return zonedTimeToUtc(date, timezone);
|
return zonedTimeToUtc(date, timezone);
|
||||||
};
|
};
|
||||||
|
|
@ -68,28 +34,16 @@ export function useTimezone() {
|
||||||
return utcToZonedTime(date, timezone);
|
return utcToZonedTime(date, timezone);
|
||||||
};
|
};
|
||||||
|
|
||||||
const localToUtc = (date: Date | string | number) => {
|
|
||||||
return zonedTimeToUtc(date, localTimeZone);
|
|
||||||
};
|
|
||||||
|
|
||||||
const localFromUtc = (date: Date | string | number) => {
|
|
||||||
return utcToZonedTime(date, localTimeZone);
|
|
||||||
};
|
|
||||||
|
|
||||||
const canonicalizeTimezone = (timezone: string): string => {
|
const canonicalizeTimezone = (timezone: string): string => {
|
||||||
return TIMEZONE_LEGACY[timezone] ?? timezone;
|
return TIMEZONE_LEGACY[timezone] ?? timezone;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
timezone,
|
timezone,
|
||||||
localTimeZone,
|
|
||||||
toUtc,
|
|
||||||
fromUtc,
|
|
||||||
localToUtc,
|
|
||||||
localFromUtc,
|
|
||||||
saveTimezone,
|
saveTimezone,
|
||||||
formatTimezoneDate,
|
formatTimezoneDate,
|
||||||
formatSeriesTimezone,
|
toUtc,
|
||||||
|
fromUtc,
|
||||||
canonicalizeTimezone,
|
canonicalizeTimezone,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
import { BarChart, BarChartProps } from '@/components/charts/BarChart';
|
import { BarChart, BarChartProps } from '@/components/charts/BarChart';
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
import {
|
import { useDateRange, useLocale, useWebsiteEventsSeriesQuery } from '@/components/hooks';
|
||||||
useDateRange,
|
|
||||||
useLocale,
|
|
||||||
useTimezone,
|
|
||||||
useWebsiteEventsSeriesQuery,
|
|
||||||
} from '@/components/hooks';
|
|
||||||
import { renderDateLabels } from '@/lib/charts';
|
import { renderDateLabels } from '@/lib/charts';
|
||||||
import { CHART_COLORS } from '@/lib/constants';
|
import { CHART_COLORS } from '@/lib/constants';
|
||||||
import { generateTimeSeries } from '@/lib/date';
|
import { generateTimeSeries } from '@/lib/date';
|
||||||
|
|
@ -18,10 +13,9 @@ export interface EventsChartProps extends BarChartProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EventsChart({ websiteId, focusLabel }: EventsChartProps) {
|
export function EventsChart({ websiteId, focusLabel }: EventsChartProps) {
|
||||||
const { timezone } = useTimezone();
|
|
||||||
const {
|
const {
|
||||||
dateRange: { startDate, endDate, unit },
|
dateRange: { startDate, endDate, unit },
|
||||||
} = useDateRange({ timezone: timezone });
|
} = useDateRange();
|
||||||
const { locale, dateLocale } = useLocale();
|
const { locale, dateLocale } = useLocale();
|
||||||
const { data, isLoading, error } = useWebsiteEventsSeriesQuery(websiteId);
|
const { data, isLoading, error } = useWebsiteEventsSeriesQuery(websiteId);
|
||||||
const [label, setLabel] = useState<string>(focusLabel);
|
const [label, setLabel] = useState<string>(focusLabel);
|
||||||
|
|
@ -39,32 +33,20 @@ export function EventsChart({ websiteId, focusLabel }: EventsChartProps) {
|
||||||
return obj;
|
return obj;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
if (!map || Object.keys(map).length === 0) {
|
return {
|
||||||
return {
|
datasets: Object.keys(map).map((key, index) => {
|
||||||
datasets: [
|
const color = colord(CHART_COLORS[index % CHART_COLORS.length]);
|
||||||
{
|
return {
|
||||||
data: generateTimeSeries([], startDate, endDate, unit, dateLocale),
|
label: key,
|
||||||
lineTension: 0,
|
data: generateTimeSeries(map[key], startDate, endDate, unit, dateLocale),
|
||||||
borderWidth: 1,
|
lineTension: 0,
|
||||||
},
|
backgroundColor: color.alpha(0.6).toRgbString(),
|
||||||
],
|
borderColor: color.alpha(0.7).toRgbString(),
|
||||||
};
|
borderWidth: 1,
|
||||||
} else {
|
};
|
||||||
return {
|
}),
|
||||||
datasets: Object.keys(map).map((key, index) => {
|
focusLabel,
|
||||||
const color = colord(CHART_COLORS[index % CHART_COLORS.length]);
|
};
|
||||||
return {
|
|
||||||
label: key,
|
|
||||||
data: generateTimeSeries(map[key], startDate, endDate, unit, dateLocale),
|
|
||||||
lineTension: 0,
|
|
||||||
backgroundColor: color.alpha(0.6).toRgbString(),
|
|
||||||
borderColor: color.alpha(0.7).toRgbString(),
|
|
||||||
borderWidth: 1,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
focusLabel,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [data, startDate, endDate, unit, focusLabel]);
|
}, [data, startDate, endDate, unit, focusLabel]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,16 @@ export function MetricLabel({ type, data }: MetricLabelProps) {
|
||||||
const { getRegionName } = useRegionNames(locale);
|
const { getRegionName } = useRegionNames(locale);
|
||||||
|
|
||||||
const { label, country, domain } = data;
|
const { label, country, domain } = data;
|
||||||
|
const isType = ['browser', 'country', 'device', 'os'].includes(type);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'browser':
|
case 'browser':
|
||||||
case 'os':
|
|
||||||
return (
|
return (
|
||||||
<FilterLink
|
<FilterLink
|
||||||
type={type}
|
type="browser"
|
||||||
value={label}
|
value={label}
|
||||||
label={formatValue(label, type)}
|
label={formatValue(label, 'browser')}
|
||||||
icon={<TypeIcon type={type} value={label} />}
|
icon={<TypeIcon type="browser" value={label} />}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ export function MetricLabel({ type, data }: MetricLabelProps) {
|
||||||
type="device"
|
type="device"
|
||||||
value={labels[label] && label}
|
value={labels[label] && label}
|
||||||
label={formatValue(label, 'device')}
|
label={formatValue(label, 'device')}
|
||||||
icon={<TypeIcon type="device" value={label} />}
|
icon={<TypeIcon type="device" value={label?.toLowerCase()} />}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -141,6 +141,14 @@ export function MetricLabel({ type, data }: MetricLabelProps) {
|
||||||
<FilterLink
|
<FilterLink
|
||||||
type={type}
|
type={type}
|
||||||
value={label}
|
value={label}
|
||||||
|
icon={
|
||||||
|
isType && (
|
||||||
|
<TypeIcon
|
||||||
|
type={type as 'browser' | 'country' | 'device' | 'os'}
|
||||||
|
value={label?.toLowerCase()?.replaceAll(/\W/g, '-')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { startOfMinute, subMinutes, isBefore } from 'date-fns';
|
||||||
import { PageviewsChart } from './PageviewsChart';
|
import { PageviewsChart } from './PageviewsChart';
|
||||||
import { DEFAULT_ANIMATION_DURATION, REALTIME_RANGE } from '@/lib/constants';
|
import { DEFAULT_ANIMATION_DURATION, REALTIME_RANGE } from '@/lib/constants';
|
||||||
import { RealtimeData } from '@/lib/types';
|
import { RealtimeData } from '@/lib/types';
|
||||||
import { useTimezone } from '@/components/hooks';
|
|
||||||
|
|
||||||
export interface RealtimeChartProps {
|
export interface RealtimeChartProps {
|
||||||
data: RealtimeData;
|
data: RealtimeData;
|
||||||
|
|
@ -12,7 +11,6 @@ export interface RealtimeChartProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RealtimeChart({ data, unit, ...props }: RealtimeChartProps) {
|
export function RealtimeChart({ data, unit, ...props }: RealtimeChartProps) {
|
||||||
const { formatSeriesTimezone, fromUtc, timezone } = useTimezone();
|
|
||||||
const endDate = startOfMinute(new Date());
|
const endDate = startOfMinute(new Date());
|
||||||
const startDate = subMinutes(endDate, REALTIME_RANGE);
|
const startDate = subMinutes(endDate, REALTIME_RANGE);
|
||||||
const prevEndDate = useRef(endDate);
|
const prevEndDate = useRef(endDate);
|
||||||
|
|
@ -23,8 +21,8 @@ export function RealtimeChart({ data, unit, ...props }: RealtimeChartProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pageviews: formatSeriesTimezone(data.series.views, 'x', timezone),
|
pageviews: data.series.views,
|
||||||
sessions: formatSeriesTimezone(data.series.visitors, 'x', timezone),
|
sessions: data.series.visitors,
|
||||||
};
|
};
|
||||||
}, [data, startDate, endDate, unit]);
|
}, [data, startDate, endDate, unit]);
|
||||||
|
|
||||||
|
|
@ -40,8 +38,8 @@ export function RealtimeChart({ data, unit, ...props }: RealtimeChartProps) {
|
||||||
return (
|
return (
|
||||||
<PageviewsChart
|
<PageviewsChart
|
||||||
{...props}
|
{...props}
|
||||||
minDate={fromUtc(startDate)}
|
minDate={startDate}
|
||||||
maxDate={fromUtc(endDate)}
|
maxDate={endDate}
|
||||||
unit={unit}
|
unit={unit}
|
||||||
data={chartData}
|
data={chartData}
|
||||||
animationDuration={animationDuration}
|
animationDuration={animationDuration}
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,12 @@ function getUTCString(date?: Date | string | number) {
|
||||||
return formatInTimeZone(date || new Date(), 'UTC', 'yyyy-MM-dd HH:mm:ss');
|
return formatInTimeZone(date || new Date(), 'UTC', 'yyyy-MM-dd HH:mm:ss');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDateStringSQL(field: string, unit: string, timezone?: string) {
|
function getDateStringSQL(data: any, unit: string = 'utc', timezone?: string) {
|
||||||
if (timezone) {
|
if (timezone) {
|
||||||
return `formatDateTime(${field}, '${CLICKHOUSE_DATE_FORMATS[unit]}', '${timezone}')`;
|
return `formatDateTime(${data}, '${CLICKHOUSE_DATE_FORMATS[unit]}', '${timezone}')`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `formatDateTime(${field}, '${CLICKHOUSE_DATE_FORMATS[unit]}')`;
|
return `formatDateTime(${data}, '${CLICKHOUSE_DATE_FORMATS[unit]}')`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDateSQL(field: string, unit: string, timezone?: string) {
|
function getDateSQL(field: string, unit: string, timezone?: string) {
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,44 @@
|
||||||
import { getDateLocale } from '@/lib/lang';
|
|
||||||
import { DateRange } from '@/lib/types';
|
|
||||||
import {
|
import {
|
||||||
addDays,
|
|
||||||
addHours,
|
|
||||||
addMinutes,
|
addMinutes,
|
||||||
|
addHours,
|
||||||
|
addDays,
|
||||||
addMonths,
|
addMonths,
|
||||||
addWeeks,
|
|
||||||
addYears,
|
addYears,
|
||||||
differenceInCalendarDays,
|
subMinutes,
|
||||||
differenceInCalendarMonths,
|
subHours,
|
||||||
differenceInCalendarWeeks,
|
subDays,
|
||||||
differenceInCalendarYears,
|
subMonths,
|
||||||
differenceInHours,
|
subYears,
|
||||||
differenceInMinutes,
|
startOfMinute,
|
||||||
endOfDay,
|
startOfHour,
|
||||||
|
startOfDay,
|
||||||
|
startOfWeek,
|
||||||
|
startOfMonth,
|
||||||
|
startOfYear,
|
||||||
endOfHour,
|
endOfHour,
|
||||||
endOfMinute,
|
endOfDay,
|
||||||
endOfMonth,
|
|
||||||
endOfWeek,
|
endOfWeek,
|
||||||
|
endOfMonth,
|
||||||
endOfYear,
|
endOfYear,
|
||||||
|
differenceInMinutes,
|
||||||
|
differenceInHours,
|
||||||
|
differenceInCalendarDays,
|
||||||
|
differenceInCalendarWeeks,
|
||||||
|
differenceInCalendarMonths,
|
||||||
|
differenceInCalendarYears,
|
||||||
format,
|
format,
|
||||||
isBefore,
|
|
||||||
isDate,
|
|
||||||
isEqual,
|
|
||||||
isSameDay,
|
|
||||||
max,
|
max,
|
||||||
min,
|
min,
|
||||||
startOfDay,
|
isDate,
|
||||||
startOfHour,
|
addWeeks,
|
||||||
startOfMinute,
|
|
||||||
startOfMonth,
|
|
||||||
startOfWeek,
|
|
||||||
startOfYear,
|
|
||||||
subDays,
|
|
||||||
subHours,
|
|
||||||
subMinutes,
|
|
||||||
subMonths,
|
|
||||||
subWeeks,
|
subWeeks,
|
||||||
subYears,
|
endOfMinute,
|
||||||
|
isSameDay,
|
||||||
|
isBefore,
|
||||||
|
isEqual,
|
||||||
} from 'date-fns';
|
} from 'date-fns';
|
||||||
import { utcToZonedTime } from 'date-fns-tz';
|
import { getDateLocale } from '@/lib/lang';
|
||||||
|
import { DateRange } from '@/lib/types';
|
||||||
|
|
||||||
export const TIME_UNIT = {
|
export const TIME_UNIT = {
|
||||||
minute: 'minute',
|
minute: 'minute',
|
||||||
|
|
@ -136,7 +135,7 @@ 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, locale = 'en-US'): DateRange {
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -157,8 +156,7 @@ export function parseDateRange(value: string, locale = 'en-US', timezone?: strin
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const date = new Date();
|
const now = new Date();
|
||||||
const now = timezone ? utcToZonedTime(date, timezone) : date;
|
|
||||||
const dateLocale = getDateLocale(locale);
|
const dateLocale = getDateLocale(locale);
|
||||||
const { num = 1, unit } = parseDateValue(value);
|
const { num = 1, unit } = parseDateValue(value);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,6 @@ const DATE_FORMATS = {
|
||||||
year: 'YYYY-01-01 HH24:00:00',
|
year: 'YYYY-01-01 HH24:00:00',
|
||||||
};
|
};
|
||||||
|
|
||||||
const DATE_FORMATS_UTC = {
|
|
||||||
minute: 'YYYY-MM-DD"T"HH24:MI:00"Z"',
|
|
||||||
hour: 'YYYY-MM-DD"T"HH24:00:00"Z"',
|
|
||||||
day: 'YYYY-MM-DD"T"HH24:00:00"Z"',
|
|
||||||
month: 'YYYY-MM-01"T"HH24:00:00"Z"',
|
|
||||||
year: 'YYYY-01-01"T"HH24:00:00"Z"',
|
|
||||||
};
|
|
||||||
|
|
||||||
function getAddIntervalQuery(field: string, interval: string): string {
|
function getAddIntervalQuery(field: string, interval: string): string {
|
||||||
return `${field} + interval '${interval}'`;
|
return `${field} + interval '${interval}'`;
|
||||||
}
|
}
|
||||||
|
|
@ -48,11 +40,11 @@ function getCastColumnQuery(field: string, type: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDateSQL(field: string, unit: string, timezone?: string): string {
|
function getDateSQL(field: string, unit: string, timezone?: string): string {
|
||||||
if (timezone && timezone !== 'utc') {
|
if (timezone) {
|
||||||
return `to_char(date_trunc('${unit}', ${field} at time zone '${timezone}'), '${DATE_FORMATS[unit]}')`;
|
return `to_char(date_trunc('${unit}', ${field} at time zone '${timezone}'), '${DATE_FORMATS[unit]}')`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `to_char(date_trunc('${unit}', ${field}), '${DATE_FORMATS_UTC[unit]}')`;
|
return `to_char(date_trunc('${unit}', ${field}), '${DATE_FORMATS[unit]}')`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDateWeeklySQL(field: string, timezone?: string) {
|
function getDateWeeklySQL(field: string, timezone?: string) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { QueryFilters } from '@/lib/types';
|
|
||||||
import { getRealtimeActivity } from '@/queries/sql/getRealtimeActivity';
|
|
||||||
import { getPageviewStats } from '@/queries/sql/pageviews/getPageviewStats';
|
import { getPageviewStats } from '@/queries/sql/pageviews/getPageviewStats';
|
||||||
|
import { getRealtimeActivity } from '@/queries/sql/getRealtimeActivity';
|
||||||
import { getSessionStats } from '@/queries/sql/sessions/getSessionStats';
|
import { getSessionStats } from '@/queries/sql/sessions/getSessionStats';
|
||||||
|
import { QueryFilters } from '@/lib/types';
|
||||||
|
|
||||||
function increment(data: object, key: string) {
|
function increment(data: object, key: string) {
|
||||||
if (key) {
|
if (key) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue