From 09a75ec720d9f935b867e4901582a5555f7b38ea Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 9 Apr 2024 22:20:11 -0700 Subject: [PATCH 1/6] Fixed region view. Closes #2648. --- src/pages/api/websites/[websiteId]/metrics.ts | 2 +- .../analytics/sessions/getSessionMetrics.ts | 18 +++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/pages/api/websites/[websiteId]/metrics.ts b/src/pages/api/websites/[websiteId]/metrics.ts index 02e3a0095a..f9893e7900 100644 --- a/src/pages/api/websites/[websiteId]/metrics.ts +++ b/src/pages/api/websites/[websiteId]/metrics.ts @@ -87,7 +87,7 @@ export default async ( } if (SESSION_COLUMNS.includes(type)) { - const data = await getSessionMetrics(websiteId, column, filters, limit, offset); + const data = await getSessionMetrics(websiteId, type, filters, limit, offset); if (type === 'language') { const combined = {}; diff --git a/src/queries/analytics/sessions/getSessionMetrics.ts b/src/queries/analytics/sessions/getSessionMetrics.ts index 77ccb4105f..e28f1fb2e7 100644 --- a/src/queries/analytics/sessions/getSessionMetrics.ts +++ b/src/queries/analytics/sessions/getSessionMetrics.ts @@ -1,17 +1,11 @@ import prisma from 'lib/prisma'; import clickhouse from 'lib/clickhouse'; import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db'; -import { EVENT_TYPE, SESSION_COLUMNS } from 'lib/constants'; +import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from 'lib/constants'; import { QueryFilters } from 'lib/types'; export async function getSessionMetrics( - ...args: [ - websiteId: string, - column: string, - filters: QueryFilters, - limit?: number, - offset?: number, - ] + ...args: [websiteId: string, type: string, filters: QueryFilters, limit?: number, offset?: number] ) { return runQuery({ [PRISMA]: () => relationalQuery(...args), @@ -21,11 +15,12 @@ export async function getSessionMetrics( async function relationalQuery( websiteId: string, - column: string, + type: string, filters: QueryFilters, limit: number = 500, offset: number = 0, ) { + const column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = prisma; const { filterQuery, joinSession, params } = await parseFilters( websiteId, @@ -34,7 +29,7 @@ async function relationalQuery( eventType: EVENT_TYPE.pageView, }, { - joinSession: SESSION_COLUMNS.includes(column), + joinSession: SESSION_COLUMNS.includes(type), }, ); const includeCountry = column === 'city' || column === 'subdivision1'; @@ -63,11 +58,12 @@ async function relationalQuery( async function clickhouseQuery( websiteId: string, - column: string, + type: string, filters: QueryFilters, limit: number = 500, offset: number = 0, ): Promise<{ x: string; y: number }[]> { + const column = FILTER_COLUMNS[type] || type; const { parseFilters, rawQuery } = clickhouse; const { filterQuery, params } = await parseFilters(websiteId, { ...filters, From 6973b2b760d1fa40c4af4ba383d9b5955b921973 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 10 Apr 2024 12:26:09 -0700 Subject: [PATCH 2/6] Pass start and end dates to filter component. Closes #2646. --- src/app/(main)/reports/[reportId]/FilterParameters.tsx | 2 ++ src/app/(main)/reports/[reportId]/FilterSelectForm.tsx | 6 ++++-- src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx | 5 ++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/app/(main)/reports/[reportId]/FilterParameters.tsx b/src/app/(main)/reports/[reportId]/FilterParameters.tsx index 3118a6f4b8..ddbe4d1e81 100644 --- a/src/app/(main)/reports/[reportId]/FilterParameters.tsx +++ b/src/app/(main)/reports/[reportId]/FilterParameters.tsx @@ -55,6 +55,8 @@ export function FilterParameters() { !filters.find(f => f.name === name))} + startDate={dateRange?.startDate} + endDate={dateRange?.endDate} onChange={handleAdd} /> diff --git a/src/app/(main)/reports/[reportId]/FilterSelectForm.tsx b/src/app/(main)/reports/[reportId]/FilterSelectForm.tsx index b81c857672..77a36c3cc4 100644 --- a/src/app/(main)/reports/[reportId]/FilterSelectForm.tsx +++ b/src/app/(main)/reports/[reportId]/FilterSelectForm.tsx @@ -1,11 +1,12 @@ import { useState } from 'react'; import FieldSelectForm from './FieldSelectForm'; import FieldFilterEditForm from './FieldFilterEditForm'; -import { useDateRange } from 'components/hooks'; export interface FilterSelectFormProps { websiteId?: string; fields: any[]; + startDate?: Date; + endDate?: Date; onChange?: (filter: { name: string; type: string; operator: string; value: string }) => void; allowFilterSelect?: boolean; } @@ -13,11 +14,12 @@ export interface FilterSelectFormProps { export default function FilterSelectForm({ websiteId, fields, + startDate, + endDate, onChange, allowFilterSelect, }: FilterSelectFormProps) { const [field, setField] = useState<{ name: string; label: string; type: string }>(); - const [{ startDate, endDate }] = useDateRange(websiteId); if (!field) { return ; diff --git a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx index dda7cb063a..a96717571b 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteFilterButton.tsx @@ -2,7 +2,7 @@ import classNames from 'classnames'; import { Button, Icon, Icons, Popup, PopupTrigger, Text } from 'react-basics'; import PopupForm from 'app/(main)/reports/[reportId]/PopupForm'; import FilterSelectForm from 'app/(main)/reports/[reportId]/FilterSelectForm'; -import { useFields, useMessages, useNavigation } from 'components/hooks'; +import { useFields, useMessages, useNavigation, useDateRange } from 'components/hooks'; import { OPERATOR_PREFIXES } from 'lib/constants'; import styles from './WebsiteFilterButton.module.css'; @@ -16,6 +16,7 @@ export function WebsiteFilterButton({ const { formatMessage, labels } = useMessages(); const { renderUrl, router } = useNavigation(); const { fields } = useFields(); + const [{ startDate, endDate }] = useDateRange(websiteId); const handleAddFilter = ({ name, operator, value }) => { const prefix = OPERATOR_PREFIXES[operator]; @@ -38,6 +39,8 @@ export function WebsiteFilterButton({ { handleAddFilter(value); close(); From 7899289b3c70d2c7cb46870704c85165f40856e9 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Fri, 5 Apr 2024 12:21:54 -0700 Subject: [PATCH 3/6] fix case sensitivity for psql getValues --- src/lib/prisma.ts | 8 ++++++++ src/queries/analytics/getValues.ts | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index c35e0cde3f..c5e16ddca7 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -93,6 +93,13 @@ function getTimestampDiffQuery(field1: string, field2: string): string { } } +function getSearchQuery(column: string): string { + const db = getDatabaseType(); + const like = db === POSTGRESQL ? 'ilike' : 'like'; + + return `and ${column} ${like} {{search}}`; +} + function mapFilter(column: string, operator: string, name: string, type: string = '') { const db = getDatabaseType(); const like = db === POSTGRESQL ? 'ilike' : 'like'; @@ -253,6 +260,7 @@ export default { getFilterQuery, getSearchParameters, getTimestampDiffQuery, + getSearchQuery, getQueryMode, pagedQuery, parseFilters, diff --git a/src/queries/analytics/getValues.ts b/src/queries/analytics/getValues.ts index 572fbac250..7cd349940f 100644 --- a/src/queries/analytics/getValues.ts +++ b/src/queries/analytics/getValues.ts @@ -18,11 +18,11 @@ async function relationalQuery( endDate: Date, search: string, ) { - const { rawQuery } = prisma; + const { rawQuery, getSearchQuery } = prisma; let searchQuery = ''; if (search) { - searchQuery = `and ${column} LIKE {{search}}`; + searchQuery = getSearchQuery(column); } return rawQuery( From 357c13fb1569865c3a8d387717d766415b253233 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 10 Apr 2024 16:05:59 -0700 Subject: [PATCH 4/6] Bump version v2.11.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bd27a4cfe5..887ed43dc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "2.11.0", + "version": "2.11.1", "description": "A simple, fast, privacy-focused alternative to Google Analytics.", "author": "Umami Software, Inc. ", "license": "MIT", From bd360207a65391332ce8c20dbe71c363716bccb9 Mon Sep 17 00:00:00 2001 From: Cedric Date: Mon, 15 Apr 2024 23:25:15 +0200 Subject: [PATCH 5/6] fix(tracker): Remove domain name when parsing url --- src/tracker/index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tracker/index.js b/src/tracker/index.js index 43a5150131..438c08d2a5 100644 --- a/src/tracker/index.js +++ b/src/tracker/index.js @@ -52,6 +52,12 @@ }; const parseURL = url => { + try { + const { pathname, search } = new URL(url); + url = pathname + search; + } catch { + /* empty */ + } return excludeSearch ? url.split('?')[0] : url; }; From 0225e63abcf1160cf6bad0f7c8d06747a1bc69a6 Mon Sep 17 00:00:00 2001 From: Cedric Date: Mon, 15 Apr 2024 23:34:52 +0200 Subject: [PATCH 6/6] fix(tracker): Respect excludeSearch consistently --- src/tracker/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tracker/index.js b/src/tracker/index.js index 438c08d2a5..cc6b8dbbfe 100644 --- a/src/tracker/index.js +++ b/src/tracker/index.js @@ -7,7 +7,7 @@ document, history, } = window; - const { hostname, pathname, search } = location; + const { hostname, href } = location; const { currentScript, referrer } = document; if (!currentScript) return; @@ -244,7 +244,7 @@ }; } - let currentUrl = `${pathname}${search}`; + let currentUrl = parseURL(href); let currentRef = referrer !== hostname ? referrer : ''; let title = document.title; let cache;