import { LOCAL_STORAGE_KEYS, useParams } from 'common' import dayjs from 'dayjs' import { ArrowUpDown, X } from 'lucide-react' import Link from 'next/link' import { useMemo } from 'react' import { Badge, Button, Checkbox, Label, ResizableHandle, ResizablePanel, ResizablePanelGroup, Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, Tooltip, TooltipContent, TooltipTrigger, } from 'ui' import { Admonition } from 'ui-patterns' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' import BarChart from '@/components/ui/Charts/BarChart' import NoDataPlaceholder from '@/components/ui/Charts/NoDataPlaceholder' import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage' type Results = { rows: readonly any[] } export type ChartConfig = { view?: 'table' | 'chart' type: 'bar' | 'line' cumulative: boolean xKey: string yKey: string showLabels?: boolean showGrid?: boolean logScale?: boolean } const getCumulativeResults = (results: Results, config: ChartConfig) => { if (!results?.rows?.length) { return [] } const cumulativeResults = results.rows.reduce((acc, row) => { const prev = acc[acc.length - 1] || {} const next = { ...row, [config.yKey]: (prev[config.yKey] || 0) + row[config.yKey], } return [...acc, next] }, []) return cumulativeResults } const VALID_RESULT_KEY_TYPES = ['number', 'string', 'date'] type ChartConfigProps = { results: Results config: ChartConfig onConfigChange: (config: ChartConfig) => void } export const ChartConfig = ({ results = { rows: [] }, config, onConfigChange, }: ChartConfigProps) => { const { ref } = useParams() const [acknowledged, setAcknowledged] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.SQL_EDITOR_SQL_BLOCK_ACKNOWLEDGED(ref as string), false ) // If a result key is not valid, it will be filtered out const resultKeys = useMemo(() => { return Object.keys(results.rows[0] || {}).filter((key) => { const type = typeof results.rows[0][key] return VALID_RESULT_KEY_TYPES.includes(type) }) }, [results]) // Only allow Y-axis keys that are numbers const yAxisKeys = useMemo(() => { if (!results.rows[0]) return [] return Object.keys(results.rows[0]).filter((key) => { const value = results.rows[0][key] return typeof value === 'number' || !isNaN(Number(value)) }) }, [results]) const hasConfig = config.xKey && config.yKey const canFlip = useMemo(() => { if (!hasConfig) return false const xKeyType = typeof results.rows[0]?.[config.xKey] const yKeyType = typeof results.rows[0]?.[config.yKey] return xKeyType === 'number' && yKeyType === 'number' }, [hasConfig, results.rows, config.xKey, config.yKey]) // Compute cumulative results only if necessary const cumulativeResults = useMemo(() => getCumulativeResults(results, config), [results, config]) const resultToRender = config.cumulative ? cumulativeResults : results.rows const getDateFormat = (key: any) => { const value = resultToRender?.[0]?.[key] || '' if (typeof value === 'number') return 'number' if (dayjs(value).isValid()) return 'date' return 'string' } const xKeyDateFormat = getDateFormat(config.xKey) const onFlip = () => { const newY = config.xKey const newX = config.yKey onConfigChange({ ...config, xKey: newX, yKey: newY }) } if (!resultKeys.length) { return (
Add this chart to custom reports
SQL snippets can now be added and saved to your custom reports. Try it out now!