Skip to content

Commit c92afa8

Browse files
Copilothotlong
andcommitted
refactor: address code review feedback - rename helpers, add docs and logging
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent a8c5c70 commit c92afa8

File tree

5 files changed

+19
-10
lines changed

5 files changed

+19
-10
lines changed

ROADMAP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,7 @@ The `FlowDesigner` is a canvas-based flow editor that bridges the gap between th
986986
- [x] **P1: Dashboard Widget Data Blank — useDataScope/dataSource Injection Fix** — Fixed root cause of dashboard widgets showing blank data with no server requests: `useDataScope(undefined)` was returning the full context `dataSource` (service adapter) instead of `undefined` when no bind path was given, causing ObjectChart and all data components (ObjectKanban, ObjectGallery, ObjectTimeline, ObjectGrid) to treat the adapter as pre-bound data and skip async fetching. Fixed `useDataScope` to return `undefined` when no path is provided. Also improved ObjectChart fault tolerance: uses `useContext` directly instead of `useSchemaContext` (no throw without provider), validates `dataSource.find` is callable before invoking. 14 new tests (7 useDataScope + 7 ObjectChart data fetch/fault tolerance).
987987
- [x] **P1: URL-Driven Debug/Developer Panel** — Universal debug mode activated via `?__debug` URL parameter (amis devtools-style). `@object-ui/core`: exported `DebugFlags`, `DebugCollector` (perf/expr/event data collection, tree-shakeable), `parseDebugFlags()`, enhanced `isDebugEnabled()` (URL → globalThis → env resolution, SSR-safe). `@object-ui/react`: `useDebugMode` hook with URL detection, Ctrl+Shift+D shortcut, manual toggle; `SchemaRendererContext` extended with `debugFlags`; `SchemaRenderer` injects `data-debug-type`/`data-debug-id` attrs + reports render perf to `DebugCollector` when debug enabled. `@object-ui/components`: floating `DebugPanel` with 7 built-in tabs (Schema, Data, Perf, Expr, Events, Registry, Flags), plugin-extensible via `extraTabs`. Console `MetadataInspector` auto-opens when `?__debug` detected. Fine-grained sub-flags: `?__debug_schema`, `?__debug_perf`, `?__debug_data`, `?__debug_expr`, `?__debug_events`, `?__debug_registry`. 48 new tests.
988988
- [x] **P1: Chart Widget Server-Side Aggregation** — Fixed chart widgets (bar/line/area/pie/donut/scatter) downloading all raw data and aggregating client-side. Added optional `aggregate()` method to `DataSource` interface (`AggregateParams`, `AggregateResult` types) enabling server-side grouping/aggregation via analytics API (e.g. `GET /api/v1/analytics/{resource}?category=…&metric=…&agg=…`). `ObjectChart` now prefers `dataSource.aggregate()` when available, falling back to `dataSource.find()` + client-side aggregation for backward compatibility. Implemented `aggregate()` in `ValueDataSource` (in-memory), `ApiDataSource` (HTTP), and `ObjectStackAdapter` (analytics API with client-side fallback). Only detail widgets (grid/table/list) continue to fetch full data. 9 new tests.
989+
- [x] **P1: Spec-Aligned CRM I18n** — Fixed CRM internationalization not taking effect on the console. Root cause: CRM metadata used plain string labels instead of spec-aligned `I18nLabel` objects. Fix: (1) Updated CRM app/dashboard/navigation metadata to use `I18nLabel` objects (`{ key, defaultValue }`) per spec. (2) Updated `NavigationItem` and `NavigationArea` types to support I18nLabel. (3) Added `resolveLabel()` helper in NavigationRenderer. (4) Updated `resolveI18nLabel()` to accept `t()` function for translation. (5) Added `loadLanguage` callback in I18nProvider for API-based translation loading. (6) Added `/api/v1/i18n/:lang` endpoint to mock server. Console contains zero CRM-specific code.
989990

