Skip to content

fix: Dashboard widgets with provider: 'object' render blank — delegate to ObjectChart with client-side aggregation#830

Merged
hotlong merged 3 commits intomainfrom
copilot/fix-dashboard-widget-issue
Feb 24, 2026
Merged

fix: Dashboard widgets with provider: 'object' render blank — delegate to ObjectChart with client-side aggregation#830
hotlong merged 3 commits intomainfrom
copilot/fix-dashboard-widget-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 24, 2026

DashboardRenderer.getComponentSchema() only extracts widgetData?.items || [] for chart/table/pivot widgets. When provider: 'object', the data config is { provider: 'object', object: 'opportunity', aggregate: {...} } — no items property exists, so charts always receive [] and render blank.

Changes

  • DashboardRenderer.tsx — Add isObjectProvider() type guard. For chart widgets with provider: 'object', emit type: 'object-chart' schema with objectName/aggregate passthrough instead of type: 'chart' with empty data: []. Same pattern for table and pivot widget types.

  • ObjectChart.tsx — Add aggregateRecords() for client-side groupBy + aggregation (sum/count/avg/min/max) applied after dataSource.find() when schema.aggregate is present.

  • Tests — 4 new DashboardRenderer.widgetData tests (chart, objectName fallback, table, pivot with provider: 'object'). 8 new aggregateRecords unit tests.

Example: before vs after schema generation

// Widget config (CRM "Revenue by Account")
{ type: 'bar', options: { data: { provider: 'object', object: 'opportunity',
    aggregate: { field: 'amount', function: 'sum', groupBy: 'account' } } } }

// Before: getComponentSchema() produced
{ type: 'chart', chartType: 'bar', data: [] }  // ← always blank

// After: getComponentSchema() produces
{ type: 'object-chart', chartType: 'bar',
  objectName: 'opportunity',
  aggregate: { field: 'amount', function: 'sum', groupBy: 'account' } }
Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug] Dashboard 图表不支持 provider: 'object',导致动态聚合类 widget 均显示空白</issue_title>
<issue_description># CRM Dashboard "Revenue by Account" 图表数据展示与 provider: 'object' 适配相关问题

主要问题描述

在 CRM Demo Dashboard(crm_dashboard)中,"Revenue by Account" 这一 widget 采用了 provider: 'object' 或聚合对象数据(如:sum by account),但在页面中始终无法显示任何数据,呈现空白。

经过源码排查,发现存在如下核心问题:

1. DashboardRenderer 只支持 provider: 'value' 的静态/演示数据

代码位置:packages/plugin-dashboard/src/DashboardRenderer.tsx, getComponentSchema()

  • 当前的 getComponentSchema() 仅能识别:
    • widgetData 为数组(即硬编码数据)
    • widgetData.items(provider: 'value' 格式)
  • 对于 provider: 'object' 场景,dashboard 配置只会传递聚合描述对象(如 { provider: 'object', object: 'opportunity', aggregate: {...} }),而当前实现直接取 widgetData?.items || [],于是 chart 渲染始终接收到空数组,实际未启动过真正的数据查询,因此始终显示空白。

2. 未将 object provider 的 data schema 向下传递给 ObjectChart 等图表组件

  • DashboardRenderer 实际缺少对 provider: 'object' 的 schema 透传能力,导致如 ObjectChart 等异步数据组件没法根据配置自行请求并渲染数据。
  • demo 配置未能全流程走通"动态聚合数据→画图"这条链路。

3. 其他潜在相关问题

  • 代码内文档和 WidgetConfig 面板未明确当前聚合/动态数据 provider 的适配边界,易让开发和维护成员误以为 dashboard 已支持所有数据源类型,造成踩坑。
  • 其他有同样数据 provider 但非静态 items 的 widget 亦会出现该现象。
  • 当前 DashboardRenderer TESTS 未覆盖"对象聚合"真实数据流动场景。

建议修复方案

  1. DashboardRenderer 需识别 provider: 'object' 并将 Schema 透传
    • 由图表子组件(如 ObjectChart)负责根据 config.provider=object 配置异步加载并管理 loading/error 状态,DashboardRenderer 不再直接取 items 数组,而应透传整个 data 配置。
  2. 完善相关 Widget 的测试,覆盖 provider: 'object' 场景(含异步 mock 数据流动、渲染和出错态)。
  3. 完善文档和设计面板提示,避免使用者被静态 demo 迷惑。

问题复现和定位路径(for QA/dev)

  • 打开 https://demo.objectui.org/apps/crm_app/dashboard/crm_dashboard
  • 查看 "Revenue by Account" 图表,一直空白;Chrome F12 可见 DOM 下数据数组为空
  • 查看源码:examples/crm/src/dashboards/crm.dashboard.ts(最后一个widget配置)
  • 跟进 renderer:packages/plugin-dashboard/src/DashboardRenderer.tsx,getComponentSchema()

