Files
supabase/apps/studio/components/interfaces/Explorer/QueryCell/QueryResultChart.tsx
T
Joshen Lim d434c63bad joshen/fe 4150 explorer query cells result display settings (#49003)
## Context

Related to Explorer / Notebooks - this adds chart functionality for the
Query cells
<img width="250" alt="image"
src="https://github.com/user-attachments/assets/4ea37c14-87dc-4c43-ba7f-cb9436085c81"
/>

Query results can be rendered as either bar or line chart - using the
chart packages from `ui-patterns`
[NOTE]: For design team reviewers - am patching the chart packages to be
agnostic to the `timestamp` property within the provided data set. Would
love to use this component from a consistency POV instead of the old
`BarChart` component we have.

Have intentionally omitted log scale functionality from this PR - will
have that separately 🙏

<img width="999" height="483" alt="image"
src="https://github.com/user-attachments/assets/14356ee4-c658-4fd1-90e0-17c38dac4822"
/>
<img width="988" height="478" alt="image"
src="https://github.com/user-attachments/assets/cd0ca088-9a03-4aa3-9884-17bc36d3cabf"
/>



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added chart views for notebook query results, including bar and line
charts.
- Added display settings for selecting X/Y columns, chart type, scale,
cumulative values, and label visibility.
  - Added configurable X-axis support for charts.
  - Display preferences are saved with each notebook cell.

- **Improvements**
  - New database cells default to table view.
  - Chart results better handle varied data types.
- Empty results and incomplete chart settings now display clear
placeholders.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-13 10:09:54 +07:00

97 lines
2.9 KiB
TypeScript

import { useMemo } from 'react'
import { Chart, ChartBar, ChartCard, ChartContent, ChartLine } from 'ui-patterns/Chart'
import { type Snapshot } from 'valtio'
import { type QueryResult } from '../types'
import NoDataPlaceholder from '@/components/ui/Charts/NoDataPlaceholder'
import { getCumulativeResults } from '@/components/ui/QueryBlock/QueryBlock.utils'
import { type DatabaseCell as DatabaseCellSchema } from '@/data/content/notebooks/notebook-schema'
interface QueryResultChartProps {
cell: Snapshot<DatabaseCellSchema>
result?: QueryResult
}
// [Joshen] Will need to implement log scale - refer to QueryBlock.tsx `effectiveLogScale`
// [Joshen] Will also need to implement error handling where appropriate (e.g if query errors)
const toChartValue = (value: unknown): string | number => {
if (typeof value === 'number' || typeof value === 'string') return value
if (value === null || value === undefined) return ''
return String(value)
}
export const QueryResultChart = ({ cell, result }: QueryResultChartProps) => {
const { chart } = cell
const { type, x_column, y_columns = [], cumulative, show_labels } = chart ?? {}
const hasConfig = !!x_column && y_columns.length > 0
const chartRows = useMemo(() => {
const xKey = x_column ?? ''
const yKey = y_columns[0] ?? ''
return (result?.rows ?? []).map((row) => ({
[xKey]: toChartValue(row[xKey]),
[yKey]: toChartValue(row[yKey]),
}))
}, [result, x_column, y_columns])
const cumulativeResults = useMemo(
() => getCumulativeResults({ rows: chartRows }, { yKey: y_columns[0] ?? '' }),
[chartRows, y_columns]
)
const resultToRender = cumulative ? cumulativeResults : chartRows
if (!result || (result?.rows && result.rows.length === 0)) {
return (
<NoDataPlaceholder
className="bg border-0"
size="normal"
message="No results"
description="Your query returned no rows"
/>
)
}
if (!hasConfig) {
return (
<NoDataPlaceholder
className="bg border-0"
size="normal"
message="Configure your chart"
description="Select your X and Y axis in the display settings"
/>
)
}
return (
<Chart>
<ChartCard className="rounded-none border-0">
<ChartContent>
<div className="h-40">
{type === 'bar' && (
<ChartBar
isFullHeight
xKey={x_column}
dataKey={y_columns[0]}
showXAxis={show_labels}
showYAxis={show_labels}
data={resultToRender}
/>
)}
{type === 'line' && (
<ChartLine
isFullHeight
xKey={x_column}
dataKey={y_columns[0]}
showXAxis={show_labels}
showYAxis={show_labels}
data={resultToRender}
/>
)}
</div>
</ChartContent>
</ChartCard>
</Chart>
)
}