wip event list

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-02-15 21:29:45 +01:00
parent 1328825e7c
commit a74acda707
29 changed files with 995 additions and 883 deletions

View File

@@ -173,7 +173,6 @@ export function EventListItem({
{profile && (
<KeyValueSubtle
name="Profile"
// icon={<ProfileAvatar size="xs" {...(profile ?? {})} />}
value={getProfileName(profile)}
href={`/${params.organizationId}/${params.projectId}/profiles/${profile.id}`}
/>
@@ -191,28 +190,36 @@ export function EventListItem({
}
image={<EventIcon name={name} />}
>
{propertiesList.length > 0 && (
<div className="p-4 flex flex-col gap-4">
<div className="font-medium">Your properties</div>
<div className="flex flex-wrap gap-x-4 gap-y-2">
{propertiesList.map((item) => (
<KeyValue key={item.name} name={item.name} value={item.value} />
))}
<div className="p-2">
<div className="bg-gradient-to-tr from-slate-100 to-white rounded-md">
{propertiesList.length > 0 && (
<div className="p-4 flex flex-col gap-4">
<div className="font-medium">Your properties</div>
<div className="flex flex-wrap gap-x-4 gap-y-2">
{propertiesList.map((item) => (
<KeyValue
key={item.name}
name={item.name}
value={item.value}
/>
))}
</div>
</div>
)}
<div className="p-4 flex flex-col gap-4">
<div className="font-medium">Properties</div>
<div className="flex flex-wrap gap-x-4 gap-y-2">
{keyValueList.map((item) => (
<KeyValue
onClick={() => item.onClick?.()}
key={item.name}
name={item.name}
value={item.value}
/>
))}
</div>
</div>
</div>
)}
<div className="p-4 flex flex-col gap-4">
<div className="font-medium">Properties</div>
<div className="flex flex-wrap gap-x-4 gap-y-2">
{keyValueList.map((item) => (
<KeyValue
onClick={item.onClick}
key={item.name}
name={item.name}
value={item.value}
/>
))}
</div>
</div>
</ExpandableListItem>
);

View File

@@ -0,0 +1,53 @@
'use client';
import { FullPageEmptyState } from '@/components/FullPageEmptyState';
import { Pagination } from '@/components/Pagination';
import { Button } from '@/components/ui/button';
import { useCursor } from '@/hooks/useCursor';
import { GanttChartIcon } from 'lucide-react';
import { last } from 'ramda';
import { IServiceCreateEventPayload } from '@mixan/db';
import { EventListItem } from './event-list-item';
interface EventListProps {
data: IServiceCreateEventPayload[];
}
export function EventList({ data }: EventListProps) {
const { cursor, setCursor } = useCursor();
return (
<>
<div className="p-4">
{data.length === 0 ? (
<FullPageEmptyState title="No events here" icon={GanttChartIcon}>
{/* {filterEvents.length ? (
<p>Could not find any events with your filter</p>
) : (
<p>We have not recieved any events yet</p>
)} */}
<p>We have not recieved any events yet</p>
</FullPageEmptyState>
) : (
<>
<div className="flex flex-col gap-4">
{data.map((item) => (
<EventListItem
key={item.createdAt.toString() + item.name + item.profileId}
{...item}
/>
))}
</div>
<Button
variant="outline"
size="sm"
onClick={() => setCursor(last(data)?.createdAt ?? null)}
>
Next
</Button>
</>
)}
</div>
</>
);
}

View File

@@ -1,75 +0,0 @@
'use client';
import { useMemo, useState } from 'react';
import { api } from '@/app/_trpc/client';
import { StickyBelowHeader } from '@/app/(app)/[organizationId]/[projectId]/layout-sticky-below-header';
import { FullPageEmptyState } from '@/components/FullPageEmptyState';
import { Pagination, usePagination } from '@/components/Pagination';
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
import { GanttChartIcon } from 'lucide-react';
import { parseAsArrayOf, parseAsString, useQueryState } from 'nuqs';
import { EventListItem } from './event-list-item';
interface ListEventsProps {
projectId: string;
}
export function ListEvents({ projectId }: ListEventsProps) {
const pagination = usePagination();
const [eventFilters, setEventFilters] = useQueryState(
'events',
parseAsArrayOf(parseAsString).withDefault([])
);
const eventsQuery = api.event.list.useQuery({
events: eventFilters,
projectId: projectId,
...pagination,
});
const events = useMemo(() => eventsQuery.data ?? [], [eventsQuery]);
const filterEventsQuery = api.chart.events.useQuery({
projectId: projectId,
});
const filterEvents = (filterEventsQuery.data ?? []).map((item) => ({
value: item.name,
label: item.name,
}));
return (
<>
<StickyBelowHeader className="p-4 flex justify-between">
<div>
<ComboboxAdvanced
items={filterEvents}
value={eventFilters}
onChange={setEventFilters}
placeholder="Filter by event"
/>
</div>
</StickyBelowHeader>
<div className="p-4">
{events.length === 0 ? (
<FullPageEmptyState title="No events here" icon={GanttChartIcon}>
{eventFilters.length ? (
<p>Could not find any events with your filter</p>
) : (
<p>We have not recieved any events yet</p>
)}
</FullPageEmptyState>
) : (
<>
<div className="flex flex-col gap-4">
{events.map((item) => (
<EventListItem key={item.createdAt.toString()} {...item} />
))}
</div>
<div className="mt-2">
<Pagination {...pagination} />
</div>
</>
)}
</div>
</>
);
}

View File

@@ -1,22 +1,39 @@
import { Suspense } from 'react';
import PageLayout from '@/app/(app)/[organizationId]/[projectId]/page-layout';
import { OverviewFiltersDrawer } from '@/components/overview/filters/overview-filters-drawer';
import { getExists } from '@/server/pageExists';
import { ListEvents } from './list-events';
import { getEventList, getEvents } from '@mixan/db';
import { StickyBelowHeader } from '../layout-sticky-below-header';
import { EventList } from './event-list';
interface PageProps {
params: {
projectId: string;
organizationId: string;
};
searchParams: {
cursor?: string;
};
}
export default async function Page({
params: { projectId, organizationId },
searchParams: { cursor },
}: PageProps) {
await getExists(organizationId, projectId);
const events = await getEventList({
cursor,
projectId,
take: 50,
});
return (
<PageLayout title="Events" organizationSlug={organizationId}>
<ListEvents projectId={projectId} />
<StickyBelowHeader className="p-4 flex justify-between">
<OverviewFiltersDrawer projectId={projectId} />
</StickyBelowHeader>
<EventList data={events} />
</PageLayout>
);
}

View File

@@ -1,12 +1,10 @@
'use client';
import { Suspense } from 'react';
import { WidgetHead } from '@/components/overview/overview-widget';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { Chart } from '@/components/report/chart';
import { ChartLoading } from '@/components/report/chart/ChartLoading';
import { MetricCardLoading } from '@/components/report/chart/MetricCard';
import { Widget, WidgetBody } from '@/components/Widget';
import { useEventFilters } from '@/hooks/useEventQueryFilters';
import type { IChartInput } from '@/types';
import { cn } from '@/utils/cn';
@@ -15,8 +13,8 @@ interface OverviewMetricsProps {
}
export default function OverviewMetrics({ projectId }: OverviewMetricsProps) {
const { previous, range, interval, metric, setMetric, filters } =
useOverviewOptions();
const { previous, range, interval, metric, setMetric } = useOverviewOptions();
const filters = useEventFilters();
const reports = [
{

View File

@@ -2,26 +2,8 @@
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { ReportRange } from '@/components/report/ReportRange';
import { Button } from '@/components/ui/button';
import { SheetTrigger } from '@/components/ui/sheet';
import { FilterIcon } from 'lucide-react';
export function OverviewReportRange() {
const { previous, range, setRange, interval, metric, setMetric, filters } =
useOverviewOptions();
const { range, setRange } = useOverviewOptions();
return <ReportRange value={range} onChange={(value) => setRange(value)} />;
}
export function OverviewFilterSheetTrigger() {
const { previous, range, setRange, interval, metric, setMetric, filters } =
useOverviewOptions();
return (
<SheetTrigger asChild>
<Button variant="outline" responsive icon={FilterIcon}>
Filters
</Button>
</SheetTrigger>
);
}

View File

@@ -1,7 +1,7 @@
import PageLayout from '@/app/(app)/[organizationId]/[projectId]/page-layout';
import { OverviewFiltersButtons } from '@/components/overview/filters/overview-filters-buttons';
import { OverviewFiltersDrawer } from '@/components/overview/filters/overview-filters-drawer';
import ServerLiveCounter from '@/components/overview/live-counter';
import { OverviewFilters } from '@/components/overview/overview-filters';
import { OverviewFiltersButtons } from '@/components/overview/overview-filters-buttons';
import { OverviewLiveHistogram } from '@/components/overview/overview-live-histogram';
import { OverviewShare } from '@/components/overview/overview-share';
import OverviewTopDevices from '@/components/overview/overview-top-devices';
@@ -9,17 +9,13 @@ import OverviewTopEvents from '@/components/overview/overview-top-events';
import OverviewTopGeo from '@/components/overview/overview-top-geo';
import OverviewTopPages from '@/components/overview/overview-top-pages';
import OverviewTopSources from '@/components/overview/overview-top-sources';
import { Sheet, SheetContent } from '@/components/ui/sheet';
import { getExists } from '@/server/pageExists';
import { db } from '@mixan/db';
import { StickyBelowHeader } from './layout-sticky-below-header';
import OverviewMetrics from './overview-metrics';
import {
OverviewFilterSheetTrigger,
OverviewReportRange,
} from './overview-sticky-header';
import { OverviewReportRange } from './overview-sticky-header';
interface PageProps {
params: {
@@ -42,37 +38,32 @@ export default async function Page({
return (
<PageLayout title="Overview" organizationSlug={organizationId}>
<Sheet>
<StickyBelowHeader>
<div className="p-4 flex gap-2 justify-between">
<div className="flex gap-2">
<OverviewReportRange />
<OverviewFilterSheetTrigger />
</div>
<div className="flex gap-2">
<ServerLiveCounter projectId={projectId} />
<OverviewShare data={share} />
</div>
<StickyBelowHeader>
<div className="p-4 flex gap-2 justify-between">
<div className="flex gap-2">
<OverviewReportRange />
<OverviewFiltersDrawer projectId={projectId} />
</div>
<OverviewFiltersButtons />
</StickyBelowHeader>
<div className="p-4 grid gap-4 grid-cols-6">
<div className="col-span-6">
<OverviewLiveHistogram projectId={projectId} />
</div>
<OverviewMetrics projectId={projectId} />
<OverviewTopSources projectId={projectId} />
<OverviewTopPages projectId={projectId} />
<OverviewTopDevices projectId={projectId} />
<OverviewTopEvents projectId={projectId} />
<div className="col-span-6">
<OverviewTopGeo projectId={projectId} />
<div className="flex gap-2">
<ServerLiveCounter projectId={projectId} />
<OverviewShare data={share} />
</div>
</div>
<SheetContent className="!max-w-lg w-full" side="right">
<OverviewFilters projectId={projectId} />
</SheetContent>
</Sheet>
<OverviewFiltersButtons />
</StickyBelowHeader>
<div className="p-4 grid gap-4 grid-cols-6">
<div className="col-span-6">
<OverviewLiveHistogram projectId={projectId} />
</div>
<OverviewMetrics projectId={projectId} />
<OverviewTopSources projectId={projectId} />
<OverviewTopPages projectId={projectId} />
<OverviewTopDevices projectId={projectId} />
<OverviewTopEvents projectId={projectId} />
<div className="col-span-6">
<OverviewTopGeo projectId={projectId} />
</div>
</div>
</PageLayout>
);
}