Skip to content

Commit f0b1c8b

Browse files
Copilothotlong
andcommitted
fix: adapt examples to v3.0.10 protocol (widget id + ViewFilterRule format)
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 4ccb58a commit f0b1c8b

File tree

10 files changed

+57
-10
lines changed

10 files changed

+57
-10
lines changed

ROADMAP.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# ObjectUI Development Roadmap
22

3-
> **Last Updated:** February 24, 2026
3+
> **Last Updated:** February 25, 2026
44
> **Current Version:** v0.5.x
5-
> **Spec Version:** @objectstack/spec v3.0.9
6-
> **Client Version:** @objectstack/client v3.0.9
5+
> **Spec Version:** @objectstack/spec v3.0.10
6+
> **Client Version:** @objectstack/client v3.0.10
77
> **Target UX Benchmark:** 🎯 Airtable parity
88
> **Current Priority:** AppShell Navigation · Designer Interaction · View Config Live Preview Sync · Dashboard Config Panel · Airtable UX Polish · **Flow Designer ✅** · **App Creation & Editing Flow ✅** · **System Settings & App Management ✅** · **Right-Side Visual Editor Drawer ✅**
99
@@ -49,6 +49,28 @@ ObjectUI is a universal Server-Driven UI (SDUI) engine built on React + Tailwind
4949

5050
---
5151

52+
## 🔄 Spec v3.0.10 Upgrade Summary
53+
54+
> Upgraded from `@objectstack/spec v3.0.9``v3.0.10` on February 25, 2026. UI sub-export adds new Zod schemas and `ViewFilterRule` type. Dashboard widgets now require `id` field. View filters must use object format.
55+
56+
**New Protocol Capabilities (v3.0.10):**
57+
58+
| Area | What's New | Impact on ObjectUI |
59+
|------|------------|-------------------|
60+
| **UI Schemas** | `DensityModeSchema`, `ThemeModeSchema`, `WcagContrastLevelSchema` Zod schemas | Re-exported from `@object-ui/types` for runtime validation |
61+
| **View Filter Rules** | `ViewFilterRule`, `ViewFilterRuleSchema` — structured filter format `{ field, operator, value }` | All view filters migrated from tuple `['field', '=', 'value']` to object format |
62+
| **Dashboard Widgets** | `id` field now required on `DashboardWidgetSchema` | All example dashboard widgets updated with explicit `id` |
63+
| **Filter AST** | `isFilterAST`, `parseFilterAST`, `VALID_AST_OPERATORS` in data sub-export | Filter engine utilities (P2.4) |
64+
| **Multi-Tenant** | `TursoMultiTenantConfig`, `TenantResolverStrategy`, `TenantDatabaseLifecycle` | Cloud multi-tenancy (P2.4) |
65+
| **Contracts** | `IAppLifecycleService`, `IDeployPipelineService`, `IProvisioningService`, `ITenantRouter`, `ISchemaDiffService` | Cloud deployment & lifecycle (P2.4) |
66+
67+
**Breaking Changes Applied:**
68+
- All CRM view filters converted from `['field', '=', 'value']` to `[{ field, operator: '=', value }]`
69+
- All dashboard widgets (kitchen-sink, todo, CRM) given explicit `id` fields
70+
- Todo active filter converted from `[['status', '!=', 'Done']]` to `[{ field: 'status', operator: '!=', value: 'Done' }]`
71+
72+
---
73+
5274
## 🎯 P0 — Must Ship (v1.0 Blockers)
5375

5476
### P0.1 AppShell & Navigation Renderer

