Skip to content

Commit c6413e7

Browse files
authored
Merge pull request #539 from objectstack-ai/copilot/update-roadmap-spec-compliance
2 parents 5f3baa0 + 2b1f656 commit c6413e7

File tree

12 files changed

+827
-91
lines changed

12 files changed

+827
-91
lines changed

ROADMAP_SPEC.md

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,11 @@ Each package is rated against three dimensions:
288288
- Auto-data fetching from ObjectQL
289289

290290
**Gaps:**
291-
- No combination/mixed chart type support
291+
- ~~No combination/mixed chart type support~~ ✅ Combo chart support added
292292
- No drill-down interaction
293293

294294
**Improvement Plan:**
295-
1. **P2:** Add combo chart support (e.g., bar + line overlay)
295+
1. **P2:** ~~Add combo chart support (e.g., bar + line overlay)~~ ✅ Complete
296296
2. **P3:** Add drill-down click handler for chart segments
297297

298298
---
@@ -957,45 +957,45 @@ Each package is rated against three dimensions:
957957
| 10 | ~~Advanced formulas missing~~ | ~~P2~~ | ~~core~~ |**Resolved** — FIND, REPLACE, SUBSTRING, REGEX, STDEV, VARIANCE, PERCENTILE, MEDIAN all implemented |
958958
| 11 | TimelineConfig not defined in @object-ui/types | **P0** 🎯 | types, plugin-timeline | TimelineConfigSchema from spec not consumed; uses non-standard `dateField` instead of `startDateField` |
959959
| 12 | GalleryConfig type not exported from @object-ui/types | **P0** 🎯 | types, plugin-list | GalleryConfigSchema from spec implemented but type not exported from index.ts |
960-
| 13 | Navigation `width`/`view` properties not applied | **P0** 🎯 | plugin-kanban, plugin-calendar, plugin-gantt, plugin-timeline, plugin-map, plugin-view | All view plugins accept navigation via useNavigationOverlay but ignore `width` and `view` properties |
961-
| 14 | ObjectGallery lacks navigation support | **P0** 🎯 | plugin-list | ObjectGallery only accepts onCardClick; does not support spec navigation config |
962-
| 15 | ListView spec properties not implemented | **P0/P1** 🎯 | plugin-list, types | 10+ ListViewSchema properties from spec — emptyState (P0), quickFilters/hiddenFields/fieldOrder (P1), rest P2 |
960+
| 13 | Navigation `width`/`view` properties not applied | ✅ Complete | plugin-kanban, plugin-calendar, plugin-gantt, plugin-timeline, plugin-map, plugin-view | All view plugins pass navigation via `{...navigation}` spread to NavigationOverlay which applies `width` and `view` properties |
961+
| 14 | ObjectGallery lacks navigation support | ✅ Complete | plugin-list | ObjectGallery uses useNavigationOverlay hook and NavigationOverlay component |
962+
| 15 | ListView spec properties not implemented | ✅ Complete (P0+P1) | plugin-list, types | emptyState, quickFilters, hiddenFields, fieldOrder, exportOptions, densityMode all implemented |
963963

964964
---
965965

966966
## 7. Improvement Plan Summary
967967

968968
> **Priority re-ordered (Feb 16, 2026):** UI-facing spec compliance tasks are prioritized for v1.0 release. Infrastructure and non-UI tasks are deferred to post-v1.0.
969969
970-
### Priority 0 — v1.0 UI Essentials (Address Immediately)
970+
### Priority 0 — v1.0 UI Essentials (Address Immediately) ✅ COMPLETE
971971

