Skip to content

Commit

Permalink
Merge branch 'dev' into brian/um-16-clickhouse-support
Browse files Browse the repository at this point in the history
  • Loading branch information
briancao committed Jul 23, 2022
2 parents 65910c7 + 6f92677 commit 304314f
Show file tree
Hide file tree
Showing 114 changed files with 1,491 additions and 1,036 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"react/display-name": "off",
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"import/no-anonymous-default-export": "off"
"import/no-anonymous-default-export": "off",
"@next/next/no-img-element": "off"
},
"globals": {
"React": "writable"
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ jobs:
strategy:
matrix:
include:
- node-version: 12.x
db-type: postgresql
- node-version: 12.x
db-type: mysql
- node-version: 14.x
db-type: postgresql
- node-version: 14.x
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ npm install -g yarn
### Get the source code and install packages

```
git clone https://github.com/mikecao/umami.git
git clone https://github.com/umami-software/umami.git
cd umami
yarn install
```
Expand All @@ -32,7 +32,7 @@ yarn install
Create an `.env` file with the following

```
DATABASE_URL=(connection url)
DATABASE_URL=connection-url
```

The connection url is in the following format:
Expand Down Expand Up @@ -76,12 +76,12 @@ docker-compose up

Alternatively, to pull just the Umami Docker image with PostgreSQL support:
```bash
docker pull ghcr.io/mikecao/umami:postgresql-latest
docker pull docker.umami.is/umami-software/umami:postgresql-latest
```

Or with MySQL support:
```bash
docker pull ghcr.io/mikecao/umami:mysql-latest
docker pull docker.umami.is/umami-software/umami:mysql-latest
```

## Getting updates
Expand Down
2 changes: 1 addition & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Umami is a simple, fast, website analytics alternative to Google Analytics.",
"keywords": ["analytics", "charts", "statistics", "web-analytics"],
"website": "https://umami.is",
"repository": "https://github.com/mikecao/umami",
"repository": "https://github.com/umami-software/umami",
"addons": ["heroku-postgresql"],
"env": {
"HASH_SALT": {
Expand Down
6 changes: 3 additions & 3 deletions components/common/UpdateNotice.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { FormattedMessage } from 'react-intl';
import ButtonLayout from 'components/layout/ButtonLayout';
import useStore, { checkVersion } from 'store/version';
import { setItem } from 'lib/web';
import { VERSION_CHECK, VERSION_URL } from 'lib/constants';
import { REPO_URL, VERSION_CHECK } from 'lib/constants';
import Button from './Button';
import styles from './UpdateNotice.module.css';

export default function UpdateNotice() {
const { latest, checked, hasUpdate } = useStore();
const { latest, checked, hasUpdate, releaseUrl } = useStore();
const [dismissed, setDismissed] = useState(false);

const updateCheck = useCallback(() => {
Expand All @@ -18,7 +18,7 @@ export default function UpdateNotice() {
function handleViewClick() {
updateCheck();
setDismissed(true);
location.href = VERSION_URL;
location.href = releaseUrl || REPO_URL;
}

function handleDismissClick() {
Expand Down
7 changes: 5 additions & 2 deletions components/layout/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
import Link from 'components/common/Link';
import styles from './Footer.module.css';
import useStore from 'store/version';
import { HOMEPAGE_URL, VERSION_URL } from 'lib/constants';
import { HOMEPAGE_URL, REPO_URL } from 'lib/constants';

export default function Footer() {
const { current } = useStore();
Expand All @@ -26,8 +26,11 @@ export default function Footer() {
/>
</div>
<div className={classNames(styles.version, 'col-12 col-md-4')}>
<Link href={VERSION_URL}>{`v${current}`}</Link>
<Link href={REPO_URL}>{`v${current}`}</Link>
</div>
{!process.env.telemetryDisabled && (
<img src={`https://i.umami.is/a.png?v=${current}`} alt="" />
)}
</footer>
);
}
3 changes: 2 additions & 1 deletion components/metrics/FilterTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import classNames from 'classnames';
import Button from 'components/common/Button';
import Times from 'assets/times.svg';
import { safeDecodeURI } from 'lib/url';
import styles from './FilterTags.module.css';

export default function FilterTags({ params, onClick }) {
Expand All @@ -17,7 +18,7 @@ export default function FilterTags({ params, onClick }) {
return (
<div key={key} className={styles.tag}>
<Button icon={<Times />} onClick={() => onClick(key)} variant="action" iconRight>
{`${key}: ${params[key]}`}
{`${key}: ${safeDecodeURI(params[key])}`}
</Button>
</div>
);
Expand Down
5 changes: 3 additions & 2 deletions components/metrics/MetricsTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default function MetricsTable({
filterOptions,
limit,
onDataLoad,
delay = null,
...props
}) {
const [{ startDate, endDate, modified }] = useDateRange(websiteId);
Expand All @@ -46,9 +47,9 @@ export default function MetricsTable({
country,
},
onDataLoad,
delay: DEFAULT_ANIMATION_DURATION,
delay: delay || DEFAULT_ANIMATION_DURATION,
},
[modified, url, referrer, os, browser, device, country],
[type, modified, url, referrer, os, browser, device, country],
);

const filteredData = useMemo(() => {
Expand Down
26 changes: 18 additions & 8 deletions components/metrics/PagesTable.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { useIntl, defineMessage } from 'react-intl';
import FilterLink from 'components/common/FilterLink';
import FilterButtons from 'components/common/FilterButtons';
import { urlFilter } from 'lib/filters';
Expand All @@ -8,15 +8,26 @@ import MetricsTable from './MetricsTable';
export const FILTER_COMBINED = 0;
export const FILTER_RAW = 1;

export default function PagesTable({ websiteId, websiteDomain, showFilters, ...props }) {
const messages = defineMessage({
combined: { id: 'metrics.filter.combined', defaultMessage: 'Combined' },
raw: { id: 'metrics.filter.raw', defaultMessage: 'Raw' },
pages: { id: 'metrics.pages', defaultMessage: 'Pages' },
views: { id: 'metrics.views', defaultMessage: 'View' },
});

export default function PagesTable({ websiteId, showFilters, ...props }) {
const [filter, setFilter] = useState(FILTER_COMBINED);
const { formatMessage } = useIntl();

const buttons = [
{
label: <FormattedMessage id="metrics.filter.combined" defaultMessage="Combined" />,
label: formatMessage(messages.combined),
value: FILTER_COMBINED,
},
{ label: <FormattedMessage id="metrics.filter.raw" defaultMessage="Raw" />, value: FILTER_RAW },
{
label: formatMessage(messages.raw),
value: FILTER_RAW,
},
];

const renderLink = ({ x: url }) => {
Expand All @@ -27,12 +38,11 @@ export default function PagesTable({ websiteId, websiteDomain, showFilters, ...p
<>
{showFilters && <FilterButtons buttons={buttons} selected={filter} onClick={setFilter} />}
<MetricsTable
title={<FormattedMessage id="metrics.pages" defaultMessage="Pages" />}
title={formatMessage(messages.pages)}
type="url"
metric={<FormattedMessage id="metrics.views" defaultMessage="Views" />}
metric={formatMessage(messages.views)}
websiteId={websiteId}
dataFilter={urlFilter}
filterOptions={{ domain: websiteDomain, raw: filter === FILTER_RAW }}
dataFilter={filter !== FILTER_RAW ? urlFilter : null}
renderLabel={renderLink}
{...props}
/>
Expand Down
44 changes: 24 additions & 20 deletions components/metrics/ReferrersTable.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,52 @@
import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { useIntl, defineMessages } from 'react-intl';
import MetricsTable from './MetricsTable';
import FilterButtons from 'components/common/FilterButtons';
import FilterLink from 'components/common/FilterLink';
import { refFilter } from 'lib/filters';

export const FILTER_DOMAIN_ONLY = 0;
export const FILTER_COMBINED = 1;
export const FILTER_RAW = 2;
export const FILTER_COMBINED = 0;
export const FILTER_RAW = 1;

export default function ReferrersTable({ websiteId, websiteDomain, showFilters, ...props }) {
const messages = defineMessages({
combined: { id: 'metrics.filter.combined', defaultMessage: 'Combined' },
raw: { id: 'metrics.filter.raw', defaultMessage: 'Raw' },
referrers: { id: 'metrics.referrers', defaultMessage: 'Referrers' },
views: { id: 'metrics.views', defaultMessage: 'Views' },
none: { id: 'label.none', defaultMessage: 'None' },
});

export default function ReferrersTable({ websiteId, showFilters, ...props }) {
const [filter, setFilter] = useState(FILTER_COMBINED);
const { formatMessage } = useIntl();
const none = formatMessage(messages.none);

const buttons = [
{
label: <FormattedMessage id="metrics.filter.domain-only" defaultMessage="Domain only" />,
value: FILTER_DOMAIN_ONLY,
},
{
label: <FormattedMessage id="metrics.filter.combined" defaultMessage="Combined" />,
label: formatMessage(messages.combined),
value: FILTER_COMBINED,
},
{ label: <FormattedMessage id="metrics.filter.raw" defaultMessage="Raw" />, value: FILTER_RAW },
{ label: formatMessage(messages.raw), value: FILTER_RAW },
];

const renderLink = ({ w: link, x: referrer }) => {
return <FilterLink id="referrer" value={referrer} externalUrl={link} />;
return referrer ? (
<FilterLink id="referrer" value={referrer} externalUrl={link} />
) : (
`(${none})`
);
};

return (
<>
{showFilters && <FilterButtons buttons={buttons} selected={filter} onClick={setFilter} />}
<MetricsTable
{...props}
title={<FormattedMessage id="metrics.referrers" defaultMessage="Referrers" />}
title={formatMessage(messages.referrers)}
type="referrer"
metric={<FormattedMessage id="metrics.views" defaultMessage="Views" />}
metric={formatMessage(messages.views)}
websiteId={websiteId}
dataFilter={refFilter}
filterOptions={{
domain: websiteDomain,
domainOnly: filter === FILTER_DOMAIN_ONLY,
raw: filter === FILTER_RAW,
}}
dataFilter={filter !== FILTER_RAW ? refFilter : null}
renderLabel={renderLink}
/>
</>
Expand Down
15 changes: 15 additions & 0 deletions components/metrics/ScreenTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import MetricsTable from './MetricsTable';
import { FormattedMessage } from 'react-intl';

export default function ScreenTable({ websiteId, ...props }) {
return (
<MetricsTable
{...props}
title={<FormattedMessage id="metrics.screens" defaultMessage="Screen" />}
type="screen"
metric={<FormattedMessage id="metrics.visitors" defaultMessage="Visitors" />}
websiteId={websiteId}
/>
);
}
47 changes: 47 additions & 0 deletions components/metrics/UTMTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { useState } from 'react';
import { useIntl, defineMessages } from 'react-intl';
import MetricsTable from './MetricsTable';
import FilterButtons from 'components/common/FilterButtons';

export const UTM_SOURCE = 'utm_source';
export const UTM_MEDIUM = 'utm_medium';
export const UTM_CAMPAIGN = 'utm_campaign';
export const UTM_CONTENT = 'utm_content';
export const UTM_TERM = 'utm_term';

const messages = defineMessages({
utm_source: { id: 'metrics.utm_source', defaultMessage: 'UTM Source' },
utm_medium: { id: 'metrics.utm_medium', defaultMessage: 'UTM Medium' },
utm_campaign: { id: 'metrics.utm_campaign', defaultMessage: 'UTM Campaign' },
utm_content: { id: 'metrics.utm_content', defaultMessage: 'UTM Content' },
utm_term: { id: 'metrics.utm_term', defaultMessage: 'UTM Term' },
views: { id: 'metrics.views', defaultMessage: 'Views' },
none: { id: 'label.none', defaultMessage: 'None' },
});

export default function UTMTable({ websiteId, showFilters, ...props }) {
const [type, setType] = useState(UTM_SOURCE);
const { formatMessage } = useIntl();

const buttons = [
{ label: formatMessage(messages.utm_source), value: UTM_SOURCE },
{ label: formatMessage(messages.utm_medium), value: UTM_MEDIUM },
{ label: formatMessage(messages.utm_campaign), value: UTM_CAMPAIGN },
{ label: formatMessage(messages.utm_content), value: UTM_CONTENT },
{ label: formatMessage(messages.utm_term), value: UTM_TERM },
];

return (
<>
{showFilters && <FilterButtons buttons={buttons} selected={type} onClick={setType} />}
<MetricsTable
{...props}
title={formatMessage(messages[type])}
type={type}
metric={formatMessage(messages.views)}
websiteId={websiteId}
delay={0}
/>
</>
);
}
12 changes: 12 additions & 0 deletions components/pages/WebsiteDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,20 @@ import useFetch from 'hooks/useFetch';
import usePageQuery from 'hooks/usePageQuery';
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
import styles from './WebsiteDetails.module.css';
import ScreenTable from 'components/metrics/ScreenTable';
import UTMTable from 'components/metrics/UTMTable';

const views = {
url: PagesTable,
referrer: ReferrersTable,
browser: BrowsersTable,
os: OSTable,
device: DevicesTable,
screen: ScreenTable,
country: CountriesTable,
language: LanguagesTable,
event: EventsTable,
utm: UTMTable,
};

export default function WebsiteDetails({ websiteId }) {
Expand Down Expand Up @@ -64,6 +68,10 @@ export default function WebsiteDetails({ websiteId }) {
label: <FormattedMessage id="metrics.referrers" defaultMessage="Referrers" />,
value: resolve({ view: 'referrer' }),
},
{
label: <FormattedMessage id="metrics.screens" defaultMessage="Screens" />,
value: resolve({ view: 'screen' }),
},
{
label: <FormattedMessage id="metrics.browsers" defaultMessage="Browsers" />,
value: resolve({ view: 'browser' }),
Expand All @@ -88,6 +96,10 @@ export default function WebsiteDetails({ websiteId }) {
label: <FormattedMessage id="metrics.events" defaultMessage="Events" />,
value: resolve({ view: 'event' }),
},
{
label: <FormattedMessage id="metrics.utm" defaultMessage="UTM" />,
value: resolve({ view: 'utm' }),
},
];

const tableProps = {
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
version: '3'
services:
umami:
image: ghcr.io/mikecao/umami:postgresql-latest
image: ghcr.io/umami-software/umami:postgresql-latest
ports:
- "3000:3000"
environment:
Expand Down
Loading

0 comments on commit 304314f

Please sign in to comment.