mirror of
https://github.com/kremalicious/umami.git
synced 2024-12-24 18:26:20 +01:00
Merge branch 'dev' of https://github.com/umami-software/umami into bug/um-200-fix-referrer-filters
This commit is contained in:
commit
ffb2771819
@ -1,4 +1,4 @@
|
|||||||
import { useState, useRef, useEffect, useMemo } from 'react';
|
import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
||||||
import { StatusLight } from 'react-basics';
|
import { StatusLight } from 'react-basics';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Chart from 'chart.js/auto';
|
import Chart from 'chart.js/auto';
|
||||||
@ -15,14 +15,14 @@ export default function BarChart({
|
|||||||
datasets,
|
datasets,
|
||||||
unit,
|
unit,
|
||||||
animationDuration = DEFAULT_ANIMATION_DURATION,
|
animationDuration = DEFAULT_ANIMATION_DURATION,
|
||||||
className,
|
|
||||||
stacked = false,
|
stacked = false,
|
||||||
loading = false,
|
loading = false,
|
||||||
onCreate = () => {},
|
onCreate = () => {},
|
||||||
onUpdate = () => {},
|
onUpdate = () => {},
|
||||||
|
className,
|
||||||
}) {
|
}) {
|
||||||
const canvas = useRef();
|
const canvas = useRef();
|
||||||
const chart = useRef();
|
const chart = useRef(null);
|
||||||
const [tooltip, setTooltip] = useState(null);
|
const [tooltip, setTooltip] = useState(null);
|
||||||
const { locale } = useLocale();
|
const { locale } = useLocale();
|
||||||
const [theme] = useTheme();
|
const [theme] = useTheme();
|
||||||
@ -39,34 +39,45 @@ export default function BarChart({
|
|||||||
return +label > 1000 ? formatLongNumber(label) : label;
|
return +label > 1000 ? formatLongNumber(label) : label;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderTooltip = model => {
|
const renderTooltip = useCallback(
|
||||||
const { opacity, labelColors, dataPoints } = model.tooltip;
|
model => {
|
||||||
|
const { opacity, labelColors, dataPoints } = model.tooltip;
|
||||||
|
|
||||||
if (!dataPoints?.length || !opacity) {
|
if (!dataPoints?.length || !opacity) {
|
||||||
setTooltip(null);
|
setTooltip(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const format = unit === 'hour' ? 'EEE p — PPP' : 'PPPP';
|
const formats = {
|
||||||
|
millisecond: 'T',
|
||||||
|
second: 'pp',
|
||||||
|
minute: 'p',
|
||||||
|
hour: 'h aaa',
|
||||||
|
day: 'PPPP',
|
||||||
|
week: 'PPPP',
|
||||||
|
month: 'LLLL yyyy',
|
||||||
|
quarter: 'qqq',
|
||||||
|
year: 'yyyy',
|
||||||
|
};
|
||||||
|
|
||||||
setTooltip(
|
setTooltip(
|
||||||
<>
|
<div className={styles.tooltip}>
|
||||||
<div>{dateFormat(new Date(dataPoints[0].raw.x), format, locale)}</div>
|
<div>{dateFormat(new Date(dataPoints[0].raw.x), formats[unit], locale)}</div>
|
||||||
<div>
|
<div>
|
||||||
<StatusLight color={labelColors?.[0]?.backgroundColor}>
|
<StatusLight color={labelColors?.[0]?.backgroundColor}>
|
||||||
<b>
|
<div className={styles.value}>
|
||||||
{formatLongNumber(dataPoints[0].raw.y)} {dataPoints[0].dataset.label}
|
{formatLongNumber(dataPoints[0].raw.y)} {dataPoints[0].dataset.label}
|
||||||
</b>
|
</div>
|
||||||
</StatusLight>
|
</StatusLight>
|
||||||
</div>
|
</div>
|
||||||
</>,
|
</div>,
|
||||||
);
|
);
|
||||||
};
|
},
|
||||||
|
[unit],
|
||||||
|
);
|
||||||
|
|
||||||
const createChart = () => {
|
const getOptions = useCallback(() => {
|
||||||
Chart.defaults.font.family = 'Inter';
|
return {
|
||||||
|
|
||||||
const options = {
|
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
animation: {
|
animation: {
|
||||||
@ -124,6 +135,12 @@ export default function BarChart({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
}, [animationDuration, renderTooltip, stacked, colors]);
|
||||||
|
|
||||||
|
const createChart = () => {
|
||||||
|
Chart.defaults.font.family = 'Inter';
|
||||||
|
|
||||||
|
const options = getOptions();
|
||||||
|
|
||||||
onCreate(options);
|
onCreate(options);
|
||||||
|
|
||||||
@ -137,15 +154,9 @@ export default function BarChart({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateChart = () => {
|
const updateChart = () => {
|
||||||
const { animation, scales } = chart.current.options;
|
setTooltip(null);
|
||||||
|
|
||||||
animation.duration = animationDuration;
|
chart.current.options = getOptions();
|
||||||
scales.x.ticks.color = colors.text;
|
|
||||||
scales.x.time.unit = unit;
|
|
||||||
scales.x.border.color = colors.line;
|
|
||||||
scales.y.ticks.color = colors.text;
|
|
||||||
scales.y.grid.color = colors.line;
|
|
||||||
scales.y.border.color = colors.line;
|
|
||||||
|
|
||||||
onUpdate(chart.current);
|
onUpdate(chart.current);
|
||||||
|
|
||||||
@ -157,7 +168,6 @@ export default function BarChart({
|
|||||||
if (!chart.current) {
|
if (!chart.current) {
|
||||||
createChart();
|
createChart();
|
||||||
} else {
|
} else {
|
||||||
setTooltip(null);
|
|
||||||
updateChart();
|
updateChart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,16 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip .value {
|
||||||
|
text-transform: lowercase;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 992px) {
|
@media only screen and (max-width: 992px) {
|
||||||
.chart {
|
.chart {
|
||||||
/*height: 200px;*/
|
/*height: 200px;*/
|
||||||
|
@ -33,12 +33,12 @@ export default function EventsChart({ websiteId, className, token }) {
|
|||||||
if (!data) return [];
|
if (!data) return [];
|
||||||
if (isLoading) return data;
|
if (isLoading) return data;
|
||||||
|
|
||||||
const map = data.reduce((obj, { x, t, y }) => {
|
const map = data.reduce((obj, { x, y }) => {
|
||||||
if (!obj[x]) {
|
if (!obj[x]) {
|
||||||
obj[x] = [];
|
obj[x] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
obj[x].push({ t, y });
|
obj[x].push({ x, y });
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}, {});
|
}, {});
|
||||||
|
@ -58,14 +58,12 @@ export default function PageviewsChart({
|
|||||||
{
|
{
|
||||||
label: formatMessage(labels.uniqueVisitors),
|
label: formatMessage(labels.uniqueVisitors),
|
||||||
data: data.sessions,
|
data: data.sessions,
|
||||||
lineTension: 0,
|
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
...colors.visitors,
|
...colors.visitors,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: formatMessage(labels.pageViews),
|
label: formatMessage(labels.pageViews),
|
||||||
data: data.pageviews,
|
data: data.pageviews,
|
||||||
lineTension: 0,
|
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
...colors.views,
|
...colors.views,
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,7 @@ import { FixedSizeList } from 'react-window';
|
|||||||
import firstBy from 'thenby';
|
import firstBy from 'thenby';
|
||||||
import FilterButtons from 'components/common/FilterButtons';
|
import FilterButtons from 'components/common/FilterButtons';
|
||||||
import NoData from 'components/common/NoData';
|
import NoData from 'components/common/NoData';
|
||||||
import { getDeviceMessage, labels, messages } from 'components/messages';
|
import { labels, messages } from 'components/messages';
|
||||||
import useLocale from 'hooks/useLocale';
|
import useLocale from 'hooks/useLocale';
|
||||||
import useCountryNames from 'hooks/useCountryNames';
|
import useCountryNames from 'hooks/useCountryNames';
|
||||||
import { BROWSERS } from 'lib/constants';
|
import { BROWSERS } from 'lib/constants';
|
||||||
@ -102,7 +102,7 @@ export default function RealtimeLog({ data, websiteDomain }) {
|
|||||||
country: <b>{countryNames[country] || formatMessage(labels.unknown)}</b>,
|
country: <b>{countryNames[country] || formatMessage(labels.unknown)}</b>,
|
||||||
browser: <b>{BROWSERS[browser]}</b>,
|
browser: <b>{BROWSERS[browser]}</b>,
|
||||||
os: <b>{os}</b>,
|
os: <b>{os}</b>,
|
||||||
device: <b>{formatMessage(getDeviceMessage(device))}</b>,
|
device: <b>{formatMessage(labels[device] || labels.unknown)}</b>,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user