990991
### Ecosystem & Marketplace
991992
- Plugin marketplace website with search, ratings, and install count

apps/console/src/main.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@ import '@object-ui/plugin-markdown';
3434
async function loadLanguage(lang: string): Promise<Record<string, unknown>> {
3535
try {
3636
const res = await fetch(`/api/v1/i18n/${lang}`);
37-
if (!res.ok) return {};
37+
if (!res.ok) {
38+
console.warn(`[i18n] Failed to load translations for '${lang}': HTTP ${res.status}`);
39+
return {};
40+
}
3841
return await res.json();
39-
} catch {
42+
} catch (err) {
43+
console.warn(`[i18n] Failed to load translations for '${lang}':`, err);
4044
return {};
4145
}
4246
}

apps/console/src/mocks/browser.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ let driver: InMemoryDriver | null = null;
2121
let mswPlugin: MSWPlugin | null = null;
2222

2323
/**
24-
* Lazy-load CRM locale bundles for the i18n API endpoint.
24+
* Load application-specific locale bundles for the i18n API endpoint.
25+
* In this mock environment, loads translations from installed example packages.
2526
* Returns a flat translation resource for the given language code.
2627
*/
27-
async function loadCrmLocale(lang: string): Promise<Record<string, unknown>> {
28+
async function loadAppLocale(lang: string): Promise<Record<string, unknown>> {
2829
try {
2930
const { crmLocales } = await import('@object-ui/example-crm');
3031
const translations = (crmLocales as Record<string, any>)[lang];
3132
if (!translations) return {};
32-
// Nest under `crm.*` namespace so keys like `crm.navigation.dashboard` resolve
3333
return { crm: translations };
3434
} catch {
3535
return {};
@@ -63,7 +63,7 @@ export async function startMockServer() {
6363
// Serve i18n translation bundles via API
6464
http.get('/api/v1/i18n/:lang', async ({ params }) => {
6565
const lang = params.lang as string;
66-
const resources = await loadCrmLocale(lang);
66+
const resources = await loadAppLocale(lang);
6767
return HttpResponse.json(resources);
6868
}),
6969
],

apps/console/src/mocks/server.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ let mswPlugin: MSWPlugin | null = null;
2323
let server: ReturnType<typeof setupServer> | null = null;
2424

2525
/**
26-
* Lazy-load CRM locale bundles for the i18n API endpoint.
26+
* Load application-specific locale bundles for the i18n API endpoint.
27+
* In this mock environment, loads translations from installed example packages.
2728
*/
28-
async function loadCrmLocale(lang: string): Promise<Record<string, unknown>> {
29+
async function loadAppLocale(lang: string): Promise<Record<string, unknown>> {
2930
try {
3031
const { crmLocales } = await import('@object-ui/example-crm');
3132
const translations = (crmLocales as Record<string, any>)[lang];
@@ -53,7 +54,7 @@ export async function startMockServer() {
5354
customHandlers: [
5455
http.get('/api/v1/i18n/:lang', async ({ params }) => {
5556
const lang = params.lang as string;
56-
const resources = await loadCrmLocale(lang);
57+
const resources = await loadAppLocale(lang);
5758
return HttpResponse.json(resources);
5859
}),
5960
],

packages/layout/src/NavigationRenderer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ export function resolveIcon(name?: string): React.ComponentType<any> {
157157

158158
/**
159159
* Resolve a NavigationItem label to a plain string.
160-
* Supports both plain strings and I18nLabel objects { key, defaultValue }.
160+
* Handles both plain strings and I18nLabel objects { key, defaultValue }.
161+
* This is a basic client-side fallback resolver — actual i18n translation
162+
* is performed at the application level by passing labels through the
163+
* i18n `t()` function (e.g. via resolveI18nLabel in the console).
161164
*/
162165
export function resolveLabel(label: string | { key: string; defaultValue?: string; params?: Record<string, any> }): string {
163166
if (typeof label === 'string') return label;

0 commit comments

Comments
 (0)