Skip to content

Commit

Permalink
Merge pull request umami-software#1312 from umami-software/dev
Browse files Browse the repository at this point in the history
v1.34.0
  • Loading branch information
mikecao authored Jul 21, 2022
2 parents b290f95 + 358c725 commit 16046a5
Show file tree
Hide file tree
Showing 157 changed files with 2,751 additions and 2,156 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
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
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}
/>
);
}
6 changes: 6 additions & 0 deletions components/pages/WebsiteDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ 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';

const views = {
url: PagesTable,
referrer: ReferrersTable,
browser: BrowsersTable,
os: OSTable,
device: DevicesTable,
screen: ScreenTable,
country: CountriesTable,
language: LanguagesTable,
event: EventsTable,
Expand Down Expand Up @@ -64,6 +66,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 Down
10 changes: 5 additions & 5 deletions db/mysql/migrations/01_init/migration.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CREATE TABLE `account` (

UNIQUE INDEX `username`(`username`),
PRIMARY KEY (`user_id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `event` (
Expand All @@ -25,7 +25,7 @@ CREATE TABLE `event` (
INDEX `event_session_id_idx`(`session_id`),
INDEX `event_website_id_idx`(`website_id`),
PRIMARY KEY (`event_id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `pageview` (
Expand All @@ -42,7 +42,7 @@ CREATE TABLE `pageview` (
INDEX `pageview_website_id_idx`(`website_id`),
INDEX `pageview_website_id_session_id_created_at_idx`(`website_id`, `session_id`, `created_at`),
PRIMARY KEY (`view_id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `session` (
Expand All @@ -62,7 +62,7 @@ CREATE TABLE `session` (
INDEX `session_created_at_idx`(`created_at`),
INDEX `session_website_id_idx`(`website_id`),
PRIMARY KEY (`session_id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `website` (
Expand All @@ -78,7 +78,7 @@ CREATE TABLE `website` (
UNIQUE INDEX `share_id`(`share_id`),
INDEX `website_user_id_idx`(`user_id`),
PRIMARY KEY (`website_id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- AddForeignKey
ALTER TABLE `event` ADD CONSTRAINT `event_ibfk_2` FOREIGN KEY (`session_id`) REFERENCES `session`(`session_id`) ON DELETE CASCADE ON UPDATE NO ACTION;
Expand Down
28 changes: 14 additions & 14 deletions db/postgresql/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ datasource db {

model account {
user_id Int @id @default(autoincrement())
username String @unique(map: "account.username_unique") @db.VarChar(255)
username String @unique @db.VarChar(255)
password String @db.VarChar(60)
is_admin Boolean @default(false)
created_at DateTime? @default(now()) @db.Timestamptz(6)
Expand All @@ -25,8 +25,8 @@ model event {
url String @db.VarChar(500)
event_type String @db.VarChar(50)
event_value String @db.VarChar(50)
session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade)
website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade)
session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade, onUpdate: NoAction)
website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction)
@@index([created_at])
@@index([session_id])
Expand All @@ -40,8 +40,8 @@ model pageview {
created_at DateTime? @default(now()) @db.Timestamptz(6)
url String @db.VarChar(500)
referrer String? @db.VarChar(500)
session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade)
website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade)
session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade, onUpdate: NoAction)
website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction)
@@index([created_at])
@@index([session_id])
Expand All @@ -52,17 +52,17 @@ model pageview {

model session {
session_id Int @id @default(autoincrement())
session_uuid String @unique(map: "session.session_uuid_unique") @db.Uuid
session_uuid String @unique @db.Uuid
website_id Int
created_at DateTime? @default(now()) @db.Timestamptz(6)
hostname String? @db.VarChar(100)
browser String? @db.VarChar(20)
os String? @db.VarChar(20)
device String? @db.VarChar(20)
screen String? @db.VarChar(11)
language String? @db.VarChar(35)
country String? @db.Char(2)
website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade)
device String? @db.VarChar(20)
website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction)
event event[]
pageview pageview[]
Expand All @@ -72,16 +72,16 @@ model session {

model website {
website_id Int @id @default(autoincrement())
website_uuid String @unique(map: "website.website_uuid_unique") @db.Uuid
user_id Int
website_uuid String @unique @db.Uuid
name String @db.VarChar(100)
domain String? @db.VarChar(500)
share_id String? @unique(map: "website.share_id_unique") @db.VarChar(64)
created_at DateTime? @default(now()) @db.Timestamptz(6)
account account @relation(fields: [user_id], references: [user_id], onDelete: Cascade)
user_id Int
domain String? @db.VarChar(500)
share_id String? @unique(map: "website_share_id_idx") @db.VarChar(64)
account account @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
event event[]
pageview pageview[]
session session[]
@@index([user_id])
}
}
3 changes: 2 additions & 1 deletion lang/ar-SA.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"label.more": "المزيد",
"label.name": "الإسم",
"label.new-password": "كلمة مرور جديدة",
"label.none": "None",
"label.owner": "Owner",
"label.password": "كلمة المرور",
"label.passwords-dont-match": "كلمة المرور غير متطابقة",
Expand Down Expand Up @@ -97,13 +98,13 @@
"metrics.devices": "الأجهزة",
"metrics.events": "الأحداث",
"metrics.filter.combined": "مجمعة",
"metrics.filter.domain-only": "نطاق فقط",
"metrics.filter.raw": "مفصلة",
"metrics.languages": "Languages",
"metrics.operating-systems": "نظام التشغيل",
"metrics.page-views": "مشاهدات الصفحة",
"metrics.pages": "الصفحات",
"metrics.referrers": "التحويلات",
"metrics.screens": "Screens",
"metrics.unique-visitors": "زائرون فريدون",
"metrics.views": "مشاهدات",
"metrics.visitors": "زوار"
Expand Down
Loading

0 comments on commit 16046a5

Please sign in to comment.