Skip to content

Commit 5d74e86

Browse files
authored
Merge pull request #916 from mikecao/dev
v1.25.0
2 parents b756fcd + ddb5492 commit 5d74e86

108 files changed

Lines changed: 885 additions & 388 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

components/common/Button.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ function Button({
2424
data-tip={tooltip}
2525
data-effect="solid"
2626
data-for={tooltipId}
27+
data-offset={JSON.stringify({ left: 10 })}
2728
type={type}
2829
className={classNames(styles.button, className, {
2930
[styles.large]: size === 'large',

components/common/Calendar.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,14 @@ export default function Calendar({ date, minDate, maxDate, onChange }) {
106106
}
107107

108108
const DaySelector = ({ date, minDate, maxDate, locale, onSelect }) => {
109-
const startWeek = startOfWeek(date, { locale: getDateLocale(locale) });
110-
const startMonth = startOfMonth(date, { locale: getDateLocale(locale) });
111-
const startDay = subDays(startMonth, startMonth.getDay());
109+
const dateLocale = getDateLocale(locale);
110+
const weekStartsOn = dateLocale?.options?.weekStartsOn || 0;
111+
const startWeek = startOfWeek(date, {
112+
locale: dateLocale,
113+
weekStartsOn,
114+
});
115+
const startMonth = startOfMonth(date);
116+
const startDay = subDays(startMonth, startMonth.getDay() - weekStartsOn);
112117
const month = date.getMonth();
113118
const year = date.getFullYear();
114119

components/common/DateFilter.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Modal from './Modal';
66
import DropDown from './DropDown';
77
import DatePickerForm from 'components/forms/DatePickerForm';
88
import useLocale from 'hooks/useLocale';
9-
import { getDateRange, dateFormat } from 'lib/date';
9+
import { dateFormat } from 'lib/date';
1010
import Calendar from 'assets/calendar-alt.svg';
1111
import Icon from './Icon';
1212

@@ -47,6 +47,11 @@ const filterOptions = [
4747
value: '90day',
4848
},
4949
{ label: <FormattedMessage id="label.this-year" defaultMessage="This year" />, value: '1year' },
50+
{
51+
label: <FormattedMessage id="label.all-time" defaultMessage="All time" />,
52+
value: 'all',
53+
divider: true,
54+
},
5055
{
5156
label: <FormattedMessage id="label.custom-range" defaultMessage="Custom range" />,
5257
value: 'custom',
@@ -55,7 +60,6 @@ const filterOptions = [
5560
];
5661

5762
function DateFilter({ value, startDate, endDate, onChange, className }) {
58-
const { locale } = useLocale();
5963
const [showPicker, setShowPicker] = useState(false);
6064
const displayValue =
6165
value === 'custom' ? (
@@ -64,12 +68,12 @@ function DateFilter({ value, startDate, endDate, onChange, className }) {
6468
value
6569
);
6670

67-
function handleChange(value) {
71+
async function handleChange(value) {
6872
if (value === 'custom') {
6973
setShowPicker(true);
7074
return;
7175
}
72-
onChange(getDateRange(value, locale));
76+
onChange(value);
7377
}
7478

7579
function handlePickerChange(value) {

components/common/RefreshButton.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,17 @@ import Button from './Button';
77
import Refresh from 'assets/redo.svg';
88
import Dots from 'assets/ellipsis-h.svg';
99
import useDateRange from 'hooks/useDateRange';
10-
import { getDateRange } from '../../lib/date';
11-
import useLocale from 'hooks/useLocale';
1210

1311
function RefreshButton({ websiteId }) {
1412
const dispatch = useDispatch();
15-
const { locale } = useLocale();
1613
const [dateRange] = useDateRange(websiteId);
1714
const [loading, setLoading] = useState(false);
1815
const completed = useSelector(state => state.queries[`/api/website/${websiteId}/stats`]);
1916

2017
function handleClick() {
2118
if (dateRange) {
2219
setLoading(true);
23-
dispatch(setDateRange(websiteId, getDateRange(dateRange.value, locale)));
20+
dispatch(setDateRange(websiteId, dateRange));
2421
}
2522
}
2623

components/common/WorldMap.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
44
import ReactTooltip from 'react-tooltip';
55
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
66
import classNames from 'classnames';
7-
import tinycolor from 'tinycolor2';
7+
import { colord } from 'colord';
88
import useTheme from 'hooks/useTheme';
99
import { ISO_COUNTRIES, THEME_COLORS, MAP_FILE } from 'lib/constants';
1010
import styles from './WorldMap.module.css';
@@ -35,9 +35,9 @@ function WorldMap({ data, className }) {
3535
return colors.fillColor;
3636
}
3737

38-
return tinycolor(colors.baseColor)[theme === 'light' ? 'lighten' : 'darken'](
39-
40 * (1.0 - country.z / 100),
40-
);
38+
return colord(colors.baseColor)
39+
[theme === 'light' ? 'lighten' : 'darken'](0.4 * (1.0 - country.z / 100))
40+
.toHex();
4141
}
4242

4343
function getOpacity(code) {

components/metrics/BarChart.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import { formatLongNumber } from 'lib/format';
66
import { dateFormat } from 'lib/date';
77
import useLocale from 'hooks/useLocale';
88
import useTheme from 'hooks/useTheme';
9+
import useForceUpdate from 'hooks/useForceUpdate';
910
import { DEFAUL_CHART_HEIGHT, DEFAULT_ANIMATION_DURATION, THEME_COLORS } from 'lib/constants';
1011
import styles from './BarChart.module.css';
1112
import ChartTooltip from './ChartTooltip';
12-
import useForceUpdate from '../../hooks/useForceUpdate';
1313

1414
export default function BarChart({
1515
chartId,

components/metrics/EventsChart.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useMemo } from 'react';
2-
import tinycolor from 'tinycolor2';
2+
import { colord } from 'colord';
33
import BarChart from './BarChart';
44
import { getDateArray, getDateLength } from 'lib/date';
55
import useFetch from 'hooks/useFetch';
@@ -51,13 +51,13 @@ export default function EventsChart({ websiteId, className, token }) {
5151
});
5252

5353
return Object.keys(map).map((key, index) => {
54-
const color = tinycolor(EVENT_COLORS[index % EVENT_COLORS.length]);
54+
const color = colord(EVENT_COLORS[index % EVENT_COLORS.length]);
5555
return {
5656
label: key,
5757
data: map[key],
5858
lineTension: 0,
59-
backgroundColor: color.setAlpha(0.6).toRgbString(),
60-
borderColor: color.setAlpha(0.7).toRgbString(),
59+
backgroundColor: color.alpha(0.6).toRgbString(),
60+
borderColor: color.alpha(0.7).toRgbString(),
6161
borderWidth: 1,
6262
};
6363
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react';
2+
import MetricsTable from './MetricsTable';
3+
import { percentFilter } from 'lib/filters';
4+
import { FormattedMessage } from 'react-intl';
5+
import useLanguageNames from 'hooks/useLanguageNames';
6+
import useLocale from 'hooks/useLocale';
7+
8+
export default function LanguagesTable({ websiteId, onDataLoad, ...props }) {
9+
const { locale } = useLocale();
10+
const languageNames = useLanguageNames(locale);
11+
12+
function renderLabel({ x }) {
13+
return (
14+
<div className={locale}>
15+
{languageNames[x] ?? <FormattedMessage id="label.unknown" defaultMessage="Unknown" />}{' '}
16+
</div>
17+
);
18+
}
19+
20+
return (
21+
<MetricsTable
22+
{...props}
23+
title={<FormattedMessage id="metrics.languages" defaultMessage="Languages" />}
24+
type="language"
25+
metric={<FormattedMessage id="metrics.visitors" defaultMessage="Visitors" />}
26+
websiteId={websiteId}
27+
onDataLoad={data => onDataLoad?.(percentFilter(data))}
28+
renderLabel={renderLabel}
29+
/>
30+
);
31+
}

components/metrics/Legend.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react';
2+
import { colord } from 'colord';
23
import classNames from 'classnames';
34
import Dot from 'components/common/Dot';
45
import useLocale from 'hooks/useLocale';
6+
import useForceUpdate from 'hooks/useForceUpdate';
57
import styles from './Legend.module.css';
6-
import useForceUpdate from '../../hooks/useForceUpdate';
78

89
export default function Legend({ chart }) {
910
const { locale } = useLocale();
@@ -25,16 +26,20 @@ export default function Legend({ chart }) {
2526

2627
return (
2728
<div className={styles.legend}>
28-
{chart.legend.legendItems.map(({ text, fillStyle, datasetIndex, hidden }) => (
29-
<div
30-
key={text}
31-
className={classNames(styles.label, { [styles.hidden]: hidden })}
32-
onClick={() => handleClick(datasetIndex)}
33-
>
34-
<Dot color={fillStyle} />
35-
<span className={locale}>{text}</span>
36-
</div>
37-
))}
29+
{chart.legend.legendItems.map(({ text, fillStyle, datasetIndex, hidden }) => {
30+
const color = colord(fillStyle);
31+
32+
return (
33+
<div
34+
key={text}
35+
className={classNames(styles.label, { [styles.hidden]: hidden })}
36+
onClick={() => handleClick(datasetIndex)}
37+
>
38+
<Dot color={color.alpha(color.alpha() + 0.2).toHex()} />
39+
<span className={locale}>{text}</span>
40+
</div>
41+
);
42+
})}
3843
</div>
3944
);
4045
}

components/metrics/MetricCard.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const MetricCard = ({
99
label,
1010
reverseColors = false,
1111
format = formatNumber,
12+
hideComparison = false,
1213
}) => {
1314
const props = useSpring({ x: Number(value) || 0, from: { x: 0 } });
1415
const changeProps = useSpring({ x: Number(change) || 0, from: { x: 0 } });
@@ -18,8 +19,8 @@ const MetricCard = ({
1819
<animated.div className={styles.value}>{props.x.interpolate(x => format(x))}</animated.div>
1920
<div className={styles.label}>
2021
{label}
21-
{~~change === 0 && <span className={styles.change}>{format(0)}</span>}
22-
{~~change !== 0 && (
22+
{~~change === 0 && !hideComparison && <span className={styles.change}>{format(0)}</span>}
23+
{~~change !== 0 && !hideComparison && (
2324
<animated.span
2425
className={`${styles.change} ${
2526
change >= 0

0 commit comments

Comments
 (0)