Skip to content

Commit 8b93a0d

Browse files
authored
Merge pull request #832 from objectstack-ai/copilot/fix-view-components-ui-spec
2 parents 275fc86 + aec77d0 commit 8b93a0d

File tree

6 files changed

+48
-7
lines changed

6 files changed

+48
-7
lines changed

ROADMAP.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,13 @@ The `FlowDesigner` is a canvas-based flow editor that bridges the gap between th
755755
- [ ] Navigation `view` property: specify target form/view on record click across all plugins
756756
- [ ] Support App `engine` field (`{ objectstack: string }`) for version pinning (v3.0.9)
757757
- [ ] Integrate v3.0.9 package upgrade protocol (`PackageArtifact`, `ArtifactChecksum`, `UpgradeContext`)
758+
- [x] `@object-ui/types`: Align `ViewType` with spec ListView type enum — add `'gallery'` and `'gantt'` (was missing from `views.ts` and `views.zod.ts`)
759+
- [x] `@object-ui/types`: Sync `DetailViewFieldSchema` Zod validator with TS interface — add data-oriented field types (`number`, `currency`, `percent`, `boolean`, `select`, `lookup`, `master_detail`, `email`, `url`, `phone`, `user`) and missing properties (`options`, `reference_to`, `reference_field`, `currency`)
760+
- [x] `@object-ui/types`: Add `showBorder` and `headerColor` to `DetailViewSectionSchema` Zod validator (already in TS interface)
761+
- [x] `@object-ui/plugin-view`: Add `gallery` and `gantt` to ViewSwitcher default labels and icons
762+
- [x] `@object-ui/plugin-list`: Fix `list-view` and `list` registration `viewType` enum — remove invalid `'list'`/`'chart'`, add `'gallery'`/`'timeline'`/`'gantt'`/`'map'` to match spec
763+
- [x] `@object-ui/plugin-detail`: Add missing `detail-view` registration inputs (`layout`, `columns`, `loading`, `backUrl`, `editUrl`, `deleteConfirmation`, `header`, `footer`)
764+
- [x] `@object-ui/plugin-detail`: Add `showBorder` and `headerColor` inputs to `detail-section` registration
758765

759766
### P2.6 ListView Spec Protocol Gaps (Remaining) ✅
760767

