mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-16 02:05:04 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
56ee52e349
@ -13,6 +13,7 @@ export function DateFilter({
|
||||
endDate,
|
||||
className,
|
||||
onChange,
|
||||
selectedUnit,
|
||||
showAllTime = false,
|
||||
alignment = 'end',
|
||||
}) {
|
||||
@ -66,7 +67,12 @@ export function DateFilter({
|
||||
|
||||
const renderValue = value => {
|
||||
return value.startsWith('range') ? (
|
||||
<CustomRange startDate={startDate} endDate={endDate} onClick={() => handleChange('custom')} />
|
||||
<CustomRange
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
selectedUnit={selectedUnit}
|
||||
onClick={() => handleChange('custom')}
|
||||
/>
|
||||
) : (
|
||||
options.find(e => e.value === value).label
|
||||
);
|
||||
@ -120,9 +126,11 @@ export function DateFilter({
|
||||
);
|
||||
}
|
||||
|
||||
const CustomRange = ({ startDate, endDate, onClick }) => {
|
||||
const CustomRange = ({ startDate, endDate, selectedUnit, onClick }) => {
|
||||
const { locale } = useLocale();
|
||||
|
||||
const monthFormat = +selectedUnit?.num === 1 && selectedUnit?.unit === 'month';
|
||||
|
||||
function handleClick(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
@ -135,8 +143,14 @@ const CustomRange = ({ startDate, endDate, onClick }) => {
|
||||
<Icons.Calendar />
|
||||
</Icon>
|
||||
<Text>
|
||||
{formatDate(startDate, 'd LLL y', locale)}
|
||||
{!isSameDay(startDate, endDate) && ` — ${formatDate(endDate, 'd LLL y', locale)}`}
|
||||
{monthFormat ? (
|
||||
<>{formatDate(startDate, 'MMMM yyyy', locale)}</>
|
||||
) : (
|
||||
<>
|
||||
{formatDate(startDate, 'd LLL y', locale)}
|
||||
{!isSameDay(startDate, endDate) && ` — ${formatDate(endDate, 'd LLL y', locale)}`}
|
||||
</>
|
||||
)}
|
||||
</Text>
|
||||
</Flexbox>
|
||||
);
|
||||
|
@ -1,24 +1,51 @@
|
||||
import useDateRange from 'components/hooks/useDateRange';
|
||||
import { isAfter } from 'date-fns';
|
||||
import { incrementDateRange } from 'lib/date';
|
||||
import { Button, Flexbox, Icon, Icons } from 'react-basics';
|
||||
import DateFilter from './DateFilter';
|
||||
import styles from './WebsiteDateFilter.module.css';
|
||||
|
||||
export function WebsiteDateFilter({ websiteId }) {
|
||||
const [dateRange, setDateRange] = useDateRange(websiteId);
|
||||
const { value, startDate, endDate } = dateRange;
|
||||
const { value, startDate, endDate, selectedUnit } = dateRange;
|
||||
|
||||
const isFutureDate = isAfter(incrementDateRange(dateRange, -1).startDate, new Date());
|
||||
|
||||
const handleChange = async value => {
|
||||
setDateRange(value);
|
||||
};
|
||||
|
||||
const handleIncrement = async value => {
|
||||
const newValue = incrementDateRange(dateRange, value);
|
||||
|
||||
setDateRange(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<DateFilter
|
||||
className={styles.dropdown}
|
||||
value={value}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onChange={handleChange}
|
||||
showAllTime={true}
|
||||
/>
|
||||
<>
|
||||
<DateFilter
|
||||
className={styles.dropdown}
|
||||
value={value}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
selectedUnit={selectedUnit}
|
||||
onChange={handleChange}
|
||||
showAllTime={true}
|
||||
/>
|
||||
<Flexbox justifyContent="center" gap={10} className={styles.container}>
|
||||
<Button onClick={() => handleIncrement(1)}>
|
||||
<Icon rotate={90}>
|
||||
<Icons.ChevronDown />
|
||||
</Icon>
|
||||
</Button>
|
||||
|
||||
<Button onClick={() => handleIncrement(-1)} disabled={isFutureDate}>
|
||||
<Icon rotate={270}>
|
||||
<Icons.ChevronDown />
|
||||
</Icon>
|
||||
</Button>
|
||||
</Flexbox>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -110,8 +110,8 @@ export function WebsiteMetricsBar({ websiteId, sticky }) {
|
||||
</Column>
|
||||
<Column defaultSize={12} xl={4}>
|
||||
<div className={styles.actions}>
|
||||
<RefreshButton websiteId={websiteId} />
|
||||
<WebsiteDateFilter websiteId={websiteId} />
|
||||
<RefreshButton websiteId={websiteId} />
|
||||
</div>
|
||||
</Column>
|
||||
</Row>
|
||||
|
@ -29,9 +29,19 @@ import {
|
||||
max,
|
||||
min,
|
||||
isDate,
|
||||
subWeeks,
|
||||
} from 'date-fns';
|
||||
import { getDateLocale } from 'lib/lang';
|
||||
|
||||
export const TIME_UNIT = {
|
||||
minute: 'minute',
|
||||
hour: 'hour',
|
||||
day: 'day',
|
||||
week: 'week',
|
||||
month: 'month',
|
||||
year: 'year',
|
||||
};
|
||||
|
||||
const dateFuncs = {
|
||||
minute: [differenceInMinutes, addMinutes, startOfMinute],
|
||||
hour: [differenceInHours, addHours, startOfHour],
|
||||
@ -81,6 +91,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
if (!match) return null;
|
||||
|
||||
const { num, unit } = match.groups;
|
||||
const selectedUnit = { num, unit };
|
||||
|
||||
if (+num === 1) {
|
||||
switch (unit) {
|
||||
@ -90,6 +101,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: endOfDay(now),
|
||||
unit: 'hour',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
case 'week':
|
||||
return {
|
||||
@ -97,6 +109,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: endOfWeek(now, { locale: dateLocale }),
|
||||
unit: 'day',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
case 'month':
|
||||
return {
|
||||
@ -104,6 +117,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: endOfMonth(now),
|
||||
unit: 'day',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
case 'year':
|
||||
return {
|
||||
@ -111,6 +125,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: endOfYear(now),
|
||||
unit: 'month',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -123,6 +138,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: subDays(endOfDay(now), 1),
|
||||
unit: 'hour',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
case 'week':
|
||||
return {
|
||||
@ -130,6 +146,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: subDays(endOfWeek(now, { locale: dateLocale }), 1),
|
||||
unit: 'day',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
case 'month':
|
||||
return {
|
||||
@ -137,6 +154,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: subMonths(endOfMonth(now), 1),
|
||||
unit: 'day',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
case 'year':
|
||||
return {
|
||||
@ -144,6 +162,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: subYears(endOfYear(now), 1),
|
||||
unit: 'month',
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -155,6 +174,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: endOfDay(now),
|
||||
unit,
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
case 'hour':
|
||||
return {
|
||||
@ -162,6 +182,46 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
endDate: endOfHour(now),
|
||||
unit,
|
||||
value,
|
||||
selectedUnit,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function incrementDateRange(value, increment) {
|
||||
const { startDate, endDate, selectedUnit } = value;
|
||||
|
||||
const { num, unit } = selectedUnit;
|
||||
|
||||
const sub = num * increment;
|
||||
|
||||
switch (unit) {
|
||||
case 'day':
|
||||
return {
|
||||
...value,
|
||||
startDate: subDays(startDate, sub),
|
||||
endDate: subDays(endDate, sub),
|
||||
value: 'range',
|
||||
};
|
||||
case 'week':
|
||||
return {
|
||||
...value,
|
||||
startDate: subWeeks(startDate, sub),
|
||||
endDate: subWeeks(endDate, sub),
|
||||
value: 'range',
|
||||
};
|
||||
case 'month':
|
||||
return {
|
||||
...value,
|
||||
startDate: subMonths(startDate, sub),
|
||||
endDate: subMonths(endDate, sub),
|
||||
value: 'range',
|
||||
};
|
||||
case 'year':
|
||||
return {
|
||||
...value,
|
||||
startDate: subYears(startDate, sub),
|
||||
endDate: subYears(endDate, sub),
|
||||
value: 'range',
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -237,7 +297,7 @@ export function getDateLength(startDate, endDate, unit) {
|
||||
return diff(endDate, startDate) + 1;
|
||||
}
|
||||
|
||||
export const customFormats = {
|
||||
export const CUSTOM_FORMATS = {
|
||||
'en-US': {
|
||||
p: 'ha',
|
||||
pp: 'h:mm:ss',
|
||||
@ -252,7 +312,7 @@ export const customFormats = {
|
||||
export function formatDate(date, str, locale = 'en-US') {
|
||||
return format(
|
||||
typeof date === 'string' ? new Date(date) : date,
|
||||
customFormats?.[locale]?.[str] || str,
|
||||
CUSTOM_FORMATS?.[locale]?.[str] || str,
|
||||
{
|
||||
locale: getDateLocale(locale),
|
||||
},
|
||||
|
@ -12,9 +12,12 @@ import {
|
||||
WEBSITE_FILTER_TYPES,
|
||||
} from './constants';
|
||||
import * as yup from 'yup';
|
||||
import { TIME_UNIT } from './date';
|
||||
|
||||
type ObjectValues<T> = T[keyof T];
|
||||
|
||||
export type TimeUnit = ObjectValues<typeof TIME_UNIT>;
|
||||
|
||||
export type CollectionType = ObjectValues<typeof COLLECTION_TYPE>;
|
||||
export type Role = ObjectValues<typeof ROLES>;
|
||||
export type EventType = ObjectValues<typeof EVENT_TYPE>;
|
||||
@ -181,6 +184,8 @@ export interface DateRange {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
value: string;
|
||||
unit?: TimeUnit;
|
||||
selectedUnit?: TimeUnit;
|
||||
}
|
||||
|
||||
export interface QueryFilters {
|
||||
|
@ -20,7 +20,8 @@
|
||||
"baseUrl": "./src",
|
||||
"strictNullChecks": false,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve"
|
||||
"jsx": "preserve",
|
||||
"incremental": true
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
|
Loading…
Reference in New Issue
Block a user