fix: make table rows clickable
This commit is contained in:
@@ -1,3 +1,17 @@
|
|||||||
|
import type { IServiceEvent } from '@openpanel/db';
|
||||||
|
import type { UseInfiniteQueryResult } from '@tanstack/react-query';
|
||||||
|
import type { Table } from '@tanstack/react-table';
|
||||||
|
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||||
|
import { useWindowVirtualizer } from '@tanstack/react-virtual';
|
||||||
|
import type { TRPCInfiniteData } from '@trpc/tanstack-react-query';
|
||||||
|
import { format } from 'date-fns';
|
||||||
|
import { CalendarIcon, Loader2Icon } from 'lucide-react';
|
||||||
|
import { parseAsIsoDateTime, useQueryState } from 'nuqs';
|
||||||
|
import { last } from 'ramda';
|
||||||
|
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
|
import { useInViewport } from 'react-in-viewport';
|
||||||
|
import EventListener from '../event-listener';
|
||||||
|
import { useColumns } from './columns';
|
||||||
import { FullPageEmptyState } from '@/components/full-page-empty-state';
|
import { FullPageEmptyState } from '@/components/full-page-empty-state';
|
||||||
import {
|
import {
|
||||||
OverviewFilterButton,
|
OverviewFilterButton,
|
||||||
@@ -12,20 +26,6 @@ import { useAppParams } from '@/hooks/use-app-params';
|
|||||||
import { pushModal } from '@/modals';
|
import { pushModal } from '@/modals';
|
||||||
import type { RouterInputs, RouterOutputs } from '@/trpc/client';
|
import type { RouterInputs, RouterOutputs } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import type { IServiceEvent } from '@openpanel/db';
|
|
||||||
import type { UseInfiniteQueryResult } from '@tanstack/react-query';
|
|
||||||
import type { Table } from '@tanstack/react-table';
|
|
||||||
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
|
||||||
import { useWindowVirtualizer } from '@tanstack/react-virtual';
|
|
||||||
import type { TRPCInfiniteData } from '@trpc/tanstack-react-query';
|
|
||||||
import { format } from 'date-fns';
|
|
||||||
import { CalendarIcon, FilterIcon, Loader2Icon } from 'lucide-react';
|
|
||||||
import { parseAsIsoDateTime, useQueryState } from 'nuqs';
|
|
||||||
import { last } from 'ramda';
|
|
||||||
import { memo, useEffect, useMemo, useRef } from 'react';
|
|
||||||
import { useInViewport } from 'react-in-viewport';
|
|
||||||
import EventListener from '../event-listener';
|
|
||||||
import { useColumns } from './columns';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
query: UseInfiniteQueryResult<
|
query: UseInfiniteQueryResult<
|
||||||
@@ -54,6 +54,7 @@ interface VirtualRowProps {
|
|||||||
scrollMargin: number;
|
scrollMargin: number;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
headerColumnsHash: string;
|
headerColumnsHash: string;
|
||||||
|
onRowClick?: (row: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VirtualRow = memo(
|
const VirtualRow = memo(
|
||||||
@@ -63,12 +64,26 @@ const VirtualRow = memo(
|
|||||||
headerColumns,
|
headerColumns,
|
||||||
scrollMargin,
|
scrollMargin,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
onRowClick,
|
||||||
}: VirtualRowProps) {
|
}: VirtualRowProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className={cn(
|
||||||
|
'group/row absolute top-0 left-0 w-full border-b transition-colors hover:bg-muted/50',
|
||||||
|
onRowClick && 'cursor-pointer'
|
||||||
|
)}
|
||||||
data-index={virtualRow.index}
|
data-index={virtualRow.index}
|
||||||
|
onClick={
|
||||||
|
onRowClick
|
||||||
|
? (e) => {
|
||||||
|
if ((e.target as HTMLElement).closest('a, button')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onRowClick(row);
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
ref={virtualRow.measureElement}
|
ref={virtualRow.measureElement}
|
||||||
className="absolute top-0 left-0 w-full border-b hover:bg-muted/50 transition-colors group/row"
|
|
||||||
style={{
|
style={{
|
||||||
transform: `translateY(${virtualRow.start - scrollMargin}px)`,
|
transform: `translateY(${virtualRow.start - scrollMargin}px)`,
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@@ -83,8 +98,8 @@ const VirtualRow = memo(
|
|||||||
const width = `${cell.column.getSize()}px`;
|
const width = `${cell.column.getSize()}px`;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className="flex items-center whitespace-nowrap p-2 px-4 align-middle"
|
||||||
key={cell.id}
|
key={cell.id}
|
||||||
className="flex items-center p-2 px-4 align-middle whitespace-nowrap"
|
|
||||||
style={{
|
style={{
|
||||||
width,
|
width,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
@@ -114,16 +129,18 @@ const VirtualRow = memo(
|
|||||||
prevProps.virtualRow.start === nextProps.virtualRow.start &&
|
prevProps.virtualRow.start === nextProps.virtualRow.start &&
|
||||||
prevProps.virtualRow.size === nextProps.virtualRow.size &&
|
prevProps.virtualRow.size === nextProps.virtualRow.size &&
|
||||||
prevProps.isLoading === nextProps.isLoading &&
|
prevProps.isLoading === nextProps.isLoading &&
|
||||||
prevProps.headerColumnsHash === nextProps.headerColumnsHash
|
prevProps.headerColumnsHash === nextProps.headerColumnsHash &&
|
||||||
|
prevProps.onRowClick === nextProps.onRowClick
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const VirtualizedEventsTable = ({
|
const VirtualizedEventsTable = ({
|
||||||
table,
|
table,
|
||||||
data,
|
data,
|
||||||
isLoading,
|
isLoading,
|
||||||
}: VirtualizedEventsTableProps) => {
|
onRowClick,
|
||||||
|
}: VirtualizedEventsTableProps & { onRowClick?: (row: any) => void }) => {
|
||||||
const parentRef = useRef<HTMLDivElement>(null);
|
const parentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const headerColumns = table.getAllLeafColumns().filter((col) => {
|
const headerColumns = table.getAllLeafColumns().filter((col) => {
|
||||||
@@ -145,12 +162,12 @@ const VirtualizedEventsTable = ({
|
|||||||
const headerColumnsHash = headerColumns.map((col) => col.id).join(',');
|
const headerColumnsHash = headerColumns.map((col) => col.id).join(',');
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className="w-full overflow-x-auto rounded-md border bg-card"
|
||||||
ref={parentRef}
|
ref={parentRef}
|
||||||
className="w-full overflow-x-auto border rounded-md bg-card"
|
|
||||||
>
|
>
|
||||||
{/* Table Header */}
|
{/* Table Header */}
|
||||||
<div
|
<div
|
||||||
className="sticky top-0 z-10 bg-card border-b"
|
className="sticky top-0 z-10 border-b bg-card"
|
||||||
style={{
|
style={{
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: headerColumns
|
gridTemplateColumns: headerColumns
|
||||||
@@ -164,8 +181,8 @@ const VirtualizedEventsTable = ({
|
|||||||
const width = `${column.getSize()}px`;
|
const width = `${column.getSize()}px`;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className="flex h-10 items-center whitespace-nowrap px-4 text-left font-semibold text-[10px] text-foreground uppercase"
|
||||||
key={column.id}
|
key={column.id}
|
||||||
className="flex items-center h-10 px-4 text-left text-[10px] uppercase text-foreground font-semibold whitespace-nowrap"
|
|
||||||
style={{
|
style={{
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
@@ -178,8 +195,8 @@ const VirtualizedEventsTable = ({
|
|||||||
|
|
||||||
{!isLoading && data.length === 0 && (
|
{!isLoading && data.length === 0 && (
|
||||||
<FullPageEmptyState
|
<FullPageEmptyState
|
||||||
title="No events"
|
|
||||||
description={"Start sending events and you'll see them here"}
|
description={"Start sending events and you'll see them here"}
|
||||||
|
title="No events"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -194,20 +211,23 @@ const VirtualizedEventsTable = ({
|
|||||||
>
|
>
|
||||||
{virtualRows.map((virtualRow) => {
|
{virtualRows.map((virtualRow) => {
|
||||||
const row = table.getRowModel().rows[virtualRow.index];
|
const row = table.getRowModel().rows[virtualRow.index];
|
||||||
if (!row) return null;
|
if (!row) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VirtualRow
|
<VirtualRow
|
||||||
|
headerColumns={headerColumns}
|
||||||
|
headerColumnsHash={headerColumnsHash}
|
||||||
|
isLoading={isLoading}
|
||||||
key={row.id}
|
key={row.id}
|
||||||
|
onRowClick={onRowClick}
|
||||||
row={row}
|
row={row}
|
||||||
|
scrollMargin={rowVirtualizer.options.scrollMargin}
|
||||||
virtualRow={{
|
virtualRow={{
|
||||||
...virtualRow,
|
...virtualRow,
|
||||||
measureElement: rowVirtualizer.measureElement,
|
measureElement: rowVirtualizer.measureElement,
|
||||||
}}
|
}}
|
||||||
headerColumns={headerColumns}
|
|
||||||
headerColumnsHash={headerColumnsHash}
|
|
||||||
scrollMargin={rowVirtualizer.options.scrollMargin}
|
|
||||||
isLoading={isLoading}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -220,6 +240,14 @@ export const EventsTable = ({ query, showEventListener = false }: Props) => {
|
|||||||
const { isLoading } = query;
|
const { isLoading } = query;
|
||||||
const columns = useColumns();
|
const columns = useColumns();
|
||||||
|
|
||||||
|
const handleRowClick = useCallback((row: any) => {
|
||||||
|
pushModal('EventDetails', {
|
||||||
|
id: row.original.id,
|
||||||
|
createdAt: row.original.createdAt,
|
||||||
|
projectId: row.original.projectId,
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return LOADING_DATA;
|
return LOADING_DATA;
|
||||||
@@ -273,13 +301,22 @@ export const EventsTable = ({ query, showEventListener = false }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EventsTableToolbar query={query} table={table} showEventListener={showEventListener} />
|
<EventsTableToolbar
|
||||||
<VirtualizedEventsTable table={table} data={data} isLoading={isLoading} />
|
query={query}
|
||||||
<div className="w-full h-10 center-center pt-4" ref={inViewportRef}>
|
showEventListener={showEventListener}
|
||||||
|
table={table}
|
||||||
|
/>
|
||||||
|
<VirtualizedEventsTable
|
||||||
|
data={data}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onRowClick={handleRowClick}
|
||||||
|
table={table}
|
||||||
|
/>
|
||||||
|
<div className="center-center h-10 w-full pt-4" ref={inViewportRef}>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'size-8 bg-background rounded-full center-center border opacity-0 transition-opacity',
|
'center-center size-8 rounded-full border bg-background opacity-0 transition-opacity',
|
||||||
query.isFetchingNextPage && 'opacity-100',
|
query.isFetchingNextPage && 'opacity-100'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Loader2Icon className="size-4 animate-spin" />
|
<Loader2Icon className="size-4 animate-spin" />
|
||||||
@@ -301,17 +338,17 @@ function EventsTableToolbar({
|
|||||||
const { projectId } = useAppParams();
|
const { projectId } = useAppParams();
|
||||||
const [startDate, setStartDate] = useQueryState(
|
const [startDate, setStartDate] = useQueryState(
|
||||||
'startDate',
|
'startDate',
|
||||||
parseAsIsoDateTime,
|
parseAsIsoDateTime
|
||||||
);
|
);
|
||||||
const [endDate, setEndDate] = useQueryState('endDate', parseAsIsoDateTime);
|
const [endDate, setEndDate] = useQueryState('endDate', parseAsIsoDateTime);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataTableToolbarContainer>
|
<DataTableToolbarContainer>
|
||||||
<div className="flex flex-1 flex-wrap items-center gap-2">
|
<div className="flex flex-1 flex-wrap items-center gap-2">
|
||||||
{showEventListener && <EventListener onRefresh={() => query.refetch()} />}
|
{showEventListener && (
|
||||||
|
<EventListener onRefresh={() => query.refetch()} />
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
icon={CalendarIcon}
|
icon={CalendarIcon}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
pushModal('DateRangerPicker', {
|
pushModal('DateRangerPicker', {
|
||||||
@@ -323,6 +360,8 @@ function EventsTableToolbar({
|
|||||||
endDate: endDate || undefined,
|
endDate: endDate || undefined,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
>
|
>
|
||||||
{startDate && endDate
|
{startDate && endDate
|
||||||
? `${format(startDate, 'MMM d')} - ${format(endDate, 'MMM d')}`
|
? `${format(startDate, 'MMM d')} - ${format(endDate, 'MMM d')}`
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ import {
|
|||||||
DataTableToolbarContainer,
|
DataTableToolbarContainer,
|
||||||
} from '@/components/ui/data-table/data-table-toolbar';
|
} from '@/components/ui/data-table/data-table-toolbar';
|
||||||
import { DataTableViewOptions } from '@/components/ui/data-table/data-table-view-options';
|
import { DataTableViewOptions } from '@/components/ui/data-table/data-table-view-options';
|
||||||
|
import { useAppParams } from '@/hooks/use-app-params';
|
||||||
import { useSearchQueryState } from '@/hooks/use-search-query-state';
|
import { useSearchQueryState } from '@/hooks/use-search-query-state';
|
||||||
import { arePropsEqual } from '@/utils/are-props-equal';
|
import { arePropsEqual } from '@/utils/are-props-equal';
|
||||||
import type { IServiceProfile } from '@openpanel/db';
|
import type { IServiceProfile } from '@openpanel/db';
|
||||||
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
import type { PaginationState, Table, Updater } from '@tanstack/react-table';
|
import type { PaginationState, Table, Updater } from '@tanstack/react-table';
|
||||||
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||||
import { memo } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
|
|
||||||
const PAGE_SIZE = 50;
|
const PAGE_SIZE = 50;
|
||||||
|
|
||||||
@@ -32,6 +34,22 @@ export const ProfilesTable = memo(
|
|||||||
({ type, query, pageSize = PAGE_SIZE }: Props) => {
|
({ type, query, pageSize = PAGE_SIZE }: Props) => {
|
||||||
const { data, isLoading } = query;
|
const { data, isLoading } = query;
|
||||||
const columns = useColumns(type);
|
const columns = useColumns(type);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { organizationId, projectId } = useAppParams();
|
||||||
|
|
||||||
|
const handleRowClick = useCallback(
|
||||||
|
(row: any) => {
|
||||||
|
navigate({
|
||||||
|
to: '/$organizationId/$projectId/profiles/$profileId' as any,
|
||||||
|
params: {
|
||||||
|
organizationId,
|
||||||
|
projectId,
|
||||||
|
profileId: encodeURIComponent(row.original.id),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[navigate, organizationId, projectId],
|
||||||
|
);
|
||||||
|
|
||||||
const { setPage, state: pagination } = useDataTablePagination(pageSize);
|
const { setPage, state: pagination } = useDataTablePagination(pageSize);
|
||||||
const {
|
const {
|
||||||
@@ -78,6 +96,7 @@ export const ProfilesTable = memo(
|
|||||||
<DataTable
|
<DataTable
|
||||||
table={table}
|
table={table}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
|
onRowClick={handleRowClick}
|
||||||
empty={{
|
empty={{
|
||||||
title: 'No profiles',
|
title: 'No profiles',
|
||||||
description: "Looks like you haven't identified any profiles yet.",
|
description: "Looks like you haven't identified any profiles yet.",
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export function useColumns() {
|
|||||||
if (session.profile) {
|
if (session.profile) {
|
||||||
return (
|
return (
|
||||||
<ProjectLink
|
<ProjectLink
|
||||||
className="row items-center gap-2 font-medium"
|
className="row items-center gap-2 font-medium hover:underline"
|
||||||
href={`/profiles/${encodeURIComponent(session.profile.id)}`}
|
href={`/profiles/${encodeURIComponent(session.profile.id)}`}
|
||||||
>
|
>
|
||||||
<ProfileAvatar size="sm" {...session.profile} />
|
<ProfileAvatar size="sm" {...session.profile} />
|
||||||
|
|||||||
@@ -44,17 +44,19 @@ import {
|
|||||||
DataTableToolbarContainer,
|
DataTableToolbarContainer,
|
||||||
} from '@/components/ui/data-table/data-table-toolbar';
|
} from '@/components/ui/data-table/data-table-toolbar';
|
||||||
import { DataTableViewOptions } from '@/components/ui/data-table/data-table-view-options';
|
import { DataTableViewOptions } from '@/components/ui/data-table/data-table-view-options';
|
||||||
|
import { useAppParams } from '@/hooks/use-app-params';
|
||||||
import { useSearchQueryState } from '@/hooks/use-search-query-state';
|
import { useSearchQueryState } from '@/hooks/use-search-query-state';
|
||||||
import { arePropsEqual } from '@/utils/are-props-equal';
|
import { arePropsEqual } from '@/utils/are-props-equal';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import type { IServiceSession } from '@openpanel/db';
|
import type { IServiceSession } from '@openpanel/db';
|
||||||
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
import type { Table } from '@tanstack/react-table';
|
import type { Table } from '@tanstack/react-table';
|
||||||
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
import { getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||||
import { useWindowVirtualizer } from '@tanstack/react-virtual';
|
import { useWindowVirtualizer } from '@tanstack/react-virtual';
|
||||||
import type { TRPCInfiniteData } from '@trpc/tanstack-react-query';
|
import type { TRPCInfiniteData } from '@trpc/tanstack-react-query';
|
||||||
import { Loader2Icon } from 'lucide-react';
|
import { Loader2Icon } from 'lucide-react';
|
||||||
import { last } from 'ramda';
|
import { last } from 'ramda';
|
||||||
import { memo, useEffect, useMemo, useRef, useState } from 'react';
|
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useInViewport } from 'react-in-viewport';
|
import { useInViewport } from 'react-in-viewport';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -83,6 +85,7 @@ interface VirtualRowProps {
|
|||||||
scrollMargin: number;
|
scrollMargin: number;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
headerColumnsHash: string;
|
headerColumnsHash: string;
|
||||||
|
onRowClick?: (row: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VirtualRow = memo(
|
const VirtualRow = memo(
|
||||||
@@ -92,12 +95,24 @@ const VirtualRow = memo(
|
|||||||
headerColumns,
|
headerColumns,
|
||||||
scrollMargin,
|
scrollMargin,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
onRowClick,
|
||||||
}: VirtualRowProps) {
|
}: VirtualRowProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-index={virtualRow.index}
|
data-index={virtualRow.index}
|
||||||
ref={virtualRow.measureElement}
|
ref={virtualRow.measureElement}
|
||||||
className="absolute top-0 left-0 w-full border-b hover:bg-muted/50 transition-colors group/row"
|
className={cn(
|
||||||
|
'absolute top-0 left-0 w-full border-b hover:bg-muted/50 transition-colors group/row',
|
||||||
|
onRowClick && 'cursor-pointer',
|
||||||
|
)}
|
||||||
|
onClick={
|
||||||
|
onRowClick
|
||||||
|
? (e) => {
|
||||||
|
if ((e.target as HTMLElement).closest('a, button')) return;
|
||||||
|
onRowClick(row);
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
style={{
|
style={{
|
||||||
transform: `translateY(${virtualRow.start - scrollMargin}px)`,
|
transform: `translateY(${virtualRow.start - scrollMargin}px)`,
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@@ -143,7 +158,8 @@ const VirtualRow = memo(
|
|||||||
prevProps.virtualRow.start === nextProps.virtualRow.start &&
|
prevProps.virtualRow.start === nextProps.virtualRow.start &&
|
||||||
prevProps.virtualRow.size === nextProps.virtualRow.size &&
|
prevProps.virtualRow.size === nextProps.virtualRow.size &&
|
||||||
prevProps.isLoading === nextProps.isLoading &&
|
prevProps.isLoading === nextProps.isLoading &&
|
||||||
prevProps.headerColumnsHash === nextProps.headerColumnsHash
|
prevProps.headerColumnsHash === nextProps.headerColumnsHash &&
|
||||||
|
prevProps.onRowClick === nextProps.onRowClick
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -152,7 +168,8 @@ const VirtualizedSessionsTable = ({
|
|||||||
table,
|
table,
|
||||||
data,
|
data,
|
||||||
isLoading,
|
isLoading,
|
||||||
}: VirtualizedSessionsTableProps) => {
|
onRowClick,
|
||||||
|
}: VirtualizedSessionsTableProps & { onRowClick?: (row: any) => void }) => {
|
||||||
const parentRef = useRef<HTMLDivElement>(null);
|
const parentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const headerColumns = table.getAllLeafColumns().filter((col) => {
|
const headerColumns = table.getAllLeafColumns().filter((col) => {
|
||||||
@@ -234,6 +251,7 @@ const VirtualizedSessionsTable = ({
|
|||||||
headerColumnsHash={headerColumnsHash}
|
headerColumnsHash={headerColumnsHash}
|
||||||
scrollMargin={rowVirtualizer.options.scrollMargin}
|
scrollMargin={rowVirtualizer.options.scrollMargin}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
onRowClick={onRowClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -245,6 +263,18 @@ const VirtualizedSessionsTable = ({
|
|||||||
export const SessionsTable = ({ query }: Props) => {
|
export const SessionsTable = ({ query }: Props) => {
|
||||||
const { isLoading } = query;
|
const { isLoading } = query;
|
||||||
const columns = useColumns();
|
const columns = useColumns();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { organizationId, projectId } = useAppParams();
|
||||||
|
|
||||||
|
const handleRowClick = useCallback(
|
||||||
|
(row: any) => {
|
||||||
|
navigate({
|
||||||
|
to: '/$organizationId/$projectId/sessions/$sessionId' as any,
|
||||||
|
params: { organizationId, projectId, sessionId: row.original.id },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[navigate, organizationId, projectId],
|
||||||
|
);
|
||||||
|
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
@@ -304,6 +334,7 @@ export const SessionsTable = ({ query }: Props) => {
|
|||||||
table={table}
|
table={table}
|
||||||
data={data}
|
data={data}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
onRowClick={handleRowClick}
|
||||||
/>
|
/>
|
||||||
<div className="w-full h-10 center-center pt-4" ref={inViewportRef}>
|
<div className="w-full h-10 center-center pt-4" ref={inViewportRef}>
|
||||||
<div
|
<div
|
||||||
|
|||||||
Reference in New Issue
Block a user