Skip to content

Commit 1fdd255

Browse files
committed
Merge branch 'mikecao:master' into master
2 parents 12d603b + 5ecaf55 commit 1fdd255

19 files changed

+854
-628
lines changed

.eslintrc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"es2020": true,
55
"node": true
66
},
7-
"extends": ["eslint:recommended", "plugin:react/recommended", "prettier", "prettier/react"],
7+
"extends": ["eslint:recommended", "plugin:react/recommended", "prettier"],
88
"parserOptions": {
99
"ecmaFeatures": {
1010
"jsx": true

assets/chart-bar.svg

+1
Loading

components/common/Checkbox.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,22 @@ import styles from './Checkbox.module.css';
77
function Checkbox({ name, value, label, onChange }) {
88
const ref = useRef();
99

10+
const onClick = () => ref.current.click();
11+
1012
return (
1113
<div className={styles.container}>
12-
<div className={styles.checkbox} onClick={() => ref.current.click()}>
14+
<div className={styles.checkbox} onClick={onClick}>
1315
{value && <Icon icon={<Check />} size="small" />}
1416
</div>
15-
<label className={styles.label} htmlFor={name}>
17+
<label className={styles.label} htmlFor={name} onClick={onClick}>
1618
{label}
1719
</label>
1820
<input
1921
ref={ref}
2022
className={styles.input}
2123
type="checkbox"
2224
name={name}
23-
value={value}
25+
defaultChecked={value}
2426
onChange={onChange}
2527
/>
2628
</div>

components/common/Checkbox.module.css

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
.label {
1919
margin-left: 10px;
20+
user-select: none; /* disable text selection when clicking to toggle the checkbox */
2021
}
2122

2223
.input {

components/forms/WebsiteEditForm.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export default function WebsiteEditForm({ values, onSave, onClose }) {
7777
</div>
7878
</FormRow>
7979
<FormRow>
80-
<label></label>
80+
<label />
8181
<Field name="enable_share_url">
8282
{({ field }) => (
8383
<Checkbox

components/layout/Header.module.css

+14-6
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@
7070
padding: 0 15px;
7171
}
7272

73+
.title {
74+
padding: 0.5rem;
75+
margin-bottom: 0.5rem;
76+
}
77+
7378
.nav {
7479
font-size: var(--font-size-normal);
7580
flex-wrap: wrap;
@@ -102,6 +107,9 @@
102107
.burger {
103108
display: block;
104109
/* color: #4a4a4a; */
110+
background: none;
111+
border: 1px solid var(--gray900);
112+
border-radius: 4px;
105113
cursor: pointer;
106114
height: 3.25rem;
107115
width: 3.25rem;
@@ -112,20 +120,20 @@
112120
}
113121

114122
.burger span {
115-
transform: translateX(-50%);
123+
transform: translateX(25%);
116124
padding: 1px 0px;
117125
margin: 6px 0;
118-
width: 20px;
126+
width: 65%;
119127
display: block;
120-
background-color: white;
128+
background-color: var(--gray900);
121129
}
122130

123131
.burger div {
124-
height: 100%;
125-
color: white;
132+
/* height: 100%; */
133+
color: var(--gray900);
126134
text-align: center;
127135
margin: auto;
128136
font-size: 1.5rem;
129-
transform: translateX(-50%);
137+
/* transform: translateX(-50%); */
130138
}
131139
}

components/metrics/WebsiteChart.js

+10-7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default function WebsiteChart({
2323
domain,
2424
stickyHeader = false,
2525
showLink = false,
26+
hideChart = false,
2627
onDataLoad = () => {},
2728
}) {
2829
const shareToken = useShareToken();
@@ -91,13 +92,15 @@ export default function WebsiteChart({
9192
<div className="row">
9293
<div className="col">
9394
{error && <ErrorMessage />}
94-
<PageviewsChart
95-
websiteId={websiteId}
96-
data={chartData}
97-
unit={unit}
98-
records={getDateLength(startDate, endDate, unit)}
99-
loading={loading}
100-
/>
95+
{!hideChart && (
96+
<PageviewsChart
97+
websiteId={websiteId}
98+
data={chartData}
99+
unit={unit}
100+
records={getDateLength(startDate, endDate, unit)}
101+
loading={loading}
102+
/>
103+
)}
101104
</div>
102105
</div>
103106
</div>

components/pages/WebsiteList.js

+27-10
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import { FormattedMessage } from 'react-intl';
33
import Link from 'components/common/Link';
44
import WebsiteChart from 'components/metrics/WebsiteChart';
55
import Page from 'components/layout/Page';
66
import EmptyPlaceholder from 'components/common/EmptyPlaceholder';
7+
import Button from 'components/common/Button';
78
import useFetch from 'hooks/useFetch';
89
import Arrow from 'assets/arrow-right.svg';
10+
import Chart from 'assets/chart-bar.svg';
911
import styles from './WebsiteList.module.css';
1012

1113
export default function WebsiteList({ userId }) {
1214
const { data } = useFetch('/api/websites', { params: { user_id: userId } });
15+
const [hideCharts, setHideCharts] = useState(false);
1316

1417
if (!data) {
1518
return null;
1619
}
1720

18-
return (
19-
<Page>
20-
{data.map(({ website_id, name, domain }) => (
21-
<div key={website_id} className={styles.website}>
22-
<WebsiteChart websiteId={website_id} title={name} domain={domain} showLink />
23-
</div>
24-
))}
25-
{data.length === 0 && (
21+
if (data.length === 0) {
22+
return (
23+
<Page>
2624
<EmptyPlaceholder
2725
msg={
2826
<FormattedMessage
@@ -35,7 +33,26 @@ export default function WebsiteList({ userId }) {
3533
<FormattedMessage id="message.go-to-settings" defaultMessage="Go to settings" />
3634
</Link>
3735
</EmptyPlaceholder>
38-
)}
36+
</Page>
37+
);
38+
}
39+
40+
return (
41+
<Page>
42+
<div className={styles.menubar}>
43+
<Button icon={<Chart />} onClick={() => setHideCharts(!hideCharts)} />
44+
</div>
45+
{data.map(({ website_id, name, domain }) => (
46+
<div key={website_id} className={styles.website}>
47+
<WebsiteChart
48+
websiteId={website_id}
49+
title={name}
50+
domain={domain}
51+
hideChart={hideCharts}
52+
showLink
53+
/>
54+
</div>
55+
))}
3956
</Page>
4057
);
4158
}

components/pages/WebsiteList.module.css

+7
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@
99
border-bottom: 0;
1010
margin-bottom: 0;
1111
}
12+
13+
.menubar {
14+
display: flex;
15+
align-items: center;
16+
justify-content: flex-end;
17+
padding-top: 10px;
18+
}

hooks/useTheme.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import { THEME_CONFIG } from 'lib/constants';
55
import { useEffect } from 'react';
66

77
export default function useTheme() {
8-
const theme = useSelector(state => state.app.theme || getItem(THEME_CONFIG) || 'light');
8+
const defaultTheme =
9+
typeof window !== 'undefined'
10+
? window?.matchMedia('prefers-color-scheme: dark')?.matches
11+
? 'dark'
12+
: 'light'
13+
: 'light';
14+
const theme = useSelector(state => state.app.theme || getItem(THEME_CONFIG) || defaultTheme);
915
const dispatch = useDispatch();
1016

1117
function saveTheme(value) {

lang/nl-NL.json

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"label.administrator": "Administrator",
66
"label.all": "Alles",
77
"label.all-websites": "Alle websites",
8+
"label.all-events": "Alle gebeurtenissen",
89
"label.back": "Terug",
910
"label.cancel": "Annuleren",
1011
"label.change-password": "Wachtwoord wijzigen",

lang/ru-RU.json

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"label.administrator": "Администратор",
66
"label.all": "Все",
77
"label.all-websites": "Все сайты",
8+
"label.all-events": "Все события",
89
"label.back": "Назад",
910
"label.cancel": "Отменить",
1011
"label.change-password": "Изменить пароль",

lang/uk-UA.json

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"label.administrator": "Адміністратор",
66
"label.all": "Всі",
77
"label.all-websites": "Всі сайти",
8+
"label.all-events": "Всі події",
89
"label.back": "Назад",
910
"label.cancel": "Відмінити",
1011
"label.change-password": "Змінити пароль",

lib/crypto.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import crypto from 'crypto';
22
import { v4, v5, validate } from 'uuid';
3-
import bcrypt from 'bcrypt';
3+
import bcrypt from 'bcryptjs';
44
import { JWT, JWE, JWK } from 'jose';
55
import { startOfMonth } from 'date-fns';
66

@@ -40,11 +40,11 @@ export function getRandomChars(n) {
4040
}
4141

4242
export async function hashPassword(password) {
43-
return bcrypt.hash(password, SALT_ROUNDS);
43+
return bcrypt.hashSync(password, SALT_ROUNDS);
4444
}
4545

4646
export async function checkPassword(password, hash) {
47-
return bcrypt.compare(password, hash);
47+
return bcrypt.compareSync(password, hash);
4848
}
4949

5050
export async function createToken(payload) {

lib/filters.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const urlFilter = (data, { raw }) => {
1818
return `${pathname}${search}`;
1919
}
2020

21-
return removeTrailingSlash(pathname);
21+
return pathname;
2222
} catch {
2323
return null;
2424
}

lib/request.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
MOBILE_SCREEN_WIDTH,
1313
} from './constants';
1414

15+
let lookup;
16+
1517
export function getIpAddress(req) {
1618
// Cloudflare
1719
if (req.headers['cf-connecting-ip']) {
@@ -61,7 +63,9 @@ export async function getCountry(req, ip) {
6163
}
6264

6365
// Database lookup
64-
const lookup = await maxmind.open(path.resolve('./public/geo/GeoLite2-Country.mmdb'));
66+
if (!lookup) {
67+
lookup = await maxmind.open(path.resolve('./public/geo/GeoLite2-Country.mmdb'));
68+
}
6569

6670
const result = lookup.get(ip);
6771

0 commit comments

Comments
 (0)