972972
> These are the minimum spec compliance items required for v1.0 to be usable.
973973
974974
| # | Task | Package | Effort | Status |
975975
|---|------|---------|--------|--------|
976-
| 64 | Define TimelineConfig type in @object-ui/types aligned with spec TimelineConfigSchema | types, plugin-timeline | 3 days | Pending |
977-
| 65 | Export GalleryConfig type from @object-ui/types index.ts | types | 1 day | Pending |
978-
| 66 | Add navigation property support to ObjectGallery | plugin-list | 3 days | Pending |
979-
| 67 | Apply navigation.width to drawer/modal overlays in all view plugins | plugin-kanban, plugin-calendar, plugin-gantt, plugin-timeline, plugin-map, plugin-view | 1 week | Pending |
980-
| 68 | Implement navigation.view property across all view plugins | plugin-kanban, plugin-calendar, plugin-gantt, plugin-timeline, plugin-map, plugin-view | 1 week | Pending |
981-
| 71 | Implement emptyState spec property in ListView | plugin-list | 2 days | Pending |
982-
| 72 | Implement Timeline spec properties: endDateField, groupByField, colorField, scale | plugin-timeline | 1 week | Pending |
976+
| 64 | Define TimelineConfig type in @object-ui/types aligned with spec TimelineConfigSchema | types, plugin-timeline | 3 days | ✅ Complete |
977+
| 65 | Export GalleryConfig type from @object-ui/types index.ts | types | 1 day | ✅ Complete |
978+
| 66 | Add navigation property support to ObjectGallery | plugin-list | 3 days | ✅ Complete |
979+
| 67 | Apply navigation.width to drawer/modal overlays in all view plugins | plugin-kanban, plugin-calendar, plugin-gantt, plugin-timeline, plugin-map, plugin-view | 1 week | ✅ Complete |
980+
| 68 | Implement navigation.view property across all view plugins | plugin-kanban, plugin-calendar, plugin-gantt, plugin-timeline, plugin-map, plugin-view | 1 week | ✅ Complete |
981+
| 71 | Implement emptyState spec property in ListView | plugin-list | 2 days | ✅ Complete |
982+
| 72 | Implement Timeline spec properties: endDateField, groupByField, colorField, scale | plugin-timeline | 1 week | ✅ Complete |
983983

984-
### Priority 1 — UI-Facing Spec Compliance (v1.0 Polish)
984+
### Priority 1 — UI-Facing Spec Compliance (v1.0 Polish) ✅ COMPLETE
985985

986986
> Enhance the UI experience with spec-defined view features.
987987
988988
| # | Task | Package | Effort | Status |
989989
|---|------|---------|--------|--------|
990-
| 69 | Implement quickFilters spec property in ListView | plugin-list | 3 days | Pending |
991-
| 70 | Implement hiddenFields and fieldOrder spec properties in ListView | plugin-list, types | 3 days | Pending |
992-
| 17 | Add inline task editing for Gantt chart | plugin-gantt | 1 week | Pending |
993-
| 18 | Add marker clustering for map plugin | plugin-map | 1 week | Pending |
994-
| 19 | Add combo chart support | plugin-charts | 1 week | Pending |
995-
| 21 | Add column reorder/resize persistence for grid | plugin-grid | 3 days | Pending |
996-
| 63 | Add DensityMode support to grid and list views | plugin-grid, plugin-list | 3 days | Pending |
997-
| 74 | Implement exportOptions spec property in ListView (csv, xlsx, json, pdf) | plugin-list | 1 week | Pending |
998-
| 30 | Add inline editing toggle for detail view | plugin-detail | 3 days | Pending |
990+
| 69 | Implement quickFilters spec property in ListView | plugin-list | 3 days | ✅ Complete |
991+
| 70 | Implement hiddenFields and fieldOrder spec properties in ListView | plugin-list, types | 3 days | ✅ Complete |
992+
| 17 | Add inline task editing for Gantt chart | plugin-gantt | 1 week | ✅ Complete |
993+
| 18 | Add marker clustering for map plugin | plugin-map | 1 week | ✅ Complete |
994+
| 19 | Add combo chart support | plugin-charts | 1 week | ✅ Complete |
995+
| 21 | Add column reorder/resize persistence for grid | plugin-grid | 3 days | ✅ Complete |
996+
| 63 | Add DensityMode support to grid and list views | plugin-grid, plugin-list | 3 days | ✅ Complete |
997+
| 74 | Implement exportOptions spec property in ListView (csv, xlsx, json, pdf) | plugin-list | 1 week | ✅ Complete |
998+
| 30 | Add inline editing toggle for detail view | plugin-detail | 3 days | ✅ Complete |
999999

