@object-ui/app-shell 5.3.2 → 5.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/dist/providers/MetadataProvider.js +33 -17
- package/dist/views/ObjectView.js +56 -11
- package/package.json +25 -25
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @object-ui/app-shell — Changelog
|
|
2
2
|
|
|
3
|
+
## 5.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4afe667: ai
|
|
8
|
+
- @object-ui/types@5.4.1
|
|
9
|
+
- @object-ui/core@5.4.1
|
|
10
|
+
- @object-ui/i18n@5.4.1
|
|
11
|
+
- @object-ui/react@5.4.1
|
|
12
|
+
- @object-ui/components@5.4.1
|
|
13
|
+
- @object-ui/fields@5.4.1
|
|
14
|
+
- @object-ui/layout@5.4.1
|
|
15
|
+
- @object-ui/data-objectstack@5.4.1
|
|
16
|
+
- @object-ui/auth@5.4.1
|
|
17
|
+
- @object-ui/permissions@5.4.1
|
|
18
|
+
- @object-ui/collaboration@5.4.1
|
|
19
|
+
- @object-ui/providers@5.4.1
|
|
20
|
+
|
|
21
|
+
## 5.4.0
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [3a8c754]
|
|
26
|
+
- @object-ui/types@5.4.0
|
|
27
|
+
- @object-ui/auth@5.4.0
|
|
28
|
+
- @object-ui/collaboration@5.4.0
|
|
29
|
+
- @object-ui/components@5.4.0
|
|
30
|
+
- @object-ui/core@5.4.0
|
|
31
|
+
- @object-ui/data-objectstack@5.4.0
|
|
32
|
+
- @object-ui/fields@5.4.0
|
|
33
|
+
- @object-ui/layout@5.4.0
|
|
34
|
+
- @object-ui/permissions@5.4.0
|
|
35
|
+
- @object-ui/providers@5.4.0
|
|
36
|
+
- @object-ui/react@5.4.0
|
|
37
|
+
- @object-ui/i18n@5.4.0
|
|
38
|
+
|
|
3
39
|
## 5.3.2
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
|
@@ -61,17 +61,6 @@ function isNamedItem(item) {
|
|
|
61
61
|
'name' in item &&
|
|
62
62
|
typeof item.name === 'string');
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Merge `view` metadata (the @objectstack/spec View container, keyed by
|
|
66
|
-
* target object name) into object definitions so that `objectDef.listViews`
|
|
67
|
-
* is populated for the renderer (`@object-ui/plugin-view`) which expects it.
|
|
68
|
-
*
|
|
69
|
-
* Each View has shape `{ list?, form?, listViews?, formViews? }`. We collapse:
|
|
70
|
-
* - `view.list` → `listViews[view.list.name || 'default']`
|
|
71
|
-
* - `view.listViews` → spread into `listViews`
|
|
72
|
-
*
|
|
73
|
-
* Existing `obj.listViews` / `obj.list_views` win to preserve overrides.
|
|
74
|
-
*/
|
|
75
64
|
function mergeViewsIntoObjects(objects, views) {
|
|
76
65
|
if (!objects.length || !views.length)
|
|
77
66
|
return objects;
|
|
@@ -80,14 +69,27 @@ function mergeViewsIntoObjects(objects, views) {
|
|
|
80
69
|
const objName = view?.name || view?.list?.data?.object || view?.form?.data?.object;
|
|
81
70
|
if (!objName)
|
|
82
71
|
continue;
|
|
83
|
-
const bucket = (byObject[objName] || (byObject[objName] = {}));
|
|
72
|
+
const bucket = (byObject[objName] || (byObject[objName] = { listViews: {}, formViews: {} }));
|
|
84
73
|
if (view.list) {
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
// Preserve the primary list view as `obj.list` per @objectstack/spec
|
|
75
|
+
// ViewSchema. Also mirror it into `listViews` under its name so legacy
|
|
76
|
+
// consumers (that only iterate `listViews`) still see it. Consumers
|
|
77
|
+
// honoring `obj.list` (e.g. ObjectView) should dedup by id.
|
|
78
|
+
bucket.primary = view.list;
|
|
79
|
+
const k = view.list.name || 'list';
|
|
80
|
+
bucket.listViews[k] = view.list;
|
|
81
|
+
}
|
|
82
|
+
if (view.form) {
|
|
83
|
+
bucket.form = view.form;
|
|
87
84
|
}
|
|
88
85
|
if (view.listViews && typeof view.listViews === 'object') {
|
|
89
86
|
for (const [k, v] of Object.entries(view.listViews)) {
|
|
90
|
-
bucket[k] = v;
|
|
87
|
+
bucket.listViews[k] = v;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (view.formViews && typeof view.formViews === 'object') {
|
|
91
|
+
for (const [k, v] of Object.entries(view.formViews)) {
|
|
92
|
+
bucket.formViews[k] = v;
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
}
|
|
@@ -95,8 +97,22 @@ function mergeViewsIntoObjects(objects, views) {
|
|
|
95
97
|
const extra = byObject[obj.name];
|
|
96
98
|
if (!extra)
|
|
97
99
|
return obj;
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
+
const existingListViews = obj.listViews || obj.list_views || {};
|
|
101
|
+
const existingFormViews = obj.formViews || obj.form_views || {};
|
|
102
|
+
const merged = {
|
|
103
|
+
...obj,
|
|
104
|
+
listViews: { ...extra.listViews, ...existingListViews },
|
|
105
|
+
};
|
|
106
|
+
if (Object.keys(extra.formViews).length || Object.keys(existingFormViews).length) {
|
|
107
|
+
merged.formViews = { ...extra.formViews, ...existingFormViews };
|
|
108
|
+
}
|
|
109
|
+
if (extra.primary && !obj.list) {
|
|
110
|
+
merged.list = extra.primary;
|
|
111
|
+
}
|
|
112
|
+
if (extra.form && !obj.form) {
|
|
113
|
+
merged.form = extra.form;
|
|
114
|
+
}
|
|
115
|
+
return merged;
|
|
100
116
|
});
|
|
101
117
|
}
|
|
102
118
|
function emptyEntry() {
|
package/dist/views/ObjectView.js
CHANGED
|
@@ -461,6 +461,13 @@ export function ObjectView({ dataSource, objects, onEdit, externalRefreshKey })
|
|
|
461
461
|
}
|
|
462
462
|
const definedViews = (objectDef.listViews || objectDef.list_views || {});
|
|
463
463
|
const ids = Object.keys(definedViews);
|
|
464
|
+
// Include the primary view id so overrides apply to it too.
|
|
465
|
+
const primary = objectDef.list;
|
|
466
|
+
if (primary && typeof primary === 'object') {
|
|
467
|
+
const primaryId = primary.name || 'list';
|
|
468
|
+
if (!ids.includes(primaryId))
|
|
469
|
+
ids.unshift(primaryId);
|
|
470
|
+
}
|
|
464
471
|
if (ids.length === 0) {
|
|
465
472
|
setViewOverrides({});
|
|
466
473
|
return;
|
|
@@ -505,7 +512,7 @@ export function ObjectView({ dataSource, objects, onEdit, externalRefreshKey })
|
|
|
505
512
|
setViewOverrides(map);
|
|
506
513
|
});
|
|
507
514
|
return () => { cancelled = true; };
|
|
508
|
-
}, [dataSource, objectName, objectDef.listViews, objectDef.list_views, refreshKey]);
|
|
515
|
+
}, [dataSource, objectName, objectDef.listViews, objectDef.list_views, objectDef.list, refreshKey]);
|
|
509
516
|
// Resolve Views from objectDef.listViews (camelCase per @objectstack/spec)
|
|
510
517
|
const views = useMemo(() => {
|
|
511
518
|
// Default column resolution priority:
|
|
@@ -551,6 +558,29 @@ export function ObjectView({ dataSource, objects, onEdit, externalRefreshKey })
|
|
|
551
558
|
type: (override?.type) || value.type || 'grid',
|
|
552
559
|
};
|
|
553
560
|
});
|
|
561
|
+
// Honor `objectDef.list` (the primary list view, per @objectstack/spec
|
|
562
|
+
// ViewSchema). MetadataProvider mirrors it into `listViews` so it's
|
|
563
|
+
// already in `viewList` above; promote it to the front and mark it as
|
|
564
|
+
// the default so `defaultViewId` picks it over secondary listViews.
|
|
565
|
+
const primary = objectDef.list;
|
|
566
|
+
if (primary && typeof primary === 'object') {
|
|
567
|
+
const primaryId = primary.name || 'list';
|
|
568
|
+
const idx = viewList.findIndex(v => v.id === primaryId);
|
|
569
|
+
if (idx >= 0) {
|
|
570
|
+
const [entry] = viewList.splice(idx, 1);
|
|
571
|
+
viewList.unshift({ ...entry, isDefault: true });
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
const override = viewOverrides[primaryId];
|
|
575
|
+
viewList.unshift({
|
|
576
|
+
id: primaryId,
|
|
577
|
+
...primary,
|
|
578
|
+
...(override || {}),
|
|
579
|
+
type: (override?.type) || primary.type || 'grid',
|
|
580
|
+
isDefault: true,
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
554
584
|
if (viewList.length === 0) {
|
|
555
585
|
viewList.push({
|
|
556
586
|
id: 'all',
|
|
@@ -566,7 +596,10 @@ export function ObjectView({ dataSource, objects, onEdit, externalRefreshKey })
|
|
|
566
596
|
const id = sv.id || sv._id;
|
|
567
597
|
if (!id)
|
|
568
598
|
continue;
|
|
569
|
-
|
|
599
|
+
// Drop undefined fields so a partial overlay (e.g. baseline row
|
|
600
|
+
// with no user customization) does not stomp `isDefault`/`columns`
|
|
601
|
+
// populated from the metadata view it shadows.
|
|
602
|
+
const rawNormalized = {
|
|
570
603
|
label: sv.label || sv.name || id,
|
|
571
604
|
type: sv.type || 'grid',
|
|
572
605
|
columns: sv.columns,
|
|
@@ -582,6 +615,11 @@ export function ObjectView({ dataSource, objects, onEdit, externalRefreshKey })
|
|
|
582
615
|
...sv,
|
|
583
616
|
id,
|
|
584
617
|
};
|
|
618
|
+
const normalized = {};
|
|
619
|
+
for (const [k, v] of Object.entries(rawNormalized)) {
|
|
620
|
+
if (v !== undefined)
|
|
621
|
+
normalized[k] = v;
|
|
622
|
+
}
|
|
585
623
|
if (metaIds.has(id)) {
|
|
586
624
|
const idx = viewList.findIndex(v => v.id === id);
|
|
587
625
|
viewList[idx] = { ...viewList[idx], ...normalized };
|
|
@@ -627,17 +665,24 @@ export function ObjectView({ dataSource, objects, onEdit, externalRefreshKey })
|
|
|
627
665
|
return 1;
|
|
628
666
|
const aSaved = savedViews.find((sv) => (sv.id || sv._id) === a.id);
|
|
629
667
|
const bSaved = savedViews.find((sv) => (sv.id || sv._id) === b.id);
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
668
|
+
const aHasOrder = aSaved && typeof aSaved.sortOrder === 'number';
|
|
669
|
+
const bHasOrder = bSaved && typeof bSaved.sortOrder === 'number';
|
|
670
|
+
// Only an explicit user `sortOrder` should reorder views away from
|
|
671
|
+
// the metadata-declared sequence. A bare overlay row (no sortOrder)
|
|
672
|
+
// must not demote a metadata view: that would break primary-view
|
|
673
|
+
// promotion (which relies on declared order) for objects whose
|
|
674
|
+
// overlay seeded a baseline `sys_view` row without sort info.
|
|
675
|
+
if (aHasOrder && bHasOrder) {
|
|
676
|
+
if (aSaved.sortOrder !== bSaved.sortOrder) {
|
|
677
|
+
return aSaved.sortOrder - bSaved.sortOrder;
|
|
678
|
+
}
|
|
679
|
+
return (aSaved.created_at || '').localeCompare(bSaved.created_at || '');
|
|
680
|
+
}
|
|
681
|
+
if (aHasOrder)
|
|
633
682
|
return -1;
|
|
634
|
-
if (
|
|
683
|
+
if (bHasOrder)
|
|
635
684
|
return 1;
|
|
636
|
-
|
|
637
|
-
const bo = typeof bSaved.sortOrder === 'number' ? bSaved.sortOrder : Number.MAX_SAFE_INTEGER;
|
|
638
|
-
if (ao !== bo)
|
|
639
|
-
return ao - bo;
|
|
640
|
-
return (aSaved.created_at || '').localeCompare(bSaved.created_at || '');
|
|
685
|
+
return (indexOf.get(a.id) ?? 0) - (indexOf.get(b.id) ?? 0);
|
|
641
686
|
});
|
|
642
687
|
return viewList;
|
|
643
688
|
}, [objectDef, savedViews, viewOverrides, t]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/app-shell",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Minimal application shell for ObjectUI - framework-agnostic rendering engine",
|
|
@@ -28,35 +28,35 @@
|
|
|
28
28
|
"@sentry/react": "^8.55.2",
|
|
29
29
|
"lucide-react": "^1.16.0",
|
|
30
30
|
"sonner": "^2.0.7",
|
|
31
|
-
"@object-ui/auth": "5.
|
|
32
|
-
"@object-ui/collaboration": "5.
|
|
33
|
-
"@object-ui/components": "5.
|
|
34
|
-
"@object-ui/core": "5.
|
|
35
|
-
"@object-ui/data-objectstack": "5.
|
|
36
|
-
"@object-ui/fields": "5.
|
|
37
|
-
"@object-ui/i18n": "5.
|
|
38
|
-
"@object-ui/layout": "5.
|
|
39
|
-
"@object-ui/permissions": "5.
|
|
40
|
-
"@object-ui/providers": "5.
|
|
41
|
-
"@object-ui/react": "5.
|
|
42
|
-
"@object-ui/types": "5.
|
|
31
|
+
"@object-ui/auth": "5.4.1",
|
|
32
|
+
"@object-ui/collaboration": "5.4.1",
|
|
33
|
+
"@object-ui/components": "5.4.1",
|
|
34
|
+
"@object-ui/core": "5.4.1",
|
|
35
|
+
"@object-ui/data-objectstack": "5.4.1",
|
|
36
|
+
"@object-ui/fields": "5.4.1",
|
|
37
|
+
"@object-ui/i18n": "5.4.1",
|
|
38
|
+
"@object-ui/layout": "5.4.1",
|
|
39
|
+
"@object-ui/permissions": "5.4.1",
|
|
40
|
+
"@object-ui/providers": "5.4.1",
|
|
41
|
+
"@object-ui/react": "5.4.1",
|
|
42
|
+
"@object-ui/types": "5.4.1"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"react": "^18.0.0 || ^19.0.0",
|
|
46
46
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
47
47
|
"react-router-dom": "^6.0.0 || ^7.0.0",
|
|
48
|
-
"@object-ui/plugin-calendar": "^5.
|
|
49
|
-
"@object-ui/plugin-charts": "^5.
|
|
50
|
-
"@object-ui/plugin-chatbot": "^5.
|
|
51
|
-
"@object-ui/plugin-dashboard": "^5.
|
|
52
|
-
"@object-ui/plugin-designer": "^5.
|
|
53
|
-
"@object-ui/plugin-detail": "^5.
|
|
54
|
-
"@object-ui/plugin-form": "^5.
|
|
55
|
-
"@object-ui/plugin-grid": "^5.
|
|
56
|
-
"@object-ui/plugin-kanban": "^5.
|
|
57
|
-
"@object-ui/plugin-list": "^5.
|
|
58
|
-
"@object-ui/plugin-report": "^5.
|
|
59
|
-
"@object-ui/plugin-view": "^5.
|
|
48
|
+
"@object-ui/plugin-calendar": "^5.4.1",
|
|
49
|
+
"@object-ui/plugin-charts": "^5.4.1",
|
|
50
|
+
"@object-ui/plugin-chatbot": "^5.4.1",
|
|
51
|
+
"@object-ui/plugin-dashboard": "^5.4.1",
|
|
52
|
+
"@object-ui/plugin-designer": "^5.4.1",
|
|
53
|
+
"@object-ui/plugin-detail": "^5.4.1",
|
|
54
|
+
"@object-ui/plugin-form": "^5.4.1",
|
|
55
|
+
"@object-ui/plugin-grid": "^5.4.1",
|
|
56
|
+
"@object-ui/plugin-kanban": "^5.4.1",
|
|
57
|
+
"@object-ui/plugin-list": "^5.4.1",
|
|
58
|
+
"@object-ui/plugin-report": "^5.4.1",
|
|
59
|
+
"@object-ui/plugin-view": "^5.4.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/node": "^25.9.0",
|