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> </Geographies>
</ZoomableGroup> </ZoomableGroup>
</ComposableMap> </ComposableMap>
{tooltip && <HoverTooltip tooltip={tooltip} />} {tooltip && <HoverTooltip>{tooltip}</HoverTooltip>}
</div> </div>
); );
} }

View File

@ -4,16 +4,12 @@ import classNames from 'classnames';
import Chart from 'chart.js/auto'; import Chart from 'chart.js/auto';
import HoverTooltip from 'components/common/HoverTooltip'; import HoverTooltip from 'components/common/HoverTooltip';
import Legend from 'components/metrics/Legend'; import Legend from 'components/metrics/Legend';
import { formatLongNumber } from 'lib/format';
import useLocale from 'hooks/useLocale'; import useLocale from 'hooks/useLocale';
import useTheme from 'hooks/useTheme'; import useTheme from 'hooks/useTheme';
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants'; import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
import { renderNumberLabels } from 'lib/charts';
import styles from './BarChart.module.css'; import styles from './BarChart.module.css';
function defaultRenderYLabel(label) {
return +label > 1000 ? formatLongNumber(label) : label;
}
export function BarChart({ export function BarChart({
datasets, datasets,
unit, unit,
@ -90,7 +86,7 @@ export function BarChart({
}, },
ticks: { ticks: {
color: colors.text, 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 { Loading } from 'react-basics';
import { colord } from 'colord'; import { colord } from 'colord';
import BarChart from './BarChart'; import BarChart from './BarChart';
import { getDateArray, getDateLength } from 'lib/date'; import { getDateArray } from 'lib/date';
import useApi from 'hooks/useApi'; import { useApi, useLocale, useDateRange, useTimezone, usePageQuery } from 'hooks';
import useDateRange from 'hooks/useDateRange';
import useTimezone from 'hooks/useTimezone';
import usePageQuery from 'hooks/usePageQuery';
import { EVENT_COLORS } from 'lib/constants'; import { EVENT_COLORS } from 'lib/constants';
import { renderDateLabels, renderStatusTooltip } from 'lib/charts';
export function EventsChart({ websiteId, className, token }) { export function EventsChart({ websiteId, className, token }) {
const { get, useQuery } = useApi(); const { get, useQuery } = useApi();
const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId); const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId);
const { locale } = useLocale();
const [timezone] = useTimezone(); const [timezone] = useTimezone();
const { const {
query: { url, eventName }, query: { url, eventName },
@ -70,9 +69,10 @@ export function EventsChart({ websiteId, className, token }) {
datasets={datasets} datasets={datasets}
unit={unit} unit={unit}
height={300} height={300}
records={getDateLength(startDate, endDate, unit)}
loading={isLoading} loading={isLoading}
stacked stacked
renderXLabel={renderDateLabels(unit, locale)}
renderTooltip={renderStatusTooltip(unit, locale)}
/> />
); );
} }

View File

@ -1,74 +1,13 @@
import { useCallback, useMemo } from 'react'; import { useMemo } from 'react';
import { StatusLight } from 'react-basics';
import BarChart from './BarChart'; import BarChart from './BarChart';
import useTheme from 'hooks/useTheme'; import { useLocale, useTheme, useMessages } from 'hooks';
import useMessages from 'hooks/useMessages'; import { renderDateLabels, renderStatusTooltip } from 'lib/charts';
import useLocale from 'hooks/useLocale';
import { dateFormat } from 'lib/date';
import { formatLongNumber } from 'lib/format';
export function PageviewsChart({ websiteId, data, unit, className, loading, ...props }) { export function PageviewsChart({ websiteId, data, unit, className, loading, ...props }) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const { colors } = useTheme(); const { colors } = useTheme();
const { locale } = useLocale(); 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(() => { const datasets = useMemo(() => {
if (!data) return []; if (!data) return [];
@ -96,8 +35,8 @@ export function PageviewsChart({ websiteId, data, unit, className, loading, ...p
datasets={datasets} datasets={datasets}
unit={unit} unit={unit}
loading={loading} loading={loading}
renderXLabel={renderXLabel} renderXLabel={renderDateLabels(unit, locale)}
renderTooltip={renderTooltip} renderTooltip={renderStatusTooltip(unit, locale)}
/> />
); );
} }

View File

@ -11,6 +11,7 @@ import {
SubmitButton, SubmitButton,
Text, Text,
TextField, TextField,
Tooltip,
} from 'react-basics'; } from 'react-basics';
import Icons from 'components/icons'; import Icons from 'components/icons';
import { updateReport } from 'store/reports'; import { updateReport } from 'store/reports';
@ -91,28 +92,30 @@ function AddURLButton({ onAdd }) {
}; };
return ( return (
<ModalTrigger> <Tooltip label={formatMessage(labels.addUrl)}>
<Icon> <ModalTrigger>
<Icons.Plus /> <Icon>
</Icon> <Icons.Plus />
<Modal> </Icon>
{close => { <Modal>
return ( {close => {
<Form> return (
<FormRow label={formatMessage(labels.url)}> <Form>
<TextField name="url" value={url} onChange={handleChange} autoComplete="off" /> <FormRow label={formatMessage(labels.url)}>
</FormRow> <TextField name="url" value={url} onChange={handleChange} autoComplete="off" />
<FormButtons align="center" flex> </FormRow>
<Button variant="primary" onClick={() => handleAdd(close)}> <FormButtons align="center" flex>
{formatMessage(labels.add)} <Button variant="primary" onClick={() => handleAdd(close)}>
</Button> {formatMessage(labels.add)}
<Button onClick={() => handleClose(close)}>{formatMessage(labels.cancel)}</Button> </Button>
</FormButtons> <Button onClick={() => handleClose(close)}>{formatMessage(labels.cancel)}</Button>
</Form> </FormButtons>
); </Form>
}} );
</Modal> }}
</ModalTrigger> </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>
</>,
);
};
}