@rebasepro/admin 0.16.0 → 0.16.1-canary.g2d1aec8
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/dist/{CollectionEditorDialog-D2Vf4C3-.js → CollectionEditorDialog-Cec5jU6R.js} +7 -3
- package/dist/{CollectionEditorDialog-D2Vf4C3-.js.map → CollectionEditorDialog-Cec5jU6R.js.map} +1 -1
- package/dist/{PropertyEditView-D3NBsK9_.js → PropertyEditView-BuSPZwnQ.js} +2 -2
- package/dist/{PropertyEditView-D3NBsK9_.js.map → PropertyEditView-BuSPZwnQ.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-hPB54l3Q.js → RouterCollectionsStudioView-BiNFpEii.js} +4 -4
- package/dist/{RouterCollectionsStudioView-hPB54l3Q.js.map → RouterCollectionsStudioView-BiNFpEii.js.map} +1 -1
- package/dist/SchemaChangeDialog-WKIbzS6P.js +327 -0
- package/dist/SchemaChangeDialog-WKIbzS6P.js.map +1 -0
- package/dist/collection_editor/ConfigControllerProvider.d.ts +4 -4
- package/dist/collection_editor/_cms_internals.d.ts +23 -23
- package/dist/collection_editor/api/index.d.ts +1 -1
- package/dist/collection_editor/extensibility_types.d.ts +1 -1
- package/dist/collection_editor/index.d.ts +21 -21
- package/dist/collection_editor/liveSchemaClient.d.ts +170 -0
- package/dist/collection_editor/serializable_utils.d.ts +1 -1
- package/dist/collection_editor/types/collection_editor_controller.d.ts +1 -1
- package/dist/collection_editor/types/config_controller.d.ts +11 -0
- package/dist/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/AIModifiedPathsContext.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +4 -4
- package/dist/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/CollectionStudioView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/CollectionsStudioView.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/GeneralSettingsForm.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/PropertyEditView.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/RouterCollectionStudioView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/RouterCollectionsStudioView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/SchemaChangeDialog.d.ts +66 -0
- package/dist/collection_editor/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/import/clean_import_data.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/properties/conditions/index.d.ts +6 -6
- package/dist/collection_editor/useCollectionEditorController.d.ts +1 -1
- package/dist/collection_editor/useCollectionsConfigController.d.ts +1 -1
- package/dist/collection_editor/useJsonCollectionsConfigController.d.ts +2 -2
- package/dist/collection_editor/useLiveSchemaEditing.d.ts +71 -0
- package/dist/collection_editor/useLocalCollectionsConfigController.d.ts +1 -1
- package/dist/collection_editor_ui.d.ts +12 -12
- package/dist/collection_editor_ui.js +4 -4
- package/dist/components/CollectionTableBinding/CollectionTableBinding.d.ts +1 -1
- package/dist/components/CollectionTableBinding/PropertyTableCell.d.ts +1 -1
- package/dist/components/CollectionTableBinding/fields/TableStorageUpload.d.ts +1 -1
- package/dist/components/CollectionTableBinding/index.d.ts +5 -5
- package/dist/components/CollectionTableBinding/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/components/CollectionViewBinding/SlotValue.d.ts +2 -2
- package/dist/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.d.ts +1 -1
- package/dist/components/EditFormActions.d.ts +1 -1
- package/dist/components/EditViewBinding.d.ts +3 -3
- package/dist/components/EntityInspector.d.ts +1 -1
- package/dist/components/EntityPreviewBinding.d.ts +1 -1
- package/dist/components/EntityViewBinding.d.ts +1 -1
- package/dist/components/HomePage/index.d.ts +4 -4
- package/dist/components/PropertyCollectionView.d.ts +1 -1
- package/dist/components/ReferenceWidget.d.ts +1 -1
- package/dist/components/admin/index.d.ts +1 -1
- package/dist/components/app/AppBar.d.ts +1 -1
- package/dist/components/app/index.d.ts +4 -4
- package/dist/components/common/index.d.ts +1 -1
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/components/history/EntityHistoryEntry.d.ts +2 -2
- package/dist/components/history/index.d.ts +5 -5
- package/dist/components/index.d.ts +45 -45
- package/dist/data_export/export/index.d.ts +4 -4
- package/dist/data_export/index.d.ts +1 -1
- package/dist/data_import/components/DataNewPropertiesMapping.d.ts +1 -1
- package/dist/data_import/components/ImportSaveInProgress.d.ts +1 -1
- package/dist/data_import/components/index.d.ts +4 -4
- package/dist/data_import/hooks/index.d.ts +1 -1
- package/dist/data_import/hooks/useImportConfig.d.ts +1 -1
- package/dist/data_import/import/ImportCollectionAction.d.ts +1 -1
- package/dist/data_import/import/index.d.ts +1 -1
- package/dist/data_import/index.d.ts +5 -5
- package/dist/data_import/types/index.d.ts +1 -1
- package/dist/data_import/utils/file_to_json.d.ts +1 -1
- package/dist/data_import/utils/index.d.ts +5 -5
- package/dist/editor/components/SlashCommandMenu.d.ts +2 -2
- package/dist/editor/components/index.d.ts +5 -5
- package/dist/editor/editor.d.ts +2 -2
- package/dist/editor/index.d.ts +2 -2
- package/dist/editor/nodeViews/ImageComponent.d.ts +1 -1
- package/dist/editor/nodeViews/TaskItemComponent.d.ts +1 -1
- package/dist/editor/types.d.ts +1 -1
- package/dist/{export-oauWlxuu.js → export-BItpoIu0.js} +2 -2
- package/dist/{export-oauWlxuu.js.map → export-BItpoIu0.js.map} +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/EntityFormActions.d.ts +1 -1
- package/dist/form/EntityFormBinding.d.ts +1 -1
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/StorageItemPreview.d.ts +1 -1
- package/dist/form/components/index.d.ts +6 -6
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BinaryFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/DateTimeFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/GeopointFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +2 -2
- package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MultipleRelationFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/VectorFieldBinding.d.ts +1 -1
- package/dist/form/index.d.ts +24 -24
- package/dist/{history-C2cqc0bw.js → history-C7WF14VR.js} +2 -2
- package/dist/{history-C2cqc0bw.js.map → history-C7WF14VR.js.map} +1 -1
- package/dist/hooks/index.d.ts +16 -16
- package/dist/hooks/navigation/contexts/index.d.ts +3 -3
- package/dist/hooks/useBuildSideDialogsController.d.ts +1 -1
- package/dist/hooks/useSelectionDialog.d.ts +1 -1
- package/dist/{import-Bxv5JPm-.js → import-CZgNAlcd.js} +2 -2
- package/dist/{import-Bxv5JPm-.js.map → import-CZgNAlcd.js.map} +1 -1
- package/dist/index.d.ts +17 -15
- package/dist/index.js +238 -21
- package/dist/index.js.map +1 -1
- package/dist/preview/PropertyPreview.d.ts +1 -1
- package/dist/preview/components/ArrayEnumPreview.d.ts +1 -1
- package/dist/preview/components/BooleanPreview.d.ts +1 -1
- package/dist/preview/components/ImagePreview.d.ts +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +1 -1
- package/dist/preview/components/RelationPreview.d.ts +1 -1
- package/dist/preview/components/StorageThumbnail.d.ts +1 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -2
- package/dist/preview/components/UserPreview.d.ts +1 -1
- package/dist/preview/index.d.ts +24 -24
- package/dist/preview/property_previews/ArrayOfMapsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfReferencesPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfRelationsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOneOfPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayPropertyEnumPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/MapPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/NumberPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
- package/dist/preview/property_previews/StringPropertyPreview.d.ts +1 -1
- package/dist/preview/util.d.ts +1 -1
- package/dist/routes/index.d.ts +2 -2
- package/dist/types/components/EntityFormActionsProps.d.ts +2 -2
- package/dist/types/components/EntityFormProps.d.ts +3 -3
- package/dist/types/components/index.d.ts +3 -3
- package/dist/types/fields.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/util/index.d.ts +5 -5
- package/dist/{util-C4qsI1QV.js → util-wrBH4QSB.js} +130 -7
- package/dist/util-wrBH4QSB.js.map +1 -0
- package/package.json +10 -10
- package/src/collection_editor/ConfigControllerProvider.tsx +5 -0
- package/src/collection_editor/liveSchemaClient.ts +272 -0
- package/src/collection_editor/types/config_controller.tsx +11 -0
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +10 -0
- package/src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx +368 -0
- package/src/collection_editor/useLiveSchemaEditing.tsx +285 -0
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +109 -10
- package/src/index.ts +6 -0
- package/dist/util-C4qsI1QV.js.map +0 -1
|
@@ -5,6 +5,7 @@ import { getSubcollections } from "@rebasepro/common";
|
|
|
5
5
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import type { AdminCollection } from "@rebasepro/admin-types";
|
|
7
7
|
import { DEFAULT_API_PATH } from "@rebasepro/app";
|
|
8
|
+
import { useLiveSchemaEditing } from "./useLiveSchemaEditing";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* What the backend said about its schema editor, and how sure we are.
|
|
@@ -172,6 +173,47 @@ export function useLocalCollectionsConfigController(
|
|
|
172
173
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
173
174
|
}, [editorUrl, forcedReadOnly, authKey]);
|
|
174
175
|
|
|
176
|
+
// ── Live schema editing ───────────────────────────────────────────
|
|
177
|
+
// The same edit, against a backend that can also change the database and
|
|
178
|
+
// commit the result. When it is available, a save is planned and shown
|
|
179
|
+
// before anything happens; when it is not, this is inert and writes go
|
|
180
|
+
// straight to the source-only editor exactly as before.
|
|
181
|
+
const liveSchema = useLiveSchemaEditing({
|
|
182
|
+
baseUrl: `${String(clientBaseUrl).replace(/\/$/, "")}${clientApiPath}/admin/schema`,
|
|
183
|
+
getAuthToken: resolveToken,
|
|
184
|
+
authKey,
|
|
185
|
+
// The fallback the dialog offers when a change cannot be applied —
|
|
186
|
+
// removing a property, most often, which the ensure path has no way to
|
|
187
|
+
// carry out. Writing the source and leaving the database alone is what
|
|
188
|
+
// the editor did before any of this existed.
|
|
189
|
+
writeSourceOnly: async ({ collectionId, collection }) => {
|
|
190
|
+
await request("/collection/save", { collectionId, collectionData: collection });
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Perform a write, through the live editor when there is one.
|
|
196
|
+
*
|
|
197
|
+
* `sourceOnly` is the write this controller has always done. It stays the
|
|
198
|
+
* whole behaviour on a backend that cannot edit its schema — a bundle
|
|
199
|
+
* deployment, a non-Postgres driver, a version too old to be asked — so
|
|
200
|
+
* nothing about the editor depends on the feature being there.
|
|
201
|
+
*/
|
|
202
|
+
const write = async (
|
|
203
|
+
collectionId: string,
|
|
204
|
+
collection: Record<string, unknown>,
|
|
205
|
+
sourceOnly: () => Promise<void>
|
|
206
|
+
): Promise<void> => {
|
|
207
|
+
// `ready()`, not `status` — the rendered status is undefined for one
|
|
208
|
+
// round trip after mount, so reading it here would send a save issued
|
|
209
|
+
// in that window down the source-only path with no confirmation, while
|
|
210
|
+
// the same save a second later would open a dialog. One round trip is
|
|
211
|
+
// cheap; behaviour that depends on how fast somebody clicked is not.
|
|
212
|
+
const available = await liveSchema.ready();
|
|
213
|
+
if (!available.enabled) return sourceOnly();
|
|
214
|
+
await liveSchema.reviewChange({ collectionId, collection });
|
|
215
|
+
};
|
|
216
|
+
|
|
175
217
|
const readOnly = forcedReadOnly
|
|
176
218
|
?? (availability.state === "known" ? !availability.enabled : buildModeGuess());
|
|
177
219
|
|
|
@@ -179,24 +221,42 @@ export function useLocalCollectionsConfigController(
|
|
|
179
221
|
? availability.reason
|
|
180
222
|
: "Collections can only be edited against a backend running the schema editor, which is off in production.";
|
|
181
223
|
|
|
224
|
+
const findCollection = (id: string): AdminCollection | undefined =>
|
|
225
|
+
parsedCollections.find(c => (c as AdminCollection & { id?: string }).id === id || c.slug === id);
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* The whole collection as it should end up.
|
|
229
|
+
*
|
|
230
|
+
* Live editing computes the proposed state by replacing one collection in
|
|
231
|
+
* the set, so it needs all of it: handed a patch, it would read every
|
|
232
|
+
* property the patch does not mention as a removal and refuse the change.
|
|
233
|
+
* A collection this does not recognise is a new one, and the patch is the
|
|
234
|
+
* whole of it.
|
|
235
|
+
*/
|
|
236
|
+
const wholeCollection = (id: string, patch: Record<string, unknown>): Record<string, unknown> => {
|
|
237
|
+
const current = findCollection(id) as Record<string, unknown> | undefined;
|
|
238
|
+
return current ? { ...current, ...patch } : patch;
|
|
239
|
+
};
|
|
240
|
+
|
|
182
241
|
return useMemo(() => ({
|
|
183
242
|
loading: false,
|
|
184
243
|
readOnly,
|
|
185
244
|
readOnlyReason,
|
|
186
245
|
collections: parsedCollections,
|
|
246
|
+
dialog: liveSchema.dialog,
|
|
187
247
|
getCollection: (id: string) => {
|
|
188
|
-
const found =
|
|
248
|
+
const found = findCollection(id);
|
|
189
249
|
if (found) return found;
|
|
190
250
|
throw Error(`Collection ${id} not found in local mode`);
|
|
191
251
|
},
|
|
192
252
|
|
|
193
253
|
saveCollection: async ({ id, collectionData }: SaveCollectionParams) => {
|
|
194
|
-
await
|
|
195
|
-
collectionData });
|
|
254
|
+
await write(id, collectionData as unknown as Record<string, unknown>, () =>
|
|
255
|
+
request("/collection/save", { collectionId: id, collectionData }));
|
|
196
256
|
},
|
|
197
257
|
updateCollection: async ({ id, collectionData }: UpdateCollectionParams) => {
|
|
198
|
-
await
|
|
199
|
-
collectionData });
|
|
258
|
+
await write(id, wholeCollection(id, collectionData as Record<string, unknown>), () =>
|
|
259
|
+
request("/collection/save", { collectionId: id, collectionData }));
|
|
200
260
|
},
|
|
201
261
|
deleteCollection: async ({ id }: DeleteCollectionParams) => {
|
|
202
262
|
await request("/collection/delete", { collectionId: id });
|
|
@@ -207,14 +267,30 @@ collectionData });
|
|
|
207
267
|
// mention — `securityRules` first, which then falls back to the
|
|
208
268
|
// directory default and widens who can read the collection.
|
|
209
269
|
saveProperty: async ({ path, propertyKey, property, newPropertiesOrder }: SavePropertyParams) => {
|
|
210
|
-
|
|
270
|
+
// Assembled into the whole collection before it is planned. This is
|
|
271
|
+
// the write that most often *is* a schema change — adding a field
|
|
272
|
+
// to a collection is adding a column — and the one whose payload
|
|
273
|
+
// says least about it on its own.
|
|
274
|
+
const current = findCollection(path) as Record<string, unknown> | undefined;
|
|
275
|
+
const properties = {
|
|
276
|
+
...(current?.properties as Record<string, unknown> | undefined ?? {}),
|
|
277
|
+
[propertyKey]: property
|
|
278
|
+
};
|
|
279
|
+
const proposed = wholeCollection(path, {
|
|
280
|
+
properties,
|
|
281
|
+
...(newPropertiesOrder ? { propertiesOrder: newPropertiesOrder } : {})
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
await write(path, proposed, async () => {
|
|
285
|
+
await request("/property/save", { collectionId: path,
|
|
211
286
|
propertyKey,
|
|
212
287
|
propertyConfig: property });
|
|
213
|
-
|
|
214
|
-
|
|
288
|
+
if (newPropertiesOrder) {
|
|
289
|
+
await request("/collection/save", { collectionId: path,
|
|
215
290
|
collectionData: { propertiesOrder: newPropertiesOrder },
|
|
216
291
|
partial: true });
|
|
217
|
-
|
|
292
|
+
}
|
|
293
|
+
});
|
|
218
294
|
},
|
|
219
295
|
deleteProperty: async ({ path, propertyKey, newPropertiesOrder }: DeletePropertyParams) => {
|
|
220
296
|
await request("/property/delete", { collectionId: path,
|
|
@@ -238,5 +314,28 @@ partial: true });
|
|
|
238
314
|
|
|
239
315
|
navigationEntries: [],
|
|
240
316
|
saveNavigationEntries: async () => { }
|
|
241
|
-
|
|
317
|
+
// `liveSchema.dialog` and `liveSchema.status` both change as the flow
|
|
318
|
+
// runs — a plan arrives, a dialog opens — and a controller memoised
|
|
319
|
+
// without them would keep handing back a closed dialog and a stale
|
|
320
|
+
// answer about whether the backend can edit its schema at all.
|
|
321
|
+
//
|
|
322
|
+
// `write`, `request`, `findCollection` and `wholeCollection` are
|
|
323
|
+
// rebuilt on every render, so listing them would defeat the memo
|
|
324
|
+
// entirely. Each is already covered *transitively* by what is listed:
|
|
325
|
+
// `request` closes over `editorUrl` and a ref, and `editorUrl` derives
|
|
326
|
+
// from `clientOrUrl`; `findCollection` and `wholeCollection` close over
|
|
327
|
+
// `parsedCollections`; `write` closes over `liveSchema.status` and
|
|
328
|
+
// `liveSchema.reviewChange`, and the latter is a `useCallback` keyed on
|
|
329
|
+
// a client built from `clientOrUrl`. Every input that can change is in
|
|
330
|
+
// the array under the name it actually varies with.
|
|
331
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
332
|
+
}), [
|
|
333
|
+
clientOrUrl,
|
|
334
|
+
parsedCollections,
|
|
335
|
+
readOnly,
|
|
336
|
+
readOnlyReason,
|
|
337
|
+
options?.getAuthToken,
|
|
338
|
+
liveSchema.dialog,
|
|
339
|
+
liveSchema.status
|
|
340
|
+
]);
|
|
242
341
|
}
|
package/src/index.ts
CHANGED
|
@@ -112,6 +112,12 @@ export * from "./data_export";
|
|
|
112
112
|
|
|
113
113
|
// Collection editor — moved from @rebasepro/studio (admin-dependent visual schema editor)
|
|
114
114
|
export * from "./collection_editor";
|
|
115
|
+
export * from "./collection_editor/liveSchemaClient";
|
|
116
|
+
export * from "./collection_editor/useLiveSchemaEditing";
|
|
117
|
+
// `SchemaChangeDialog` is deliberately absent, like `CollectionEditorDialog`
|
|
118
|
+
// and `PropertyFormDialog` beside it: re-exporting it from the barrel puts it
|
|
119
|
+
// back in the eager bundle and undoes the `lazyChunk` in `useLiveSchemaEditing`.
|
|
120
|
+
// Import it by path if you need the component itself.
|
|
115
121
|
|
|
116
122
|
|
|
117
123
|
export { CreationResultDialog } from "./components/admin/CreationResultDialog";
|