Moved render functions into lib/charts.

This commit is contained in:
Mike Cao 2023-05-25 10:26:00 -07:00
parent 5a5127c921
commit 3ccdd95f49
6 changed files with 101 additions and 101 deletions

View File

@ -86,7 +86,7 @@ export function WorldMap({ data, className }) {
</Geographies>
</ZoomableGroup>
</ComposableMap>
{tooltip && <HoverTooltip tooltip={tooltip} />}
{tooltip && <HoverTooltip>{tooltip}</HoverTooltip>}
</div>
);
}

View File

@ -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,
},
},
},

View File

@ -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)}
/>
);
}

View File

@ -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)}
/>
);
}

View File

@ -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
View 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>
</>,
);
};
}