Skip to content

Commit f55ba7b

Browse files
authored
Merge pull request #1137 from mikecao/dev
v1.31.0
2 parents 8384d6a + 52fe59f commit f55ba7b

26 files changed

Lines changed: 323 additions & 271 deletions

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ Umami is a simple, fast, privacy-focused alternative to Google Analytics.
66

77
A detailed getting started guide can be found at [https://umami.is/docs/](https://umami.is/docs/)
88

9+
A fast way to get up and running is to use Railway
10+
11+
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template/umami)
12+
13+
See [Running on Railway](https://umami.is/docs/running-on-railway) to get started.
14+
915
## Installing from source
1016

1117
### Requirements

components/common/FilterLink.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22
import Link from 'next/link';
33
import classNames from 'classnames';
44
import usePageQuery from 'hooks/usePageQuery';
5-
import { safeDecodeURI } from 'lib/url';
65
import Icon from './Icon';
76
import External from 'assets/arrow-up-right-from-square.svg';
87
import styles from './FilterLink.module.css';
@@ -21,7 +20,7 @@ export default function FilterLink({ id, value, label, externalUrl }) {
2120
[styles.active]: active && selected,
2221
})}
2322
>
24-
{safeDecodeURI(label || value)}
23+
{label || value}
2524
</a>
2625
</Link>
2726
{externalUrl && (

components/metrics/ActiveUsers.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,16 @@ import { FormattedMessage } from 'react-intl';
33
import classNames from 'classnames';
44
import useFetch from 'hooks/useFetch';
55
import Dot from 'components/common/Dot';
6-
import { TOKEN_HEADER } from 'lib/constants';
7-
import useShareToken from 'hooks/useShareToken';
86
import styles from './ActiveUsers.module.css';
97

108
export default function ActiveUsers({ websiteId, className, value, interval = 60000 }) {
11-
const shareToken = useShareToken();
129
const url = websiteId ? `/website/${websiteId}/active` : null;
1310
const { data } = useFetch(url, {
1411
interval,
15-
headers: { [TOKEN_HEADER]: shareToken?.token },
1612
});
1713
const count = useMemo(() => {
1814
if (websiteId) {
19-
return data?.[0]?.x || 0
15+
return data?.[0]?.x || 0;
2016
}
2117

2218
return value !== undefined ? value : 0;

components/metrics/EventsChart.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ import useFetch from 'hooks/useFetch';
66
import useDateRange from 'hooks/useDateRange';
77
import useTimezone from 'hooks/useTimezone';
88
import usePageQuery from 'hooks/usePageQuery';
9-
import useShareToken from 'hooks/useShareToken';
10-
import { EVENT_COLORS, TOKEN_HEADER } from 'lib/constants';
9+
import { EVENT_COLORS } from 'lib/constants';
1110

1211
export default function EventsChart({ websiteId, className, token }) {
1312
const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId);
1413
const [timezone] = useTimezone();
1514
const {
1615
query: { url, eventType },
1716
} = usePageQuery();
18-
const shareToken = useShareToken();
1917

2018
const { data, loading } = useFetch(
2119
`/website/${websiteId}/events`,
@@ -29,7 +27,6 @@ export default function EventsChart({ websiteId, className, token }) {
2927
event_type: eventType,
3028
token,
3129
},
32-
headers: { [TOKEN_HEADER]: shareToken?.token },
3330
},
3431
[modified, eventType],
3532
);

components/metrics/MetricsBar.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,11 @@ import ErrorMessage from 'components/common/ErrorMessage';
66
import useFetch from 'hooks/useFetch';
77
import useDateRange from 'hooks/useDateRange';
88
import usePageQuery from 'hooks/usePageQuery';
9-
import useShareToken from 'hooks/useShareToken';
109
import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
11-
import { TOKEN_HEADER } from 'lib/constants';
1210
import MetricCard from './MetricCard';
1311
import styles from './MetricsBar.module.css';
1412

1513
export default function MetricsBar({ websiteId, className }) {
16-
const shareToken = useShareToken();
1714
const [dateRange] = useDateRange(websiteId);
1815
const { startDate, endDate, modified } = dateRange;
1916
const [format, setFormat] = useState(true);
@@ -34,7 +31,6 @@ export default function MetricsBar({ websiteId, className }) {
3431
device,
3532
country,
3633
},
37-
headers: { [TOKEN_HEADER]: shareToken?.token },
3834
},
3935
[modified, url, referrer, os, browser, device, country],
4036
);

components/metrics/MetricsTable.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import Arrow from 'assets/arrow-right.svg';
99
import { percentFilter } from 'lib/filters';
1010
import useDateRange from 'hooks/useDateRange';
1111
import usePageQuery from 'hooks/usePageQuery';
12-
import useShareToken from 'hooks/useShareToken';
1312
import ErrorMessage from 'components/common/ErrorMessage';
1413
import DataTable from './DataTable';
15-
import { DEFAULT_ANIMATION_DURATION, TOKEN_HEADER } from 'lib/constants';
14+
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
1615
import styles from './MetricsTable.module.css';
1716

1817
export default function MetricsTable({
@@ -25,7 +24,6 @@ export default function MetricsTable({
2524
onDataLoad,
2625
...props
2726
}) {
28-
const shareToken = useShareToken();
2927
const [{ startDate, endDate, modified }] = useDateRange(websiteId);
3028
const {
3129
resolve,
@@ -49,7 +47,6 @@ export default function MetricsTable({
4947
},
5048
onDataLoad,
5149
delay: DEFAULT_ANIMATION_DURATION,
52-
headers: { [TOKEN_HEADER]: shareToken?.token },
5350
},
5451
[modified, url, referrer, os, browser, device, country],
5552
);

components/metrics/WebsiteChart.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ import useDateRange from 'hooks/useDateRange';
1212
import useTimezone from 'hooks/useTimezone';
1313
import usePageQuery from 'hooks/usePageQuery';
1414
import { getDateArray, getDateLength, getDateRangeValues } from 'lib/date';
15-
import useShareToken from 'hooks/useShareToken';
1615
import useApi from 'hooks/useApi';
17-
import { TOKEN_HEADER } from 'lib/constants';
1816
import styles from './WebsiteChart.module.css';
1917

2018
export default function WebsiteChart({
@@ -26,7 +24,6 @@ export default function WebsiteChart({
2624
showChart = true,
2725
onDataLoad = () => {},
2826
}) {
29-
const shareToken = useShareToken();
3027
const [dateRange, setDateRange] = useDateRange(websiteId);
3128
const { startDate, endDate, unit, value, modified } = dateRange;
3229
const [timezone] = useTimezone();
@@ -53,7 +50,6 @@ export default function WebsiteChart({
5350
country,
5451
},
5552
onDataLoad,
56-
headers: { [TOKEN_HEADER]: shareToken?.token },
5753
},
5854
[modified, url, referrer, os, browser, device, country],
5955
);

components/pages/RealtimeDashboard.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import useFetch from 'hooks/useFetch';
1414
import useLocale from 'hooks/useLocale';
1515
import useCountryNames from 'hooks/useCountryNames';
1616
import { percentFilter } from 'lib/filters';
17-
import { TOKEN_HEADER, REALTIME_RANGE, REALTIME_INTERVAL } from 'lib/constants';
17+
import { SHARE_TOKEN_HEADER, REALTIME_RANGE, REALTIME_INTERVAL } from 'lib/constants';
1818
import styles from './RealtimeDashboard.module.css';
1919

2020
function mergeData(state, data, time) {
@@ -38,7 +38,7 @@ export default function RealtimeDashboard() {
3838
params: { start_at: data?.timestamp },
3939
disabled: !init?.websites?.length || !data,
4040
interval: REALTIME_INTERVAL,
41-
headers: { [TOKEN_HEADER]: init?.token },
41+
headers: { [SHARE_TOKEN_HEADER]: init?.token },
4242
});
4343

4444
const renderCountryName = useCallback(

components/pages/WebsiteDetails.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ import EventsTable from 'components/metrics/EventsTable';
2020
import EventsChart from 'components/metrics/EventsChart';
2121
import useFetch from 'hooks/useFetch';
2222
import usePageQuery from 'hooks/usePageQuery';
23-
import useShareToken from 'hooks/useShareToken';
24-
import { DEFAULT_ANIMATION_DURATION, TOKEN_HEADER } from 'lib/constants';
23+
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
2524
import styles from './WebsiteDetails.module.css';
2625

2726
const views = {
@@ -36,10 +35,7 @@ const views = {
3635
};
3736

3837
export default function WebsiteDetails({ websiteId }) {
39-
const shareToken = useShareToken();
40-
const { data } = useFetch(`/website/${websiteId}`, {
41-
headers: { [TOKEN_HEADER]: shareToken?.token },
42-
});
38+
const { data } = useFetch(`/website/${websiteId}`);
4339
const [chartLoaded, setChartLoaded] = useState(false);
4440
const [countryData, setCountryData] = useState();
4541
const [eventsData, setEventsData] = useState();

hooks/useApi.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,69 @@
11
import { useCallback } from 'react';
22
import { useRouter } from 'next/router';
33
import { get, post, put, del, getItem } from 'lib/web';
4-
import { AUTH_TOKEN } from 'lib/constants';
4+
import { AUTH_TOKEN, SHARE_TOKEN_HEADER } from 'lib/constants';
5+
import useStore from 'store/app';
56

6-
function includeAuthToken(headers = {}) {
7-
const authToken = getItem(AUTH_TOKEN);
7+
const selector = state => state.shareToken;
88

9+
function parseHeaders(headers = {}, { authToken, shareToken }) {
910
if (authToken) {
10-
headers.Authorization = `Bearer ${authToken}`;
11+
headers.authorization = `Bearer ${authToken}`;
12+
}
13+
14+
if (shareToken) {
15+
headers[SHARE_TOKEN_HEADER] = shareToken.token;
1116
}
1217

1318
return headers;
1419
}
1520

1621
export default function useApi() {
1722
const { basePath } = useRouter();
23+
const authToken = getItem(AUTH_TOKEN);
24+
const shareToken = useStore(selector);
1825

1926
return {
2027
get: useCallback(
2128
async (url, params, headers) => {
22-
return get(`${basePath}/api${url}`, params, includeAuthToken(headers));
29+
return get(
30+
`${basePath}/api${url}`,
31+
params,
32+
parseHeaders(headers, { authToken, shareToken }),
33+
);
2334
},
2435
[get],
2536
),
2637

2738
post: useCallback(
2839
async (url, params, headers) => {
29-
return post(`${basePath}/api${url}`, params, includeAuthToken(headers));
40+
return post(
41+
`${basePath}/api${url}`,
42+
params,
43+
parseHeaders(headers, { authToken, shareToken }),
44+
);
3045
},
3146
[post],
3247
),
3348

3449
put: useCallback(
3550
async (url, params, headers) => {
36-
return put(`${basePath}/api${url}`, params, includeAuthToken(headers));
51+
return put(
52+
`${basePath}/api${url}`,
53+
params,
54+
parseHeaders(headers, { authToken, shareToken }),
55+
);
3756
},
3857
[put],
3958
),
4059

4160
del: useCallback(
4261
async (url, params, headers) => {
43-
return del(`${basePath}/api${url}`, params, includeAuthToken(headers));
62+
return del(
63+
`${basePath}/api${url}`,
64+
params,
65+
parseHeaders(headers, { authToken, shareToken }),
66+
);
4467
},
4568
[del],
4669
),

0 commit comments

Comments
 (0)