mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 09:45:04 +01:00
Moved render functions into lib/charts.
This commit is contained in:
parent
5a5127c921
commit
3ccdd95f49
@ -86,7 +86,7 @@ export function WorldMap({ data, className }) {
|
||||
</Geographies>
|
||||
</ZoomableGroup>
|
||||
</ComposableMap>
|
||||
{tooltip && <HoverTooltip tooltip={tooltip} />}
|
||||
{tooltip && <HoverTooltip>{tooltip}</HoverTooltip>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -4,16 +4,12 @@ import classNames from 'classnames';
|
||||
import Chart from 'chart.js/auto';
|
||||
import HoverTooltip from 'components/common/HoverTooltip';
|
||||
import Legend from 'components/metrics/Legend';
|
||||
import { formatLongNumber } from 'lib/format';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import useTheme from 'hooks/useTheme';
|
||||
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
|
||||
import { renderNumberLabels } from 'lib/charts';
|
||||
import styles from './BarChart.module.css';
|
||||
|
||||
function defaultRenderYLabel(label) {
|
||||
return +label > 1000 ? formatLongNumber(label) : label;
|
||||
}
|
||||
|
||||
export function BarChart({
|
||||
datasets,
|
||||
unit,
|
||||
@ -90,7 +86,7 @@ export function BarChart({
|
||||
},
|
||||
ticks: {
|
||||
color: colors.text,
|
||||
callback: renderYLabel || defaultRenderYLabel,
|
||||
callback: renderYLabel || renderNumberLabels,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2,16 +2,15 @@ import { useMemo } from 'react';
|
||||
import { Loading } from 'react-basics';
|
||||
import { colord } from 'colord';
|
||||
import BarChart from './BarChart';
|
||||
import { getDateArray, getDateLength } from 'lib/date';
|
||||
import useApi from 'hooks/useApi';
|
||||
import useDateRange from 'hooks/useDateRange';
|
||||
import useTimezone from 'hooks/useTimezone';
|
||||
import usePageQuery from 'hooks/usePageQuery';
|
||||
import { getDateArray } from 'lib/date';
|
||||
import { useApi, useLocale, useDateRange, useTimezone, usePageQuery } from 'hooks';
|
||||
import { EVENT_COLORS } from 'lib/constants';
|
||||
import { renderDateLabels, renderStatusTooltip } from 'lib/charts';
|
||||
|
||||
export function EventsChart({ websiteId, className, token }) {
|
||||
const { get, useQuery } = useApi();
|
||||
const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId);
|
||||
const { locale } = useLocale();
|
||||
const [timezone] = useTimezone();
|
||||
const {
|
||||
query: { url, eventName },
|
||||
@ -70,9 +69,10 @@ export function EventsChart({ websiteId, className, token }) {
|
||||
datasets={datasets}
|
||||
unit={unit}
|
||||
height={300}
|
||||
records={getDateLength(startDate, endDate, unit)}
|
||||
loading={isLoading}
|
||||
stacked
|
||||
renderXLabel={renderDateLabels(unit, locale)}
|
||||
renderTooltip={renderStatusTooltip(unit, locale)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,74 +1,13 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { StatusLight } from 'react-basics';
|
||||
import { useMemo } from 'react';
|
||||
import BarChart from './BarChart';
|
||||
import useTheme from 'hooks/useTheme';
|
||||
import useMessages from 'hooks/useMessages';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import { dateFormat } from 'lib/date';
|
||||
import { formatLongNumber } from 'lib/format';
|
||||
import { useLocale, useTheme, useMessages } from 'hooks';
|
||||
import { renderDateLabels, renderStatusTooltip } from 'lib/charts';
|
||||
|
||||
export function PageviewsChart({ websiteId, data, unit, className, loading, ...props }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { colors } = useTheme();
|
||||
const { locale } = useLocale();
|
||||
|
||||
const renderXLabel = useCallback(
|
||||
(label, index, values) => {
|
||||
const d = new Date(values[index].value);
|
||||
|
||||
switch (unit) {
|
||||
case 'minute':
|
||||
return dateFormat(d, 'h:mm', locale);
|
||||
case 'hour':
|
||||
return dateFormat(d, 'p', locale);
|
||||
case 'day':
|
||||
return dateFormat(d, 'MMM d', locale);
|
||||
case 'month':
|
||||
return dateFormat(d, 'MMM', locale);
|
||||
case 'year':
|
||||
return dateFormat(d, 'YYY', locale);
|
||||
default:
|
||||
return label;
|
||||
}
|
||||
},
|
||||
[locale, unit],
|
||||
);
|
||||
|
||||
const renderTooltip = useCallback(
|
||||
(setTooltip, model) => {
|
||||
const { opacity, labelColors, dataPoints } = model.tooltip;
|
||||
|
||||
if (!dataPoints?.length || !opacity) {
|
||||
setTooltip(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const formats = {
|
||||
millisecond: 'T',
|
||||
second: 'pp',
|
||||
minute: 'p',
|
||||
hour: 'h:mm aaa - PP',
|
||||
day: 'PPPP',
|
||||
week: 'PPPP',
|
||||
month: 'LLLL yyyy',
|
||||
quarter: 'qqq',
|
||||
year: 'yyyy',
|
||||
};
|
||||
|
||||
setTooltip(
|
||||
<>
|
||||
<div>{dateFormat(new Date(dataPoints[0].raw.x), formats[unit], locale)}</div>
|
||||
<div>
|
||||
<StatusLight color={labelColors?.[0]?.backgroundColor}>
|
||||
{formatLongNumber(dataPoints[0].raw.y)} {dataPoints[0].dataset.label}
|
||||
</StatusLight>
|
||||
</div>
|
||||
</>,
|
||||
);
|
||||
},
|
||||
[unit],
|
||||
);
|
||||
|
||||
const datasets = useMemo(() => {
|
||||
if (!data) return [];
|
||||
|
||||
@ -96,8 +35,8 @@ export function PageviewsChart({ websiteId, data, unit, className, loading, ...p
|
||||
datasets={datasets}
|
||||
unit={unit}
|
||||
loading={loading}
|
||||
renderXLabel={renderXLabel}
|
||||
renderTooltip={renderTooltip}
|
||||
renderXLabel={renderDateLabels(unit, locale)}
|
||||
renderTooltip={renderStatusTooltip(unit, locale)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
SubmitButton,
|
||||
Text,
|
||||
TextField,
|
||||
Tooltip,
|
||||
} from 'react-basics';
|
||||
import Icons from 'components/icons';
|
||||
import { updateReport } from 'store/reports';
|
||||
@ -91,28 +92,30 @@ function AddURLButton({ onAdd }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalTrigger>
|
||||
<Icon>
|
||||
<Icons.Plus />
|
||||
</Icon>
|
||||
<Modal>
|
||||
{close => {
|
||||
return (
|
||||
<Form>
|
||||
<FormRow label={formatMessage(labels.url)}>
|
||||
<TextField name="url" value={url} onChange={handleChange} autoComplete="off" />
|
||||
</FormRow>
|
||||
<FormButtons align="center" flex>
|
||||
<Button variant="primary" onClick={() => handleAdd(close)}>
|
||||
{formatMessage(labels.add)}
|
||||
</Button>
|
||||
<Button onClick={() => handleClose(close)}>{formatMessage(labels.cancel)}</Button>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Modal>
|
||||
</ModalTrigger>
|
||||
<Tooltip label={formatMessage(labels.addUrl)}>
|
||||
<ModalTrigger>
|
||||
<Icon>
|
||||
<Icons.Plus />
|
||||
</Icon>
|
||||
<Modal>
|
||||
{close => {
|
||||
return (
|
||||
<Form>
|
||||
<FormRow label={formatMessage(labels.url)}>
|
||||
<TextField name="url" value={url} onChange={handleChange} autoComplete="off" />
|
||||
</FormRow>
|
||||
<FormButtons align="center" flex>
|
||||
<Button variant="primary" onClick={() => handleAdd(close)}>
|
||||
{formatMessage(labels.add)}
|
||||
</Button>
|
||||
<Button onClick={() => handleClose(close)}>{formatMessage(labels.cancel)}</Button>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Modal>
|
||||
</ModalTrigger>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
|
62
lib/charts.js
Normal file
62
lib/charts.js
Normal file
@ -0,0 +1,62 @@
|
||||
import { StatusLight } from 'react-basics';
|
||||
import { dateFormat } from 'lib/date';
|
||||
import { formatLongNumber } from 'lib/format';
|
||||
|
||||
export function renderNumberLabels(label) {
|
||||
return +label > 1000 ? formatLongNumber(label) : label;
|
||||
}
|
||||
|
||||
export function renderDateLabels(unit, locale) {
|
||||
return (label, index, values) => {
|
||||
const d = new Date(values[index].value);
|
||||
|
||||
switch (unit) {
|
||||
case 'minute':
|
||||
return dateFormat(d, 'h:mm', locale);
|
||||
case 'hour':
|
||||
return dateFormat(d, 'p', locale);
|
||||
case 'day':
|
||||
return dateFormat(d, 'MMM d', locale);
|
||||
case 'month':
|
||||
return dateFormat(d, 'MMM', locale);
|
||||
case 'year':
|
||||
return dateFormat(d, 'YYY', locale);
|
||||
default:
|
||||
return label;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function renderStatusTooltip(unit, locale) {
|
||||
return (setTooltip, model) => {
|
||||
const { opacity, labelColors, dataPoints } = model.tooltip;
|
||||
|
||||
if (!dataPoints?.length || !opacity) {
|
||||
setTooltip(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const formats = {
|
||||
millisecond: 'T',
|
||||
second: 'pp',
|
||||
minute: 'p',
|
||||
hour: 'h:mm aaa - PP',
|
||||
day: 'PPPP',
|
||||
week: 'PPPP',
|
||||
month: 'LLLL yyyy',
|
||||
quarter: 'qqq',
|
||||
year: 'yyyy',
|
||||
};
|
||||
|
||||
setTooltip(
|
||||
<>
|
||||
<div>{dateFormat(new Date(dataPoints[0].raw.x), formats[unit], locale)}</div>
|
||||
<div>
|
||||
<StatusLight color={labelColors?.[0]?.backgroundColor}>
|
||||
{formatLongNumber(dataPoints[0].raw.y)} {dataPoints[0].dataset.label}
|
||||
</StatusLight>
|
||||
</div>
|
||||
</>,
|
||||
);
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user