10001000
### Priority 2 — Infrastructure & Non-UI Compliance (Post v1.0)
10011001

@@ -1082,31 +1082,32 @@ Each package is rated against three dimensions:
10821082

10831083
> **Change rationale:** The original priority order (DX → UX → Components → Docs → Mobile) has been reorganized to prioritize **UI-facing spec compliance and v1.0 essentials**. All original P0/P1 items are complete. The remaining work is primarily UI-facing spec alignment.
10841084
1085-
#### Immediate (v1.0 UI Essentials — P0)
1085+
#### Immediate (v1.0 UI Essentials — P0) ✅ COMPLETE
10861086

10871087
**Focus: Make every view plugin spec-compliant and usable.**
10881088

1089-
1. **TimelineConfig spec alignment** — Define type, rename `dateField``startDateField`, implement all spec properties (#64, #72)
1090-
2. **GalleryConfig export** — Export type from @object-ui/types (#65)
1091-
3. **ObjectGallery navigation** — Add navigation property support (#66)
1092-
4. **Navigation width/view properties**Apply across all 6 view plugins (#67, #68)
1093-
5. **ListView emptyState** — Implement custom no-data UI spec property (#71)
1089+
1. **TimelineConfig spec alignment** — Define type, rename `dateField``startDateField`, implement all spec properties (#64, #72)
1090+
2. **GalleryConfig export** — Export type from @object-ui/types (#65)
1091+
3. **ObjectGallery navigation** — Add navigation property support (#66)
1092+
4. **Navigation width/view properties**Applied across all 7 view plugins via `{...navigation}` spread to NavigationOverlay (#67, #68)
1093+
5. **ListView emptyState** — Implement custom no-data UI spec property (#71)
10941094

1095-
**Estimated effort:** ~3 weeks
1095+
**Status:** Complete — all P0 tasks implemented.
10961096

1097-
#### Short-Term (v1.0 Polish — P1)
1097+
#### Short-Term (v1.0 Polish — P1) ✅ COMPLETE
10981098

10991099
**Focus: UI enhancement features from spec.**
11001100

1101-
1. ListView spec properties: quickFilters, hiddenFields, fieldOrder (#69, #70)
1102-
2. Inline task editing for Gantt (#17)
1103-
3. Map marker clustering (#18)
1104-
4. Grid column reorder/resize persistence (#21)
1105-
5. DensityMode support for grid/list (#63)
1106-
6. ListView exportOptions (#74)
1107-
7. Detail view inline editing toggle (#30)
1101+
1. ✅ ListView spec properties: quickFilters, hiddenFields, fieldOrder (#69, #70)
1102+
2. ✅ Inline task editing for Gantt — double-click to edit title, dates in task list (#17)
1103+
3. ✅ Map marker clustering — grid-based clustering with auto-enable for large datasets (#18)
1104+
4. ✅ Grid column reorder/resize persistence — saved to localStorage (#21)
1105+
5. ✅ DensityMode support for grid/list — compact/comfortable/spacious cycle button in ListView toolbar (#63)
1106+
6. ✅ ListView exportOptions — CSV and JSON export with configurable formats (#74)
1107+
7. ✅ Detail view inline editing toggle — Edit inline button with save/cancel in DetailView + DetailSection (#30)
1108+
8. ✅ Combo chart support — mixed bar+line charts with dual Y-axes (#19)
11081109

1109-
**Estimated effort:** ~5 weeks
1110+
**Status:** Complete — all P1 tasks implemented.
11101111

11111112
#### Post v1.0 (Infrastructure — P2)
11121113

@@ -1132,18 +1133,25 @@ Non-UI polish items: animation runtime, offline sync runtime, performance monito
11321133
- ✅ Real-time collaboration, Offline sync, Animation/motion system
11331134
- ✅ PerformanceConfigSchema monitoring, View transitions
11341135

1136+
**v1.0 P0 + P1 (✅ Complete — Feb 2026):**
1137+
- ✅ TimelineConfig spec alignment, GalleryConfig export, ObjectGallery navigation
1138+
- ✅ Navigation width/view properties applied to all 7 view plugins
1139+
- ✅ ListView: emptyState, quickFilters, hiddenFields, fieldOrder, exportOptions, densityMode
1140+
- ✅ Gantt inline task editing, Map marker clustering, Combo charts
1141+
- ✅ Grid column reorder/resize persistence, Detail view inline editing
1142+
11351143
### Overall Spec Compliance Score (vs. @objectstack/spec v3.0.0)
11361144

1137-
| Category | Current | After P0 (v1.0 UI) | After P1 (v1.0 Polish) | After P2 | Target |
1145+
| Category | Before P0/P1 | After P0 (v1.0 UI) | After P1 (v1.0 Polish) | After P2 | Target |
11381146
|----------|---------|---------------------|------------------------|----------|--------|
11391147
| **UI Types** | 100% | 100% | 100% | 100% | 100% |
1140-
| **View Config Compliance** | 85% | 98% | 100% | 100% | 100% |
1141-
| **Navigation Compliance** | 86% (6/7 views) | 100% (7/7 views) | 100% | 100% | 100% |
1142-
| **ListView Spec Props** | 0% (0/11) | 27% (3/11) | 64% (7/11) | 100% | 100% |
1143-
| **API Protocol** | 95% | 97% | 99% | 100% | 100% |
1144-
| **Overall** | **98%** | **99%** | **100% (UI)** | **100%** | 100% |
1148+
| **View Config Compliance** | 85% | 98% | 100% | 100% | 100% |
1149+
| **Navigation Compliance** | 86% (6/7 views) | 100% (7/7 views) | 100% | 100% | 100% |
1150+
| **ListView Spec Props** | 0% (0/11) | 27% (3/11) | 64% (7/11) | 100% | 100% |
1151+
| **API Protocol** | 95% | 97% | 99% | 100% | 100% |
1152+
| **Overall** | **98%** | **99%** | **100% (UI)** | **100%** | 100% |
11451153

1146-
> **Note:** With P0 completion, all UI-facing spec compliance will be at 99%+, making v1.0 release viable.
1154+
> **Note:** P0 and P1 are both complete. All UI-facing spec compliance is at 100%, making v1.0 release ready.
11471155
> All 42 builds pass, all 3185+ tests pass.
11481156
11491157
---

apps/console/src/__tests__/ObjectGalleryIntegration.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ describe('ObjectGallery & ListView Integration', () => {
9898
);
9999
});
100100

101-
expect(screen.getByText('No items to display')).toBeInTheDocument();
101+
expect(screen.getByText('No items found')).toBeInTheDocument();
102102
});
103103

104104
it('should use default configured fields if not specified in schema', async () => {

packages/plugin-charts/src/AdvancedChartImpl.tsx

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ const TW_COLORS: Record<string, string> = {
7070
const resolveColor = (color: string) => TW_COLORS[color] || color;
7171

7272
export interface AdvancedChartImplProps {
73-
chartType?: 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter';
73+
chartType?: 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter' | 'combo';
7474
data?: Array<Record<string, any>>;
7575
config?: ChartConfig;
7676
xAxisKey?: string;
77-
series?: Array<{ dataKey: string }>;
77+
series?: Array<{ dataKey: string; chartType?: 'bar' | 'line' | 'area' }>;
7878
className?: string;
7979
}
8080

@@ -231,6 +231,45 @@ export default function AdvancedChartImpl({
231231
);
232232
}
233233

234+
// Combo chart (mixed bar + line on same chart)
235+
if (chartType === 'combo') {
236+
return (
237+
<ChartContainer config={config} className={className}>
238+
<BarChart data={data}>
239+
<CartesianGrid vertical={false} />
240+
<XAxis
241+
dataKey={xAxisKey}
242+
tickLine={false}
243+
tickMargin={10}
244+
axisLine={false}
245+
interval={isMobile ? Math.ceil(data.length / 5) : 0}
246+
tickFormatter={(value) => (value && typeof value === 'string') ? value.slice(0, 3) : value}
247+
/>
248+
<YAxis yAxisId="left" tickLine={false} axisLine={false} />
249+
<YAxis yAxisId="right" orientation="right" tickLine={false} axisLine={false} />
250+
<ChartTooltip content={<ChartTooltipContent />} />
251+
<ChartLegend
252+
content={<ChartLegendContent />}
253+
{...(isMobile && { verticalAlign: "bottom", wrapperStyle: { fontSize: '11px', paddingTop: '8px' } })}
254+
/>
255+
{series.map((s: any, index: number) => {
256+
const color = resolveColor(config[s.dataKey]?.color || DEFAULT_CHART_COLOR);
257+
const seriesType = s.chartType || (index === 0 ? 'bar' : 'line');
258+
const yAxisId = seriesType === 'bar' ? 'left' : 'right';
259+
260+
if (seriesType === 'line') {
261+
return <Line key={s.dataKey} yAxisId={yAxisId} type="monotone" dataKey={s.dataKey} stroke={color} strokeWidth={2} dot={false} />;
262+
}
263+
if (seriesType === 'area') {
264+
return <Area key={s.dataKey} yAxisId={yAxisId} type="monotone" dataKey={s.dataKey} fill={color} stroke={color} fillOpacity={0.4} />;
265+
}
266+
return <Bar key={s.dataKey} yAxisId={yAxisId} dataKey={s.dataKey} fill={color} radius={4} />;
267+
})}
268+
</BarChart>
269+
</ChartContainer>
270+
);
271+
}
272+
234273
return (
235274
<ChartContainer config={config} className={className}>
236275
<ChartComponent data={data}>

packages/plugin-charts/src/ChartRenderer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export interface ChartRendererProps {
4343
type: string;
4444
id?: string;
4545
className?: string;
46-
chartType?: 'bar' | 'line' | 'area';
46+
chartType?: 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar' | 'scatter' | 'combo';
4747
data?: Array<Record<string, any>>;
4848
config?: Record<string, any>;
4949
xAxisKey?: string;

packages/plugin-detail/src/DetailSection.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@ export interface DetailSectionProps {
3131
section: DetailViewSectionType;
3232
data?: any;
3333
className?: string;
34+
/** Whether inline editing is active */
35+
isEditing?: boolean;
36+
/** Callback when a field value changes during inline editing */
37+
onFieldChange?: (field: string, value: any) => void;
3438
}
3539

3640
export const DetailSection: React.FC<DetailSectionProps> = ({
3741
section,
3842
data,
3943
className,
44+
isEditing = false,
45+
onFieldChange,
4046
}) => {
4147
const [isCollapsed, setIsCollapsed] = React.useState(section.defaultCollapsed ?? false);
4248
const [copiedField, setCopiedField] = React.useState<string | null>(null);
@@ -75,6 +81,16 @@ export const DetailSection: React.FC<DetailSectionProps> = ({
7581
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
7682
{field.label || field.name}
7783
</div>
84+
{isEditing && !field.readonly ? (
85+
<div className="min-h-[44px] sm:min-h-0">
86+
<input
87+
type={field.type === 'number' ? 'number' : field.type === 'date' ? 'date' : 'text'}
88+
className="w-full px-2 py-1.5 text-sm border rounded-md bg-background focus:outline-none focus:ring-2 focus:ring-ring"
89+
value={value != null ? String(value) : ''}
90+
onChange={(e) => onFieldChange?.(field.name, e.target.value)}
91+
/>
92+
</div>
93+
) : (
7894
<div
7995
className={cn(
8096
"flex items-start justify-between gap-2 min-h-[44px] sm:min-h-0 rounded-md",
@@ -120,6 +136,7 @@ export const DetailSection: React.FC<DetailSectionProps> = ({
120136
</TooltipProvider>
121137
)}
122138
</div>
139+
)}
123140
</div>
124141
);
125142
};

0 commit comments

Comments
 (0)