packages/plugin-detail/src/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,22 @@ ComponentRegistry.register('detail-view', DetailView, {
6666
{ name: 'resourceId', type: 'string', label: 'Resource ID' },
6767
{ name: 'api', type: 'string', label: 'API Endpoint' },
6868
{ name: 'data', type: 'object', label: 'Data' },
69+
{ name: 'layout', type: 'enum', label: 'Layout Mode', enum: ['vertical', 'horizontal', 'grid'] },
70+
{ name: 'columns', type: 'number', label: 'Grid Columns' },
6971
{ name: 'sections', type: 'array', label: 'Sections' },
7072
{ name: 'fields', type: 'array', label: 'Fields' },
7173
{ name: 'tabs', type: 'array', label: 'Tabs' },
7274
{ name: 'related', type: 'array', label: 'Related Lists' },
7375
{ name: 'actions', type: 'array', label: 'Actions' },
7476
{ name: 'showBack', type: 'boolean', label: 'Show Back Button', defaultValue: true },
77+
{ name: 'backUrl', type: 'string', label: 'Back URL' },
7578
{ name: 'showEdit', type: 'boolean', label: 'Show Edit Button', defaultValue: false },
79+
{ name: 'editUrl', type: 'string', label: 'Edit URL' },
7680
{ name: 'showDelete', type: 'boolean', label: 'Show Delete Button', defaultValue: false },
81+
{ name: 'deleteConfirmation', type: 'string', label: 'Delete Confirmation Message' },
82+
{ name: 'loading', type: 'boolean', label: 'Show Loading State' },
83+
{ name: 'header', type: 'object', label: 'Custom Header' },
84+
{ name: 'footer', type: 'object', label: 'Custom Footer' },
7785
],
7886
defaultProps: {
7987
title: 'Detail View',
@@ -99,6 +107,8 @@ ComponentRegistry.register('detail-section', DetailSection, {
99107
{ name: 'collapsible', type: 'boolean', label: 'Collapsible', defaultValue: false },
100108
{ name: 'defaultCollapsed', type: 'boolean', label: 'Default Collapsed', defaultValue: false },
101109
{ name: 'columns', type: 'number', label: 'Columns', defaultValue: 2 },
110+
{ name: 'showBorder', type: 'boolean', label: 'Show Border', defaultValue: true },
111+
{ name: 'headerColor', type: 'string', label: 'Header Color' },
102112
],
103113
});
104114

packages/plugin-list/src/index.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ ComponentRegistry.register('list-view', ListView, {
3131
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
3232
{ name: 'viewType', type: 'enum', label: 'Default View', enum: [
3333
{ label: 'Grid', value: 'grid' },
34-
{ label: 'List', value: 'list' },
3534
{ label: 'Kanban', value: 'kanban' },
35+
{ label: 'Gallery', value: 'gallery' },
3636
{ label: 'Calendar', value: 'calendar' },
37-
{ label: 'Chart', value: 'chart' }
37+
{ label: 'Timeline', value: 'timeline' },
38+
{ label: 'Gantt', value: 'gantt' },
39+
{ label: 'Map', value: 'map' },
3840
], defaultValue: 'grid' },
3941
{ name: 'fields', type: 'array', label: 'Fields' },
4042
{ name: 'filters', type: 'array', label: 'Filters' },
@@ -61,10 +63,12 @@ ComponentRegistry.register('list', ListView, {
6163
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
6264
{ name: 'viewType', type: 'enum', label: 'Default View', enum: [
6365
{ label: 'Grid', value: 'grid' },
64-
{ label: 'List', value: 'list' },
6566
{ label: 'Kanban', value: 'kanban' },
67+
{ label: 'Gallery', value: 'gallery' },
6668
{ label: 'Calendar', value: 'calendar' },
67-
{ label: 'Chart', value: 'chart' }
69+
{ label: 'Timeline', value: 'timeline' },
70+
{ label: 'Gantt', value: 'gantt' },
71+
{ label: 'Map', value: 'map' },
6872
], defaultValue: 'grid' },
6973
{ name: 'fields', type: 'array', label: 'Fields' },
7074
{ name: 'filters', type: 'array', label: 'Filters' },

packages/plugin-view/src/ViewSwitcher.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ import {
2626
Activity,
2727
Calendar,
2828
FileText,
29+
GanttChartSquare,
2930
Grid,
31+
Images,
3032
LayoutGrid,
3133
List,
3234
Map,
@@ -51,6 +53,8 @@ const DEFAULT_VIEW_LABELS: Record<ViewType, string> = {
5153
calendar: 'Calendar',
5254
timeline: 'Timeline',
5355
map: 'Map',
56+
gallery: 'Gallery',
57+
gantt: 'Gantt',
5458
};
5559

5660
const DEFAULT_VIEW_ICONS: Record<ViewType, LucideIcon> = {
@@ -61,6 +65,8 @@ const DEFAULT_VIEW_ICONS: Record<ViewType, LucideIcon> = {
6165
calendar: Calendar,
6266
timeline: Activity,
6367
map: Map,
68+
gallery: Images,
69+
gantt: GanttChartSquare,
6470
};
6571

6672
const viewSwitcherLayout = cva('flex gap-4', {

packages/types/src/views.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import type { SelectOptionMetadata } from './field-types';
2525
/**
2626
* View Type
2727
*/
28-
export type ViewType = 'list' | 'detail' | 'grid' | 'kanban' | 'calendar' | 'timeline' | 'map';
28+
export type ViewType = 'list' | 'detail' | 'grid' | 'kanban' | 'calendar' | 'timeline' | 'map' | 'gallery' | 'gantt';
2929

3030
/**
3131
* Detail View Field Configuration

packages/types/src/zod/views.zod.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,33 @@ import { BaseSchema, SchemaNodeSchema } from './base.zod.js';
2222
/**
2323
* View Type Schema
2424
*/
25-
export const ViewTypeSchema = z.enum(['list', 'detail', 'grid', 'kanban', 'calendar', 'timeline', 'map']).describe('View type');
25+
export const ViewTypeSchema = z.enum(['list', 'detail', 'grid', 'kanban', 'calendar', 'timeline', 'map', 'gallery', 'gantt']).describe('View type');
2626

2727
/**
2828
* Detail View Field Schema
2929
*/
3030
export const DetailViewFieldSchema = z.object({
3131
name: z.string().describe('Field name/path'),
3232
label: z.string().optional().describe('Display label'),
33-
type: z.enum(['text', 'image', 'link', 'badge', 'date', 'datetime', 'json', 'html', 'markdown', 'custom']).optional().describe('Field type for rendering'),
33+
type: z.enum([
34+
'text', 'number', 'currency', 'percent', 'boolean', 'select', 'lookup', 'master_detail',
35+
'email', 'url', 'phone', 'user',
36+
'image', 'link', 'badge', 'date', 'datetime', 'json', 'html', 'markdown', 'custom',
37+
]).optional().describe('Field type for rendering'),
3438
format: z.string().optional().describe('Format string (e.g., date format)'),
3539
render: SchemaNodeSchema.optional().describe('Custom renderer'),
3640
value: z.any().optional().describe('Field value'),
3741
readonly: z.boolean().optional().describe('Whether field is read-only'),
3842
visible: z.union([z.boolean(), z.string()]).optional().describe('Field visibility condition'),
3943
span: z.number().optional().describe('Span across columns (for grid layout)'),
44+
options: z.array(z.object({
45+
label: z.string(),
46+
value: z.union([z.string(), z.number(), z.boolean()]),
47+
color: z.string().optional(),
48+
})).optional().describe('Options for select/lookup fields'),
49+
reference_to: z.string().optional().describe('Referenced object name for lookup/master_detail fields'),
50+
reference_field: z.string().optional().describe('Display field on the referenced object'),
51+
currency: z.string().optional().describe('Currency code for currency fields (e.g. USD, EUR)'),
4052
});
4153

4254
/**
@@ -51,6 +63,8 @@ export const DetailViewSectionSchema = z.object({
5163
defaultCollapsed: z.boolean().optional().describe('Default collapsed state'),
5264
columns: z.number().optional().describe('Grid columns for field layout'),
5365
visible: z.union([z.boolean(), z.string()]).optional().describe('Section visibility condition'),
66+
showBorder: z.boolean().optional().describe('Show border around section'),
67+
headerColor: z.string().optional().describe('Header background color (Tailwind class)'),
5468
});
5569

5670
/**

0 commit comments

Comments
 (0)