From 028ad35533474594abf29f68e8e5bedac5e5160b Mon Sep 17 00:00:00 2001 From: Jack Date: Sun, 7 Jun 2026 19:17:27 +0800 Subject: [PATCH] feat(plugin-dashboard): render dataset-bound widgets (ADR-0021 B-P1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A dashboard widget that binds a semantic-layer `dataset` (instead of an inline `object`+`valueField` query) now renders via the governed queryDataset path: new DatasetWidget fetches `dataSource.queryDataset(dataset, {dimensions, measures: values, compareTo})` and renders a KPI value (metric) or a bar chart (dimensioned) — numbers match the dataset everywhere. DashboardRenderer branches to it when `widget.dataset` is set (early, before the object-aggregate path), at both render sites. Additive/dual-form: inline widgets unchanged. Errors surface instead of wrong/empty numbers. Widget fields read via `(widget as any)` until objectui bumps @objectstack/spec (the bundled DashboardWidget type gains dataset/dimensions/values then). Tests: DatasetWidget (6) — KPI value, chart query mapping, compareTo forwarding, error surfacing, no-dataset-support guard, no-measures prompt. Pairs with framework dashboard.zod dual-form. Co-Authored-By: Claude Opus 4.8 --- .../src/DashboardRenderer.tsx | 15 ++- .../plugin-dashboard/src/DatasetWidget.tsx | 98 +++++++++++++++++++ .../src/__tests__/DatasetWidget.test.tsx | 48 +++++++++ 3 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 packages/plugin-dashboard/src/DatasetWidget.tsx create mode 100644 packages/plugin-dashboard/src/__tests__/DatasetWidget.test.tsx diff --git a/packages/plugin-dashboard/src/DashboardRenderer.tsx b/packages/plugin-dashboard/src/DashboardRenderer.tsx index bc6bc277f..0485cb98b 100644 --- a/packages/plugin-dashboard/src/DashboardRenderer.tsx +++ b/packages/plugin-dashboard/src/DashboardRenderer.tsx @@ -30,6 +30,7 @@ import { } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { isObjectProvider } from './utils'; +import { DatasetWidget } from './DatasetWidget'; interface SortableWidgetWrapperProps { id: string; @@ -402,6 +403,12 @@ export const DashboardRenderer = forwardRef { if (widget.component) return widget.component; @@ -786,7 +793,9 @@ export const DashboardRenderer = forwardRef - + {datasetBound + ?
+ : } {designMode && ) : ( @@ -813,7 +822,9 @@ export const DashboardRenderer = forwardRef
- + {datasetBound + ? + : }
{designMode &&