建议标签/类型

  • labels: plugin: charts, data-adapter, bug
  • type: Bug
    </issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui Ready Ready Preview, Comment Feb 24, 2026 10:18am
objectui-demo Ready Ready Preview, Comment Feb 24, 2026 10:18am
objectui-storybook Ready Ready Preview, Comment Feb 24, 2026 10:18am

Request Review

Copilot AI and others added 2 commits February 24, 2026 10:07
…elegation and client-side aggregation

- DashboardRenderer.getComponentSchema() now detects provider: 'object' and produces
  type: 'object-chart' schema with objectName/aggregate config instead of empty data[]
- Same pattern applied to table and pivot widget types (pass through dataProvider)
- ObjectChart.aggregateRecords() performs client-side sum/count/avg/min/max grouping
- Added 4 new DashboardRenderer tests (chart/fallback/table/pivot with provider: object)
- Added 8 new ObjectChart aggregation unit tests
- Updated ROADMAP.md

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…e review

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix dashboard widget not displaying data with provider 'object' fix: Dashboard widgets with provider: 'object' render blank — delegate to ObjectChart with client-side aggregation Feb 24, 2026
Copilot AI requested a review from hotlong February 24, 2026 10:13
@hotlong hotlong marked this pull request as ready for review February 24, 2026 10:15
Copilot AI review requested due to automatic review settings February 24, 2026 10:15
@hotlong hotlong merged commit b188e5f into main Feb 24, 2026
3 of 4 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a critical bug where dashboard widgets with provider: 'object' were rendering blank. The root cause was that DashboardRenderer.getComponentSchema() only extracted static data arrays (widgetData?.items || []) but didn't handle the async object provider pattern where data configuration includes provider metadata instead of actual data items.

Changes:

  • Added isObjectProvider() type guard and delegation logic in DashboardRenderer to route object provider widgets to async-capable components (object-chart for charts, data-table and pivot with dataProvider passthrough)
  • Implemented aggregateRecords() in ObjectChart for client-side aggregation (sum/count/avg/min/max by groupBy field) when server-side aggregation isn't available
  • Added comprehensive test coverage (4 DashboardRenderer tests, 8 aggregateRecords unit tests) validating the new data flow

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/plugin-dashboard/src/DashboardRenderer.tsx Added isObjectProvider() helper and conditional logic in getComponentSchema() to detect provider: 'object' and delegate to type: 'object-chart' for charts, type: 'data-table' with dataProvider for tables, and type: 'pivot' with dataProvider for pivot widgets, passing through objectName and aggregate config instead of empty data arrays
packages/plugin-charts/src/ObjectChart.tsx Added aggregateRecords() function for client-side groupBy + aggregation (sum/count/avg/min/max) and integrated it into the data fetch flow when schema.aggregate is present; updated useEffect dependency array to include schema.aggregate; added aggregate field to ComponentRegistry metadata
packages/plugin-dashboard/src/tests/DashboardRenderer.widgetData.test.tsx Added 4 new tests validating object provider handling: chart with aggregate, objectName fallback from widget.object, table with provider:object, pivot with provider:object
packages/plugin-charts/src/tests/ObjectChart.aggregation.test.ts Added 8 comprehensive unit tests for aggregateRecords covering all aggregation functions (sum/count/avg/min/max), edge cases (missing groupBy field, empty records, non-numeric values)
ROADMAP.md Updated P2: Dashboard Dynamic Data entry to reflect completion with implementation details

Comment on lines +12 to +50
export function aggregateRecords(
records: any[],
aggregate: { field: string; function: string; groupBy: string }
): any[] {
const { field, function: aggFn, groupBy } = aggregate;
const groups: Record<string, any[]> = {};

for (const record of records) {
const key = String(record[groupBy] ?? 'Unknown');
if (!groups[key]) groups[key] = [];
groups[key].push(record);
}

return Object.entries(groups).map(([key, group]) => {
const values = group.map(r => Number(r[field]) || 0);
let result: number;

switch (aggFn) {
case 'count':
result = group.length;
break;
case 'avg':
result = values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0;
break;
case 'min':
result = values.length > 0 ? Math.min(...values) : 0;
break;
case 'max':
result = values.length > 0 ? Math.max(...values) : 0;
break;
case 'sum':
default:
result = values.reduce((a, b) => a + b, 0);
break;
}

return { [groupBy]: key, [field]: result };
});
}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding JSDoc type annotations for better type safety and IDE support. The aggregate parameter should be typed more strictly to match the expected shape with literal types for the function field (e.g., 'sum' | 'count' | 'avg' | 'min' | 'max'). This would prevent typos and provide better autocomplete support.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Dashboard 图表不支持 provider: 'object',导致动态聚合类 widget 均显示空白

3 participants