diff --git a/.eslintrc.json b/.eslintrc.json
index 5e7ef0a0..f04178c4 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -4,7 +4,7 @@
"es2020": true,
"node": true
},
- "extends": ["eslint:recommended", "plugin:react/recommended", "prettier", "prettier/react"],
+ "extends": ["eslint:recommended", "plugin:react/recommended", "prettier"],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ab56cb38..ec7dfa4c 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -28,9 +28,9 @@ jobs:
.
- name: Docker login
- env:
- CR_PAT: ${{ secrets.CR_PAT }}
- run: docker login -u $GITHUB_ACTOR -p $CR_PAT ghcr.io
+ run: >-
+ echo "${{ secrets.GITHUB_TOKEN }}"
+ | docker login -u "${{ github.actor }}" --password-stdin ghcr.io
- name: Push image to GitHub
run: |
diff --git a/assets/chart-bar.svg b/assets/chart-bar.svg
new file mode 100644
index 00000000..d1d72fdc
--- /dev/null
+++ b/assets/chart-bar.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/components/common/Calendar.js b/components/common/Calendar.js
index 237f065e..92fd311c 100644
--- a/components/common/Calendar.js
+++ b/components/common/Calendar.js
@@ -20,6 +20,7 @@ import Button from './Button';
import useLocale from 'hooks/useLocale';
import { dateFormat } from 'lib/date';
import { chunk } from 'lib/array';
+import { dateLocales } from 'lib/lang';
import Chevron from 'assets/chevron-down.svg';
import Cross from 'assets/times.svg';
import styles from './Calendar.module.css';
@@ -105,8 +106,8 @@ export default function Calendar({ date, minDate, maxDate, onChange }) {
}
const DaySelector = ({ date, minDate, maxDate, locale, onSelect }) => {
- const startWeek = startOfWeek(date);
- const startMonth = startOfMonth(date);
+ const startWeek = startOfWeek(date, { locale: dateLocales[locale] });
+ const startMonth = startOfMonth(date, { locale: dateLocales[locale] });
const startDay = subDays(startMonth, startMonth.getDay());
const month = date.getMonth();
const year = date.getFullYear();
diff --git a/components/common/Checkbox.js b/components/common/Checkbox.js
index 67eea80d..0cd0dcad 100644
--- a/components/common/Checkbox.js
+++ b/components/common/Checkbox.js
@@ -7,12 +7,14 @@ import styles from './Checkbox.module.css';
function Checkbox({ name, value, label, onChange }) {
const ref = useRef();
+ const onClick = () => ref.current.click();
+
return (
-
ref.current.click()}>
+
{value && } size="small" />}
-
diff --git a/components/common/Checkbox.module.css b/components/common/Checkbox.module.css
index 267a4054..c9a01eac 100644
--- a/components/common/Checkbox.module.css
+++ b/components/common/Checkbox.module.css
@@ -17,6 +17,7 @@
.label {
margin-left: 10px;
+ user-select: none; /* disable text selection when clicking to toggle the checkbox */
}
.input {
diff --git a/components/common/DateFilter.js b/components/common/DateFilter.js
index 45950086..7e35a010 100644
--- a/components/common/DateFilter.js
+++ b/components/common/DateFilter.js
@@ -55,6 +55,7 @@ const filterOptions = [
];
function DateFilter({ value, startDate, endDate, onChange, className }) {
+ const [locale] = useLocale();
const [showPicker, setShowPicker] = useState(false);
const displayValue =
value === 'custom' ? (
@@ -68,7 +69,7 @@ function DateFilter({ value, startDate, endDate, onChange, className }) {
setShowPicker(true);
return;
}
- onChange(getDateRange(value));
+ onChange(getDateRange(value, locale));
}
function handlePickerChange(value) {
diff --git a/components/common/EmptyPlaceholder.js b/components/common/EmptyPlaceholder.js
index a223814d..b5394e85 100644
--- a/components/common/EmptyPlaceholder.js
+++ b/components/common/EmptyPlaceholder.js
@@ -8,7 +8,7 @@ function EmptyPlaceholder({ msg, children }) {
return (
} size="xlarge" />
-
{msg}
+ {msg}
{children}
);
diff --git a/components/common/EmptyPlaceholder.module.css b/components/common/EmptyPlaceholder.module.css
index 58332566..a9231836 100644
--- a/components/common/EmptyPlaceholder.module.css
+++ b/components/common/EmptyPlaceholder.module.css
@@ -9,3 +9,7 @@
.icon {
margin-bottom: 30px;
}
+
+.msg {
+ margin-bottom: 15px;
+}
diff --git a/components/common/RefreshButton.js b/components/common/RefreshButton.js
index a2857522..61f06a3c 100644
--- a/components/common/RefreshButton.js
+++ b/components/common/RefreshButton.js
@@ -8,9 +8,11 @@ import Refresh from 'assets/redo.svg';
import Dots from 'assets/ellipsis-h.svg';
import useDateRange from 'hooks/useDateRange';
import { getDateRange } from '../../lib/date';
+import useLocale from 'hooks/useLocale';
function RefreshButton({ websiteId }) {
const dispatch = useDispatch();
+ const [locale] = useLocale();
const [dateRange] = useDateRange(websiteId);
const [loading, setLoading] = useState(false);
const completed = useSelector(state => state.queries[`/api/website/${websiteId}/stats`]);
@@ -18,7 +20,7 @@ function RefreshButton({ websiteId }) {
function handleClick() {
if (dateRange) {
setLoading(true);
- dispatch(setDateRange(websiteId, getDateRange(dateRange.value)));
+ dispatch(setDateRange(websiteId, getDateRange(dateRange.value, locale)));
}
}
diff --git a/components/common/WorldMap.js b/components/common/WorldMap.js
index ee3a0a00..0fa4c234 100644
--- a/components/common/WorldMap.js
+++ b/components/common/WorldMap.js
@@ -1,17 +1,15 @@
import React, { useState, useMemo } from 'react';
+import { useRouter } from 'next/router';
import PropTypes from 'prop-types';
import ReactTooltip from 'react-tooltip';
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
import classNames from 'classnames';
import tinycolor from 'tinycolor2';
import useTheme from 'hooks/useTheme';
-import { THEME_COLORS } from 'lib/constants';
+import { ISO_COUNTRIES, THEME_COLORS, MAP_FILE } from 'lib/constants';
import styles from './WorldMap.module.css';
import useCountryNames from 'hooks/useCountryNames';
import useLocale from 'hooks/useLocale';
-import { useRouter } from 'next/router';
-
-const geoUrl = '/world-110m.json';
function WorldMap({ data, className }) {
const { basePath } = useRouter();
@@ -60,10 +58,10 @@ function WorldMap({ data, className }) {
>
-
+
{({ geographies }) => {
return geographies.map(geo => {
- const code = geo.properties.ISO_A2;
+ const code = ISO_COUNTRIES[geo.id];
return (
-
+
-
+
{({ field }) => (
div {
position: relative;
+ flex: 1 1;
+}
+
+.row > div > input {
+ width: 100%;
+ min-width: 240px;
}
.buttons {
diff --git a/components/layout/Header.js b/components/layout/Header.js
index b0d59492..f607e32a 100644
--- a/components/layout/Header.js
+++ b/components/layout/Header.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { useSelector } from 'react-redux';
import classNames from 'classnames';
@@ -13,40 +13,66 @@ import styles from './Header.module.css';
export default function Header() {
const user = useSelector(state => state.user);
+ const [active, setActive] = useState(false);
+
+ function handleClick() {
+ setActive(state => !state);
+ }
return (
-
+