Files
supabase/apps/studio/components/interfaces/ExplainVisualizer/ExplainVisualizer.tsx
T
Ali Waseem 3a41846044 Feature: Pretty explain in SQL Editor (#41289)
* added cleaner explanation

* update UI

* refactored components

* updated logic

* removed steps

* updated UI

* updated read

* updated node render styles

* added tests

* updated file naming

* updated utility method

* updated description

* updated spacing

* updated to include header

* updated logic

* added flag to hide pretty explain

* updated cost width

* added aria label

* move index scan down

* updated to catch schema and qoutes

* remove node

* forgot the missed node

* addressed PR feedback

* updated bad slop

* removing tests

* updated node to be undefined, null remove it makes the logic cleaner

* updated function name

* updated row indicator to be separate components

* updated code rabbit feedback

* added divide by zero check

* updated test description
2025-12-12 20:35:18 +00:00

40 lines
1.4 KiB
TypeScript

import { useMemo } from 'react'
import { ExplainHeader } from './ExplainVisualizer.Header'
import { ExplainNodeRenderer } from './ExplainVisualizer.NodeRenderer'
import { calculateMaxCost, calculateSummary, createNodeTree } from './ExplainVisualizer.parser'
import type { QueryPlanRow } from './ExplainVisualizer.types'
export interface ExplainVisualizerProps {
rows: readonly QueryPlanRow[]
onShowRaw?: () => void
}
export function ExplainVisualizer({ rows, onShowRaw }: ExplainVisualizerProps) {
const parsedTree = useMemo(() => createNodeTree(rows), [rows])
const maxCost = useMemo(() => calculateMaxCost(parsedTree), [parsedTree])
const summary = useMemo(() => calculateSummary(parsedTree), [parsedTree])
if (parsedTree.length === 0) {
return (
<div className="bg-table-header-light [[data-theme*=dark]_&]:bg-table-header-dark">
<p className="m-0 border-0 px-4 py-3 font-mono text-sm text-foreground-light">
No execution plan data available
</p>
</div>
)
}
return (
<div className="bg-studio border-t h-full flex flex-col">
{onShowRaw && <ExplainHeader mode="visual" onToggleMode={onShowRaw} summary={summary} />}
{/* Tree visualization */}
<div className="p-4 mb-10 overflow-auto flex-1">
{parsedTree.map((node, idx) => (
<ExplainNodeRenderer key={idx} node={node} depth={0} maxCost={maxCost} isRoot={true} />
))}
</div>
</div>
)
}