mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 01:35:17 +01:00
Fixed date range calculations.
This commit is contained in:
parent
9f112c8cc9
commit
38abd673f3
@ -7,6 +7,9 @@ const filterOptions = [
|
|||||||
{ label: 'Last 7 days', value: '7day' },
|
{ label: 'Last 7 days', value: '7day' },
|
||||||
{ label: 'Last 30 days', value: '30day' },
|
{ label: 'Last 30 days', value: '30day' },
|
||||||
{ label: 'Last 90 days', value: '90day' },
|
{ label: 'Last 90 days', value: '90day' },
|
||||||
|
{ label: 'Today', value: '1day' },
|
||||||
|
{ label: 'This week', value: '1week' },
|
||||||
|
{ label: 'This month', value: '1month' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function DateFilter({ value, onChange }) {
|
export default function DateFilter({ value, onChange }) {
|
||||||
|
@ -9,13 +9,15 @@ export default function DropDown({ value, options = [], onChange }) {
|
|||||||
setShowMenu(state => !state);
|
setShowMenu(state => !state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelect(value) {
|
function handleSelect(value, e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
setShowMenu(false);
|
||||||
onChange(value);
|
onChange(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function hideMenu(e) {
|
function hideMenu(e) {
|
||||||
if (ref.current && !ref.current.contains(e.target)) {
|
if (!ref.current.contains(e.target)) {
|
||||||
setShowMenu(false);
|
setShowMenu(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,13 @@
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
border: 1px solid #b3b3b3;
|
border: 1px solid #b3b3b3;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.option {
|
.option {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export default function PageviewsChart({ data, unit, children }) {
|
|||||||
const n = data.pageviews.length;
|
const n = data.pageviews.length;
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case 'day':
|
case 'day':
|
||||||
if (n > 7) {
|
if (n >= 15) {
|
||||||
return index % ~~(n / 15) === 0 ? format(d, 'MMM d') : '';
|
return index % ~~(n / 15) === 0 ? format(d, 'MMM d') : '';
|
||||||
}
|
}
|
||||||
return format(d, 'EEE M/d');
|
return format(d, 'EEE M/d');
|
||||||
|
@ -10,7 +10,7 @@ import DateFilter from './DateFilter';
|
|||||||
export default function WebsiteChart({ title, websiteId }) {
|
export default function WebsiteChart({ title, websiteId }) {
|
||||||
const [data, setData] = useState();
|
const [data, setData] = useState();
|
||||||
const [dateRange, setDateRange] = useState(getDateRange('7day'));
|
const [dateRange, setDateRange] = useState(getDateRange('7day'));
|
||||||
const { startDate, endDate, unit } = dateRange;
|
const { startDate, endDate, unit, value } = dateRange;
|
||||||
|
|
||||||
const [pageviews, uniques] = useMemo(() => {
|
const [pageviews, uniques] = useMemo(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -46,10 +46,10 @@ export default function WebsiteChart({ title, websiteId }) {
|
|||||||
<div className={styles.title}>{title}</div>
|
<div className={styles.title}>{title}</div>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<MetricsBar websiteId={websiteId} startDate={startDate} endDate={endDate} />
|
<MetricsBar websiteId={websiteId} startDate={startDate} endDate={endDate} />
|
||||||
<DateFilter value={dateRange.value} onChange={handleDateChange} />
|
<DateFilter value={value} onChange={handleDateChange} />
|
||||||
</div>
|
</div>
|
||||||
<PageviewsChart data={{ pageviews, uniques }} unit={unit}>
|
<PageviewsChart data={{ pageviews, uniques }} unit={unit}>
|
||||||
<QuickButtons value={dateRange.value} onChange={handleDateChange} />
|
<QuickButtons value={value} onChange={handleDateChange} />
|
||||||
</PageviewsChart>
|
</PageviewsChart>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { get } from 'lib/web';
|
import { get } from 'lib/web';
|
||||||
import WebsiteChart from './WebsiteChart';
|
import WebsiteChart from './WebsiteChart';
|
||||||
import DateFilter from './DateFilter';
|
|
||||||
import styles from './WebsiteList.module.css';
|
import styles from './WebsiteList.module.css';
|
||||||
|
|
||||||
export default function WebsiteList() {
|
export default function WebsiteList() {
|
||||||
|
54
lib/date.js
54
lib/date.js
@ -7,10 +7,14 @@ import {
|
|||||||
subDays,
|
subDays,
|
||||||
startOfHour,
|
startOfHour,
|
||||||
startOfDay,
|
startOfDay,
|
||||||
|
startOfWeek,
|
||||||
|
startOfMonth,
|
||||||
endOfHour,
|
endOfHour,
|
||||||
endOfDay,
|
endOfDay,
|
||||||
|
endOfWeek,
|
||||||
|
endOfMonth,
|
||||||
differenceInHours,
|
differenceInHours,
|
||||||
differenceInDays,
|
differenceInCalendarDays,
|
||||||
} from 'date-fns';
|
} from 'date-fns';
|
||||||
|
|
||||||
export function getTimezone() {
|
export function getTimezone() {
|
||||||
@ -23,23 +27,47 @@ export function getLocalTime(t) {
|
|||||||
|
|
||||||
export function getDateRange(value) {
|
export function getDateRange(value) {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const hour = endOfHour(now);
|
|
||||||
const day = endOfDay(now);
|
|
||||||
|
|
||||||
const { num, unit } = value.match(/^(?<num>[0-9]+)(?<unit>hour|day)$/).groups;
|
const { num, unit } = value.match(/^(?<num>[0-9]+)(?<unit>hour|day|week|month)$/).groups;
|
||||||
|
|
||||||
|
if (+num === 1) {
|
||||||
|
switch (unit) {
|
||||||
|
case 'day':
|
||||||
|
return {
|
||||||
|
startDate: startOfDay(now),
|
||||||
|
endDate: endOfDay(now),
|
||||||
|
unit: 'hour',
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
case 'week':
|
||||||
|
return {
|
||||||
|
startDate: startOfWeek(now),
|
||||||
|
endDate: endOfWeek(now),
|
||||||
|
unit: 'day',
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
case 'month':
|
||||||
|
return {
|
||||||
|
startDate: startOfMonth(now),
|
||||||
|
endDate: endOfMonth(now),
|
||||||
|
unit: 'day',
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case 'day':
|
case 'day':
|
||||||
return {
|
return {
|
||||||
startDate: subDays(day, num),
|
startDate: subDays(startOfDay(now), num - 1),
|
||||||
endDate: day,
|
endDate: endOfDay(now),
|
||||||
unit,
|
unit,
|
||||||
value,
|
value,
|
||||||
};
|
};
|
||||||
case 'hour':
|
case 'hour':
|
||||||
return {
|
return {
|
||||||
startDate: subHours(hour, num),
|
startDate: subHours(startOfHour(now), num - 1),
|
||||||
endDate: hour,
|
endDate: endOfHour(now),
|
||||||
unit,
|
unit,
|
||||||
value,
|
value,
|
||||||
};
|
};
|
||||||
@ -48,20 +76,22 @@ export function getDateRange(value) {
|
|||||||
|
|
||||||
const dateFuncs = {
|
const dateFuncs = {
|
||||||
hour: [differenceInHours, addHours, startOfHour],
|
hour: [differenceInHours, addHours, startOfHour],
|
||||||
day: [differenceInDays, addDays, startOfDay],
|
day: [differenceInCalendarDays, addDays, startOfDay],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getDateArray(data, startDate, endDate, unit) {
|
export function getDateArray(data, startDate, endDate, unit) {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
const [diff, add, normalize] = dateFuncs[unit];
|
const [diff, add, normalize] = dateFuncs[unit];
|
||||||
const n = diff(endDate, startDate);
|
const n = diff(endDate, startDate) + 1;
|
||||||
|
|
||||||
function findData(t) {
|
function findData(t) {
|
||||||
return data.find(e => getLocalTime(e.t).getTime() === normalize(t).getTime())?.y || 0;
|
const x = data.find(e => new Date(e.t).getTime() === normalize(new Date(t)).getTime());
|
||||||
|
|
||||||
|
return x?.y || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
const t = add(startDate, i + 1);
|
const t = add(startDate, i);
|
||||||
const y = findData(t);
|
const y = findData(t);
|
||||||
|
|
||||||
arr.push({ t, y });
|
arr.push({ t, y });
|
||||||
|
@ -165,7 +165,7 @@ export async function getPageviewData(
|
|||||||
return runQuery(
|
return runQuery(
|
||||||
prisma.queryRaw(
|
prisma.queryRaw(
|
||||||
`
|
`
|
||||||
select date_trunc('${unit}', created_at at time zone '${timezone}') t,
|
select date_trunc('${unit}', created_at at time zone '${timezone}') at time zone '${timezone}' t,
|
||||||
count(${count}) y
|
count(${count}) y
|
||||||
from pageview
|
from pageview
|
||||||
where website_id=$1
|
where website_id=$1
|
||||||
|
Loading…
Reference in New Issue
Block a user