Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- **CI build errors** (`@object-ui/console`): Removed unused imports (`resolveI18nLabel` in `HomePage.tsx`, `Upload`/`FileText` in `QuickActions.tsx`) that caused TS6133 errors. Fixed `appConfig` → `appConfigs[0]` in `i18n-translations.test.ts` (TS2552). Extracted `customReportsConfig` from aggregated `sharedConfig` into a standalone export so the mock server kernel includes the `sales_performance_q1` report, fixing `ReportView.test.tsx` failures.

- **Charts groupBy value→label resolution** (`@object-ui/plugin-charts`): Chart X-axis labels now display human-readable labels instead of raw values. Select/picklist fields resolve value→label via field metadata options, lookup/master_detail fields batch-fetch referenced record names, and all other fields fall back to `humanizeLabel()` (snake_case → Title Case). Removed hardcoded `value.slice(0, 3)` truncation from `AdvancedChartImpl.tsx` XAxis tick formatters — desktop now shows full labels with angle rotation for long text, mobile truncates at 8 characters with "…".

- **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`).
Expand Down
39 changes: 26 additions & 13 deletions apps/console/objectstack.shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,31 @@ export const setupAppConfig = {
manifest: { id: 'setup', name: 'setup' },
};

/**
* Additional reports that are not part of any individual app config.
* Loaded as a separate AppPlugin instance by the mock server (server.ts)
* and browser mock (browser.ts) so that these reports appear in the
* kernel's metadata alongside the app-specific reports.
*/
Comment on lines +54 to +59
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

customReportsConfig is only appended to the MSW/mock kernels (src/mocks/server.ts + src/mocks/browser.ts). In server mode, apps/console/objectstack.config.ts registers metadata via per-config new AppPlugin(config) for appConfigs and setupAppConfig only, so sales_performance_q1 may still be missing when running pnpm start (and the CRM navigation link will lead to “Report Not Found”). Consider also loading customReportsConfig in server mode (e.g., add new AppPlugin(customReportsConfig) there or fold it into the exported appConfigs list).

Copilot uses AI. Check for mistakes.
export const customReportsConfig = {
reports: [
{
name: 'sales_performance_q1',
label: 'Q1 Sales Performance',
description: 'Quarterly analysis of sales revenue by region and product line',
objectName: 'opportunity',
type: 'summary',
columns: [
{ field: 'name', label: 'Deal Name' },
{ field: 'amount', label: 'Amount', aggregate: 'sum' },
{ field: 'stage', label: 'Stage' },
{ field: 'close_date', label: 'Close Date' }
]
}
],
manifest: { id: 'reports', name: 'reports' },
};

// Patch CRM App Navigation to include Report using a supported navigation type
const apps = [
...JSON.parse(JSON.stringify(appConfigs.flatMap((c: any) => c.apps || []))),
Expand Down Expand Up @@ -92,19 +117,7 @@ export const sharedConfig = {
dashboards: appConfigs.flatMap((c: any) => c.dashboards || []),
reports: [
...appConfigs.flatMap((c: any) => c.reports || []),
{
name: 'sales_performance_q1',
label: 'Q1 Sales Performance',
description: 'Quarterly analysis of sales revenue by region and product line',
objectName: 'opportunity',
type: 'summary',
columns: [
{ field: 'name', label: 'Deal Name' },
{ field: 'amount', label: 'Amount', aggregate: 'sum' },
{ field: 'stage', label: 'Stage' },
{ field: 'close_date', label: 'Close Date' }
]
}
...customReportsConfig.reports,
],
pages: appConfigs.flatMap((c: any) => c.pages || []),
manifest: {
Expand Down
4 changes: 2 additions & 2 deletions apps/console/src/__tests__/i18n-translations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe('i18n translations pipeline', () => {
});

it('appConfig.translations is spec-format array for AppPlugin', () => {
const translations = (appConfig as any).translations;
const translations = (appConfigs[0] as any).translations;

expect(Array.isArray(translations)).toBe(true);
expect(translations.length).toBeGreaterThan(0);
Expand All @@ -162,7 +162,7 @@ describe('i18n translations pipeline', () => {
const svc = createMemoryI18n();

// Simulate AppPlugin.loadTranslations() iterating the spec-format translations array
const translations = (appConfig as any).translations;
const translations = (appConfigs[0] as any).translations;
for (const bundle of translations) {
for (const [locale, data] of Object.entries(bundle)) {
if (data && typeof data === 'object') {
Expand Down
4 changes: 2 additions & 2 deletions apps/console/src/mocks/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { setupWorker } from 'msw/browser';
import { ObjectKernel } from '@objectstack/runtime';
import { InMemoryDriver } from '@objectstack/driver-memory';
import type { MSWPlugin } from '@objectstack/plugin-msw';
import { appConfigs, setupAppConfig } from '../../objectstack.shared';
import { appConfigs, setupAppConfig, customReportsConfig } from '../../objectstack.shared';
import { createKernel } from './createKernel';
import { createAuthHandlers } from './authHandlers';

Expand All @@ -43,7 +43,7 @@ export async function startMockServer() {
if (import.meta.env.DEV) console.log('[MSW] Starting ObjectStack Runtime (Browser Mode)...');

const result = await createKernel({
appConfigs: [...appConfigs, setupAppConfig],
appConfigs: [...appConfigs, setupAppConfig, customReportsConfig],
mswOptions: {
enableBrowser: false,
baseUrl: '/api/v1',
Expand Down
4 changes: 2 additions & 2 deletions apps/console/src/mocks/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { ObjectKernel } from '@objectstack/runtime';
import { InMemoryDriver } from '@objectstack/driver-memory';
import { setupServer } from 'msw/node';
import type { MSWPlugin } from '@objectstack/plugin-msw';
import { appConfigs, setupAppConfig } from '../../objectstack.shared';
import { appConfigs, setupAppConfig, customReportsConfig } from '../../objectstack.shared';
import { createKernel } from './createKernel';
import { createAuthHandlers } from './authHandlers';

Expand All @@ -34,7 +34,7 @@ export async function startMockServer() {
console.log('[MSW] Starting ObjectStack Runtime (Test Mode)...');

const result = await createKernel({
appConfigs: [...appConfigs, setupAppConfig],
appConfigs: [...appConfigs, setupAppConfig, customReportsConfig],
persistence: false,
mswOptions: {
enableBrowser: false,
Expand Down
1 change: 0 additions & 1 deletion apps/console/src/pages/home/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { useMetadata } from '../../context/MetadataProvider';
import { useRecentItems } from '../../hooks/useRecentItems';
import { useFavorites } from '../../hooks/useFavorites';
import { useObjectTranslation } from '@object-ui/i18n';
import { resolveI18nLabel } from '../../utils';
import { QuickActions } from './QuickActions';
import { AppCard } from './AppCard';
import { RecentApps } from './RecentApps';
Expand Down
2 changes: 1 addition & 1 deletion apps/console/src/pages/home/QuickActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import { useNavigate } from 'react-router-dom';
import { useObjectTranslation } from '@object-ui/i18n';
import { Card, CardContent } from '@object-ui/components';
import { Plus, Upload, Settings, Database, FileText } from 'lucide-react';
import { Plus, Settings, Database } from 'lucide-react';
import { cn } from '@object-ui/components';

interface QuickAction {
Expand Down
Loading