examples/crm/src/dashboards/crm.dashboard.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const CrmDashboard = {
55
widgets: [
66
// --- KPI Row ---
77
{
8+
id: 'total_revenue',
89
title: 'Total Revenue',
910
type: 'metric' as const,
1011
object: 'opportunity',
@@ -17,6 +18,7 @@ export const CrmDashboard = {
1718
}
1819
},
1920
{
21+
id: 'active_deals',
2022
title: 'Active Deals',
2123
type: 'metric' as const,
2224
object: 'opportunity',
@@ -29,6 +31,7 @@ export const CrmDashboard = {
2931
}
3032
},
3133
{
34+
id: 'win_rate',
3235
title: 'Win Rate',
3336
type: 'metric' as const,
3437
object: 'opportunity',
@@ -41,6 +44,7 @@ export const CrmDashboard = {
4144
}
4245
},
4346
{
47+
id: 'avg_deal_size',
4448
title: 'Avg Deal Size',
4549
type: 'metric' as const,
4650
object: 'opportunity',
@@ -55,6 +59,7 @@ export const CrmDashboard = {
5559

5660
// --- Row 2: Charts (provider: 'object' — dynamic aggregation) ---
5761
{
62+
id: 'revenue_trends',
5863
title: 'Revenue Trends',
5964
type: 'area' as const,
6065
object: 'opportunity',
@@ -73,6 +78,7 @@ export const CrmDashboard = {
7378
},
7479
},
7580
{
81+
id: 'lead_source',
7682
title: 'Lead Source',
7783
type: 'donut' as const,
7884
object: 'opportunity',
@@ -93,6 +99,7 @@ export const CrmDashboard = {
9399

94100
// --- Row 3: More Charts (provider: 'object' — dynamic aggregation) ---
95101
{
102+
id: 'pipeline_by_stage',
96103
title: 'Pipeline by Stage',
97104
type: 'bar' as const,
98105
object: 'opportunity',
@@ -111,6 +118,7 @@ export const CrmDashboard = {
111118
},
112119
},
113120
{
121+
id: 'top_products',
114122
title: 'Top Products',
115123
type: 'bar' as const,
116124
object: 'product',
@@ -131,6 +139,7 @@ export const CrmDashboard = {
131139

132140
// --- Row 4: Table (provider: 'object' — dynamic data) ---
133141
{
142+
id: 'recent_opportunities',
134143
title: 'Recent Opportunities',
135144
type: 'table' as const,
136145
object: 'opportunity',
@@ -151,6 +160,7 @@ export const CrmDashboard = {
151160

152161
// --- Row 5: Dynamic KPI from Object Data ---
153162
{
163+
id: 'revenue_by_account',
154164
title: 'Revenue by Account',
155165
type: 'bar' as const,
156166
object: 'opportunity',
@@ -171,6 +181,7 @@ export const CrmDashboard = {
171181

172182
// --- Row 6: Additional aggregate functions (avg, max) + cross-object ---
173183
{
184+
id: 'avg_deal_by_stage',
174185
title: 'Avg Deal Size by Stage',
175186
type: 'line' as const,
176187
object: 'opportunity',
@@ -189,6 +200,7 @@ export const CrmDashboard = {
189200
},
190201
},
191202
{
203+
id: 'orders_by_status',
192204
title: 'Orders by Status',
193205
type: 'bar' as const,
194206
object: 'order',

examples/crm/src/views/account.view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const AccountView = {
1414
type: 'grid' as const,
1515
data: { provider: 'object' as const, object: 'account' },
1616
columns: ['name', 'industry', 'annual_revenue', 'phone', 'owner'],
17-
filter: ['type', '=', 'Customer'],
17+
filter: [{ field: 'type', operator: '=', value: 'Customer' }],
1818
sort: [{ field: 'annual_revenue', order: 'desc' as const }],
1919
},
2020
},

examples/crm/src/views/contact.view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const ContactView = {
1414
type: 'grid' as const,
1515
data: { provider: 'object' as const, object: 'contact' },
1616
columns: ['name', 'email', 'title', 'account', 'status'],
17-
filter: ['is_active', '=', true],
17+
filter: [{ field: 'is_active', operator: '=', value: true }],
1818
},
1919
},
2020
form: {

examples/crm/src/views/event.view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const EventView = {
2626
type: 'grid' as const,
2727
data: { provider: 'object' as const, object: 'event' },
2828
columns: ['subject', 'start', 'location', 'organizer'],
29-
filter: ['type', '=', 'meeting'],
29+
filter: [{ field: 'type', operator: '=', value: 'meeting' }],
3030
sort: [{ field: 'start', order: 'asc' as const }],
3131
},
3232
},

examples/crm/src/views/order.view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const OrderView = {
1414
type: 'grid' as const,
1515
data: { provider: 'object' as const, object: 'order' },
1616
columns: ['name', 'customer', 'amount', 'order_date'],
17-
filter: ['status', '=', 'pending'],
17+
filter: [{ field: 'status', operator: '=', value: 'pending' }],
1818
},
1919
},
2020
form: {

examples/crm/src/views/product.view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export const ProductView = {
3939
{ field: 'stock', label: 'STOCK', type: 'number' as const, width: 80, align: 'right' as const },
4040
{ field: 'tags', label: 'TAGS', type: 'select' as const, width: 130 },
4141
],
42-
filter: ['is_active', '=', true],
42+
filter: [{ field: 'is_active', operator: '=', value: true }],
4343
rowHeight: 'short' as const,
4444
},
4545
},

examples/crm/src/views/user.view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const UserView = {
1414
type: 'grid' as const,
1515
data: { provider: 'object' as const, object: 'user' },
1616
columns: ['name', 'email', 'role', 'title'],
17-
filter: ['active', '=', true],
17+
filter: [{ field: 'active', operator: '=', value: true }],
1818
},
1919
},
2020
form: {

examples/kitchen-sink/objectstack.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export default defineStack({
110110
widgets: [
111111
// --- KPI Row ---
112112
{
113+
id: 'total_records',
113114
title: 'Total Records',
114115
type: 'metric',
115116
object: 'kitchen_sink',
@@ -121,6 +122,7 @@ export default defineStack({
121122
},
122123
},
123124
{
125+
id: 'active_items',
124126
title: 'Active Items',
125127
type: 'metric',
126128
object: 'kitchen_sink',
@@ -133,6 +135,7 @@ export default defineStack({
133135
},
134136
},
135137
{
138+
id: 'total_value',
136139
title: 'Total Value',
137140
type: 'metric',
138141
object: 'kitchen_sink',
@@ -145,6 +148,7 @@ export default defineStack({
145148
},
146149
},
147150
{
151+
id: 'avg_rating',
148152
title: 'Avg Rating',
149153
type: 'metric',
150154
object: 'kitchen_sink',
@@ -159,6 +163,7 @@ export default defineStack({
159163

160164
// --- Charts Row ---
161165
{
166+
id: 'records_by_category',
162167
title: 'Records by Category',
163168
type: 'donut',
164169
object: 'kitchen_sink',
@@ -180,6 +185,7 @@ export default defineStack({
180185
},
181186
},
182187
{
188+
id: 'value_distribution',
183189
title: 'Value Distribution',
184190
type: 'bar',
185191
object: 'kitchen_sink',
@@ -205,6 +211,7 @@ export default defineStack({
205211

206212
// --- Trend Row ---
207213
{
214+
id: 'monthly_trend',
208215
title: 'Monthly Trend',
209216
type: 'area',
210217
object: 'kitchen_sink',

examples/todo/objectstack.config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export default defineStack({
4949
type: 'grid',
5050
data: { provider: 'object', object: 'todo_task' },
5151
columns: ['subject', 'status', 'priority', 'assignee', 'due_date'],
52-
filter: [['status', '!=', 'Done']],
52+
filter: [{ field: 'status', operator: '!=', value: 'Done' }],
5353
sort: [{ field: 'priority', order: 'asc' }],
5454
},
5555
},
@@ -112,6 +112,7 @@ export default defineStack({
112112
description: 'Task metrics, status distribution, and category breakdown',
113113
widgets: [
114114
{
115+
id: 'total_tasks',
115116
title: 'Total Tasks',
116117
type: 'metric',
117118
object: 'todo_task',
@@ -123,6 +124,7 @@ export default defineStack({
123124
},
124125
},
125126
{
127+
id: 'in_progress',
126128
title: 'In Progress',
127129
type: 'metric',
128130
object: 'todo_task',
@@ -135,6 +137,7 @@ export default defineStack({
135137
},
136138
},
137139
{
140+
id: 'completed',
138141
title: 'Completed',
139142
type: 'metric',
140143
object: 'todo_task',
@@ -147,6 +150,7 @@ export default defineStack({
147150
},
148151
},
149152
{
153+
id: 'overdue',
150154
title: 'Overdue',
151155
type: 'metric',
152156
object: 'todo_task',
@@ -159,6 +163,7 @@ export default defineStack({
159163
},
160164
},
161165
{
166+
id: 'tasks_by_status',
162167
title: 'Tasks by Status',
163168
type: 'donut',
164169
object: 'todo_task',
@@ -182,6 +187,7 @@ export default defineStack({
182187
},
183188
},
184189
{
190+
id: 'tasks_by_category',
185191
title: 'Tasks by Category',
186192
type: 'bar',
187193
object: 'todo_task',

0 commit comments

Comments
 (0)