diff --git a/.husky/pre-commit b/.husky/pre-commit index 2312dc587..36af21989 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + npx lint-staged diff --git a/package.components.json b/package.components.json index 51214f892..d231f5b9b 100644 --- a/package.components.json +++ b/package.components.json @@ -1,6 +1,6 @@ { "name": "@umami/components", - "version": "0.129.0", + "version": "0.128.0", "description": "Umami React components.", "author": "Mike Cao ", "license": "MIT", diff --git a/package.json b/package.json index 78ee92685..d52a7777a 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@react-spring/web": "^10.0.3", "@svgr/cli": "^8.1.0", "@tanstack/react-query": "^5.90.2", - "@umami/react-zen": "^0.196.0", + "@umami/react-zen": "^0.189.0", "@umami/redis-client": "^0.29.0", "bcryptjs": "^3.0.2", "chalk": "^5.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f8e64277..d3ad08bc8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.90.2 version: 5.90.2(react@19.1.1) '@umami/react-zen': - specifier: ^0.196.0 - version: 0.196.0(@babel/core@7.28.3)(@types/react@19.1.16)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.3)(use-sync-external-store@1.6.0(react@19.1.1)) + specifier: ^0.189.0 + version: 0.189.0(@babel/core@7.28.3)(@types/react@19.1.16)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.3)(use-sync-external-store@1.6.0(react@19.1.1)) '@umami/redis-client': specifier: ^0.29.0 version: 0.29.0 @@ -364,6 +364,8 @@ importers: specifier: ^5.9.3 version: 5.9.3 + dist: {} + packages: '@ampproject/remapping@2.3.0': @@ -2754,8 +2756,8 @@ packages: resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@umami/react-zen@0.196.0': - resolution: {integrity: sha512-CLxrDAJOdo+0aJAclOq7naIDg+2I5wP9wXxAFhxhQVPXHV8yUHqH9Ula632cLMo51JYp0l+eEtOtuimpuKX3jg==} + '@umami/react-zen@0.189.0': + resolution: {integrity: sha512-E5t5HvMrGfuilrnF6LJV+jeooC4qXpwUC4VGhnTPV24B1vdMC2W9ByzZreNaomgZy8XOVAk1wZf8QX1elloUjA==} '@umami/redis-client@0.29.0': resolution: {integrity: sha512-Jaqh++jskqDB7ny75pfC02OvKp1JTS4asGDsFrRL3qy8sxL3PAl9+/mybCJe4/6vWrXDJKqpgkSfUDJq2bFjyw==} @@ -6348,8 +6350,8 @@ packages: peerDependencies: react: '>=16.13.1' - react-hook-form@7.65.0: - resolution: {integrity: sha512-xtOzDz063WcXvGWaHgLNrNzlsdFgtUWcb32E6WFaGTd7kPZG3EeDusjdZfUsPwKCKVXy1ZlntifaHZ4l8pAsmw==} + react-hook-form@7.64.0: + resolution: {integrity: sha512-fnN+vvTiMLnRqKNTVhDysdrUay0kUUAymQnFIznmgDvapjveUWOOPqMNzPg+A+0yf9DuE2h6xzBjN1s+Qx8wcg==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 @@ -10385,7 +10387,7 @@ snapshots: '@typescript-eslint/types': 8.45.0 eslint-visitor-keys: 4.2.1 - '@umami/react-zen@0.196.0(@babel/core@7.28.3)(@types/react@19.1.16)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.3)(use-sync-external-store@1.6.0(react@19.1.1))': + '@umami/react-zen@0.189.0(@babel/core@7.28.3)(@types/react@19.1.16)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.3)(use-sync-external-store@1.6.0(react@19.1.1))': dependencies: '@fontsource/jetbrains-mono': 5.2.8 '@internationalized/date': 3.10.0 @@ -10399,7 +10401,7 @@ snapshots: react: 19.1.1 react-aria-components: 1.13.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-dom: 19.1.1(react@19.1.1) - react-hook-form: 7.65.0(react@19.1.1) + react-hook-form: 7.64.0(react@19.1.1) react-icons: 5.5.0(react@19.1.1) thenby: 1.3.4 zustand: 5.0.8(@types/react@19.1.16)(immer@10.1.3)(react@19.1.1)(use-sync-external-store@1.6.0(react@19.1.1)) @@ -14532,7 +14534,7 @@ snapshots: '@babel/runtime': 7.28.3 react: 19.1.1 - react-hook-form@7.65.0(react@19.1.1): + react-hook-form@7.64.0(react@19.1.1): dependencies: react: 19.1.1 diff --git a/src/app/(main)/App.tsx b/src/app/(main)/App.tsx index 32218d115..52c9257a3 100644 --- a/src/app/(main)/App.tsx +++ b/src/app/(main)/App.tsx @@ -4,7 +4,6 @@ import Script from 'next/script'; import { UpdateNotice } from './UpdateNotice'; import { SideNav } from '@/app/(main)/SideNav'; import { useLoginQuery, useConfig, useNavigation } from '@/components/hooks'; -import { MobileNav } from '@/app/(main)/MobileNav'; export function App({ children }) { const { user, isLoading, error } = useLoginQuery(); @@ -29,16 +28,9 @@ export function App({ children }) { } return ( - - - - - + + + diff --git a/src/app/(main)/MobileNav.tsx b/src/app/(main)/MobileNav.tsx deleted file mode 100644 index 32751f0e5..000000000 --- a/src/app/(main)/MobileNav.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { - Row, - Dialog, - DialogTrigger, - Button, - Icon, - Modal, - NavMenu, - NavMenuItem, - IconLabel, - Text, - Grid, -} from '@umami/react-zen'; -import { Globe, Grid2x2, LinkIcon, Menu } from '@/components/icons'; -import { useMessages, useNavigation } from '@/components/hooks'; -import Link from 'next/link'; -import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav'; -import { Logo } from '@/components/svg'; -import { NavButton } from '@/components/input/NavButton'; - -export function MobileNav() { - const { formatMessage, labels } = useMessages(); - const { websiteId } = useNavigation(); - - const links = [ - { - id: 'websites', - label: formatMessage(labels.websites), - path: '/websites', - icon: , - }, - { - id: 'links', - label: formatMessage(labels.links), - path: '/links', - icon: , - }, - { - id: 'pixels', - label: formatMessage(labels.pixels), - path: '/pixels', - icon: , - }, - ]; - - return ( - - - - - - - - {links.map(link => { - return ( - - - - - - ); - })} - - {websiteId && } - - - - - } style={{ width: 'auto' }}> - umami - - - - ); -} diff --git a/src/app/(main)/links/LinksTable.tsx b/src/app/(main)/links/LinksTable.tsx index 5df15b787..b84718299 100644 --- a/src/app/(main)/links/LinksTable.tsx +++ b/src/app/(main)/links/LinksTable.tsx @@ -1,18 +1,23 @@ import Link from 'next/link'; -import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen'; +import { DataTable, DataColumn, Row } from '@umami/react-zen'; import { useMessages, useNavigation, useSlug } from '@/components/hooks'; +import { Empty } from '@/components/common/Empty'; import { DateDistance } from '@/components/common/DateDistance'; import { ExternalLink } from '@/components/common/ExternalLink'; import { LinkEditButton } from './LinkEditButton'; import { LinkDeleteButton } from './LinkDeleteButton'; -export function LinksTable(props: DataTableProps) { +export function LinksTable({ data = [] }) { const { formatMessage, labels } = useMessages(); const { websiteId, renderUrl } = useNavigation(); const { getSlugUrl } = useSlug('link'); + if (data.length === 0) { + return ; + } + return ( - + {({ id, name }: any) => { return {name}; diff --git a/src/app/(main)/pixels/PixelsTable.tsx b/src/app/(main)/pixels/PixelsTable.tsx index 4edbb1cf4..dcb5307c1 100644 --- a/src/app/(main)/pixels/PixelsTable.tsx +++ b/src/app/(main)/pixels/PixelsTable.tsx @@ -1,18 +1,23 @@ import Link from 'next/link'; -import { DataTable, DataColumn, Row, DataTableProps } from '@umami/react-zen'; +import { DataTable, DataColumn, Row } from '@umami/react-zen'; import { useMessages, useNavigation, useSlug } from '@/components/hooks'; +import { Empty } from '@/components/common/Empty'; import { DateDistance } from '@/components/common/DateDistance'; import { PixelEditButton } from './PixelEditButton'; import { PixelDeleteButton } from './PixelDeleteButton'; import { ExternalLink } from '@/components/common/ExternalLink'; -export function PixelsTable(props: DataTableProps) { +export function PixelsTable({ data = [] }) { const { formatMessage, labels } = useMessages(); const { renderUrl } = useNavigation(); const { getSlugUrl } = useSlug('pixel'); + if (data.length === 0) { + return ; + } + return ( - + {({ id, name }: any) => { return {name}; diff --git a/src/app/(main)/teams/TeamsTable.tsx b/src/app/(main)/teams/TeamsTable.tsx index b5f112331..5a22bcda8 100644 --- a/src/app/(main)/teams/TeamsTable.tsx +++ b/src/app/(main)/teams/TeamsTable.tsx @@ -1,17 +1,19 @@ -import { DataColumn, DataTable, DataTableProps } from '@umami/react-zen'; +import { DataColumn, DataTable } from '@umami/react-zen'; import { useMessages } from '@/components/hooks'; import { ROLES } from '@/lib/constants'; import { ReactNode } from 'react'; -export interface TeamsTableProps extends DataTableProps { +export function TeamsTable({ + data = [], + renderLink, +}: { + data: any[]; renderLink?: (row: any) => ReactNode; -} - -export function TeamsTable({ renderLink, ...props }: TeamsTableProps) { +}) { const { formatMessage, labels } = useMessages(); return ( - + {renderLink} diff --git a/src/app/(main)/websites/WebsitesTable.tsx b/src/app/(main)/websites/WebsitesTable.tsx index c2f7e0d46..d6d743906 100644 --- a/src/app/(main)/websites/WebsitesTable.tsx +++ b/src/app/(main)/websites/WebsitesTable.tsx @@ -1,22 +1,30 @@ import { ReactNode } from 'react'; -import { Icon, DataTable, DataColumn, DataTableProps } from '@umami/react-zen'; +import { Icon, DataTable, DataColumn } from '@umami/react-zen'; import { LinkButton } from '@/components/common/LinkButton'; import { useMessages, useNavigation } from '@/components/hooks'; import { SquarePen } from '@/components/icons'; +import { Empty } from '@/components/common/Empty'; -export interface WebsitesTableProps extends DataTableProps { +export function WebsitesTable({ + data = [], + showActions, + renderLink, +}: { + data: Record[]; showActions?: boolean; allowEdit?: boolean; allowView?: boolean; renderLink?: (row: any) => ReactNode; -} - -export function WebsitesTable({ showActions, renderLink, ...props }: WebsitesTableProps) { +}) { const { formatMessage, labels } = useMessages(); const { renderUrl } = useNavigation(); + if (data.length === 0) { + return ; + } + return ( - + {renderLink} diff --git a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx index c92bbd9c8..d357c6a3c 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteLayout.tsx @@ -12,7 +12,6 @@ export function WebsiteLayout({ websiteId, children }: { websiteId: string; chil ; + } + return ( - + {(row: any) => { return ( - - - : } - label={formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)} - /> - - + + + + + {row.eventName ? : } + + {formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)} + + {row.eventName || row.urlPath} ); }} - - {(row: any) => { - return ( - - - - ); - }} - {(row: any) => ( diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx index 53b35b214..4c459bdc1 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsDataTable.tsx @@ -8,7 +8,7 @@ export function SessionsDataTable({ websiteId }: { websiteId?: string; teamId?: return ( {({ data }) => { - return ; + return ; }} ); diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx index ab4977ea2..391c57f43 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx @@ -1,17 +1,17 @@ import Link from 'next/link'; -import { DataColumn, DataTable, DataTableProps } from '@umami/react-zen'; +import { DataColumn, DataTable } from '@umami/react-zen'; import { useFormat, useMessages, useNavigation } from '@/components/hooks'; import { Avatar } from '@/components/common/Avatar'; import { TypeIcon } from '@/components/common/TypeIcon'; import { DateDistance } from '@/components/common/DateDistance'; -export function SessionsTable(props: DataTableProps) { +export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean }) { const { formatMessage, labels } = useMessages(); const { formatValue } = useFormat(); const { updateParams } = useNavigation(); return ( - + {(row: any) => ( diff --git a/src/app/api/admin/teams/route.ts b/src/app/api/admin/teams/route.ts index ceb16ab11..fa203a299 100644 --- a/src/app/api/admin/teams/route.ts +++ b/src/app/api/admin/teams/route.ts @@ -24,26 +24,22 @@ export async function GET(request: Request) { const teams = await getTeams( { include: { + _count: { + select: { + members: true, + websites: true, + }, + }, members: { - include: { + select: { user: { - select: { - id: true, - username: true, + omit: { + password: true, }, }, }, - }, - _count: { - select: { - websites: { - where: { deletedAt: null }, - }, - members: { - where: { - user: { deletedAt: null }, - }, - }, + where: { + role: 'team-owner', }, }, }, diff --git a/src/app/api/reports/route.ts b/src/app/api/reports/route.ts index 123a7e66a..ec8a4d239 100644 --- a/src/app/api/reports/route.ts +++ b/src/app/api/reports/route.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; import { uuid } from '@/lib/crypto'; -import { pagingParams, reportSchema, reportTypeParam } from '@/lib/schema'; +import { pagingParams, reportSchema } from '@/lib/schema'; import { parseRequest } from '@/lib/request'; import { canViewWebsite, canUpdateWebsite } from '@/permissions'; import { unauthorized, json } from '@/lib/response'; @@ -9,7 +9,7 @@ import { getReports, createReport } from '@/queries/prisma'; export async function GET(request: Request) { const schema = z.object({ websiteId: z.uuid(), - type: reportTypeParam.optional(), + type: z.string().optional(), ...pagingParams, }); diff --git a/src/app/api/users/[userId]/route.ts b/src/app/api/users/[userId]/route.ts index c15b4b71b..fbb794746 100644 --- a/src/app/api/users/[userId]/route.ts +++ b/src/app/api/users/[userId]/route.ts @@ -26,9 +26,9 @@ export async function GET(request: Request, { params }: { params: Promise<{ user export async function POST(request: Request, { params }: { params: Promise<{ userId: string }> }) { const schema = z.object({ - username: z.string().max(255).optional(), + username: z.string().max(255), password: z.string().max(255).optional(), - role: userRoleParam.optional(), + role: userRoleParam, }); const { auth, body, error } = await parseRequest(request, schema); diff --git a/src/app/api/websites/[websiteId]/event-data/properties/route.ts b/src/app/api/websites/[websiteId]/event-data/properties/route.ts index c3b884ae7..0028d7477 100644 --- a/src/app/api/websites/[websiteId]/event-data/properties/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/properties/route.ts @@ -3,16 +3,15 @@ import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/permissions'; import { getEventDataProperties } from '@/queries/sql'; -import { dateRangeParams, filterParams } from '@/lib/schema'; export async function GET( request: Request, { params }: { params: Promise<{ websiteId: string }> }, ) { const schema = z.object({ + startAt: z.coerce.number().int(), + endAt: z.coerce.number().int(), propertyName: z.string().optional(), - ...dateRangeParams, - ...filterParams, }); const { auth, query, error } = await parseRequest(request, schema); diff --git a/src/app/api/websites/[websiteId]/event-data/values/route.ts b/src/app/api/websites/[websiteId]/event-data/values/route.ts index 5cf406658..4966764b6 100644 --- a/src/app/api/websites/[websiteId]/event-data/values/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/values/route.ts @@ -3,17 +3,16 @@ import { getQueryFilters, parseRequest } from '@/lib/request'; import { unauthorized, json } from '@/lib/response'; import { canViewWebsite } from '@/permissions'; import { getEventDataValues } from '@/queries/sql'; -import { dateRangeParams, filterParams } from '@/lib/schema'; export async function GET( request: Request, { params }: { params: Promise<{ websiteId: string }> }, ) { const schema = z.object({ + startAt: z.coerce.number().int(), + endAt: z.coerce.number().int(), eventName: z.string().optional(), propertyName: z.string().optional(), - ...dateRangeParams, - ...filterParams, }); const { auth, query, error } = await parseRequest(request, schema); diff --git a/src/components/common/DataGrid.tsx b/src/components/common/DataGrid.tsx index 18cb763c4..d95ee5155 100644 --- a/src/components/common/DataGrid.tsx +++ b/src/components/common/DataGrid.tsx @@ -1,12 +1,5 @@ -import { - ReactNode, - useState, - useCallback, - ReactElement, - cloneElement, - isValidElement, -} from 'react'; -import { SearchField, Row, Column, useBreakpoint } from '@umami/react-zen'; +import { ReactNode, useState, useCallback } from 'react'; +import { SearchField, Row, Column } from '@umami/react-zen'; import { UseQueryResult } from '@tanstack/react-query'; import { useMessages, useNavigation } from '@/components/hooks'; import { Pager } from '@/components/common/Pager'; @@ -42,8 +35,6 @@ export function DataGrid({ const { router, updateParams, query: queryParams } = useNavigation(); const [search, setSearch] = useState(queryParams?.search || data?.search || ''); const showPager = allowPaging && data && data.count > data.pageSize; - const breakpoint = useBreakpoint(); - const displayMode = ['xs', 'sm', 'md', 'lg'].includes(breakpoint) ? 'cards' : undefined; const handleSearch = (value: string) => { if (value !== search) { @@ -59,8 +50,6 @@ export function DataGrid({ [search], ); - const child = data ? (typeof children === 'function' ? children(data) : children) : null; - return ( {allowSearch && ( @@ -84,11 +73,7 @@ export function DataGrid({ > {data && ( <> - - {isValidElement(child) - ? cloneElement(child as ReactElement, { displayMode }) - : child} - + {typeof children === 'function' ? children(data) : children} {showPager && ( {children} diff --git a/src/components/common/PageHeader.tsx b/src/components/common/PageHeader.tsx index 8905d0cda..27d33a72b 100644 --- a/src/components/common/PageHeader.tsx +++ b/src/components/common/PageHeader.tsx @@ -37,7 +37,7 @@ export function PageHeader({ {icon} )} - {title && {title}} + {title && {title}} {description && ( diff --git a/src/components/common/SideMenu.tsx b/src/components/common/SideMenu.tsx index c8a7c9983..2848e3046 100644 --- a/src/components/common/SideMenu.tsx +++ b/src/components/common/SideMenu.tsx @@ -57,6 +57,7 @@ export function SideMenu({ - get(`/websites/${websiteId}/event-data/events`, { - startAt, - endAt, - unit, - timezone, - ...filters, - }), + queryKey: ['websites:event-data:events', { websiteId, ...date, ...filters }], + queryFn: () => get(`/websites/${websiteId}/event-data/events`, { ...date, ...filters }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useEventDataPropertiesQuery.ts b/src/components/hooks/queries/useEventDataPropertiesQuery.ts index 74dd58ef2..19a2eb61d 100644 --- a/src/components/hooks/queries/useEventDataPropertiesQuery.ts +++ b/src/components/hooks/queries/useEventDataPropertiesQuery.ts @@ -5,22 +5,12 @@ import { ReactQueryOptions } from '@/lib/types'; export function useEventDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions) { const { get, useQuery } = useApi(); - const { startAt, endAt, unit, timezone } = useDateParameters(); + const date = useDateParameters(); const filters = useFilterParameters(); return useQuery({ - queryKey: [ - 'websites:event-data:properties', - { websiteId, startAt, endAt, unit, timezone, ...filters }, - ], - queryFn: () => - get(`/websites/${websiteId}/event-data/properties`, { - startAt, - endAt, - unit, - timezone, - ...filters, - }), + queryKey: ['websites:event-data:properties', { websiteId, ...date, ...filters }], + queryFn: () => get(`/websites/${websiteId}/event-data/properties`, { ...date, ...filters }), enabled: !!websiteId, ...options, }); diff --git a/src/components/hooks/queries/useEventDataQuery.ts b/src/components/hooks/queries/useEventDataQuery.ts index 5e21081ac..7e6f66ec2 100644 --- a/src/components/hooks/queries/useEventDataQuery.ts +++ b/src/components/hooks/queries/useEventDataQuery.ts @@ -5,22 +5,12 @@ import { ReactQueryOptions } from '@/lib/types'; export function useEventDataQuery(websiteId: string, eventId: string, options?: ReactQueryOptions) { const { get, useQuery } = useApi(); - const { startAt, endAt, unit, timezone } = useDateParameters(); + const date = useDateParameters(); const params = useFilterParameters(); return useQuery({ - queryKey: [ - 'websites:event-data', - { websiteId, eventId, startAt, endAt, unit, timezone, ...params }, - ], - queryFn: () => - get(`/websites/${websiteId}/event-data/${eventId}`, { - startAt, - endAt, - unit, - timezone, - ...params, - }), + queryKey: ['websites:event-data', { websiteId, eventId, ...date, ...params }], + queryFn: () => get(`/websites/${websiteId}/event-data/${eventId}`, { ...date, ...params }), enabled: !!(websiteId && eventId), ...options, }); diff --git a/src/components/hooks/queries/useEventDataValuesQuery.ts b/src/components/hooks/queries/useEventDataValuesQuery.ts index 6394a1bb4..de3b0590b 100644 --- a/src/components/hooks/queries/useEventDataValuesQuery.ts +++ b/src/components/hooks/queries/useEventDataValuesQuery.ts @@ -1,7 +1,7 @@ -import { ReactQueryOptions } from '@/lib/types'; import { useApi } from '../useApi'; -import { useDateParameters } from '../useDateParameters'; import { useFilterParameters } from '../useFilterParameters'; +import { useDateParameters } from '../useDateParameters'; +import { ReactQueryOptions } from '@/lib/types'; export function useEventDataValuesQuery( websiteId: string, @@ -10,20 +10,17 @@ export function useEventDataValuesQuery( options?: ReactQueryOptions, ) { const { get, useQuery } = useApi(); - const { startAt, endAt, unit, timezone } = useDateParameters(); + const date = useDateParameters(); const filters = useFilterParameters(); return useQuery({ queryKey: [ 'websites:event-data:values', - { websiteId, eventName, propertyName, startAt, endAt, unit, timezone, ...filters }, + { websiteId, eventName, propertyName, ...date, ...filters }, ], queryFn: () => get(`/websites/${websiteId}/event-data/values`, { - startAt, - endAt, - unit, - timezone, + ...date, ...filters, eventName, propertyName, diff --git a/src/components/input/NavButton.tsx b/src/components/input/NavButton.tsx index 8be136968..257cd685a 100644 --- a/src/components/input/NavButton.tsx +++ b/src/components/input/NavButton.tsx @@ -61,7 +61,6 @@ export function NavButton({ showText = true }: TeamsButtonProps) { borderRadius shadow="1" maxHeight="40px" - role="button" style={{ cursor: 'pointer', textWrap: 'nowrap', outline: 'none' }} > diff --git a/src/components/input/WebsiteSelect.tsx b/src/components/input/WebsiteSelect.tsx index 29ae040b0..01861fbd4 100644 --- a/src/components/input/WebsiteSelect.tsx +++ b/src/components/input/WebsiteSelect.tsx @@ -1,11 +1,6 @@ import { useState } from 'react'; import { Select, SelectProps, ListItem, Text, Row } from '@umami/react-zen'; -import { - useUserWebsitesQuery, - useMessages, - useLoginQuery, - useWebsiteQuery, -} from '@/components/hooks'; +import { useUserWebsitesQuery, useMessages, useLoginQuery, useWebsite } from '@/components/hooks'; import { Empty } from '@/components/common/Empty'; export function WebsiteSelect({ @@ -20,7 +15,7 @@ export function WebsiteSelect({ includeTeams?: boolean; } & SelectProps) { const { formatMessage, messages } = useMessages(); - const { data: website } = useWebsiteQuery(websiteId); + const website = useWebsite(); const [name, setName] = useState(website?.name); const [search, setSearch] = useState(''); const { user } = useLoginQuery(); diff --git a/src/queries/sql/events/getEventDataProperties.ts b/src/queries/sql/events/getEventDataProperties.ts index 7a618fd2e..60b46bcce 100644 --- a/src/queries/sql/events/getEventDataProperties.ts +++ b/src/queries/sql/events/getEventDataProperties.ts @@ -68,15 +68,10 @@ async function clickhouseQuery( event_name as eventName, data_key as propertyName, count(*) as total - from event_data - join website_event - on website_event.event_id = event_data.event_id - and website_event.website_id = event_data.website_id - and website_event.website_id = {websiteId:UUID} - and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} + from event_data website_event ${cohortQuery} - where event_data.website_id = {websiteId:UUID} - and event_data.created_at between {startDate:DateTime64} and {endDate:DateTime64} + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} ${filterQuery} group by event_name, data_key order by 1, 3 desc diff --git a/src/queries/sql/events/getEventDataValues.ts b/src/queries/sql/events/getEventDataValues.ts index 0af938304..bdfe7482e 100644 --- a/src/queries/sql/events/getEventDataValues.ts +++ b/src/queries/sql/events/getEventDataValues.ts @@ -75,17 +75,12 @@ async function clickhouseQuery( data_type = 4, toString(date_trunc('hour', date_value)), string_value) as "value", count(*) as "total" - from event_data - join website_event - on website_event.event_id = event_data.event_id - and website_event.website_id = event_data.website_id - and website_event.website_id = {websiteId:UUID} - and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64} + from event_data website_event ${cohortQuery} - where event_data.website_id = {websiteId:UUID} - and event_data.created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_data.data_key = {propertyName:String} - and event_data.event_name = {eventName:String} + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and data_key = {propertyName:String} + and event_name = {eventName:String} ${filterQuery} group by value order by 2 desc