Skip to content

Commit 4b8ac8e

Browse files
authored
Merge pull request #1162 from objectstack-ai/copilot/fix-charts-rendering-issue
2 parents 4e87b80 + 70cb62b commit 4b8ac8e

3 files changed

Lines changed: 55 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Fixed
1111

12-
- **Analytics aggregate measures format** (`@object-ui/data-objectstack`): Fixed `aggregate()` method to send `measures` as string array (`['amount_sum']`, `['count']`) instead of object array (`[{ field, function }]`). The backend `MemoryAnalyticsService.resolveMeasure()` expects strings and calls `.split('.')`, causing `TypeError: t.split is not a function` when receiving objects. Also fixed `dimensions` to send an empty array when `groupBy` is `'_all'` (single-bucket aggregation), and added response mapping to rename measure keys (e.g. `amount_sum`) back to the original field name (`amount`) for consumer compatibility.
12+
- **Analytics aggregate measures format** (`@object-ui/data-objectstack`): Fixed `aggregate()` method to send `measures` as string array (`['amount_sum']`, `['count']`) instead of object array (`[{ field, function }]`). The backend `MemoryAnalyticsService.resolveMeasure()` expects strings and calls `.split('.')`, causing `TypeError: t.split is not a function` when receiving objects. Also fixed `dimensions` to send an empty array when `groupBy` is `'_all'` (single-bucket aggregation), and added response mapping to rename measure keys (e.g. `amount_sum`) back to the original field name (`amount`) for consumer compatibility. Additionally fixed chart rendering blank issue: the `rawRows` extraction now handles the `{ rows: [...] }` envelope (when the SDK unwraps the outer `{ success, data }` wrapper) and the `{ data: { rows: [...] } }` envelope (when the SDK returns the full response), matching the actual shape returned by the analytics API (`/api/v1/analytics/query`).
1313
- **Fields SSR build** (`@object-ui/fields`): Added `@object-ui/i18n` to Vite `external` in `vite.config.ts` and converted to regex-based externalization pattern (consistent with `@object-ui/components`) to prevent `react-i18next` CJS code from being bundled. Fixes `"dynamic usage of require is not supported"` error during Next.js SSR prerendering of `/docs/components/basic/text`.
1414
- **Console build** (`@object-ui/console`): Added missing `@object-ui/plugin-chatbot` devDependency that caused `TS2307: Cannot find module '@object-ui/plugin-chatbot'` during build.
1515
- **Site SSR build** (`@object-ui/site`): Added `@object-ui/i18n` to `transpilePackages` in `next.config.mjs` to fix "dynamic usage of require is not supported" error when prerendering the tooltip docs page. The i18n package is a transitive dependency of `@object-ui/react` and its `react-i18next` dependency requires transpilation for Turbopack SSR compatibility.

packages/data-objectstack/src/aggregate.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,58 @@ describe('ObjectStackAdapter aggregate()', () => {
199199
]);
200200
});
201201

202+
it('should extract rows from { rows: [...] } envelope (SDK unwraps outer success/data)', async () => {
203+
mockAnalyticsQuery.mockResolvedValue({
204+
rows: [
205+
{ stage: 'closed_won', expected_revenue_sum: 225000 },
206+
{ stage: 'negotiation', expected_revenue_sum: 36000 },
207+
],
208+
fields: [
209+
{ name: 'stage', type: 'string' },
210+
{ name: 'expected_revenue_sum', type: 'number' },
211+
],
212+
});
213+
214+
const result = await adapter.aggregate('opportunity', {
215+
field: 'expected_revenue',
216+
function: 'sum',
217+
groupBy: 'stage',
218+
});
219+
220+
expect(result).toEqual([
221+
{ stage: 'closed_won', expected_revenue: 225000 },
222+
{ stage: 'negotiation', expected_revenue: 36000 },
223+
]);
224+
});
225+
226+
it('should extract rows from { data: { rows: [...] } } envelope (SDK does not unwrap)', async () => {
227+
mockAnalyticsQuery.mockResolvedValue({
228+
success: true,
229+
data: {
230+
rows: [
231+
{ stage: 'closed_won', expected_revenue_sum: 225000 },
232+
{ stage: 'negotiation', expected_revenue_sum: 36000 },
233+
],
234+
fields: [
235+
{ name: 'stage', type: 'string' },
236+
{ name: 'expected_revenue_sum', type: 'number' },
237+
],
238+
sql: '-- MongoDB Aggregation Pipeline',
239+
},
240+
});
241+
242+
const result = await adapter.aggregate('opportunity', {
243+
field: 'expected_revenue',
244+
function: 'sum',
245+
groupBy: 'stage',
246+
});
247+
248+
expect(result).toEqual([
249+
{ stage: 'closed_won', expected_revenue: 225000 },
250+
{ stage: 'negotiation', expected_revenue: 36000 },
251+
]);
252+
});
253+
202254
it('should fall back to client-side aggregation when analytics endpoint fails', async () => {
203255
mockAnalyticsQuery.mockRejectedValue(new Error('Analytics not available'));
204256

packages/data-objectstack/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,9 @@ export class ObjectStackAdapter<T = unknown> implements DataSource<T> {
849849

850850
const data = await this.client.analytics.query(payload);
851851
const rawRows: any[] = Array.isArray(data) ? data
852+
: data?.rows && Array.isArray(data.rows) ? data.rows
852853
: data?.data && Array.isArray(data.data) ? data.data
854+
: data?.data?.rows && Array.isArray(data.data.rows) ? data.data.rows
853855
: data?.results && Array.isArray(data.results) ? data.results
854856
: [];
855857

0 commit comments

Comments
 (0)