@object-ui/app-shell 6.2.1 → 6.2.3
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 +61 -0
- package/dist/console/ai/AiChatPage.js +19 -22
- package/dist/layout/ConsoleFloatingChatbot.js +44 -24
- package/dist/views/metadata-admin/EmbeddedItemEditor.d.ts +15 -0
- package/dist/views/metadata-admin/EmbeddedItemEditor.js +194 -0
- package/dist/views/metadata-admin/MetadataDetailDrawer.js +2 -26
- package/dist/views/metadata-admin/RelatedPanel.d.ts +4 -0
- package/dist/views/metadata-admin/RelatedPanel.js +2 -0
- package/dist/views/metadata-admin/ResourceEditPage.js +50 -5
- package/dist/views/metadata-admin/anchors.js +6 -0
- package/dist/views/metadata-admin/index.d.ts +2 -0
- package/dist/views/metadata-admin/index.js +6 -0
- package/dist/views/metadata-admin/preview-registry.d.ts +43 -0
- package/dist/views/metadata-admin/preview-registry.js +18 -0
- package/dist/views/metadata-admin/previews/AppPreview.d.ts +2 -0
- package/dist/views/metadata-admin/previews/AppPreview.js +101 -0
- package/dist/views/metadata-admin/previews/DashboardPreview.d.ts +2 -0
- package/dist/views/metadata-admin/previews/DashboardPreview.js +25 -0
- package/dist/views/metadata-admin/previews/EmailTemplatePreview.d.ts +2 -0
- package/dist/views/metadata-admin/previews/EmailTemplatePreview.js +65 -0
- package/dist/views/metadata-admin/previews/ObjectPreview.d.ts +2 -0
- package/dist/views/metadata-admin/previews/ObjectPreview.js +36 -0
- package/dist/views/metadata-admin/previews/PagePreview.d.ts +2 -0
- package/dist/views/metadata-admin/previews/PagePreview.js +26 -0
- package/dist/views/metadata-admin/previews/PreviewShell.d.ts +40 -0
- package/dist/views/metadata-admin/previews/PreviewShell.js +49 -0
- package/dist/views/metadata-admin/previews/ReportPreview.d.ts +2 -0
- package/dist/views/metadata-admin/previews/ReportPreview.js +27 -0
- package/dist/views/metadata-admin/previews/ViewPreview.d.ts +2 -0
- package/dist/views/metadata-admin/previews/ViewPreview.js +113 -0
- package/dist/views/metadata-admin/previews/index.d.ts +1 -0
- package/dist/views/metadata-admin/previews/index.js +26 -0
- package/dist/views/metadata-admin/registry.d.ts +17 -0
- package/package.json +26 -26
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* ReportPreview — runs the live Report draft through the same
|
|
5
|
+
* ReportRenderer the runtime ReportView uses.
|
|
6
|
+
*
|
|
7
|
+
* Uses the app-shell AdapterProvider's data source so previews see
|
|
8
|
+
* actual rows. Lazy-loaded to keep the metadata-admin bundle small.
|
|
9
|
+
*/
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
import { Loader2 } from 'lucide-react';
|
|
12
|
+
import { useAdapter } from '../../../providers/AdapterProvider';
|
|
13
|
+
import { PreviewShell, PreviewErrorBoundary, PreviewMessage } from './PreviewShell';
|
|
14
|
+
const ReportRenderer = React.lazy(() => import('@object-ui/plugin-report').then((m) => ({ default: m.ReportRenderer })));
|
|
15
|
+
export function ReportPreview({ draft }) {
|
|
16
|
+
const adapter = useAdapter();
|
|
17
|
+
// Different fixture sets use different keys for the source object:
|
|
18
|
+
// • new schema: `object`
|
|
19
|
+
// • legacy: `objectName`
|
|
20
|
+
// • some reports embed it under `data.object`
|
|
21
|
+
const objectName = draft.object ?? draft.objectName ?? draft.data?.object;
|
|
22
|
+
const visualization = draft.visualization?.type ?? draft.type;
|
|
23
|
+
if (!objectName) {
|
|
24
|
+
return (_jsx(PreviewShell, { hint: "report", children: _jsx(PreviewMessage, { tone: "warn", children: "Pick an Object in the Form tab \u2014 Reports need a source object before they can render." }) }));
|
|
25
|
+
}
|
|
26
|
+
return (_jsx(PreviewShell, { hint: `report · ${visualization ?? 'table'}`, children: _jsx(PreviewErrorBoundary, { fallbackHint: "The Report references an object/field that doesn't resolve, or its visualization config is incomplete.", children: _jsx(React.Suspense, { fallback: _jsxs("div", { className: "p-6 text-sm text-muted-foreground flex items-center gap-2", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Loading report renderer\u2026"] }), children: _jsx("div", { className: "p-3 min-h-[300px] max-h-[70vh] overflow-auto", children: _jsx(ReportRenderer, { schema: draft, dataSource: adapter }) }) }) }) }));
|
|
27
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* ViewPreview — renders a View metadata draft using the same
|
|
5
|
+
* `object-view` SchemaRenderer the runtime ObjectView route uses,
|
|
6
|
+
* with the current draft's variants injected as `listViews` so the
|
|
7
|
+
* draft drives what authors see (not the saved version).
|
|
8
|
+
*
|
|
9
|
+
* If the draft is a "single-schema legacy" view (no list/form/kanban
|
|
10
|
+
* wrappers, just one top-level `type`), we pass the schema straight
|
|
11
|
+
* to SchemaRenderer.
|
|
12
|
+
*/
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import { SchemaRenderer } from '@object-ui/react';
|
|
15
|
+
import { PreviewShell, PreviewErrorBoundary, PreviewMessage } from './PreviewShell';
|
|
16
|
+
const VIEW_VARIANT_KEYS = [
|
|
17
|
+
'list',
|
|
18
|
+
'form',
|
|
19
|
+
'kanban',
|
|
20
|
+
'calendar',
|
|
21
|
+
'gantt',
|
|
22
|
+
'map',
|
|
23
|
+
'gallery',
|
|
24
|
+
'timeline',
|
|
25
|
+
'feed',
|
|
26
|
+
'detail',
|
|
27
|
+
];
|
|
28
|
+
function detectVariants(draft) {
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const k of VIEW_VARIANT_KEYS) {
|
|
31
|
+
const v = draft[k];
|
|
32
|
+
if (v && typeof v === 'object' && !Array.isArray(v)) {
|
|
33
|
+
out.push({ key: k, schema: v });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
function resolveObjectName(draft, variantSchema) {
|
|
39
|
+
const candidates = [
|
|
40
|
+
variantSchema?.object,
|
|
41
|
+
variantSchema?.data?.object,
|
|
42
|
+
variantSchema?.objectName,
|
|
43
|
+
draft.object,
|
|
44
|
+
draft.objectName,
|
|
45
|
+
draft.data?.object,
|
|
46
|
+
draft.list?.data?.object,
|
|
47
|
+
draft.list?.object,
|
|
48
|
+
];
|
|
49
|
+
for (const c of candidates) {
|
|
50
|
+
if (typeof c === 'string' && c)
|
|
51
|
+
return c;
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
export function ViewPreview({ name, draft }) {
|
|
56
|
+
const variants = React.useMemo(() => detectVariants(draft), [draft]);
|
|
57
|
+
const objectName = React.useMemo(() => resolveObjectName(draft, variants[0]?.schema), [draft, variants]);
|
|
58
|
+
// Compose the listViews map: the draft IS the "default" — surface it as a
|
|
59
|
+
// primary named view FIRST so the view switcher picks it as default. Then
|
|
60
|
+
// append any saved sibling named listViews.
|
|
61
|
+
const { listViews, defaultViewId } = React.useMemo(() => {
|
|
62
|
+
const out = {};
|
|
63
|
+
const primaryVariant = variants.find((v) => v.key === 'list') ?? variants[0];
|
|
64
|
+
const primaryId = String(name) || primaryVariant?.key || 'default';
|
|
65
|
+
if (primaryVariant) {
|
|
66
|
+
out[primaryId] = {
|
|
67
|
+
...primaryVariant.schema,
|
|
68
|
+
label: primaryVariant.schema.label ?? draft.label ?? name,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const saved = draft.listViews;
|
|
72
|
+
if (saved && typeof saved === 'object' && !Array.isArray(saved)) {
|
|
73
|
+
for (const [k, v] of Object.entries(saved)) {
|
|
74
|
+
if (v && typeof v === 'object' && k !== primaryId)
|
|
75
|
+
out[k] = v;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { listViews: out, defaultViewId: primaryVariant ? primaryId : undefined };
|
|
79
|
+
}, [draft, variants, name]);
|
|
80
|
+
// -------------------------------------------------------------------------
|
|
81
|
+
// Path A — single-schema legacy view: render directly.
|
|
82
|
+
// -------------------------------------------------------------------------
|
|
83
|
+
if (!variants.length && draft.type) {
|
|
84
|
+
const schema = { ...draft };
|
|
85
|
+
return (_jsx(PreviewShell, { hint: `view · ${schema.type}`, children: _jsx(PreviewErrorBoundary, { fallbackHint: "The view's `type` may not be registered, or required fields are missing.", children: _jsx("div", { className: "min-h-[300px] max-h-[75vh] overflow-auto", children: _jsx(SchemaRenderer, { schema: schema }) }) }) }));
|
|
86
|
+
}
|
|
87
|
+
if (!objectName) {
|
|
88
|
+
return (_jsx(PreviewShell, { hint: "view", children: _jsxs(PreviewMessage, { tone: "warn", children: ["This view has no object binding yet. Set ", _jsx("code", { children: "list.data.object" }), " in the Form tab to fetch live data."] }) }));
|
|
89
|
+
}
|
|
90
|
+
// -------------------------------------------------------------------------
|
|
91
|
+
// Path B — multi-variant view: delegate to `object-view`, which is what
|
|
92
|
+
// the runtime route uses. Inject the draft's listViews so the preview
|
|
93
|
+
// reflects unsaved edits.
|
|
94
|
+
// -------------------------------------------------------------------------
|
|
95
|
+
const defaultViewType = variants[0]?.schema?.type ?? 'grid';
|
|
96
|
+
const schema = React.useMemo(() => ({
|
|
97
|
+
type: 'object-view',
|
|
98
|
+
objectName,
|
|
99
|
+
defaultViewType,
|
|
100
|
+
defaultListView: defaultViewId,
|
|
101
|
+
listViews,
|
|
102
|
+
showSearch: true,
|
|
103
|
+
showFilters: true,
|
|
104
|
+
showCreate: false,
|
|
105
|
+
showRefresh: true,
|
|
106
|
+
showViewSwitcher: true,
|
|
107
|
+
}), [objectName, defaultViewType, defaultViewId, listViews]);
|
|
108
|
+
const variantHint = variants
|
|
109
|
+
.map((v) => v.key)
|
|
110
|
+
.slice(0, 3)
|
|
111
|
+
.join(' · ');
|
|
112
|
+
return (_jsx(PreviewShell, { hint: `view · ${variantHint || 'list'}`, children: _jsx(PreviewErrorBoundary, { fallbackHint: "The view references an object or field that doesn't resolve.", children: _jsx("div", { className: "min-h-[300px] max-h-[75vh] overflow-auto", children: _jsx(SchemaRenderer, { schema: schema }) }) }) }));
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerBuiltinPreviews(): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* Built-in Preview-tab registrations.
|
|
4
|
+
*
|
|
5
|
+
* Each registration is one line; new types are trivially added without
|
|
6
|
+
* touching `ResourceEditPage.tsx`. To opt OUT of a built-in preview in
|
|
7
|
+
* a downstream app, call `registerMetadataPreview(type, MyVersion)`
|
|
8
|
+
* after this module runs — `registerMetadataPreview` is last-write-wins.
|
|
9
|
+
*/
|
|
10
|
+
import { registerMetadataPreview } from '../preview-registry';
|
|
11
|
+
import { PagePreview } from './PagePreview';
|
|
12
|
+
import { ViewPreview } from './ViewPreview';
|
|
13
|
+
import { DashboardPreview } from './DashboardPreview';
|
|
14
|
+
import { ReportPreview } from './ReportPreview';
|
|
15
|
+
import { AppPreview } from './AppPreview';
|
|
16
|
+
import { ObjectPreview } from './ObjectPreview';
|
|
17
|
+
import { EmailTemplatePreview } from './EmailTemplatePreview';
|
|
18
|
+
export function registerBuiltinPreviews() {
|
|
19
|
+
registerMetadataPreview('page', PagePreview);
|
|
20
|
+
registerMetadataPreview('view', ViewPreview);
|
|
21
|
+
registerMetadataPreview('dashboard', DashboardPreview);
|
|
22
|
+
registerMetadataPreview('report', ReportPreview);
|
|
23
|
+
registerMetadataPreview('app', AppPreview);
|
|
24
|
+
registerMetadataPreview('object', ObjectPreview);
|
|
25
|
+
registerMetadataPreview('email_template', EmailTemplatePreview);
|
|
26
|
+
}
|
|
@@ -180,6 +180,23 @@ export interface MetadataAnchor {
|
|
|
180
180
|
* numbers float to the top. Defaults to 100 if unset.
|
|
181
181
|
*/
|
|
182
182
|
order?: number;
|
|
183
|
+
/**
|
|
184
|
+
* For `source: 'embedded'` only. The metadata type whose schema /
|
|
185
|
+
* form should drive the embedded item's editor. Defaults to the
|
|
186
|
+
* synthetic `type` from the registration when omitted (which will
|
|
187
|
+
* fall back to JSON view).
|
|
188
|
+
*
|
|
189
|
+
* Example: object.fields → `editAs: 'field'` so the embedded editor
|
|
190
|
+
* pulls `field`'s schema + form from `/meta/types`.
|
|
191
|
+
*/
|
|
192
|
+
editAs?: string;
|
|
193
|
+
/**
|
|
194
|
+
* For `source: 'embedded'` only. Dotted path inside the parent body
|
|
195
|
+
* where the collection lives (e.g. `fields`, `validations`). Used by
|
|
196
|
+
* the embedded editor to write the modified item back into the
|
|
197
|
+
* parent on save.
|
|
198
|
+
*/
|
|
199
|
+
embeddedPath?: string;
|
|
183
200
|
}
|
|
184
201
|
/**
|
|
185
202
|
* Helper that returns a `match` reading a (possibly dotted) field path
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/app-shell",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Minimal application shell for ObjectUI - framework-agnostic rendering engine",
|
|
@@ -28,36 +28,36 @@
|
|
|
28
28
|
"@sentry/react": "^10.53.1",
|
|
29
29
|
"lucide-react": "^1.16.0",
|
|
30
30
|
"sonner": "^2.0.7",
|
|
31
|
-
"@object-ui/auth": "6.2.
|
|
32
|
-
"@object-ui/collaboration": "6.2.
|
|
33
|
-
"@object-ui/components": "6.2.
|
|
34
|
-
"@object-ui/plugin-editor": "6.2.
|
|
35
|
-
"@object-ui/core": "6.2.
|
|
36
|
-
"@object-ui/data-objectstack": "6.2.
|
|
37
|
-
"@object-ui/fields": "6.2.
|
|
38
|
-
"@object-ui/i18n": "6.2.
|
|
39
|
-
"@object-ui/layout": "6.2.
|
|
40
|
-
"@object-ui/permissions": "6.2.
|
|
41
|
-
"@object-ui/providers": "6.2.
|
|
42
|
-
"@object-ui/react": "6.2.
|
|
43
|
-
"@object-ui/types": "6.2.
|
|
31
|
+
"@object-ui/auth": "6.2.3",
|
|
32
|
+
"@object-ui/collaboration": "6.2.3",
|
|
33
|
+
"@object-ui/components": "6.2.3",
|
|
34
|
+
"@object-ui/plugin-editor": "6.2.3",
|
|
35
|
+
"@object-ui/core": "6.2.3",
|
|
36
|
+
"@object-ui/data-objectstack": "6.2.3",
|
|
37
|
+
"@object-ui/fields": "6.2.3",
|
|
38
|
+
"@object-ui/i18n": "6.2.3",
|
|
39
|
+
"@object-ui/layout": "6.2.3",
|
|
40
|
+
"@object-ui/permissions": "6.2.3",
|
|
41
|
+
"@object-ui/providers": "6.2.3",
|
|
42
|
+
"@object-ui/react": "6.2.3",
|
|
43
|
+
"@object-ui/types": "6.2.3"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"react": "^18.0.0 || ^19.0.0",
|
|
47
47
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
48
48
|
"react-router-dom": "^6.0.0 || ^7.0.0",
|
|
49
|
-
"@object-ui/plugin-calendar": "^6.2.
|
|
50
|
-
"@object-ui/plugin-charts": "^6.2.
|
|
51
|
-
"@object-ui/plugin-chatbot": "^6.2.
|
|
52
|
-
"@object-ui/plugin-dashboard": "^6.2.
|
|
53
|
-
"@object-ui/plugin-designer": "^6.2.
|
|
54
|
-
"@object-ui/plugin-detail": "^6.2.
|
|
55
|
-
"@object-ui/plugin-form": "^6.2.
|
|
56
|
-
"@object-ui/plugin-grid": "^6.2.
|
|
57
|
-
"@object-ui/plugin-kanban": "^6.2.
|
|
58
|
-
"@object-ui/plugin-list": "^6.2.
|
|
59
|
-
"@object-ui/plugin-report": "^6.2.
|
|
60
|
-
"@object-ui/plugin-view": "^6.2.
|
|
49
|
+
"@object-ui/plugin-calendar": "^6.2.3",
|
|
50
|
+
"@object-ui/plugin-charts": "^6.2.3",
|
|
51
|
+
"@object-ui/plugin-chatbot": "^6.2.3",
|
|
52
|
+
"@object-ui/plugin-dashboard": "^6.2.3",
|
|
53
|
+
"@object-ui/plugin-designer": "^6.2.3",
|
|
54
|
+
"@object-ui/plugin-detail": "^6.2.3",
|
|
55
|
+
"@object-ui/plugin-form": "^6.2.3",
|
|
56
|
+
"@object-ui/plugin-grid": "^6.2.3",
|
|
57
|
+
"@object-ui/plugin-kanban": "^6.2.3",
|
|
58
|
+
"@object-ui/plugin-list": "^6.2.3",
|
|
59
|
+
"@object-ui/plugin-report": "^6.2.3",
|
|
60
|
+
"@object-ui/plugin-view": "^6.2.3"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/node": "^25.9.1",
|