diff --git a/README.md b/README.md
index 7b8bbb33..1d3007b1 100644
--- a/README.md
+++ b/README.md
@@ -27,8 +27,8 @@ As of today (2023-12-12) I have more then 1.2 million events in PSQL and perform
- [ ] Active users (5min, 10min, 30min)
- [x] Save report to a specific dashboard
- [x] View events in a list
- - [ ] Simple filters
-- [*] View profiles in a list
+ - [x] Simple filters
+- [x] View profiles in a list
- [ ] Invite users
- [ ] Drag n Drop reports on dashboard
- [x] Manage dashboards
@@ -42,7 +42,7 @@ As of today (2023-12-12) I have more then 1.2 million events in PSQL and perform
### SDK
-- [*] Store duration on screen view events (can be done in backend as well)
+- [x] Store duration on screen view events (can be done in backend as well)
- [x] Create native sdk
- [x] Handle sessions
- [x] Create web sdk
diff --git a/apps/web/src/components/events/EventsTable.tsx b/apps/web/src/components/events/EventsTable.tsx
index 163bba72..c9b92209 100644
--- a/apps/web/src/components/events/EventsTable.tsx
+++ b/apps/web/src/components/events/EventsTable.tsx
@@ -1,7 +1,5 @@
import { useMemo } from 'react';
import { DataTable } from '@/components/DataTable';
-import { Pagination } from '@/components/Pagination';
-import type { PaginationProps } from '@/components/Pagination';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { Table, TableBody, TableCell, TableRow } from '@/components/ui/table';
import { useOrganizationParams } from '@/hooks/useOrganizationParams';
@@ -17,10 +15,9 @@ const columnHelper =
interface EventsTableProps {
data: RouterOutputs['event']['list'];
- pagination: PaginationProps;
}
-export function EventsTable({ data, pagination }: EventsTableProps) {
+export function EventsTable({ data }: EventsTableProps) {
const params = useOrganizationParams();
const columns = useMemo(() => {
return [
@@ -94,11 +91,5 @@ export function EventsTable({ data, pagination }: EventsTableProps) {
];
}, [params]);
- return (
- <>
-
-
-
- >
- );
+ return ;
}
diff --git a/apps/web/src/components/ui/combobox-advanced.tsx b/apps/web/src/components/ui/combobox-advanced.tsx
index 91d00eac..c9684f78 100644
--- a/apps/web/src/components/ui/combobox-advanced.tsx
+++ b/apps/web/src/components/ui/combobox-advanced.tsx
@@ -5,7 +5,7 @@ import { Command, CommandGroup, CommandItem } from '@/components/ui/command';
import { Checkbox } from './checkbox';
import { Input } from './input';
-type IValue = string | number | boolean | null;
+type IValue = any;
type IItem = Record<'value' | 'label', IValue>;
interface ComboboxAdvancedProps {
@@ -60,7 +60,7 @@ export function ComboboxAdvanced({
);
};
- const renderUnknownItem = (value: string | number | null | boolean) => {
+ const renderUnknownItem = (value: IValue) => {
const item = items.find((item) => item.value === value);
return item ? renderItem(item) : renderItem({ value, label: value });
};
@@ -92,7 +92,7 @@ export function ComboboxAdvanced({
{open && (
-
+
emitter.emit('push', {
name,
+ // @ts-expect-error
props: Array.isArray(rest) && rest[0] ? rest[0] : {},
});
export const replaceModal = <
@@ -194,6 +195,7 @@ export const replaceModal = <
) =>
emitter.emit('replace', {
name,
+ // @ts-expect-error
props: Array.isArray(rest) && rest[0] ? rest[0] : {},
});
export const popModal = (name?: StateItem['name']) =>
diff --git a/apps/web/src/pages/[organization]/[project]/events.tsx b/apps/web/src/pages/[organization]/[project]/events.tsx
index 48e8db3b..f73c3bb2 100644
--- a/apps/web/src/pages/[organization]/[project]/events.tsx
+++ b/apps/web/src/pages/[organization]/[project]/events.tsx
@@ -1,17 +1,20 @@
-import { useMemo } from 'react';
+import { useMemo, useState } from 'react';
import { Container } from '@/components/Container';
import { EventsTable } from '@/components/events/EventsTable';
import { MainLayout } from '@/components/layouts/MainLayout';
import { PageTitle } from '@/components/PageTitle';
-import { usePagination } from '@/components/Pagination';
+import { Pagination, usePagination } from '@/components/Pagination';
+import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
import { useOrganizationParams } from '@/hooks/useOrganizationParams';
import { api } from '@/utils/api';
export default function Events() {
const pagination = usePagination();
const params = useOrganizationParams();
+ const [eventFilters, setEventFilters] = useState
([]);
const eventsQuery = api.event.list.useQuery(
{
+ events: eventFilters,
projectSlug: params.project,
...pagination,
},
@@ -21,11 +24,32 @@ export default function Events() {
);
const events = useMemo(() => eventsQuery.data ?? [], [eventsQuery]);
+ const filterEventsQuery = api.chart.events.useQuery({
+ projectSlug: params.project,
+ });
+ const filterEvents = (filterEventsQuery.data ?? []).map((item) => ({
+ value: item.name,
+ label: item.name,
+ }));
+
return (
Events
-
+
+
+
+
);
diff --git a/apps/web/src/pages/[organization]/[project]/profiles/[profileId].tsx b/apps/web/src/pages/[organization]/[project]/profiles/[profileId].tsx
index 345b83a3..090403f3 100644
--- a/apps/web/src/pages/[organization]/[project]/profiles/[profileId].tsx
+++ b/apps/web/src/pages/[organization]/[project]/profiles/[profileId].tsx
@@ -1,12 +1,12 @@
-import { useMemo } from 'react';
+import { useMemo, useState } from 'react';
import { Container } from '@/components/Container';
import { EventsTable } from '@/components/events/EventsTable';
import { MainLayout } from '@/components/layouts/MainLayout';
import { PageTitle } from '@/components/PageTitle';
-import { usePagination } from '@/components/Pagination';
+import { Pagination, usePagination } from '@/components/Pagination';
+import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
import { useOrganizationParams } from '@/hooks/useOrganizationParams';
import { useQueryParams } from '@/hooks/useQueryParams';
-import { createServerSideProps } from '@/server/getServerSideProps';
import { api } from '@/utils/api';
import { getProfileName } from '@/utils/getters';
import { z } from 'zod';
@@ -19,6 +19,14 @@ export default function ProfileId() {
profileId: z.string(),
})
);
+ const [eventFilters, setEventFilters] = useState([]);
+ const filterEventsQuery = api.chart.events.useQuery({
+ projectSlug: params.project,
+ });
+ const filterEvents = (filterEventsQuery.data ?? []).map((item) => ({
+ value: item.name,
+ label: item.name,
+ }));
const profileQuery = api.profile.get.useQuery({
id: profileId,
});
@@ -26,6 +34,7 @@ export default function ProfileId() {
{
projectSlug: params.project,
profileId,
+ events: eventFilters,
...pagination,
},
{
@@ -40,7 +49,19 @@ export default function ProfileId() {
{getProfileName(profile)}
{JSON.stringify(profile?.properties, null, 2)}
-
+
+
+
);
diff --git a/apps/web/src/server/api/routers/event.ts b/apps/web/src/server/api/routers/event.ts
index ec7618fe..a2f5de49 100644
--- a/apps/web/src/server/api/routers/event.ts
+++ b/apps/web/src/server/api/routers/event.ts
@@ -16,27 +16,37 @@ export const eventRouter = createTRPCRouter({
take: z.number().default(100),
skip: z.number().default(0),
profileId: z.string().optional(),
+ events: z.array(z.string()).optional(),
})
)
- .query(async ({ input: { take, skip, projectSlug, profileId } }) => {
- const project = await db.project.findUniqueOrThrow({
- where: {
- slug: projectSlug,
- },
- });
- return db.event.findMany({
- take,
- skip,
- where: {
- project_id: project.id,
- profile_id: profileId,
- },
- orderBy: {
- createdAt: 'desc',
- },
- include: {
- profile: true,
- },
- });
- }),
+ .query(
+ async ({ input: { take, skip, projectSlug, profileId, events } }) => {
+ const project = await db.project.findUniqueOrThrow({
+ where: {
+ slug: projectSlug,
+ },
+ });
+ return db.event.findMany({
+ take,
+ skip,
+ where: {
+ project_id: project.id,
+ profile_id: profileId,
+ ...(events && events.length > 0
+ ? {
+ name: {
+ in: events,
+ },
+ }
+ : {}),
+ },
+ orderBy: {
+ createdAt: 'desc',
+ },
+ include: {
+ profile: true,
+ },
+ });
+ }
+ ),
});