@object-ui/app-shell 11.2.0 → 11.4.0
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 +562 -0
- package/README.md +23 -0
- package/dist/console/ConsoleShell.js +17 -2
- package/dist/console/home/CloudOnboardingNext.d.ts +9 -0
- package/dist/console/home/CloudOnboardingNext.js +14 -4
- package/dist/console/home/HomePage.js +34 -7
- package/dist/console/organizations/CreateWorkspaceDialog.js +33 -3
- package/dist/console/organizations/OrganizationsPage.js +16 -7
- package/dist/hooks/useConsoleActionRuntime.js +32 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/preview/DraftChangesPanel.d.ts +3 -1
- package/dist/preview/DraftChangesPanel.js +6 -5
- package/dist/utils/deriveRelatedLists.d.ts +20 -5
- package/dist/utils/deriveRelatedLists.js +31 -13
- package/dist/utils/index.d.ts +2 -24
- package/dist/utils/index.js +14 -101
- package/dist/utils/resolveViewId.d.ts +23 -0
- package/dist/utils/resolveViewId.js +37 -0
- package/dist/utils/warnSuppressedListNav.d.ts +10 -0
- package/dist/utils/warnSuppressedListNav.js +40 -0
- package/dist/views/DashboardView.js +2 -3
- package/dist/views/InterfaceListPage.js +10 -5
- package/dist/views/ObjectView.js +65 -12
- package/dist/views/PageView.js +2 -3
- package/dist/views/RecordDetailView.js +131 -104
- package/dist/views/RecordFormPage.js +7 -1
- package/dist/views/RelatedRecordActionsBridge.d.ts +24 -0
- package/dist/views/RelatedRecordActionsBridge.js +114 -0
- package/dist/views/ReportView.js +2 -3
- package/dist/views/metadata-admin/PackagesPage.js +18 -7
- package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +18 -1
- package/dist/views/metadata-admin/PermissionMatrixEditor.js +73 -14
- package/dist/views/metadata-admin/clientValidation.js +8 -2
- package/dist/views/metadata-admin/color-variant-field.d.ts +1 -12
- package/dist/views/metadata-admin/color-variant-field.js +11 -0
- package/dist/views/metadata-admin/i18n.d.ts +12 -21
- package/dist/views/metadata-admin/i18n.js +343 -2
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +25 -11
- package/dist/views/metadata-admin/permission-slice.d.ts +66 -0
- package/dist/views/metadata-admin/permission-slice.js +70 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.js +11 -7
- package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +16 -7
- package/dist/views/metadata-admin/previews/FlowRunsPanel.js +18 -2
- package/dist/views/metadata-admin/previews/OutlineStrip.d.ts +1 -13
- package/dist/views/metadata-admin/previews/OutlineStrip.js +12 -0
- package/dist/views/metadata-admin/previews/PagePreview.js +9 -0
- package/dist/views/metadata-admin/previews/SourcePageEditor.d.ts +28 -0
- package/dist/views/metadata-admin/previews/SourcePageEditor.js +83 -0
- package/dist/views/studio-design/BuilderLanding.d.ts +15 -0
- package/dist/views/studio-design/BuilderLanding.js +133 -0
- package/dist/views/studio-design/ObjectFormDesigner.d.ts +31 -0
- package/dist/views/studio-design/ObjectFormDesigner.js +226 -0
- package/dist/views/studio-design/ObjectSettingsPanel.d.ts +30 -0
- package/dist/views/studio-design/ObjectSettingsPanel.js +45 -0
- package/dist/views/studio-design/ObjectValidationsPanel.d.ts +30 -0
- package/dist/views/studio-design/ObjectValidationsPanel.js +78 -0
- package/dist/views/studio-design/StudioDesignSurface.d.ts +20 -0
- package/dist/views/studio-design/StudioDesignSurface.js +1306 -0
- package/dist/views/studio-design/metadataError.d.ts +23 -0
- package/dist/views/studio-design/metadataError.js +44 -0
- package/dist/views/studio-design/packages-io.d.ts +27 -0
- package/dist/views/studio-design/packages-io.js +61 -0
- package/package.json +46 -43
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,567 @@
|
|
|
1
1
|
# @object-ui/app-shell — Changelog
|
|
2
2
|
|
|
3
|
+
## 11.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8bf6295: feat: adaptive record surface + semantic field span + responsive columns (framework#2578)
|
|
8
|
+
|
|
9
|
+
Field-heavy objects (all metadata is AI-authored) now present themselves without
|
|
10
|
+
any authored presentation config:
|
|
11
|
+
|
|
12
|
+
- **Adaptive surface** — a record's create/edit/detail opens as a full page when
|
|
13
|
+
the object is field-heavy, or a drawer when it is light. Derived from field
|
|
14
|
+
count (`deriveRecordSurface`), not authored; mobile always pages. Wired into the
|
|
15
|
+
app-shell ObjectView detail navigation (an authored view/object `navigation`
|
|
16
|
+
still wins).
|
|
17
|
+
- **Semantic field span** — `FormField.span` (`auto`/`full`) is a width primitive
|
|
18
|
+
decoupled from the (per-surface derived) column count; legacy `colSpan` is
|
|
19
|
+
clamped so it never overflows. `ObjectForm` now honours per-section `columns`
|
|
20
|
+
and carries `span`/`colSpan` from section defs — fixes the bug where
|
|
21
|
+
`type:'simple'` ignored `section.columns` and grouped fields rendered single
|
|
22
|
+
column.
|
|
23
|
+
- **Responsive columns** — `inferColumns` scales the column CAP with field count
|
|
24
|
+
(≤3→1, ≤8→2, ≤15→3, 16+→4); the ACTUAL column count follows the form's real
|
|
25
|
+
width via CSS container queries, so the same form goes 1→2→3→4 columns as a
|
|
26
|
+
drawer widens or becomes a page.
|
|
27
|
+
- **Runtime overlay width** — `NavigationConfig.size` bucket is resolved to a
|
|
28
|
+
viewport-clamped width at runtime (`overlayWidthFor`); a pixel width is never
|
|
29
|
+
authored (the author cannot know the client viewport).
|
|
30
|
+
|
|
31
|
+
- 144ab55: Consume the ADR-0085 object semantic roles from `@objectstack/spec@11.7.0`, retiring the per-surface hint dialects:
|
|
32
|
+
|
|
33
|
+
- **Single-source fieldGroups derivation**: `plugin-form`'s `deriveFieldGroupSections` and `plugin-detail`'s `deriveFieldGroupDetailSections` are now thin adapters over the spec's `deriveFieldGroupLayout` (ADR-0085 §5) — forms, modals and detail pages render the SAME grouping from one implementation. The canonical `collapse: 'none' | 'expanded' | 'collapsed'` enum is honoured everywhere (deprecated `collapsible`/`collapsed` and `defaultExpanded` spellings still read for pre-11.7 metadata).
|
|
34
|
+
- **`stageField` semantic role**: the detail stepper reads the top-level `stageField`; `stageField: false` now actually suppresses stage detection (previously the `false` handling was wired to the removed `detail.stageField` key, so spec-authored `false` fell through to the name heuristic).
|
|
35
|
+
- **`highlightFields` rename**: default grid columns, card compact views, the detail highlight strip, child-record preview fields and interface-page default columns read the object's `highlightFields` (deprecated `compactLayout` spelling read as fallback for pre-11.7 metadata).
|
|
36
|
+
- **Removed dead reads**: the never-spec-writable `objectDef.views.*` UI hints and the ADR-0085-removed `detail.*` block (`sections`, `sectionGroups`, `highlightFields`, `stageField`, `useFieldGroups`, `showReferenceRail`, `hideReferenceRail`, `hideRelatedTab`, `relatedLayout`) are no longer consulted. Per-page customization goes through an assigned Page schema (`record:reference_rail` remains available there as a renderer capability). `detail.renderViaSchema` survives only as the legacy-renderer kill-switch and is removed together with that path.
|
|
37
|
+
|
|
38
|
+
- d9f5ccd: feat(studio): package Access door is draft/published, not live (ADR-0086 P2 · D6/D7)
|
|
39
|
+
|
|
40
|
+
The package **Access** pillar edited permission sets **live** — it wrote the
|
|
41
|
+
active record directly, unlike the Data and Interfaces pillars which stage a
|
|
42
|
+
draft and publish with the rest of the package. That contradicted ADR-0086 D6
|
|
43
|
+
("a package's own access is metadata → draft/publish") and left the two doors
|
|
44
|
+
sharing one live write path.
|
|
45
|
+
|
|
46
|
+
Now the **package door** (`/studio/:packageId/access`) writes **drafts**:
|
|
47
|
+
|
|
48
|
+
- The permission editor's Save (`PermissionMatrixEditPage`, package scope) and
|
|
49
|
+
the "new set" creator both call `client.save(..., { mode: 'draft', packageId })`
|
|
50
|
+
— the framework stamps the draft with the package, and the top-bar **Publish**
|
|
51
|
+
promotes it atomically (materialized into `sys_permission_set` by the framework
|
|
52
|
+
side, ADR-0086 P2 块1). The **environment-admin** door (no `packageId`) is
|
|
53
|
+
unchanged: it stays **live** (config), per D7.
|
|
54
|
+
- Reads are draft-aware: the editor loads any pending draft over the published
|
|
55
|
+
baseline, and the pillar rail merges published ∪ draft sets — so a set created
|
|
56
|
+
or edited as a draft stays visible before publish (matching Data/Interfaces).
|
|
57
|
+
Saving bumps the surface's pending-changes counter; a publish reloads the
|
|
58
|
+
published baseline.
|
|
59
|
+
- The pillar banner no longer claims "saved = live" (it said Publish didn't apply
|
|
60
|
+
here) — it now states edits save as package drafts and go live on Publish.
|
|
61
|
+
|
|
62
|
+
- 19f2533: Detail-page related lists: `relatedList: 'primary'` → own tab, multi-FK & self-referential related lists, unified picker columns (framework #2579).
|
|
63
|
+
|
|
64
|
+
- **plugin-detail** (`buildDefaultTabs`): the default related-list layout is now
|
|
65
|
+
the ADR-0085 prominence rule — lists whose FK declares `relatedList: 'primary'`
|
|
66
|
+
each get their OWN tab; every other related list collapses into a single
|
|
67
|
+
"Related" tab. With no primary lists this is byte-for-byte the previous stacked
|
|
68
|
+
default, so it is opt-in per relationship. `relatedLayout: 'tabs' | 'stack'`
|
|
69
|
+
remain app-level overrides (force all-own-tabs / all-stacked).
|
|
70
|
+
- **app-shell** (`deriveRelatedLists`): emits one related list per eligible FK —
|
|
71
|
+
a child referencing the parent through several relationships (e.g.
|
|
72
|
+
`primary_account` + `partner_account`) now surfaces each, disambiguated by the
|
|
73
|
+
FK label; includes self-referential relationships (hierarchies → a "child"
|
|
74
|
+
list); and carries the `isPrimary` prominence flag through. `RecordDetailView`
|
|
75
|
+
threads `isPrimary` into the synthesized page.
|
|
76
|
+
- **fields** (`deriveLookupColumns`): the lookup-picker default columns now
|
|
77
|
+
prefer the object's ADR-0085 `highlightFields` (then legacy `displayFields`,
|
|
78
|
+
then the field walk) — the same "how to list this object" source the related
|
|
79
|
+
list uses, so a picker and a related list of the same object agree with zero
|
|
80
|
+
per-surface config.
|
|
81
|
+
|
|
82
|
+
Pairs with the `@objectstack/spec` change that makes `relatedList` a tri-state
|
|
83
|
+
(`boolean | 'primary'`) and `record:related_list` `columns` optional.
|
|
84
|
+
|
|
85
|
+
- 17374ce: Studio Data pillar Phase B — Validations & Settings views complete the Data v1 surface (builder-ui pillars):
|
|
86
|
+
|
|
87
|
+
- **Validations view**: no-code editing of `ObjectSchema.validations` `script` rules (name / message / CEL fail-condition via the metadata-admin ConditionBuilder, fed the DRAFT field list / severity / active / delete). Non-script rule types (state_machine, format, …) stay visible read-only so the list remains a truthful inventory. New rules default to a VALID never-firing `condition: 'false'` — an empty condition 422s the whole draft save and dead-ends the create flow.
|
|
88
|
+
- **Settings view**: object basics via the shared metadata-admin default inspector (one implementation for both surfaces) plus direct editors for the ADR-0085 semantic roles — `nameField`, `stageField` (incl. the `false` "not a linear flow" state) and ordered `highlightFields` chips.
|
|
89
|
+
- **Draft-only packages fixed in the rail**: the object list now merges `listDrafts()` headers, so a freshly-created writable base shows its draft objects instead of hanging on "加载中…"; the empty state now says the package has no objects yet.
|
|
90
|
+
|
|
91
|
+
### Patch Changes
|
|
92
|
+
|
|
93
|
+
- 4f77044: fix(studio): scope the Access matrix by package + slice-merge on save (ADR-0086 P0)
|
|
94
|
+
|
|
95
|
+
The Access pillar embedded the permission matrix at **environment scope**: it
|
|
96
|
+
listed every object in the environment (the "84-object leak"), and Save
|
|
97
|
+
overwrote the whole permission set — silently dropping authorization rows other
|
|
98
|
+
packages had contributed.
|
|
99
|
+
|
|
100
|
+
Opened inside a package, the matrix now:
|
|
101
|
+
|
|
102
|
+
- lists **only the objects that package declares** (`list('object', { packageId })`),
|
|
103
|
+
so a package's Access panel no longer exposes unrelated objects; and
|
|
104
|
+
- saves via **slice-merge** — it re-reads the record and writes back only this
|
|
105
|
+
package's slice, leaving every row contributed by other packages
|
|
106
|
+
byte-for-byte intact.
|
|
107
|
+
|
|
108
|
+
The Access rail also hides environment-owned platform-default sets
|
|
109
|
+
(`admin_full_access`, `member_default`, …) from a package's panel once the
|
|
110
|
+
backend tags sets with a record-level `package_id` (framework ADR-0086 P1), with
|
|
111
|
+
a mid-migration guard that shows all sets until that provenance axis is live so
|
|
112
|
+
the rail never goes empty. Behavior is unchanged when the editor is used outside
|
|
113
|
+
a package (no `packageId`): full object list, whole-record save.
|
|
114
|
+
|
|
115
|
+
- 1813544: feat(studio): Access pillar — the fourth content pillar (permission matrix)
|
|
116
|
+
|
|
117
|
+
The pillar builder gains **Access** (builder-ui §7 / ADR-0084's fourth pillar):
|
|
118
|
+
left rail lists the environment's permission sets / profiles (search + inline
|
|
119
|
+
create), and the main zone embeds the existing Salesforce-style
|
|
120
|
+
`PermissionMatrixEditPage` unchanged — objects × CRUD/VAMA/lifecycle plus
|
|
121
|
+
per-object field-level R/W, with its own save and destructive-change guard.
|
|
122
|
+
|
|
123
|
+
Deliberate v1 semantics, said out loud in the banner: permissions are
|
|
124
|
+
platform-level authorization objects, not package content — the matrix saves
|
|
125
|
+
the ACTIVE item directly, so the shell's package draft/publish does not apply.
|
|
126
|
+
|
|
127
|
+
- 2318ea2: fix(studio): scope the Access rail server-side by package (ADR-0086 P1)
|
|
128
|
+
|
|
129
|
+
The Access pillar's permission-set rail filtered client-side on a `package_id`
|
|
130
|
+
field read from `client.list('permission')` rows. But the metadata list endpoint
|
|
131
|
+
does not echo the record-level provenance columns — every row comes back with
|
|
132
|
+
`package_id` unset — so the filter's "any set tagged?" guard never fired and the
|
|
133
|
+
rail showed **all** sets, including environment-owned platform defaults
|
|
134
|
+
(`admin_full_access`, `member_default`, …), in a package's Access panel.
|
|
135
|
+
|
|
136
|
+
The rail now scopes server-side via `client.list('permission', { packageId })`:
|
|
137
|
+
the metadata API filters `permission` by the `package_id` provenance seeded in
|
|
138
|
+
framework ADR-0086 P1, returning only the sets this package owns. Verified
|
|
139
|
+
against a live showcase backend — the panel lists exactly `showcase_contributor`
|
|
140
|
+
and `showcase_member_default`, and the four platform defaults are excluded.
|
|
141
|
+
|
|
142
|
+
Removes the now-unused `scopePermissionSetList` client-side helper. Object-matrix
|
|
143
|
+
scoping and Save slice-merge (ADR-0086 P0) are unchanged.
|
|
144
|
+
|
|
145
|
+
- 9aec681: fix(app-shell): stop double-toasting failed script/modal action errors
|
|
146
|
+
|
|
147
|
+
`serverActionHandler` toasted the action error itself **and** returned
|
|
148
|
+
`{ success: false, error }`, which `ActionRunner.handlePostExecution` also
|
|
149
|
+
surfaces as a toast — so a failed script action (e.g. a validation throw)
|
|
150
|
+
showed two identical red toasts.
|
|
151
|
+
|
|
152
|
+
`apiHandler` and `flowHandler` already only return the error and let the
|
|
153
|
+
runner own the toast; `serverActionHandler` now does the same, so a failed
|
|
154
|
+
action toasts exactly once.
|
|
155
|
+
|
|
156
|
+
- 2edcaff: Drop the `compactLayout` fallback reads (6 sites: ObjectGrid default columns, deriveHighlightFields, RecordDetailView highlight strip + child preview, ObjectView ×2, InterfaceListPage). The deprecated spelling was retired from the spec by framework#2539 (framework#2536) — served metadata carries `highlightFields` only, so the fallbacks could never fire again; keeping them would teach the retired key to the next reader.
|
|
157
|
+
- 31f96f7: feat(studio): 复制 (duplicate base) on writable packages in the builder landing
|
|
158
|
+
|
|
159
|
+
Writable base cards on the builder landing gain **复制** — a name/id inline form
|
|
160
|
+
that calls `POST /packages/:id/duplicate` (ADR-0070 D4: re-namespaced clone with
|
|
161
|
+
rewritten references) and drops the user straight into the copy's builder — the
|
|
162
|
+
Airtable "duplicate base" gesture. Read-only code packages stay browse-only:
|
|
163
|
+
duplication copies `sys_metadata` rows, which code packages don't have; their
|
|
164
|
+
customization path is template/marketplace install.
|
|
165
|
+
|
|
166
|
+
- 34b92ac: fix(studio): show a failed flow run's reason in the Runs panel (string errors)
|
|
167
|
+
|
|
168
|
+
The Studio flow **Runs** panel (`FlowRunsPanel`) rendered a run-level error as
|
|
169
|
+
`run.error?.message`, but the automation engine sends `ExecutionLog.error` as a
|
|
170
|
+
plain **string** — so `.message` was always `undefined` and the failure reason,
|
|
171
|
+
the single most useful thing about a failed run, was silently dropped. This grew
|
|
172
|
+
important now that runs are durable (framework #2581): a failed run persists with
|
|
173
|
+
its reason, but the panel showed only a red "Failed" badge and no "why".
|
|
174
|
+
|
|
175
|
+
The panel now normalizes an error through a small `errorText()` helper that
|
|
176
|
+
accepts **either** a string (the run-level shape) **or** a `{ code, message }`
|
|
177
|
+
object (the step-level shape), and uses it for both the run summary and each
|
|
178
|
+
step row. Verified with a jsdom render test (a failed run's string reason reaches
|
|
179
|
+
the DOM) and live in the browser against a real failed run (`showcase_resilient_sync`):
|
|
180
|
+
the reason now displays where it previously showed nothing.
|
|
181
|
+
|
|
182
|
+
- 346e78e: feat(home,studio): builder cover on Home + builder→app bridge
|
|
183
|
+
|
|
184
|
+
Two entries that wire the application builder into the platform journey the
|
|
185
|
+
Airtable way — Home is the cover, the app is the published front-end:
|
|
186
|
+
|
|
187
|
+
- **Home builder cover** (admins/builders only): two guided cards above "Your
|
|
188
|
+
apps" — **Build an app** (start from scratch → `/studio`, pick/create a
|
|
189
|
+
writable package) and **Start with a template** (→ marketplace). End users
|
|
190
|
+
see their apps as before.
|
|
191
|
+
- **打开应用 bridge** in the `/studio` top bar: when the package ships an app,
|
|
192
|
+
one click opens its published front-end (`/apps/<name>`) in a new tab —
|
|
193
|
+
the builder edits the 设计界面, the app is what end users see (Airtable's
|
|
194
|
+
Data ↔ published-Interfaces relationship, our draft→publish included).
|
|
195
|
+
|
|
196
|
+
- c38d107: Fix view-level `FormField.visibleOn` (CEL) never taking effect (#2212).
|
|
197
|
+
|
|
198
|
+
The spec ships `visibleOn` as an Expression object `{ dialect: 'cel', source }`
|
|
199
|
+
(what the `P` template emits) or a bare string, but the whole chain dropped it:
|
|
200
|
+
|
|
201
|
+
- `sectionFields.ts` / `ObjectForm.tsx` only accepted the bare-string shape and
|
|
202
|
+
attached a dead `visible()` closure no renderer ever called — the Expression
|
|
203
|
+
object shape was silently discarded.
|
|
204
|
+
- The form renderer destructured `visibleOn` out of the field config and never
|
|
205
|
+
evaluated it.
|
|
206
|
+
- `RecordFormPage` dropped a `simple` form view's `sections` entirely, so
|
|
207
|
+
page-mode create/edit fell back to the raw schema (every field, no authored
|
|
208
|
+
selection/grouping) while the modal path honored the same view.
|
|
209
|
+
- `ObjectForm`'s grouped-sections path matched section fields by name only,
|
|
210
|
+
dropping per-field `visibleOn` overrides.
|
|
211
|
+
|
|
212
|
+
`visibleOn` now flows through normalization verbatim (both wire shapes) and is
|
|
213
|
+
evaluated reactively by the form renderer with the canonical expression engine
|
|
214
|
+
(`evalFieldPredicate` — same engine, record scope, and fail-open semantics as
|
|
215
|
+
field-level `visibleWhen`; both predicates must allow a field for it to show).
|
|
216
|
+
Sectioned/flat normalization also copies field-level `visibleWhen` /
|
|
217
|
+
`readonlyWhen` / `requiredWhen` rules it previously lost.
|
|
218
|
+
|
|
219
|
+
- 98c9855: fix(studio): lookup target picker can see the package's own draft objects
|
|
220
|
+
|
|
221
|
+
When designing a set of related objects in one authoring pass, the field
|
|
222
|
+
inspector's lookup "related object" picker only listed **published** objects
|
|
223
|
+
(`list('object')`), so sibling objects still in draft — the ones you're most
|
|
224
|
+
likely to point a new lookup at — were invisible and had to be typed as a raw
|
|
225
|
+
API name, blind. The picker now also merges unpublished object drafts
|
|
226
|
+
(`listDrafts({ type: 'object' })`, labelled "(草稿)"), so a lookup can target a
|
|
227
|
+
sibling object before the package's first publish.
|
|
228
|
+
|
|
229
|
+
- 363e8b7: Resolve short view names in `/view/<name>` routes instead of silently falling
|
|
230
|
+
back to the default view (#2217).
|
|
231
|
+
|
|
232
|
+
Nav items emit their `viewName` verbatim — usually the short form
|
|
233
|
+
(`tabular`) — while canonical view ids are fully qualified
|
|
234
|
+
(`showcase_task.tabular`), so nav-generated view links always rendered the
|
|
235
|
+
default view with no hint anything was wrong. `ObjectView` now resolves the
|
|
236
|
+
requested name in both directions (short → `<object>.<name>`, and qualified →
|
|
237
|
+
bare key for legacy embedded listViews), and logs a warning listing the known
|
|
238
|
+
view ids when nothing matches instead of swallowing the miss.
|
|
239
|
+
|
|
240
|
+
- 0cf352b: fix(packages): Setup's package list and creator agree with the builder on writability
|
|
241
|
+
|
|
242
|
+
Two disagreements between Setup › Packages and the application builder about the
|
|
243
|
+
same package:
|
|
244
|
+
|
|
245
|
+
- **Display**: `ScopeBadge` defaulted a missing scope to `project`, so writable
|
|
246
|
+
database bases wore the same badge as read-only code packages. Scope-less
|
|
247
|
+
entries now show **可写/Writable** (emerald), `project` reads **只读 · 代码包 /
|
|
248
|
+
Read-only · code** — matching the builder's labeling.
|
|
249
|
+
- **Semantics**: the create-package dialog hardcoded `scope: 'project'` onto new
|
|
250
|
+
runtime-created bases, which made the builder's switcher/landing mislabel
|
|
251
|
+
Setup-created packages as read-only. New bases are now created scope-less,
|
|
252
|
+
the same shape the builder's own creator produces.
|
|
253
|
+
|
|
254
|
+
- 7782698: fix(components): page:header record title honours `nameField` via the unified ADR-0079 resolver
|
|
255
|
+
|
|
256
|
+
The default console record detail page renders the synthesized `page:header`
|
|
257
|
+
(`buildDefaultPageSchema`, renderViaSchema default-on), whose record-chip title
|
|
258
|
+
chain probed `objSchema.primaryField` (not a spec property — always undefined),
|
|
259
|
+
`titleFormat`, then hardcoded `name`/`full_name`/`title`/`subject`/
|
|
260
|
+
`display_name`/`label` record keys. It never consulted the object's declared
|
|
261
|
+
`nameField`/`displayNameField`, so an object titled by e.g. `subject` rendered
|
|
262
|
+
`<ObjectLabel> <id-prefix>` as its H1 instead of the record's real name.
|
|
263
|
+
|
|
264
|
+
`PageHeaderRenderer` now resolves through `getRecordDisplayName(objSchema, data,
|
|
265
|
+
{ deriveFromRecordKeys: false })` after the author overrides and before the
|
|
266
|
+
legacy probes — mirroring `DetailView.resolveDisplayTitle` so both headers
|
|
267
|
+
agree. `RecordDetailView`'s `primaryField` derivation and
|
|
268
|
+
`buildDefaultPageSchema`'s highlight-strip dedup also honour
|
|
269
|
+
`nameField`/`displayNameField`.
|
|
270
|
+
|
|
271
|
+
- 790558b: fix(studio): make the Automations and Interfaces pillars authorable in a fresh package
|
|
272
|
+
|
|
273
|
+
Dogfooding a brand-new package end-to-end (design objects → automations →
|
|
274
|
+
interfaces → publish → use) surfaced two blocking dead-ends in the pillar
|
|
275
|
+
Studio, both now fixed:
|
|
276
|
+
|
|
277
|
+
- **Automations pillar had no way to create a flow.** For a package with zero
|
|
278
|
+
flows the rail rendered an endless "加载中…" (loading conflated with empty)
|
|
279
|
+
and offered no create affordance, so automations could never be authored.
|
|
280
|
+
It now tracks the list-loaded state (real empty state "还没有自动化 — 点「新建」开始")
|
|
281
|
+
and has a "+ 新建" inline creator that saves a minimal, valid `start → end`
|
|
282
|
+
autolaunched flow skeleton as a draft and opens it in the flow designer.
|
|
283
|
+
|
|
284
|
+
- **Interfaces nav items could not be bound to a target — and silently failed
|
|
285
|
+
to save.** Selecting a nav item showed no inspector, and the item shape the
|
|
286
|
+
editor produced (`{ label, object }`, no `id`/`type`) failed the app spec's
|
|
287
|
+
navigation union ("navigation.N: Invalid input"), so the draft never
|
|
288
|
+
persisted and the published app navigation stayed empty. The right panel now
|
|
289
|
+
renders a `StudioNavItemInspector` with a business-friendly object picker
|
|
290
|
+
(populated from the package's published ∪ draft objects) that emits a
|
|
291
|
+
spec-valid `ObjectNavItem` (`{ id, type:'object', objectName, label }`), and
|
|
292
|
+
the nav save drops still-unbound placeholders + backfills a snake_case id so
|
|
293
|
+
one blank item can't fail the whole save.
|
|
294
|
+
|
|
295
|
+
Also fills in the Home builder-cover i18n keys (`home.build.*`,
|
|
296
|
+
`home.template.*`) in `en`/`zh` so the "Build an app" / "Start with a template"
|
|
297
|
+
cards resolve real strings instead of falling back to defaults.
|
|
298
|
+
|
|
299
|
+
- 3c7abf9: feat(studio): Data pillar left rail gains search + inline "new object"
|
|
300
|
+
|
|
301
|
+
Closes the two remaining v1 rail gaps from the builder design (§4): the objects rail
|
|
302
|
+
now has a **search** filter and an inline **新建对象** creator (显示名 + auto-derived
|
|
303
|
+
snake_case 标识符 — hand-editable, since CJK labels can't derive one). Creating saves
|
|
304
|
+
the object as a **draft in the current package** (same runtime-create path the classic
|
|
305
|
+
Studio editor uses), seeded with one text field, and lands in 表单 · 布局 — the
|
|
306
|
+
metadata-level designer.
|
|
307
|
+
|
|
308
|
+
Draft-only objects (no physical table until the package publish) now get honest
|
|
309
|
+
placeholders instead of broken surfaces: the Records grid explains that data arrives
|
|
310
|
+
after publish (instead of firing SQL at a table that doesn't exist), and 预览 explains
|
|
311
|
+
there is no published definition yet.
|
|
312
|
+
|
|
313
|
+
- 839f6c2: fix(studio): stamp packageId on pillar draft saves → true package-scoped publish
|
|
314
|
+
|
|
315
|
+
Studio pillar draft-saves now pass the active `packageId`, so each draft row is
|
|
316
|
+
stamped with its package binding (`sys_metadata.package_id`) instead of `null`.
|
|
317
|
+
This makes the package-scoped surfaces reliable: the top-bar count + Changes review
|
|
318
|
+
filter via `GET /meta/_drafts?packageId=`, and Publish promotes exactly this
|
|
319
|
+
package's drafts via `POST /packages/:id/publish-drafts` (which matches
|
|
320
|
+
`WHERE package_id = X`). Replaces the previous "publish all pending" fallback that
|
|
321
|
+
was only needed because null-package drafts couldn't be package-filtered or picked
|
|
322
|
+
up by publish-drafts.
|
|
323
|
+
|
|
324
|
+
- 87e7c23: feat(studio): builder landing + `studio:builder` entry — the builder joins the login journey
|
|
325
|
+
|
|
326
|
+
The pillar application builder was a URL-only surface (zero links anywhere pointed at
|
|
327
|
+
`/studio/...`). Now it has a front door wired into the platform journey:
|
|
328
|
+
|
|
329
|
+
- **BuilderLanding** — pick or create a writable base package (writable bases lead,
|
|
330
|
+
read-only code packages listed for browsing), then jump into the full-screen pillar
|
|
331
|
+
builder. Served standalone at bare **`/studio`** (bookmarkable) and embeddable via
|
|
332
|
+
the **`studio:builder`** component ref, which the framework's Studio app references
|
|
333
|
+
from its new 「App Builder」 nav entry — so the journey is: login → Home → Studio →
|
|
334
|
+
App Builder → package → build.
|
|
335
|
+
- `/studio/:packageId` now lands on **`data`** (the pillar order's first surface)
|
|
336
|
+
instead of `interfaces`.
|
|
337
|
+
- Package-list parsing/creation is extracted to `packages-io` and shared by the
|
|
338
|
+
landing and the top-bar package switcher.
|
|
339
|
+
|
|
340
|
+
- 5ba3d0e: feat(studio): WYSIWYG form-layout designer in the Data pillar
|
|
341
|
+
|
|
342
|
+
The Data pillar's Form view gains a **布局 (Layout)** designer: the object's default
|
|
343
|
+
form rendered WYSIWYG, where an admin adds **sections**, drag-reorders fields within
|
|
344
|
+
a section and drags them **across** sections, and clicks a field to edit it in the
|
|
345
|
+
**same** protocol inspector the grid uses — one screen, no Data↔Interface switch.
|
|
346
|
+
|
|
347
|
+
Sections persist as the object's `fieldGroups`, and membership/order as `field.group`
|
|
348
|
+
plus field order, via the existing draft → publish. The drag/section chrome (dnd-kit)
|
|
349
|
+
is the only new code; the data model and all mutations reuse the existing, tested
|
|
350
|
+
`object-fields-io` helpers (`readGroups`/`addGroup`/`renameGroup`/`removeGroup`/
|
|
351
|
+
`moveGroup`/`clearFieldGroup`/`groupEntries`).
|
|
352
|
+
|
|
353
|
+
Also fixes the Data pillar clobbering an in-progress draft when the metadata client
|
|
354
|
+
identity churned (e.g. toggling the live preview): the object baseline is now loaded
|
|
355
|
+
exactly once per selected object.
|
|
356
|
+
|
|
357
|
+
- c0164ad: fix(studio): surface spec-validation failures on the field at save/publish
|
|
358
|
+
|
|
359
|
+
When a Studio metadata draft failed spec validation, the designer got a single
|
|
360
|
+
opaque banner (and, on a partial publish, a false "published!" toast) — the
|
|
361
|
+
server was already returning field-anchored issues, but the client threw them
|
|
362
|
+
away. Two problems, both fixed:
|
|
363
|
+
|
|
364
|
+
- **`parseError` (data-objectstack)** read `String(body.error)`, which yields
|
|
365
|
+
`"[object Object]"` for the dispatcher's object-shaped error, and ignored the
|
|
366
|
+
validation `issues`. It now reads the message from either shape (string or
|
|
367
|
+
`{ message }`) and exposes `MetadataError.issues`, accepting all live server
|
|
368
|
+
shapes — top-level `body.issues` (REST server) and `error.details.issues`
|
|
369
|
+
(HTTP dispatcher).
|
|
370
|
+
|
|
371
|
+
- **Studio save/publish (app-shell)** now render those issues **field-anchored**.
|
|
372
|
+
A new `formatMetadataError` helper turns a caught error into one line per
|
|
373
|
+
offending field (`• fields.amount.type — Invalid option: …`); the save banners
|
|
374
|
+
render it with `whitespace-pre-line`. `doPublish` no longer claims success when
|
|
375
|
+
the response carries `data.failed[]` — it lists which drafts failed and why
|
|
376
|
+
(the server returns 200 with the failures buried, so the UI used to swallow
|
|
377
|
+
them). `formatPublishFailures` formats those per-draft.
|
|
378
|
+
|
|
379
|
+
Verified end-to-end against a live backend: an invalid object draft returns 422
|
|
380
|
+
with field-anchored issues, and the Studio banner shows
|
|
381
|
+
`• fields.amount.type — Invalid option: expected one of "text"|…` instead of a
|
|
382
|
+
generic message. Unit-tested: `parseError` on the dispatcher shape, and the
|
|
383
|
+
`formatMetadataError` / `formatPublishFailures` helpers.
|
|
384
|
+
|
|
385
|
+
- 7034306: fix(studio): Interfaces designs the CURRENT package's app, not another's
|
|
386
|
+
|
|
387
|
+
The Interfaces pillar resolved its app with an unscoped `list('app')` and a
|
|
388
|
+
client-side `.find()` by package — but list rows carry no `packageId`, so the
|
|
389
|
+
match never hit and it fell through to `?? apps[0]`, the first app in the whole
|
|
390
|
+
system. Opening `/studio/<pkg>/interfaces` for a package with no app therefore
|
|
391
|
+
rendered a **different** package's navigation tree (e.g. `showcase_app`), and a
|
|
392
|
+
package that genuinely had no app was stuck on an endless "加载中…".
|
|
393
|
+
|
|
394
|
+
Now the query is scoped to the package (`list('app', { packageId })`, matching
|
|
395
|
+
the header's own resolution) with no cross-package fallback; a freshly-created
|
|
396
|
+
(still-draft) app is picked up via `listDrafts({ packageId, type: 'app' })` so it
|
|
397
|
+
stays designable before its first publish. When the package has no app, the nav
|
|
398
|
+
rail and canvas show a real empty state ("这个软件包还没有应用") with a 创建应用
|
|
399
|
+
action wired to the header's existing create flow, and edit mode now renders the
|
|
400
|
+
nav canvas even on an empty tree so the first item can be added.
|
|
401
|
+
|
|
402
|
+
- 34accfc: fix(studio): close the three journey dead-ends found in UX review
|
|
403
|
+
|
|
404
|
+
- **Navigation**: the standalone `/studio` landing gets a slim frame with an
|
|
405
|
+
ObjectOS wordmark → Home, and the builder top bar gets a Home button — the
|
|
406
|
+
builder is no longer a browser-back-only dead end.
|
|
407
|
+
- **Fresh-package empty state**: an empty writable package no longer shows an
|
|
408
|
+
endless 加载中… — the rail says 还没有对象, the main pane explains the first
|
|
409
|
+
act (从第一个对象开始), and the object creator auto-opens.
|
|
410
|
+
- **创建应用 on-ramp**: when the package ships no app, the top-bar bridge slot
|
|
411
|
+
offers 创建应用 (draft `app` item, name + identifier popover) instead of
|
|
412
|
+
nothing; after creation it shows 应用「…」待发布, and flips to 打开应用 once
|
|
413
|
+
the package publish lands.
|
|
414
|
+
|
|
415
|
+
- 65efc01: feat(studio): package-level draft publish (replaces per-item publish)
|
|
416
|
+
|
|
417
|
+
The pillar Studio now publishes at the **package** level, not item-by-item. Edits
|
|
418
|
+
across Data / Automation / Interface accumulate as per-item **drafts**; the top bar
|
|
419
|
+
shows a pending-draft **count**, a **变更** (Changes) review, and one **发布** that
|
|
420
|
+
publishes **all** pending drafts in a single governed pass — reusing
|
|
421
|
+
`usePublishAllDrafts` (per-package `publish-drafts` with structure-before-seeds + the
|
|
422
|
+
ADR-0038 L3 probes, and by-reference for orphan / null-package drafts).
|
|
423
|
+
|
|
424
|
+
- The per-pillar **发布** buttons are removed; **保存草稿** stays (drafts accumulate).
|
|
425
|
+
- The Data grid's drag-reorder no longer **auto-publishes** — it saves a draft like
|
|
426
|
+
every other edit, so nothing goes live outside the one package publish.
|
|
427
|
+
- After a publish, pillars re-read the fresh published baseline (a publish nonce),
|
|
428
|
+
and a draft-save refreshes the pending count.
|
|
429
|
+
|
|
430
|
+
- d8b9547: feat(studio): package switcher + inline "new writable package" in the top bar
|
|
431
|
+
|
|
432
|
+
The pillar Studio's top-bar package name becomes a **switcher**: it lists the app's
|
|
433
|
+
packages (kernel/system packages hidden), marks each **可写** (database base) or
|
|
434
|
+
**只读** (code package — the ADR-0070 D4 gate refuses authoring into these), and
|
|
435
|
+
switches by navigation. A **新建软件包** inline form creates a writable base
|
|
436
|
+
(`POST /packages {id,name}` — 名称 + auto-derived, hand-editable package id) and
|
|
437
|
+
jumps straight into its Data pillar.
|
|
438
|
+
|
|
439
|
+
The current package also shows a proactive **只读** badge, so users learn the
|
|
440
|
+
package is read-only _before_ hitting the save-time gate. Writability display is a
|
|
441
|
+
heuristic (`scope: 'project'` = code, scope-less = base); the server-side gate stays
|
|
442
|
+
the authority.
|
|
443
|
+
|
|
444
|
+
- 20c1695: Studio pillars now follow the app's active locale instead of hardcoding Chinese.
|
|
445
|
+
`StudioDesignSurface` pinned `const locale = 'zh-CN'` in its Interfaces / Data /
|
|
446
|
+
Automations pillars, so the builder always rendered Chinese even when the console
|
|
447
|
+
ran in English (while the Home page and the rest of the app followed the active
|
|
448
|
+
locale). Every inline string across the design surface — package switcher,
|
|
449
|
+
publish/app-bridge header, the four pillars (Data, Automations, Interfaces,
|
|
450
|
+
Access), and the nav-item inspector — is now extracted into the metadata-admin
|
|
451
|
+
`engine.studio.*` catalog with English + Chinese entries, and a new
|
|
452
|
+
`useMetadataLocale()` hook threads the live `useObjectTranslation().language`
|
|
453
|
+
(the same source the LocaleSwitcher drives) so switching the console language
|
|
454
|
+
re-renders the Studio in lock-step. `AppNavCanvas` (used by the Studio and the
|
|
455
|
+
metadata-admin App preview) is likewise localized via `engine.appNav.*` — its
|
|
456
|
+
previously hardcoded English "NAVIGATION", "Add nav item", "Remove nav item", and
|
|
457
|
+
empty-state strings now follow the active locale.
|
|
458
|
+
- 00e7735: fix(studio): say what the Form preview shows — published definition, not the draft
|
|
459
|
+
|
|
460
|
+
The Data pillar's Form view has two sub-modes: **布局** (the WYSIWYG layout designer,
|
|
461
|
+
rendered from the draft) and **预览** (the live runtime ObjectForm). The preview
|
|
462
|
+
renders the **published** definition on purpose — a draft with structural changes has
|
|
463
|
+
no physical columns yet (DDL lands at publish), so a draft-with-data preview would
|
|
464
|
+
break — but the UI never said so: after arranging a draft in 布局, switching to 预览
|
|
465
|
+
silently showed the old shape, reading as "my changes are lost".
|
|
466
|
+
|
|
467
|
+
Now the sub-mode captions state their source (布局 = 草稿 · 含未发布改动 / 预览 =
|
|
468
|
+
已发布定义), and when unpublished changes exist the preview shows an amber note:
|
|
469
|
+
confirm the draft in 布局, or publish (top bar) first to see the published effect.
|
|
470
|
+
Publishing stays a deliberate user action — nothing auto-publishes.
|
|
471
|
+
|
|
472
|
+
- e84d64d: Block record-scoped toolbar actions launched with zero rows selected (#2210).
|
|
473
|
+
|
|
474
|
+
A flow/script action that also mounts on list rows (`locations` includes
|
|
475
|
+
`list_item`) has no record to run on when triggered from the list toolbar with
|
|
476
|
+
nothing selected — pre-fix the wizard opened anyway, collected input, and died
|
|
477
|
+
at its first record-bound node ("Update requires an ID or options.multi=true").
|
|
478
|
+
The console runtime now blocks up front with "select a row first", mirroring
|
|
479
|
+
the existing multi-selection guard. Pure object-level toolbar actions
|
|
480
|
+
(`locations: ['list_toolbar']` only) keep triggering without a record.
|
|
481
|
+
|
|
482
|
+
The action renderers (button/icon/menu/group) now forward the `locations`
|
|
483
|
+
declaration to the ActionRunner — previously it was dropped by their
|
|
484
|
+
allow-list payloads, so the runtime could not tell the two shapes apart.
|
|
485
|
+
|
|
486
|
+
- 3106584: Warn when `userFilters` / `quickFilters` on an object list view are
|
|
487
|
+
suppressed instead of dropping them silently (#2219).
|
|
488
|
+
|
|
489
|
+
ADR-0053 correctly reserves those fields for page lists (InterfaceListPage
|
|
490
|
+
"filters" mode) and suppresses them on the object default list, but until the
|
|
491
|
+
phase-4 schema guardrail lands the author got zero signal — a valid schema
|
|
492
|
+
and a toolbar with nothing where the filter controls should be. ObjectView
|
|
493
|
+
now logs a one-shot warning per object/view naming the offending fields and
|
|
494
|
+
where they belong.
|
|
495
|
+
|
|
496
|
+
- Updated dependencies [8bf6295]
|
|
497
|
+
- Updated dependencies [1948c5b]
|
|
498
|
+
- Updated dependencies [bce581a]
|
|
499
|
+
- Updated dependencies [9cd9be1]
|
|
500
|
+
- Updated dependencies [5160832]
|
|
501
|
+
- Updated dependencies [69d6b94]
|
|
502
|
+
- Updated dependencies [c38d107]
|
|
503
|
+
- Updated dependencies [243a9ba]
|
|
504
|
+
- Updated dependencies [289be5b]
|
|
505
|
+
- Updated dependencies [7782698]
|
|
506
|
+
- Updated dependencies [19f2533]
|
|
507
|
+
- Updated dependencies [790558b]
|
|
508
|
+
- Updated dependencies [c0164ad]
|
|
509
|
+
- Updated dependencies [09e1b26]
|
|
510
|
+
- Updated dependencies [e84d64d]
|
|
511
|
+
- @object-ui/types@11.4.0
|
|
512
|
+
- @object-ui/components@11.4.0
|
|
513
|
+
- @object-ui/fields@11.4.0
|
|
514
|
+
- @object-ui/i18n@11.4.0
|
|
515
|
+
- @object-ui/data-objectstack@11.4.0
|
|
516
|
+
- @object-ui/auth@11.4.0
|
|
517
|
+
- @object-ui/collaboration@11.4.0
|
|
518
|
+
- @object-ui/core@11.4.0
|
|
519
|
+
- @object-ui/layout@11.4.0
|
|
520
|
+
- @object-ui/permissions@11.4.0
|
|
521
|
+
- @object-ui/plugin-editor@11.4.0
|
|
522
|
+
- @object-ui/providers@11.4.0
|
|
523
|
+
- @object-ui/react@11.4.0
|
|
524
|
+
|
|
525
|
+
## 11.3.0
|
|
526
|
+
|
|
527
|
+
### Patch Changes
|
|
528
|
+
|
|
529
|
+
- ca4a795: fix(app-shell): restore admin design surface gated on the removed `user.role='admin'` overwrite
|
|
530
|
+
|
|
531
|
+
ADR-0068 (a3a5abff8) stopped the server `customSession` from overwriting
|
|
532
|
+
`user.role = 'admin'` for workspace owners/admins — canonical roles now arrive
|
|
533
|
+
in `user.roles[]` (`org_owner` / `org_admin`) with `user.isPlatformAdmin` as a
|
|
534
|
+
derived alias, and `useIsWorkspaceAdmin()` was introduced to read them. Four
|
|
535
|
+
runtime views were missed in that migration and still gated their admin design
|
|
536
|
+
tools on the now-defunct `user?.role === 'admin'`, so workspace owners/admins
|
|
537
|
+
silently lost:
|
|
538
|
+
|
|
539
|
+
- **ObjectView** — the list "+ New view" button plus rename/delete/pin/
|
|
540
|
+
set-default/config/manage-views and the view config panel.
|
|
541
|
+
- **PageView / DashboardView / ReportView** — the inline "Edit"/config entry
|
|
542
|
+
points for the shared page / dashboard / report definitions.
|
|
543
|
+
|
|
544
|
+
All four now call `useIsWorkspaceAdmin()` (same helper already adopted by
|
|
545
|
+
AppSidebar, UnifiedSidebar, HomePage, Marketplace…). No behavior change for
|
|
546
|
+
genuine platform admins; restores the surface for org owners/admins.
|
|
547
|
+
|
|
548
|
+
- Updated dependencies [d88c8ec]
|
|
549
|
+
- Updated dependencies [b7237bb]
|
|
550
|
+
- Updated dependencies [d23d6eb]
|
|
551
|
+
- @object-ui/components@11.3.0
|
|
552
|
+
- @object-ui/i18n@11.3.0
|
|
553
|
+
- @object-ui/core@11.3.0
|
|
554
|
+
- @object-ui/fields@11.3.0
|
|
555
|
+
- @object-ui/layout@11.3.0
|
|
556
|
+
- @object-ui/plugin-editor@11.3.0
|
|
557
|
+
- @object-ui/react@11.3.0
|
|
558
|
+
- @object-ui/data-objectstack@11.3.0
|
|
559
|
+
- @object-ui/types@11.3.0
|
|
560
|
+
- @object-ui/auth@11.3.0
|
|
561
|
+
- @object-ui/permissions@11.3.0
|
|
562
|
+
- @object-ui/collaboration@11.3.0
|
|
563
|
+
- @object-ui/providers@11.3.0
|
|
564
|
+
|
|
3
565
|
## 11.2.0
|
|
4
566
|
|
|
5
567
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -164,6 +164,29 @@ enable, or disable packages; direct `/metadata/package` links redirect there.
|
|
|
164
164
|
The Studio sidebar also flattens the root Overview group so Home and package
|
|
165
165
|
navigation sit directly under the package selector.
|
|
166
166
|
|
|
167
|
+
### Access matrix (package-scoped)
|
|
168
|
+
|
|
169
|
+
The Access pillar's permission matrix follows the active package (ADR-0086 P0).
|
|
170
|
+
A Permission Set / Profile is a single record whose `objects` / `fields` maps
|
|
171
|
+
accumulate authorization rows contributed by many packages, so the matrix:
|
|
172
|
+
|
|
173
|
+
- lists **only the objects the active package declares** — the panel never
|
|
174
|
+
exposes the whole environment's objects; and
|
|
175
|
+
- saves via **slice-merge** — it re-reads the record and writes back just this
|
|
176
|
+
package's slice, leaving rows contributed by other packages untouched.
|
|
177
|
+
|
|
178
|
+
The left rail lists only permission sets this package owns — the metadata API
|
|
179
|
+
filters `permission` by the record-level `package_id` provenance server-side
|
|
180
|
+
(framework ADR-0086 P1), via `client.list('permission', { packageId })`, so
|
|
181
|
+
environment-owned platform defaults (`admin_full_access`, `member_default`, …)
|
|
182
|
+
are excluded by the backend. (The `?package=` list rows don't echo the
|
|
183
|
+
provenance columns, so a client-side filter can't do this.) Save writes a
|
|
184
|
+
package draft and publishes with the whole package (ADR-0086 P2). Rendering
|
|
185
|
+
`PermissionMatrixEditPage` without a `packageId` keeps the environment-wide
|
|
186
|
+
behavior (full object list, whole-record save). The scope/merge helpers
|
|
187
|
+
(`scopePermissionSet`, `mergePermissionSlice`) live in
|
|
188
|
+
`metadata-admin/permission-slice.ts`.
|
|
189
|
+
|
|
167
190
|
### Visual flow canvas
|
|
168
191
|
|
|
169
192
|
The `flow` designer (`FlowPreview` → `FlowCanvas`) renders an automation as an
|
|
@@ -14,7 +14,8 @@ import { Suspense, useEffect, useRef, useState } from 'react';
|
|
|
14
14
|
import { Navigate, useLocation } from 'react-router-dom';
|
|
15
15
|
import { AuthGuard, useAuth } from '@object-ui/auth';
|
|
16
16
|
import { useObjectTranslation } from '@object-ui/i18n';
|
|
17
|
-
import { SchemaRendererProvider } from '@object-ui/react';
|
|
17
|
+
import { SchemaRendererProvider, ActionProvider } from '@object-ui/react';
|
|
18
|
+
import { useActionModal } from '../hooks/useActionModal';
|
|
18
19
|
import { createObjectStackUserStateAdapter } from '@object-ui/data-objectstack';
|
|
19
20
|
import { AdapterProvider, useAdapter } from '../providers/AdapterProvider';
|
|
20
21
|
import { MetadataProvider, useMetadata } from '../providers/MetadataProvider';
|
|
@@ -29,6 +30,20 @@ import { RemediationOverlay } from './RemediationOverlay';
|
|
|
29
30
|
export function LoadingFallback() {
|
|
30
31
|
return (_jsx("div", { className: "h-screen flex items-center justify-center text-sm text-muted-foreground", children: "Loading\u2026" }));
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Provide a MODAL handler at the console ROOT — the same level the global
|
|
35
|
+
* SchemaRendererProvider (dataSource) sits — so it reaches EVERY field widget,
|
|
36
|
+
* including a relation field inside a create/edit form that renders in a Radix
|
|
37
|
+
* Dialog portal (which sits above the lower per-view ActionProviders). This is
|
|
38
|
+
* what lets a lookup's inline "create the referenced record" open that object's
|
|
39
|
+
* OWN create form and select the result. Only ADDS the modal capability where
|
|
40
|
+
* none existed; richer per-view ActionProviders still override it where they
|
|
41
|
+
* apply. Must render inside MetadataProvider (useActionModal reads useMetadata).
|
|
42
|
+
*/
|
|
43
|
+
function GlobalCreateModalProvider({ dataSource, children }) {
|
|
44
|
+
const { modalHandler, modalElement } = useActionModal(dataSource);
|
|
45
|
+
return (_jsxs(ActionProvider, { onModal: modalHandler, children: [children, modalElement] }));
|
|
46
|
+
}
|
|
32
47
|
/**
|
|
33
48
|
* ConsoleShell — top-level provider stack shared by every console route.
|
|
34
49
|
* Wraps children in ThemeProvider + NavigationProvider + FavoritesProvider +
|
|
@@ -87,7 +102,7 @@ function ConnectedShellInner({ children }) {
|
|
|
87
102
|
return _jsx(LoadingFallback, {});
|
|
88
103
|
// Expose the adapter via SchemaRendererContext so descendant hooks like
|
|
89
104
|
// useDiscovery() (used to gate the global AI chatbot) can resolve it.
|
|
90
|
-
return (_jsx(SchemaRendererProvider, { dataSource: adapter, children: _jsxs(MetadataProvider, { adapter: adapter, children: [_jsx(UserStateBridge, {}), children] }, language) }));
|
|
105
|
+
return (_jsx(SchemaRendererProvider, { dataSource: adapter, children: _jsxs(MetadataProvider, { adapter: adapter, children: [_jsx(UserStateBridge, {}), _jsx(GlobalCreateModalProvider, { dataSource: adapter, children: children })] }, language) }));
|
|
91
106
|
}
|
|
92
107
|
/**
|
|
93
108
|
* UserStateBridge — once we have an authenticated user + a connected data
|
|
@@ -4,6 +4,15 @@ interface CloudOnboardingNextProps {
|
|
|
4
4
|
openProductionUrl?: string;
|
|
5
5
|
/** SPA route to the environments list (create / open / manage). */
|
|
6
6
|
environmentsRoute?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional backend pre-warm endpoint. When set and the caller already has
|
|
9
|
+
* a production env, the widget fires a best-effort GET the moment it knows
|
|
10
|
+
* the env exists — nudging a possibly-asleep container awake WHILE the user
|
|
11
|
+
* reads the hint, so the later "Open Production" click lands in an
|
|
12
|
+
* already-waking env instead of paying the full cold-start. No-op when
|
|
13
|
+
* unset (older page metadata), so this is safe to ship ahead of the page.
|
|
14
|
+
*/
|
|
15
|
+
warmUrl?: string;
|
|
7
16
|
};
|
|
8
17
|
}
|
|
9
18
|
export declare function CloudOnboardingNext({ properties }: CloudOnboardingNextProps): import("react").JSX.Element;
|