add tags table and filters logic

This commit is contained in:
Francis Cao 2024-10-15 16:46:57 -07:00
parent bffb98cd51
commit 8759ba9916
15 changed files with 108 additions and 30 deletions

View File

@ -1,6 +1,6 @@
-- add tag column
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
DROP TABLE umami.website_event_stats_hourly_mv;
@ -58,7 +58,7 @@ FROM (SELECT
sumIf(1, event_type = 1) views,
min(created_at) min_time,
max(created_at) max_time,
tag,
arrayFilter(x -> x != '', groupArray(tag)) tag,
toStartOfHour(created_at) timestamp
FROM umami.website_event
GROUP BY website_id,
@ -74,5 +74,4 @@ GROUP BY website_id,
subdivision1,
city,
event_type,
tag,
timestamp);

View File

@ -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 CountriesTable from 'components/metrics/CountriesTable';
import RegionsTable from 'components/metrics/RegionsTable';
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 HostsTable from 'components/metrics/HostsTable';
import LanguagesTable from 'components/metrics/LanguagesTable';
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 HostsTable from 'components/metrics/HostsTable';
import RegionsTable from 'components/metrics/RegionsTable';
import ScreenTable from 'components/metrics/ScreenTable';
import EventsTable from 'components/metrics/EventsTable';
import SideNav from 'components/layout/SideNav';
import { useNavigation, useMessages, useLocale } from 'components/hooks';
import LinkButton from 'components/common/LinkButton';
import TagsTable from 'components/metrics/TagsTable';
import { Dropdown, Icon, Icons, Item, Text } from 'react-basics';
import styles from './WebsiteExpandedView.module.css';
const views = {
@ -34,6 +35,7 @@ const views = {
language: LanguagesTable,
event: EventsTable,
query: QueryParametersTable,
tag: TagsTable,
};
export default function WebsiteExpandedView({
@ -117,6 +119,11 @@ export default function WebsiteExpandedView({
label: formatMessage(labels.hosts),
url: renderUrl({ view: 'host' }),
},
{
key: 'tag',
label: formatMessage(labels.tags),
url: renderUrl({ view: 'tag' }),
},
];
const DetailsComponent = views[view] || (() => null);

View File

@ -1,24 +1,25 @@
import { useState } from 'react';
import SideNav from 'components/layout/SideNav';
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 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 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 { 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';
const views = {
@ -35,6 +36,7 @@ const views = {
language: LanguagesTable,
event: EventsTable,
query: QueryParametersTable,
tag: TagsTable,
};
export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
@ -109,6 +111,16 @@ export function WebsiteCompareTables({ websiteId }: { websiteId: string }) {
label: formatMessage(labels.queryParameters),
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 }) => {

View File

@ -15,6 +15,7 @@ export function useFields() {
{ name: 'region', type: 'string', label: formatMessage(labels.region) },
{ name: 'city', type: 'string', label: formatMessage(labels.city) },
{ name: 'host', type: 'string', label: formatMessage(labels.host) },
{ name: 'tag', type: 'string', label: formatMessage(labels.tag) },
];
return { fields };

View File

@ -7,7 +7,21 @@ export function useFilterParams(websiteId: string) {
const { startDate, endDate, unit } = dateRange;
const { timezone, toUtc } = useTimezone();
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();
return {
@ -27,5 +41,6 @@ export function useFilterParams(websiteId: string) {
region,
city,
event,
tag,
};
}

View File

@ -98,6 +98,7 @@ export const labels = defineMessages({
devices: { id: 'label.devices', defaultMessage: 'Devices' },
countries: { id: 'label.countries', defaultMessage: 'Countries' },
languages: { id: 'label.languages', defaultMessage: 'Languages' },
tags: { id: 'label.tags', defaultMessage: 'Tags' },
count: { id: 'label.count', defaultMessage: 'Count' },
average: { id: 'label.average', defaultMessage: 'Average' },
sum: { id: 'label.sum', defaultMessage: 'Sum' },
@ -220,6 +221,7 @@ export const labels = defineMessages({
browser: { id: 'label.browser', defaultMessage: 'Browser' },
device: { id: 'label.device', defaultMessage: 'Device' },
pageTitle: { id: 'label.pageTitle', defaultMessage: 'Page title' },
tag: { id: 'label.tag', defaultMessage: 'Tag' },
day: { id: 'label.day', defaultMessage: 'Day' },
date: { id: 'label.date', defaultMessage: 'Date' },
pageOf: { id: 'label.page-of', defaultMessage: 'Page {current} of {total}' },

View File

@ -25,7 +25,7 @@ export function HostsTable(props: MetricsTableProps) {
{...props}
title={formatMessage(labels.hosts)}
type="host"
metric={formatMessage(labels.views)}
metric={formatMessage(labels.visitors)}
renderLabel={renderLink}
/>
</>

View 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;

View File

@ -33,7 +33,7 @@ export const FILTER_REFERRERS = 'filter-referrers';
export const FILTER_PAGES = 'filter-pages';
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 = [
'browser',
@ -63,6 +63,7 @@ export const FILTER_COLUMNS = {
city: 'city',
language: 'language',
event: 'event_name',
tag: 'tag',
};
export const COLLECTION_TYPE = {

View File

@ -179,6 +179,7 @@ export interface QueryFilters {
language?: string;
event?: string;
search?: string;
tag?: string;
}
export interface QueryOptions {

View File

@ -24,6 +24,7 @@ export interface WebsiteEventsRequestQuery {
country?: string;
region: string;
city?: string;
tag?: string;
}
const schema = {
@ -43,6 +44,7 @@ const schema = {
country: yup.string(),
region: yup.string(),
city: yup.string(),
tag: yup.string(),
}),
};

View File

@ -29,6 +29,7 @@ export interface WebsiteMetricsRequestQuery {
limit?: number;
offset?: number;
search?: string;
tag?: string;
}
const schema = {
@ -53,6 +54,7 @@ const schema = {
limit: yup.number(),
offset: yup.number(),
search: yup.string(),
tag: yup.string(),
}),
};

View File

@ -25,6 +25,7 @@ export interface WebsitePageviewRequestQuery {
country?: string;
region: string;
city?: string;
tag?: string;
compare?: string;
}
@ -45,6 +46,7 @@ const schema = {
country: yup.string(),
region: yup.string(),
city: yup.string(),
tag: yup.string(),
compare: yup.string(),
}),
};

View File

@ -23,6 +23,7 @@ export interface WebsiteSessionStatsRequestQuery {
country?: string;
region?: string;
city?: string;
tag?: string;
}
const schema = {
@ -42,6 +43,7 @@ const schema = {
country: yup.string(),
region: yup.string(),
city: yup.string(),
tag: yup.string(),
}),
};

View File

@ -24,6 +24,7 @@ export interface WebsiteStatsRequestQuery {
country?: string;
region?: string;
city?: string;
tag?: string;
compare?: string;
}
@ -44,6 +45,7 @@ const schema = {
country: yup.string(),
region: yup.string(),
city: yup.string(),
tag: yup.string(),
compare: yup.string(),
}),
};