Files
supabase/apps/studio/components/interfaces/QueryInsights/QueryInsightsTable/QueryInsightsTableRow.tsx
Ivan Vasilov 308cd791a2 chore: Prep work for migrating to Tailwind v4 (#45285)
This PR preps the monorepo for a migration to Tailwind v4:
- Bump all Tailwind dependencies and libraries to the latest possible
version, while still compatible with Tailwind 3.
- Cleans up obsolete Tailwind 3 specific options and configs.
- Cleans up unused CSS files and fixes the CSS imports.
- Migrates all `important` uses in `@apply` lines to using the `!`
prefix.
- Move `typography.css` to the `config` package and import it from the
apps.
- Migrated all occurrences of `flex-grow`, `flex-shrink`,
`overflow-clip` and `overflow-ellipsis` since they're deprecated and
will be removed in Tailwind 4.
- Make the default theme object typesafe in the `ui` package.
- Migrate all `bg-opacity`, `border-opacity`, `ring-opacity` and
`divider-opacity` to the new format where they're declared as part of
the property color.
- Bump and unify all imports of `postcss` dependency.
2026-04-28 11:33:53 +02:00

184 lines
5.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Loader2 } from 'lucide-react'
import { AiIconAnimation, Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import type { ClassifiedQuery } from '../QueryInsightsHealth/QueryInsightsHealth.types'
import { ISSUE_DOT_COLORS, ISSUE_ICONS } from './QueryInsightsTable.constants'
import { formatDuration, getColumnName, getTableName } from './QueryInsightsTable.utils'
interface QueryInsightsTableRowProps {
item: ClassifiedQuery
onRowClick?: () => void
onGoToLogs?: () => void
onCreateIndex?: () => void
onExplain?: () => void
onAiSuggestedFix?: () => void
isExplainLoading?: boolean
}
export const QueryInsightsTableRow = ({
item,
onRowClick,
onGoToLogs,
onCreateIndex,
onExplain,
onAiSuggestedFix,
isExplainLoading,
}: QueryInsightsTableRowProps) => {
const IssueIcon = item.issueType ? ISSUE_ICONS[item.issueType] : null
return (
<div
className="flex items-center gap-4 px-6 py-4 border-b hover:bg-surface-100 cursor-pointer group"
onClick={onRowClick}
>
{item.issueType && IssueIcon && (
<div
className={cn(
'h-6 w-6 rounded-full shrink-0 border flex items-center justify-center',
ISSUE_DOT_COLORS[item.issueType]?.border,
ISSUE_DOT_COLORS[item.issueType]?.background
)}
>
<IssueIcon size={14} className={ISSUE_DOT_COLORS[item.issueType].color} />
</div>
)}
<div className="flex-1 min-w-0">
<p className="text-xs font-mono text-foreground line-clamp-1">
<span className="text-foreground">{item.queryType ?? ''}</span>
{getTableName(item.query) && (
<>
{' '}
<span className="text-foreground-lighter">in</span> {getTableName(item.query)}
</>
)}
{getColumnName(item.query) && (
<>
<span className="text-foreground-lighter">,</span> {getColumnName(item.query)}
</>
)}
</p>
<p
className={cn(
'text-xs mt-0.5 font-mono line-clamp-1',
item.issueType === 'error' && 'text-destructive-600',
item.issueType === 'index' && 'text-warning-600',
item.issueType === 'slow' && 'text-foreground-lighter'
)}
>
{item.hint}
</p>
</div>
<div className="flex items-stretch divide-x divide-border shrink-0 tabular-nums">
<Tooltip>
<TooltipTrigger asChild>
<div className="flex flex-col items-end pr-4 cursor-default">
<span
className={cn(
'text-sm font-mono leading-snug',
item.mean_time >= 1000 && 'text-destructive-600'
)}
>
{formatDuration(item.mean_time)}
</span>
<span className="text-[10px] text-foreground-muted uppercase tracking-wide leading-snug">
avg
</span>
</div>
</TooltipTrigger>
<TooltipContent side="top" className="max-w-[220px] text-center">
Average execution time per call. High mean time means individual runs are slow
directly felt by users.
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<div className="flex flex-col items-end px-4 cursor-default">
<span className="text-sm font-mono leading-snug">
{item.prop_total_time.toFixed(1)}%
</span>
<span className="text-[10px] text-foreground-muted uppercase tracking-wide leading-snug">
of db
</span>
</div>
</TooltipTrigger>
<TooltipContent side="top" className="max-w-[220px] text-center">
Percentage of total database execution time. Fixing high-impact queries has the biggest
overall effect on your database.
</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<div className="flex flex-col items-end pl-4 cursor-default">
<span className="text-sm font-mono leading-snug">{item.calls.toLocaleString()}</span>
<span className="text-[10px] text-foreground-muted uppercase tracking-wide leading-snug">
calls
</span>
</div>
</TooltipTrigger>
<TooltipContent side="top" className="max-w-[220px] text-center">
Number of times this query ran in the selected time window.
</TooltipContent>
</Tooltip>
</div>
<div className="flex items-center gap-2 shrink-0 justify-end w-[260px]">
<Button
type="default"
size="tiny"
onClick={(e) => {
e.stopPropagation()
onGoToLogs?.()
}}
>
Go to Logs
</Button>
{(item.issueType === 'index' || item.issueType === 'slow') && (
<Button
type="default"
size="tiny"
icon={isExplainLoading ? <Loader2 size={12} className="animate-spin" /> : undefined}
onClick={(e) => {
e.stopPropagation()
onExplain?.()
}}
>
Explain
</Button>
)}
{item.issueType === 'index' && (
<Button
type="primary"
size="tiny"
onClick={(e) => {
e.stopPropagation()
onCreateIndex?.()
}}
>
Create Index
</Button>
)}
{(item.issueType === 'error' || item.issueType === 'slow') && (
<Button
type="default"
size="tiny"
icon={<AiIconAnimation size={14} />}
onClick={(e) => {
e.stopPropagation()
onAiSuggestedFix?.()
}}
>
Fix with AI
</Button>
)}
</div>
</div>
)
}