Support event type filtering.

This commit is contained in:
Mike Cao 2025-07-24 16:09:49 -07:00
parent 45c9ea9c22
commit 2e69e57445
7 changed files with 39 additions and 29 deletions

View file

@ -14,7 +14,7 @@ export function EventsDataTable({
}) { }) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const [view, setView] = useState('all'); const [view, setView] = useState('all');
const query = useWebsiteEventsQuery(websiteId); const query = useWebsiteEventsQuery(websiteId, { view });
const buttons = [ const buttons = [
{ {

View file

@ -16,6 +16,7 @@ export interface DataGridProps {
allowPaging?: boolean; allowPaging?: boolean;
autoFocus?: boolean; autoFocus?: boolean;
renderActions?: () => ReactNode; renderActions?: () => ReactNode;
renderEmpty?: () => ReactNode;
children: ReactNode | ((data: any) => ReactNode); children: ReactNode | ((data: any) => ReactNode);
} }
@ -26,12 +27,13 @@ export function DataGrid({
allowPaging = true, allowPaging = true,
autoFocus, autoFocus,
renderActions, renderActions,
renderEmpty = () => <Empty />,
children, children,
}: DataGridProps) { }: DataGridProps) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const { data, error, isLoading, isFetching } = query; const { data, error, isLoading, isFetching } = query;
const { router, updateParams, query: queryParams } = useNavigation(); const { router, updateParams, query: queryParams } = useNavigation();
const [search, setSearch] = useState(queryParams?.saerch || data?.search || ''); const [search, setSearch] = useState(queryParams?.search || data?.search || '');
const handleSearch = (value: string) => { const handleSearch = (value: string) => {
if (value !== search) { if (value !== search) {
@ -47,13 +49,9 @@ export function DataGrid({
[search], [search],
); );
if (data?.data?.length === 0) {
return <Empty />;
}
return ( return (
<Column gap="4" minHeight="300px"> <Column gap="4" minHeight="300px">
{allowSearch && (data || search) && ( {allowSearch && (
<Row alignItems="center" justifyContent="space-between"> <Row alignItems="center" justifyContent="space-between">
<SearchField <SearchField
value={search} value={search}
@ -66,7 +64,13 @@ export function DataGrid({
{renderActions?.()} {renderActions?.()}
</Row> </Row>
)} )}
<LoadingPanel data={data} isLoading={isLoading} isFetching={isFetching} error={error}> <LoadingPanel
data={data}
isLoading={isLoading}
isFetching={isFetching}
error={error}
renderEmpty={renderEmpty}
>
{data && ( {data && (
<> <>
<Column>{typeof children === 'function' ? children(data) : children}</Column> <Column>{typeof children === 'function' ? children(data) : children}</Column>

View file

@ -4,6 +4,11 @@ import { useDateParameters } from '../useDateParameters';
import { usePagedQuery } from '../usePagedQuery'; import { usePagedQuery } from '../usePagedQuery';
import { ReactQueryOptions } from '@/lib/types'; import { ReactQueryOptions } from '@/lib/types';
const EVENT_TYPES = {
views: 1,
events: 2,
};
export function useWebsiteEventsQuery( export function useWebsiteEventsQuery(
websiteId: string, websiteId: string,
params?: Record<string, any>, params?: Record<string, any>,
@ -20,7 +25,7 @@ export function useWebsiteEventsQuery(
...date, ...date,
...filters, ...filters,
...pageParams, ...pageParams,
...params, eventType: EVENT_TYPES[params.view],
}), }),
enabled: !!websiteId, enabled: !!websiteId,
...options, ...options,

View file

@ -37,18 +37,18 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) {
return ( return (
<MenuTrigger> <MenuTrigger>
<Pressable> <Pressable>
<SidebarItem <Row alignItems="center" justifyContent="space-between" width="100%" gap>
label={teamId ? team?.name : user.username} <SidebarItem
icon={teamId ? <Users /> : <User />} label={teamId ? team?.name : user.username}
> icon={teamId ? <Users /> : <User />}
<Row alignItems="center" justifyContent="space-between" width="100%" gap> >
{showText && ( {showText && (
<Icon rotate={90} size="sm"> <Icon rotate={90} size="sm">
<Chevron /> <Chevron />
</Icon> </Icon>
)} )}
</Row> </SidebarItem>
</SidebarItem> </Row>
</Pressable> </Pressable>
<Popover placement="bottom start"> <Popover placement="bottom start">
<Box minWidth="300px"> <Box minWidth="300px">
@ -60,20 +60,24 @@ export function TeamsButton({ showText = true }: { showText?: boolean }) {
> >
<MenuSection title={formatMessage(labels.myAccount)}> <MenuSection title={formatMessage(labels.myAccount)}>
<MenuItem id={user.id}> <MenuItem id={user.id}>
<Icon> <Row alignItems="center" gap>
<User /> <Icon>
</Icon> <User />
<Text wrap="nowrap">{user.username}</Text> </Icon>
<Text wrap="nowrap">{user.username}</Text>
</Row>
</MenuItem> </MenuItem>
</MenuSection> </MenuSection>
<MenuSeparator /> <MenuSeparator />
<MenuSection title={formatMessage(labels.teams)}> <MenuSection title={formatMessage(labels.teams)}>
{data?.data?.map(({ id, name }) => ( {data?.data?.map(({ id, name }) => (
<MenuItem key={id} id={id}> <MenuItem key={id} id={id}>
<Icon size="sm"> <Row alignItems="center" gap>
<Users /> <Icon size="sm">
</Icon> <Users />
<Text wrap="nowrap">{name}</Text> </Icon>
<Text wrap="nowrap">{name}</Text>
</Row>
</MenuItem> </MenuItem>
))} ))}
</MenuSection> </MenuSection>

View file

@ -8,10 +8,6 @@ export interface EventsTableProps extends MetricsTableProps {
export function EventsTable({ onLabelClick, ...props }: EventsTableProps) { export function EventsTable({ onLabelClick, ...props }: EventsTableProps) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const handleDataLoad = (data: any) => {
props.onDataLoad?.(data);
};
const renderLabel = ({ x: label }) => { const renderLabel = ({ x: label }) => {
if (onLabelClick) { if (onLabelClick) {
return ( return (
@ -30,7 +26,6 @@ export function EventsTable({ onLabelClick, ...props }: EventsTableProps) {
title={formatMessage(labels.events)} title={formatMessage(labels.events)}
type="event" type="event"
metric={formatMessage(labels.actions)} metric={formatMessage(labels.actions)}
onDataLoad={handleDataLoad}
renderLabel={renderLabel} renderLabel={renderLabel}
allowDownload={false} allowDownload={false}
/> />

View file

@ -71,6 +71,7 @@ export const FILTER_COLUMNS = {
language: 'language', language: 'language',
event: 'event_name', event: 'event_name',
tag: 'tag', tag: 'tag',
eventType: 'event_type',
}; };
export const COLLECTION_TYPE = { export const COLLECTION_TYPE = {

View file

@ -37,6 +37,7 @@ export const filterParams = {
event: z.string().optional(), event: z.string().optional(),
segment: z.string().optional(), segment: z.string().optional(),
cohort: z.string().optional(), cohort: z.string().optional(),
eventType: z.coerce.number().int().positive().optional(),
}; };
export const searchParams = { export const searchParams = {