diff --git a/.changeset/dataset-widget-real-chart-types.md b/.changeset/dataset-widget-real-chart-types.md new file mode 100644 index 0000000000..03ab9685a7 --- /dev/null +++ b/.changeset/dataset-widget-real-chart-types.md @@ -0,0 +1,15 @@ +--- +"@object-ui/plugin-dashboard": minor +--- + +Dataset-bound dashboard widgets now render their TRUE chart family instead of +always a bar chart. + +`DatasetWidget` routes by `widget.type` to the shared advanced chart renderer: +pie/donut/line/area/scatter/radar/funnel/treemap/sankey/column/horizontal-bar +each draw distinctly (one series per measure, carrying the measure label). +`table`/`pivot` render a grouped table of dimensions + measures (formatted via +the measure `format`). `metric`/`kpi`/`gauge`/`solid-gauge`/`bullet` keep the +single-value KPI rendering. Families without a distinct renderer map to their +closest relative (e.g. `spline`→line, `stacked-area`→area, `pyramid`→funnel) so +a widget never renders as a silently-wrong bar. diff --git a/packages/plugin-dashboard/src/DatasetWidget.tsx b/packages/plugin-dashboard/src/DatasetWidget.tsx index 779a55920e..8bf3393f81 100644 --- a/packages/plugin-dashboard/src/DatasetWidget.tsx +++ b/packages/plugin-dashboard/src/DatasetWidget.tsx @@ -106,7 +106,9 @@ export function DatasetWidget({ widget, dataSource }: { widget: any; dataSource: // requires a timeDimension". Only pass the structured form; drop the legacy // string (the base measure still renders; the comparison overlay is opt-in). const compareTo = widget?.compareTo && typeof widget.compareTo === 'object' ? widget.compareTo : undefined; - const isMetric = widget?.type === 'metric' || dimensions.length === 0; + const widgetType = String(widget?.type ?? ''); + const isMetric = METRIC_TYPES.has(widgetType) || dimensions.length === 0; + const isTable = widgetType === 'table' || widgetType === 'pivot'; // ADR-0021 dual-form: the widget's presentation-scope `filter` must flow into // the dataset query as `runtimeFilter`, or a dataset-bound widget renders the @@ -182,18 +184,44 @@ export function DatasetWidget({ widget, dataSource }: { widget: any; dataSource: ); } - // Chart — bar chart of the first measure over the first dimension, via the - // shared chart registry (`bar-chart`). Remap the measure column to its display - // label so the legend/tooltip read "Tasks" rather than "task_count". - const measureLabel = measureField(values[0])?.label; - const dataKey = measureLabel && measureLabel !== values[0] ? measureLabel : values[0]; - const chartRows = dataKey === values[0] - ? state.rows - : state.rows.map((r) => ({ ...r, [dataKey]: r[values[0]] })); + // Table / pivot — a grouped table of the selected dimensions + measures. + if (isTable) { + const columns = [...dimensions, ...values]; + return ( +
+ + + + {columns.map((c) => ( + + ))} + + + + {state.rows.map((row, i) => ( + + {columns.map((c) => ( + + ))} + + ))} + +
{measureField(c)?.label ?? c}
+ {values.includes(c) ? formatMeasure(row[c], measureField(c)?.format) : formatValue(row[c])} +
+
+ ); + } + + // Chart — route to the advanced renderer with the widget's TRUE chart family + // and one series per measure. Series carry the measure display label so the + // legend reads "Tasks" rather than "task_count". + const chartType = CHART_TYPE_MAP[widgetType] ?? 'bar'; + const series = values.map((v) => ({ dataKey: v, label: measureField(v)?.label ?? v })); return (
);