mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-14 21:10:34 +01:00
add tags table and filters logic
This commit is contained in:
parent
bffb98cd51
commit
8759ba9916
@ -1,6 +1,6 @@
|
|||||||
-- add tag column
|
-- add tag column
|
||||||
ALTER TABLE umami.website_event ADD COLUMN "tag" String AFTER "event_name";
|
ALTER TABLE umami.website_event ADD COLUMN "tag" String AFTER "event_name";
|
||||||
ALTER TABLE umami.website_event_stats_hourly ADD COLUMN "tag" String AFTER "max_time";
|
ALTER TABLE umami.website_event_stats_hourly ADD COLUMN "tag" SimpleAggregateFunction(groupArrayArray, Array(String)) AFTER "max_time";
|
||||||
|
|
||||||
-- update materialized view
|
-- update materialized view
|
||||||
DROP TABLE umami.website_event_stats_hourly_mv;
|
DROP TABLE umami.website_event_stats_hourly_mv;
|
||||||
@ -58,7 +58,7 @@ FROM (SELECT
|
|||||||
sumIf(1, event_type = 1) views,
|
sumIf(1, event_type = 1) views,
|
||||||
min(created_at) min_time,
|
min(created_at) min_time,
|
||||||
max(created_at) max_time,
|
max(created_at) max_time,
|
||||||
tag,
|
arrayFilter(x -> x != '', groupArray(tag)) tag,
|
||||||
toStartOfHour(created_at) timestamp
|
toStartOfHour(created_at) timestamp
|
||||||
FROM umami.website_event
|
FROM umami.website_event
|
||||||
GROUP BY website_id,
|
GROUP BY website_id,
|
||||||
@ -74,5 +74,4 @@ GROUP BY website_id,
|
|||||||
subdivision1,
|
subdivision1,
|
||||||
city,
|
city,
|
||||||
event_type,
|
event_type,
|
||||||
tag,
|
|
||||||
timestamp);
|
timestamp);
|
@ -1,20 +1,21 @@
|
|||||||
import { Icons, Icon, Text, Dropdown, Item } from 'react-basics';
|
import LinkButton from 'components/common/LinkButton';
|
||||||
|
import { useLocale, useMessages, useNavigation } from 'components/hooks';
|
||||||
|
import SideNav from 'components/layout/SideNav';
|
||||||
import BrowsersTable from 'components/metrics/BrowsersTable';
|
import BrowsersTable from 'components/metrics/BrowsersTable';
|
||||||
import CountriesTable from 'components/metrics/CountriesTable';
|
|
||||||
import RegionsTable from 'components/metrics/RegionsTable';
|
|
||||||
import CitiesTable from 'components/metrics/CitiesTable';
|
import CitiesTable from 'components/metrics/CitiesTable';
|
||||||
|
import CountriesTable from 'components/metrics/CountriesTable';
|
||||||
import DevicesTable from 'components/metrics/DevicesTable';
|
import DevicesTable from 'components/metrics/DevicesTable';
|
||||||
|
import EventsTable from 'components/metrics/EventsTable';
|
||||||
|
import HostsTable from 'components/metrics/HostsTable';
|
||||||
import LanguagesTable from 'components/metrics/LanguagesTable';
|
import LanguagesTable from 'components/metrics/LanguagesTable';
|
||||||
import OSTable from 'components/metrics/OSTable';
|
import OSTable from 'components/metrics/OSTable';
|
||||||
import PagesTable from 'components/metrics/PagesTable';
|
import PagesTable from 'components/metrics/PagesTable';
|
||||||
import QueryParametersTable from 'components/metrics/QueryParametersTable';
|
import QueryParametersTable from 'components/metrics/QueryParametersTable';
|
||||||
import ReferrersTable from 'components/metrics/ReferrersTable';
|
import ReferrersTable from 'components/metrics/ReferrersTable';
|
||||||
import HostsTable from 'components/metrics/HostsTable';
|
import RegionsTable from 'components/metrics/RegionsTable';
|
||||||
import ScreenTable from 'components/metrics/ScreenTable';
|
import ScreenTable from 'components/metrics/ScreenTable';
|
||||||
import EventsTable from 'components/metrics/EventsTable';
|
import TagsTable from 'components/metrics/TagsTable';
|
||||||
import SideNav from 'components/layout/SideNav';
|
import { Dropdown, Icon, Icons, Item, Text } from 'react-basics';
|
||||||
import { useNavigation, useMessages, useLocale } from 'components/hooks';
|
|
||||||
import LinkButton from 'components/common/LinkButton';
|
|
||||||
import styles from './WebsiteExpandedView.module.css';
|
import styles from './WebsiteExpandedView.module.css';
|
||||||
|
|
||||||
const views = {
|
const views = {
|
||||||
@ -34,6 +35,7 @@ const views = {
|
|||||||
language: LanguagesTable,
|
language: LanguagesTable,
|
||||||
event: EventsTable,
|
event: EventsTable,
|
||||||
query: QueryParametersTable,
|
query: QueryParametersTable,
|
||||||
|
tag: TagsTable,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function WebsiteExpandedView({
|
export default function WebsiteExpandedView({
|
||||||
@ -117,6 +119,11 @@ export default function WebsiteExpandedView({
|
|||||||
label: formatMessage(labels.hosts),
|
label: formatMessage(labels.hosts),
|
||||||
url: renderUrl({ view: 'host' }),
|
url: renderUrl({ view: 'host' }),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'tag',
|
||||||
|
label: formatMessage(labels.tags),
|
||||||
|
url: renderUrl({ view: 'tag' }),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const DetailsComponent = views[view] || (() => null);
|
const DetailsComponent = views[view] || (() => null);
|
||||||
|
@ -1,24 +1,25 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import SideNav from 'components/layout/SideNav';
|
|
||||||
import { useDateRange, useMessages, useNavigation } from 'components/hooks';
|
import { useDateRange, useMessages, useNavigation } from 'components/hooks';
|
||||||
import PagesTable from 'components/metrics/PagesTable';
|
|
||||||
import ReferrersTable from 'components/metrics/ReferrersTable';
|
|
||||||
import BrowsersTable from 'components/metrics/BrowsersTable';
|
|
||||||
import OSTable from 'components/metrics/OSTable';
|
|
||||||
import DevicesTable from 'components/metrics/DevicesTable';
|
|
||||||
import ScreenTable from 'components/metrics/ScreenTable';
|
|
||||||
import CountriesTable from 'components/metrics/CountriesTable';
|
|
||||||
import RegionsTable from 'components/metrics/RegionsTable';
|
|
||||||
import CitiesTable from 'components/metrics/CitiesTable';
|
|
||||||
import LanguagesTable from 'components/metrics/LanguagesTable';
|
|
||||||
import EventsTable from 'components/metrics/EventsTable';
|
|
||||||
import QueryParametersTable from 'components/metrics/QueryParametersTable';
|
|
||||||
import { Grid, GridRow } from 'components/layout/Grid';
|
import { Grid, GridRow } from 'components/layout/Grid';
|
||||||
|
import SideNav from 'components/layout/SideNav';
|
||||||
|
import BrowsersTable from 'components/metrics/BrowsersTable';
|
||||||
|
import ChangeLabel from 'components/metrics/ChangeLabel';
|
||||||
|
import CitiesTable from 'components/metrics/CitiesTable';
|
||||||
|
import CountriesTable from 'components/metrics/CountriesTable';
|
||||||
|
import DevicesTable from 'components/metrics/DevicesTable';
|
||||||
|
import EventsTable from 'components/metrics/EventsTable';
|
||||||
|
import LanguagesTable from 'components/metrics/LanguagesTable';
|
||||||
import MetricsTable from 'components/metrics/MetricsTable';
|
import MetricsTable from 'components/metrics/MetricsTable';
|
||||||
import useStore from 'store/websites';
|
import OSTable from 'components/metrics/OSTable';
|
||||||
|
import PagesTable from 'components/metrics/PagesTable';
|
||||||
|
import QueryParametersTable from 'components/metrics/QueryParametersTable';
|
||||||
|
import ReferrersTable from 'components/metrics/ReferrersTable';
|
||||||
|
import RegionsTable from 'components/metrics/RegionsTable';
|
||||||
|
import ScreenTable from 'components/metrics/ScreenTable';
|
||||||
|
import TagsTable from 'components/metrics/TagsTable';
|
||||||
import { getCompareDate } from 'lib/date';
|
import { getCompareDate } from 'lib/date';
|
||||||
import { formatNumber } from 'lib/format';
|
import { formatNumber } from 'lib/format';
|
||||||
import ChangeLabel from 'components/metrics/ChangeLabel';
|
import { useState } from 'react';
|
||||||
|
import useStore from 'store/websites';
|
||||||
import styles from './WebsiteCompareTables.module.css';
|
import styles from './WebsiteCompareTables.module.css';
|
||||||
|
|
||||||
const views = {
|
const views = {
|
||||||
@ -35,6 +36,7 @@ const views = {
|
|||||||
language: LanguagesTable,
|
language: LanguagesTable,
|
||||||
event: EventsTable,
|
event: EventsTable,
|
||||||
query: QueryParametersTable,
|
query: QueryParametersTable,
|
||||||
|
tag: TagsTable,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
|
export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
|
||||||
@ -109,6 +111,16 @@ export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
|
|||||||
label: formatMessage(labels.queryParameters),
|
label: formatMessage(labels.queryParameters),
|
||||||
url: renderUrl({ view: 'query' }),
|
url: renderUrl({ view: 'query' }),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'host',
|
||||||
|
label: formatMessage(labels.hosts),
|
||||||
|
url: renderUrl({ view: 'host' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'tag',
|
||||||
|
label: formatMessage(labels.tags),
|
||||||
|
url: renderUrl({ view: 'tag' }),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const renderChange = ({ x, y }) => {
|
const renderChange = ({ x, y }) => {
|
||||||
|
@ -15,6 +15,7 @@ export function useFields() {
|
|||||||
{ name: 'region', type: 'string', label: formatMessage(labels.region) },
|
{ name: 'region', type: 'string', label: formatMessage(labels.region) },
|
||||||
{ name: 'city', type: 'string', label: formatMessage(labels.city) },
|
{ name: 'city', type: 'string', label: formatMessage(labels.city) },
|
||||||
{ name: 'host', type: 'string', label: formatMessage(labels.host) },
|
{ name: 'host', type: 'string', label: formatMessage(labels.host) },
|
||||||
|
{ name: 'tag', type: 'string', label: formatMessage(labels.tag) },
|
||||||
];
|
];
|
||||||
|
|
||||||
return { fields };
|
return { fields };
|
||||||
|
@ -7,7 +7,21 @@ export function useFilterParams(websiteId: string) {
|
|||||||
const { startDate, endDate, unit } = dateRange;
|
const { startDate, endDate, unit } = dateRange;
|
||||||
const { timezone, toUtc } = useTimezone();
|
const { timezone, toUtc } = useTimezone();
|
||||||
const {
|
const {
|
||||||
query: { url, referrer, title, query, host, os, browser, device, country, region, city, event },
|
query: {
|
||||||
|
url,
|
||||||
|
referrer,
|
||||||
|
title,
|
||||||
|
query,
|
||||||
|
host,
|
||||||
|
os,
|
||||||
|
browser,
|
||||||
|
device,
|
||||||
|
country,
|
||||||
|
region,
|
||||||
|
city,
|
||||||
|
event,
|
||||||
|
tag,
|
||||||
|
},
|
||||||
} = useNavigation();
|
} = useNavigation();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -27,5 +41,6 @@ export function useFilterParams(websiteId: string) {
|
|||||||
region,
|
region,
|
||||||
city,
|
city,
|
||||||
event,
|
event,
|
||||||
|
tag,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,7 @@ export const labels = defineMessages({
|
|||||||
devices: { id: 'label.devices', defaultMessage: 'Devices' },
|
devices: { id: 'label.devices', defaultMessage: 'Devices' },
|
||||||
countries: { id: 'label.countries', defaultMessage: 'Countries' },
|
countries: { id: 'label.countries', defaultMessage: 'Countries' },
|
||||||
languages: { id: 'label.languages', defaultMessage: 'Languages' },
|
languages: { id: 'label.languages', defaultMessage: 'Languages' },
|
||||||
|
tags: { id: 'label.tags', defaultMessage: 'Tags' },
|
||||||
count: { id: 'label.count', defaultMessage: 'Count' },
|
count: { id: 'label.count', defaultMessage: 'Count' },
|
||||||
average: { id: 'label.average', defaultMessage: 'Average' },
|
average: { id: 'label.average', defaultMessage: 'Average' },
|
||||||
sum: { id: 'label.sum', defaultMessage: 'Sum' },
|
sum: { id: 'label.sum', defaultMessage: 'Sum' },
|
||||||
@ -220,6 +221,7 @@ export const labels = defineMessages({
|
|||||||
browser: { id: 'label.browser', defaultMessage: 'Browser' },
|
browser: { id: 'label.browser', defaultMessage: 'Browser' },
|
||||||
device: { id: 'label.device', defaultMessage: 'Device' },
|
device: { id: 'label.device', defaultMessage: 'Device' },
|
||||||
pageTitle: { id: 'label.pageTitle', defaultMessage: 'Page title' },
|
pageTitle: { id: 'label.pageTitle', defaultMessage: 'Page title' },
|
||||||
|
tag: { id: 'label.tag', defaultMessage: 'Tag' },
|
||||||
day: { id: 'label.day', defaultMessage: 'Day' },
|
day: { id: 'label.day', defaultMessage: 'Day' },
|
||||||
date: { id: 'label.date', defaultMessage: 'Date' },
|
date: { id: 'label.date', defaultMessage: 'Date' },
|
||||||
pageOf: { id: 'label.page-of', defaultMessage: 'Page {current} of {total}' },
|
pageOf: { id: 'label.page-of', defaultMessage: 'Page {current} of {total}' },
|
||||||
|
@ -25,7 +25,7 @@ export function HostsTable(props: MetricsTableProps) {
|
|||||||
{...props}
|
{...props}
|
||||||
title={formatMessage(labels.hosts)}
|
title={formatMessage(labels.hosts)}
|
||||||
type="host"
|
type="host"
|
||||||
metric={formatMessage(labels.views)}
|
metric={formatMessage(labels.visitors)}
|
||||||
renderLabel={renderLink}
|
renderLabel={renderLink}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
30
src/components/metrics/TagsTable.tsx
Normal file
30
src/components/metrics/TagsTable.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import MetricsTable, { MetricsTableProps } from './MetricsTable';
|
||||||
|
import FilterLink from 'components/common/FilterLink';
|
||||||
|
import { useMessages } from 'components/hooks';
|
||||||
|
import { Flexbox } from 'react-basics';
|
||||||
|
|
||||||
|
export function TagsTable(props: MetricsTableProps) {
|
||||||
|
const { formatMessage, labels } = useMessages();
|
||||||
|
|
||||||
|
const renderLink = ({ x: tag }) => {
|
||||||
|
return (
|
||||||
|
<Flexbox alignItems="center">
|
||||||
|
<FilterLink id="tag" value={tag} label={!tag && formatMessage(labels.none)} />
|
||||||
|
</Flexbox>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MetricsTable
|
||||||
|
{...props}
|
||||||
|
title={formatMessage(labels.tags)}
|
||||||
|
type="tag"
|
||||||
|
metric={formatMessage(labels.views)}
|
||||||
|
renderLabel={renderLink}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TagsTable;
|
@ -33,7 +33,7 @@ export const FILTER_REFERRERS = 'filter-referrers';
|
|||||||
export const FILTER_PAGES = 'filter-pages';
|
export const FILTER_PAGES = 'filter-pages';
|
||||||
|
|
||||||
export const UNIT_TYPES = ['year', 'month', 'hour', 'day', 'minute'];
|
export const UNIT_TYPES = ['year', 'month', 'hour', 'day', 'minute'];
|
||||||
export const EVENT_COLUMNS = ['url', 'entry', 'exit', 'referrer', 'title', 'query', 'event'];
|
export const EVENT_COLUMNS = ['url', 'entry', 'exit', 'referrer', 'title', 'query', 'event', 'tag'];
|
||||||
|
|
||||||
export const SESSION_COLUMNS = [
|
export const SESSION_COLUMNS = [
|
||||||
'browser',
|
'browser',
|
||||||
@ -63,6 +63,7 @@ export const FILTER_COLUMNS = {
|
|||||||
city: 'city',
|
city: 'city',
|
||||||
language: 'language',
|
language: 'language',
|
||||||
event: 'event_name',
|
event: 'event_name',
|
||||||
|
tag: 'tag',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const COLLECTION_TYPE = {
|
export const COLLECTION_TYPE = {
|
||||||
|
@ -179,6 +179,7 @@ export interface QueryFilters {
|
|||||||
language?: string;
|
language?: string;
|
||||||
event?: string;
|
event?: string;
|
||||||
search?: string;
|
search?: string;
|
||||||
|
tag?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueryOptions {
|
export interface QueryOptions {
|
||||||
|
@ -24,6 +24,7 @@ export interface WebsiteEventsRequestQuery {
|
|||||||
country?: string;
|
country?: string;
|
||||||
region: string;
|
region: string;
|
||||||
city?: string;
|
city?: string;
|
||||||
|
tag?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
@ -43,6 +44,7 @@ const schema = {
|
|||||||
country: yup.string(),
|
country: yup.string(),
|
||||||
region: yup.string(),
|
region: yup.string(),
|
||||||
city: yup.string(),
|
city: yup.string(),
|
||||||
|
tag: yup.string(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ export interface WebsiteMetricsRequestQuery {
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
offset?: number;
|
offset?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
|
tag?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
@ -53,6 +54,7 @@ const schema = {
|
|||||||
limit: yup.number(),
|
limit: yup.number(),
|
||||||
offset: yup.number(),
|
offset: yup.number(),
|
||||||
search: yup.string(),
|
search: yup.string(),
|
||||||
|
tag: yup.string(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ export interface WebsitePageviewRequestQuery {
|
|||||||
country?: string;
|
country?: string;
|
||||||
region: string;
|
region: string;
|
||||||
city?: string;
|
city?: string;
|
||||||
|
tag?: string;
|
||||||
compare?: string;
|
compare?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ const schema = {
|
|||||||
country: yup.string(),
|
country: yup.string(),
|
||||||
region: yup.string(),
|
region: yup.string(),
|
||||||
city: yup.string(),
|
city: yup.string(),
|
||||||
|
tag: yup.string(),
|
||||||
compare: yup.string(),
|
compare: yup.string(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -23,6 +23,7 @@ export interface WebsiteSessionStatsRequestQuery {
|
|||||||
country?: string;
|
country?: string;
|
||||||
region?: string;
|
region?: string;
|
||||||
city?: string;
|
city?: string;
|
||||||
|
tag?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
@ -42,6 +43,7 @@ const schema = {
|
|||||||
country: yup.string(),
|
country: yup.string(),
|
||||||
region: yup.string(),
|
region: yup.string(),
|
||||||
city: yup.string(),
|
city: yup.string(),
|
||||||
|
tag: yup.string(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ export interface WebsiteStatsRequestQuery {
|
|||||||
country?: string;
|
country?: string;
|
||||||
region?: string;
|
region?: string;
|
||||||
city?: string;
|
city?: string;
|
||||||
|
tag?: string;
|
||||||
compare?: string;
|
compare?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ const schema = {
|
|||||||
country: yup.string(),
|
country: yup.string(),
|
||||||
region: yup.string(),
|
region: yup.string(),
|
||||||
city: yup.string(),
|
city: yup.string(),
|
||||||
|
tag: yup.string(),
|
||||||
compare: yup.string(),
|
compare: yup.string(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user