mirror of
https://github.com/umami-software/umami.git
synced 2026-02-14 09:35:36 +01:00
Support event type filtering.
This commit is contained in:
parent
45c9ea9c22
commit
2e69e57445
7 changed files with 39 additions and 29 deletions
|
|
@ -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 = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue