@@ -4,7 +4,8 @@ import { memo, useEffect, useMemo, useRef, useState } from 'react'
44import { getErrorMessage } from '@sim/utils/errors'
55import type { EChartsOption } from 'echarts'
66import { useTheme } from 'next-themes'
7- import { useTableRowsSample } from '@/hooks/queries/tables'
7+ import { getColumnId } from '@/lib/table/column-keys'
8+ import { useTable , useTableRowsSample } from '@/hooks/queries/tables'
89import { PreviewLoadingFrame } from './preview-shared'
910
1011/** Hard cap on rows a table-backed chart pulls; the spec's `limit` clamps under it. */
@@ -173,13 +174,29 @@ export const ChartPreview = memo(function ChartPreview({
173174 limit : Math . min ( tableSource ?. limit ?? CHART_ROWS_DEFAULT , CHART_ROWS_MAX ) ,
174175 enabled : Boolean ( tableSource ) ,
175176 } )
177+ const tableQuery = useTable ( tableSource ? workspaceId : undefined , tableSource ?. tableId )
176178
177179 const rows = useMemo ( ( ) => {
178180 if ( ! spec ) return null
179181 if ( spec . source ?. type === 'static' ) return spec . source . rows ?? null
180- if ( tableSource ) return rowsQuery . data ?. rows . map ( ( row ) => row . data ) ?? null
181- return null
182- } , [ spec , tableSource , rowsQuery . data ] )
182+ if ( ! tableSource ) return null
183+ const fetched = rowsQuery . data ?. rows
184+ const columns = tableQuery . data ?. schema . columns
185+ if ( ! fetched || ! columns ) return null
186+ // Row data is stored keyed by column ID (an opaque uuid); chart specs —
187+ // like the mothership table tool and the public API — speak column NAMES.
188+ // Remap so `encode`/dimension references in the option match what the
189+ // author sees in the table UI.
190+ const nameByStorageKey = new Map < string , string > ( )
191+ for ( const col of columns ) nameByStorageKey . set ( getColumnId ( col ) , col . name )
192+ return fetched . map ( ( row ) => {
193+ const out : Record < string , unknown > = { }
194+ for ( const [ key , value ] of Object . entries ( row . data ) ) {
195+ out [ nameByStorageKey . get ( key ) ?? key ] = value
196+ }
197+ return out
198+ } )
199+ } , [ spec , tableSource , rowsQuery . data , tableQuery . data ] )
183200
184201 const option = useMemo ( ( ) => ( spec ? buildOption ( spec , rows ) : null ) , [ spec , rows ] )
185202 /** Stable identity for the effect below — option is a fresh object per memo. */
@@ -224,7 +241,16 @@ export const ChartPreview = memo(function ChartPreview({
224241 )
225242 }
226243
227- const waitingOnRows = Boolean ( tableSource ) && ! rowsQuery . data
244+ if ( tableSource && tableQuery . isError ) {
245+ return (
246+ < ChartErrorPanel
247+ message = { getErrorMessage ( tableQuery . error , 'failed to read the table' ) }
248+ content = { content }
249+ />
250+ )
251+ }
252+
253+ const waitingOnRows = Boolean ( tableSource ) && rows === null
228254 // Width-driven aspect box, not full-bleed: a chart stretched to the whole
229255 // panel height is unreadable in a tall resource pane. ECharts follows the
230256 // box through the ResizeObserver above.
0 commit comments