import { ArrowDown, ArrowUp, TextSearch, X } from 'lucide-react' import { useRouter } from 'next/router' import { useEffect, useRef, useState } from 'react' import DataGrid, { Column, DataGridHandle, Row } from 'react-data-grid' import { useParams } from 'common' import { DbQueryHook } from 'hooks/analytics/useDbQuery' import { Button, ResizableHandle, ResizablePanel, ResizablePanelGroup, TabsContent_Shadcn_, TabsList_Shadcn_, TabsTrigger_Shadcn_, Tabs_Shadcn_, cn, } from 'ui' import { GenericSkeletonLoader } from 'ui-patterns' import { QueryPerformanceSort } from '../Reports/Reports.queries' import { QueryDetail } from './QueryDetail' import { QueryIndexes } from './QueryIndexes' import { QUERY_PERFORMANCE_REPORTS, QUERY_PERFORMANCE_REPORT_TYPES, } from './QueryPerformance.constants' interface QueryPerformanceGridProps { queryPerformanceQuery: DbQueryHook } export const QueryPerformanceGrid = ({ queryPerformanceQuery }: QueryPerformanceGridProps) => { const router = useRouter() const gridRef = useRef(null) const { preset, sort: urlSort, order, roles, search } = useParams() const { isLoading } = queryPerformanceQuery const defaultSortValue = router.query.sort ? ({ column: router.query.sort, order: router.query.order } as QueryPerformanceSort) : undefined const [view, setView] = useState<'details' | 'suggestion'>('details') const [sort, setSort] = useState(defaultSortValue) const [selectedRow, setSelectedRow] = useState() const reportType = (preset as QUERY_PERFORMANCE_REPORT_TYPES) ?? QUERY_PERFORMANCE_REPORT_TYPES.MOST_TIME_CONSUMING const columns = QUERY_PERFORMANCE_REPORTS[reportType].map((col) => { const result: Column = { key: col.id, name: col.name, resizable: true, minWidth: col.minWidth ?? 120, headerCellClass: 'first:pl-6 cursor-pointer', renderHeaderCell: () => { return (
onSortChange(col.id)} >

{col.name}

{col.description &&

{col.description}

}
{sort?.column === col.id && ( <>{sort.order === 'desc' ? : } )}
) }, renderCell: (props) => { const value = props.row?.[col.id] const isTime = col.name.includes('time') const formattedValue = isTime ? `${Number(value.toFixed(2)).toLocaleString()}ms` : value.toLocaleString() return (

{formattedValue}

{isTime &&

{(value / 1000).toFixed(2)}s

}
) }, } return result }) const selectedQuery = selectedRow !== undefined ? queryPerformanceQuery.data?.[selectedRow]['query'] : undefined const showIndexSuggestions = (selectedQuery ?? '').trim().toLowerCase().startsWith('select') const onSortChange = (column: string) => { let updatedSort = undefined if (sort?.column === column) { if (sort.order === 'desc') { updatedSort = { column, order: 'asc' } } else { updatedSort = undefined } } else { updatedSort = { column, order: 'desc' } } setSort(updatedSort as QueryPerformanceSort) if (updatedSort === undefined) { const { sort, order, ...otherParams } = router.query router.push({ ...router, query: otherParams }) } else { router.push({ ...router, query: { ...router.query, sort: updatedSort.column, order: updatedSort.order }, }) } } useEffect(() => { setSelectedRow(undefined) }, [preset, search, roles, urlSort, order]) return ( { const isSelected = idx === selectedRow return [ `${isSelected ? 'bg-surface-300 dark:bg-surface-300' : 'bg-200'} cursor-pointer`, `${isSelected ? '[&>div:first-child]:border-l-4 border-l-secondary [&>div]:border-l-foreground' : ''}`, '[&>.rdg-cell]:border-box [&>.rdg-cell]:outline-none [&>.rdg-cell]:shadow-none', '[&>.rdg-cell:first-child>div]:ml-4', ].join(' ') }} renderers={{ renderRow(idx, props) { return ( { if (typeof idx === 'number' && idx >= 0) { setSelectedRow(idx) gridRef.current?.scrollToCell({ idx: 0, rowIdx: idx }) const selectedQuery = queryPerformanceQuery.data[idx]['query'] if (!(selectedQuery ?? '').trim().toLowerCase().startsWith('select')) { setView('details') } } }} /> ) }, noRowsFallback: isLoading ? (
) : (

No queries detected

There are no actively running queries that match the criteria

), }} />
{selectedRow !== undefined && ( <>