@firecms/collection_editor 3.0.1 → 3.1.0-canary.1df3b2c
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/ConfigControllerProvider.d.ts +6 -0
- package/dist/api/generateCollectionApi.d.ts +71 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.es.js +9418 -5587
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +9413 -5582
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collection_editor_controller.d.ts +14 -0
- package/dist/types/collection_inference.d.ts +8 -2
- package/dist/types/config_controller.d.ts +23 -2
- package/dist/ui/AddKanbanColumnAction.d.ts +11 -0
- package/dist/ui/KanbanSetupAction.d.ts +10 -0
- package/dist/ui/collection_editor/AICollectionGeneratorPopover.d.ts +33 -0
- package/dist/ui/collection_editor/AIModifiedPathsContext.d.ts +20 -0
- package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +2 -3
- package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +20 -0
- package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +3 -1
- package/dist/ui/collection_editor/CollectionJsonImportDialog.d.ts +7 -0
- package/dist/ui/collection_editor/CollectionYupValidation.d.ts +9 -13
- package/dist/ui/collection_editor/DisplaySettingsForm.d.ts +3 -0
- package/dist/ui/collection_editor/EntityActionsEditTab.d.ts +2 -1
- package/dist/ui/collection_editor/ExtendSettingsForm.d.ts +14 -0
- package/dist/ui/collection_editor/GeneralSettingsForm.d.ts +7 -0
- package/dist/ui/collection_editor/KanbanConfigSection.d.ts +4 -0
- package/dist/ui/collection_editor/PropertyEditView.d.ts +6 -1
- package/dist/ui/collection_editor/PropertyTree.d.ts +2 -1
- package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -1
- package/dist/ui/collection_editor/ViewModeSwitch.d.ts +6 -0
- package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +2 -1
- package/dist/ui/collection_editor/properties/conditions/ConditionsEditor.d.ts +10 -0
- package/dist/ui/collection_editor/properties/conditions/ConditionsPanel.d.ts +2 -0
- package/dist/ui/collection_editor/properties/conditions/EnumConditionsEditor.d.ts +6 -0
- package/dist/ui/collection_editor/properties/conditions/index.d.ts +6 -0
- package/dist/ui/collection_editor/properties/conditions/property_paths.d.ts +19 -0
- package/dist/useCollectionEditorPlugin.d.ts +7 -1
- package/dist/utils/validateCollectionJson.d.ts +22 -0
- package/package.json +11 -11
- package/src/ConfigControllerProvider.tsx +81 -47
- package/src/api/generateCollectionApi.ts +119 -0
- package/src/api/index.ts +1 -0
- package/src/index.ts +28 -1
- package/src/types/collection_editor_controller.tsx +16 -3
- package/src/types/collection_inference.ts +15 -2
- package/src/types/config_controller.tsx +27 -2
- package/src/ui/AddKanbanColumnAction.tsx +203 -0
- package/src/ui/EditorCollectionActionStart.tsx +1 -2
- package/src/ui/HomePageEditorCollectionAction.tsx +41 -13
- package/src/ui/KanbanSetupAction.tsx +38 -0
- package/src/ui/MissingReferenceWidget.tsx +1 -1
- package/src/ui/NewCollectionButton.tsx +1 -1
- package/src/ui/PropertyAddColumnComponent.tsx +1 -1
- package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +225 -0
- package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +209 -257
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +226 -167
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +130 -67
- package/src/ui/collection_editor/CollectionJsonImportDialog.tsx +171 -0
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +190 -91
- package/src/ui/collection_editor/DisplaySettingsForm.tsx +333 -0
- package/src/ui/collection_editor/EntityActionsEditTab.tsx +106 -96
- package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +6 -7
- package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +1 -3
- package/src/ui/collection_editor/EnumForm.tsx +147 -100
- package/src/ui/collection_editor/ExtendSettingsForm.tsx +93 -0
- package/src/ui/collection_editor/GeneralSettingsForm.tsx +335 -0
- package/src/ui/collection_editor/GetCodeDialog.tsx +57 -36
- package/src/ui/collection_editor/KanbanConfigSection.tsx +207 -0
- package/src/ui/collection_editor/LayoutModeSwitch.tsx +22 -41
- package/src/ui/collection_editor/PropertyEditView.tsx +205 -141
- package/src/ui/collection_editor/PropertyFieldPreview.tsx +1 -1
- package/src/ui/collection_editor/PropertyTree.tsx +130 -58
- package/src/ui/collection_editor/SubcollectionsEditTab.tsx +171 -162
- package/src/ui/collection_editor/UnsavedChangesDialog.tsx +0 -2
- package/src/ui/collection_editor/ViewModeSwitch.tsx +41 -0
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +0 -2
- package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +1 -0
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +117 -35
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +28 -21
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +0 -2
- package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +115 -39
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +1 -1
- package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +861 -0
- package/src/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +28 -0
- package/src/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +599 -0
- package/src/ui/collection_editor/properties/conditions/index.ts +6 -0
- package/src/ui/collection_editor/properties/conditions/property_paths.ts +92 -0
- package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -1
- package/src/useCollectionEditorPlugin.tsx +32 -17
- package/src/utils/validateCollectionJson.ts +380 -0
|
@@ -42,10 +42,11 @@ import {
|
|
|
42
42
|
Typography
|
|
43
43
|
} from "@firecms/ui";
|
|
44
44
|
import { YupSchema } from "./CollectionYupValidation";
|
|
45
|
-
import {
|
|
45
|
+
import { GeneralSettingsForm } from "./GeneralSettingsForm";
|
|
46
|
+
import { DisplaySettingsForm } from "./DisplaySettingsForm";
|
|
46
47
|
import { CollectionPropertiesEditorForm } from "./CollectionPropertiesEditorForm";
|
|
47
48
|
import { UnsavedChangesDialog } from "./UnsavedChangesDialog";
|
|
48
|
-
import {
|
|
49
|
+
import { ExtendSettingsForm } from "./ExtendSettingsForm";
|
|
49
50
|
import { CollectionsConfigController } from "../../types/config_controller";
|
|
50
51
|
import { CollectionEditorWelcomeView } from "./CollectionEditorWelcomeView";
|
|
51
52
|
import { CollectionInference } from "../../types/collection_inference";
|
|
@@ -57,7 +58,9 @@ import { cleanPropertiesFromImport } from "./import/clean_import_data";
|
|
|
57
58
|
import { PersistedCollection } from "../../types/persisted_collection";
|
|
58
59
|
import { Formex, FormexController, useCreateFormex } from "@firecms/formex";
|
|
59
60
|
import { getFullIdPath } from "./util";
|
|
60
|
-
import {
|
|
61
|
+
import { AICollectionGeneratorPopover } from "./AICollectionGeneratorPopover";
|
|
62
|
+
import { AIModifiedPathsProvider, useAIModifiedPaths } from "./AIModifiedPathsContext";
|
|
63
|
+
import { CollectionOperation, CollectionGenerationCallback } from "../../api/generateCollectionApi";
|
|
61
64
|
|
|
62
65
|
export interface CollectionEditorDialogProps {
|
|
63
66
|
open: boolean;
|
|
@@ -67,6 +70,11 @@ export interface CollectionEditorDialogProps {
|
|
|
67
70
|
path?: string,
|
|
68
71
|
name?: string,
|
|
69
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* A collection to duplicate from. If provided, the new collection will be
|
|
75
|
+
* pre-populated with the same properties (but with empty name, path, and id).
|
|
76
|
+
*/
|
|
77
|
+
copyFrom?: PersistedCollection;
|
|
70
78
|
editedCollectionId?: string;
|
|
71
79
|
fullPath?: string; // full path of this particular collection, like `products/123/locales`
|
|
72
80
|
parentCollectionIds?: string[]; // path ids of the parent collection, like [`products`]
|
|
@@ -84,6 +92,20 @@ export interface CollectionEditorDialogProps {
|
|
|
84
92
|
getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
|
|
85
93
|
parentCollection?: PersistedCollection;
|
|
86
94
|
existingEntities?: Entity<any>[];
|
|
95
|
+
/**
|
|
96
|
+
* Initial view to open when editing: "general", "display", or "properties".
|
|
97
|
+
* For new collections, this is ignored.
|
|
98
|
+
*/
|
|
99
|
+
initialView?: "general" | "display" | "properties";
|
|
100
|
+
/**
|
|
101
|
+
* If true, auto-expand the Kanban configuration section.
|
|
102
|
+
*/
|
|
103
|
+
expandKanban?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Callback function for generating/modifying collections.
|
|
106
|
+
* The plugin is API-agnostic - the consumer provides the implementation.
|
|
107
|
+
*/
|
|
108
|
+
generateCollection?: CollectionGenerationCallback;
|
|
87
109
|
}
|
|
88
110
|
|
|
89
111
|
export function CollectionEditorDialog(props: CollectionEditorDialogProps) {
|
|
@@ -118,30 +140,31 @@ export function CollectionEditorDialog(props: CollectionEditorDialogProps) {
|
|
|
118
140
|
onOpenChange={(open) => !open ? handleCancel() : undefined}
|
|
119
141
|
>
|
|
120
142
|
<DialogTitle hidden>Collection editor</DialogTitle>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
<AIModifiedPathsProvider>
|
|
144
|
+
{open && <CollectionEditor {...props}
|
|
145
|
+
handleCancel={handleCancel}
|
|
146
|
+
setFormDirty={setFormDirty} />}
|
|
147
|
+
|
|
148
|
+
<UnsavedChangesDialog
|
|
149
|
+
open={unsavedChangesDialogOpen}
|
|
150
|
+
handleOk={() => props.handleClose(undefined)}
|
|
151
|
+
handleCancel={() => setUnsavedChangesDialogOpen(false)}
|
|
152
|
+
body={"There are unsaved changes in this collection"} />
|
|
153
|
+
</AIModifiedPathsProvider>
|
|
131
154
|
</Dialog>
|
|
132
155
|
);
|
|
133
156
|
}
|
|
134
157
|
|
|
135
158
|
type EditorView = "welcome"
|
|
136
|
-
| "
|
|
159
|
+
| "general"
|
|
160
|
+
| "display"
|
|
137
161
|
| "import_data_mapping"
|
|
138
162
|
| "import_data_preview"
|
|
139
163
|
| "import_data_saving"
|
|
140
164
|
| "properties"
|
|
141
165
|
| "loading"
|
|
142
166
|
| "extra_view"
|
|
143
|
-
| "
|
|
144
|
-
| "custom_actions";
|
|
167
|
+
| "extend";
|
|
145
168
|
|
|
146
169
|
export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
147
170
|
handleCancel: () => void,
|
|
@@ -157,7 +180,9 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
157
180
|
} = navigation;
|
|
158
181
|
|
|
159
182
|
const initialValuesProp = props.initialValues;
|
|
160
|
-
const
|
|
183
|
+
const copyFromProp = props.copyFrom;
|
|
184
|
+
// Skip templates when duplicating (copyFrom is provided)
|
|
185
|
+
const includeTemplates = !copyFromProp && !initialValuesProp?.path && (props.parentCollectionIds ?? []).length === 0;
|
|
161
186
|
const collectionsInThisLevel = (props.parentCollection ? props.parentCollection.subcollections : collections) ?? [];
|
|
162
187
|
const existingPaths = collectionsInThisLevel.map(col => col.path.trim().toLowerCase());
|
|
163
188
|
const existingIds = collectionsInThisLevel.map(col => col.id?.trim().toLowerCase()).filter(Boolean) as string[];
|
|
@@ -194,25 +219,36 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
194
219
|
}
|
|
195
220
|
: undefined;
|
|
196
221
|
|
|
222
|
+
// Build initial values - handle copyFrom for duplication
|
|
197
223
|
const initialValues: PersistedCollection<any> = initialCollection
|
|
198
224
|
? applyPropertyConfigs(initialCollection, propertyConfigs)
|
|
199
|
-
:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
225
|
+
: copyFromProp
|
|
226
|
+
? {
|
|
227
|
+
// When duplicating, copy all properties but clear identifiers
|
|
228
|
+
...copyFromProp,
|
|
229
|
+
id: randomString(16),
|
|
230
|
+
path: "",
|
|
231
|
+
name: "",
|
|
232
|
+
subcollections: undefined, // Don't copy subcollections
|
|
233
|
+
ownerId: authController.user?.uid ?? ""
|
|
234
|
+
}
|
|
235
|
+
: {
|
|
236
|
+
id: initialValuesProp?.path ?? randomString(16),
|
|
237
|
+
path: initialValuesProp?.path ?? "",
|
|
238
|
+
name: initialValuesProp?.name ?? "",
|
|
239
|
+
group: initialValuesProp?.group ?? "",
|
|
240
|
+
properties: {} as PropertiesOrBuilders,
|
|
241
|
+
propertiesOrder: [],
|
|
242
|
+
icon: coolIconKeys[Math.floor(Math.random() * coolIconKeys.length)],
|
|
243
|
+
ownerId: authController.user?.uid ?? ""
|
|
244
|
+
};
|
|
209
245
|
|
|
210
246
|
if (!initialLoadingCompleted) {
|
|
211
|
-
return <CircularProgressCenter/>;
|
|
247
|
+
return <CircularProgressCenter />;
|
|
212
248
|
}
|
|
213
249
|
|
|
214
250
|
if (!props.isNewCollection && (!navigation.initialised || !initialLoadingCompleted)) {
|
|
215
|
-
return <CircularProgressCenter/>;
|
|
251
|
+
return <CircularProgressCenter />;
|
|
216
252
|
}
|
|
217
253
|
|
|
218
254
|
return <CollectionEditorInternal
|
|
@@ -224,46 +260,49 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
224
260
|
collection={collection}
|
|
225
261
|
setCollection={setCollection}
|
|
226
262
|
groups={groups}
|
|
227
|
-
propertyConfigs={propertyConfigs}/>
|
|
263
|
+
propertyConfigs={propertyConfigs} />
|
|
228
264
|
|
|
229
265
|
}
|
|
230
266
|
|
|
231
267
|
function CollectionEditorInternal<M extends Record<string, any>>({
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
268
|
+
isNewCollection,
|
|
269
|
+
configController,
|
|
270
|
+
editedCollectionId,
|
|
271
|
+
parentCollectionIds,
|
|
272
|
+
fullPath,
|
|
273
|
+
collectionInference,
|
|
274
|
+
handleClose,
|
|
275
|
+
reservedGroups,
|
|
276
|
+
extraView,
|
|
277
|
+
handleCancel,
|
|
278
|
+
setFormDirty,
|
|
279
|
+
getUser,
|
|
280
|
+
parentCollection,
|
|
281
|
+
getData,
|
|
282
|
+
existingPaths,
|
|
283
|
+
existingIds,
|
|
284
|
+
includeTemplates,
|
|
285
|
+
collection,
|
|
286
|
+
setCollection,
|
|
287
|
+
initialValues,
|
|
288
|
+
propertyConfigs,
|
|
289
|
+
groups,
|
|
290
|
+
existingEntities,
|
|
291
|
+
initialView: initialViewProp,
|
|
292
|
+
expandKanban,
|
|
293
|
+
generateCollection
|
|
294
|
+
}: CollectionEditorDialogProps & {
|
|
295
|
+
handleCancel: () => void,
|
|
296
|
+
setFormDirty: (dirty: boolean) => void,
|
|
297
|
+
initialValues: PersistedCollection<M>,
|
|
298
|
+
existingPaths: string[],
|
|
299
|
+
existingIds: string[],
|
|
300
|
+
includeTemplates: boolean,
|
|
301
|
+
collection: PersistedCollection<M> | undefined,
|
|
302
|
+
setCollection: (collection: PersistedCollection<M>) => void,
|
|
303
|
+
propertyConfigs: Record<string, PropertyConfig<any>>,
|
|
304
|
+
groups: string[],
|
|
305
|
+
}
|
|
267
306
|
) {
|
|
268
307
|
|
|
269
308
|
const importConfig = useImportConfig();
|
|
@@ -273,7 +312,9 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
273
312
|
// Use this ref to store which properties have errors
|
|
274
313
|
const propertyErrorsRef = useRef({});
|
|
275
314
|
|
|
276
|
-
const initialView = isNewCollection
|
|
315
|
+
const initialView = isNewCollection
|
|
316
|
+
? (includeTemplates ? "welcome" : "general")
|
|
317
|
+
: (initialViewProp ?? "properties");
|
|
277
318
|
const [currentView, setCurrentView] = useState<EditorView>(initialView); // this view can edit either the details view or the properties one
|
|
278
319
|
|
|
279
320
|
const [error, setError] = React.useState<Error | undefined>();
|
|
@@ -303,7 +344,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
303
344
|
};
|
|
304
345
|
|
|
305
346
|
const setNextMode = () => {
|
|
306
|
-
if (currentView === "
|
|
347
|
+
if (currentView === "general") {
|
|
307
348
|
if (importConfig.inUse) {
|
|
308
349
|
setCurrentView("import_data_saving");
|
|
309
350
|
} else if (extraView) {
|
|
@@ -312,22 +353,29 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
312
353
|
setCurrentView("properties");
|
|
313
354
|
}
|
|
314
355
|
} else if (currentView === "welcome") {
|
|
315
|
-
setCurrentView("
|
|
356
|
+
setCurrentView("general");
|
|
316
357
|
} else if (currentView === "import_data_mapping") {
|
|
317
358
|
setCurrentView("import_data_preview");
|
|
318
359
|
} else if (currentView === "import_data_preview") {
|
|
319
|
-
setCurrentView("
|
|
360
|
+
setCurrentView("general");
|
|
320
361
|
} else if (currentView === "extra_view") {
|
|
321
362
|
setCurrentView("properties");
|
|
322
363
|
} else {
|
|
323
|
-
setCurrentView("
|
|
364
|
+
setCurrentView("general");
|
|
324
365
|
}
|
|
325
366
|
|
|
326
367
|
};
|
|
327
368
|
|
|
328
369
|
const doCollectionInference = collectionInference ? (collection: PersistedCollection<any>) => {
|
|
329
370
|
if (!collectionInference) return undefined;
|
|
330
|
-
return collectionInference?.(
|
|
371
|
+
return collectionInference?.(
|
|
372
|
+
collection.path,
|
|
373
|
+
collection.collectionGroup ?? false,
|
|
374
|
+
parentPaths ?? [],
|
|
375
|
+
collection.databaseId,
|
|
376
|
+
collection.initialFilter,
|
|
377
|
+
collection.initialSort
|
|
378
|
+
);
|
|
331
379
|
} : undefined;
|
|
332
380
|
|
|
333
381
|
const inferCollectionFromData = async (newCollection: PersistedCollection<M>) => {
|
|
@@ -382,6 +430,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
382
430
|
|
|
383
431
|
if (!isNewCollection) {
|
|
384
432
|
saveCollection(newCollectionState).then(() => {
|
|
433
|
+
aiModifiedPaths?.clearAllPaths();
|
|
385
434
|
formexController.resetForm();
|
|
386
435
|
handleClose(newCollectionState);
|
|
387
436
|
});
|
|
@@ -391,7 +440,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
391
440
|
if (currentView === "welcome") {
|
|
392
441
|
setNextMode();
|
|
393
442
|
formexController.resetForm({ values: newCollectionState });
|
|
394
|
-
} else if (currentView === "
|
|
443
|
+
} else if (currentView === "general") {
|
|
395
444
|
if (extraView || importConfig.inUse) {
|
|
396
445
|
formexController.resetForm({ values: newCollectionState });
|
|
397
446
|
setNextMode();
|
|
@@ -406,8 +455,8 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
406
455
|
}
|
|
407
456
|
});
|
|
408
457
|
}).finally(() => {
|
|
409
|
-
|
|
410
|
-
|
|
458
|
+
setNextMode();
|
|
459
|
+
});
|
|
411
460
|
} else {
|
|
412
461
|
formexController.resetForm({ values: newCollectionState });
|
|
413
462
|
setNextMode();
|
|
@@ -442,7 +491,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
442
491
|
const validation = (col: PersistedCollection) => {
|
|
443
492
|
|
|
444
493
|
let errors: Record<string, any> = {};
|
|
445
|
-
const schema = (currentView === "properties" || currentView === "
|
|
494
|
+
const schema = (currentView === "properties" || currentView === "extend" || currentView === "general") && YupSchema;
|
|
446
495
|
if (schema) {
|
|
447
496
|
try {
|
|
448
497
|
schema.validateSync(col, { abortEarly: false });
|
|
@@ -455,7 +504,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
455
504
|
if (currentView === "properties") {
|
|
456
505
|
errors = { ...errors, ...propertyErrorsRef.current };
|
|
457
506
|
}
|
|
458
|
-
if (currentView === "
|
|
507
|
+
if (currentView === "general") {
|
|
459
508
|
const pathError = validatePath(col.path, isNewCollection, existingPaths, col.id);
|
|
460
509
|
if (pathError) {
|
|
461
510
|
errors.path = pathError;
|
|
@@ -483,15 +532,15 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
483
532
|
submitCount
|
|
484
533
|
} = formController;
|
|
485
534
|
|
|
486
|
-
// TODO: getting data is only working in root collections with this code
|
|
487
535
|
const path = values.path;
|
|
488
536
|
const updatedFullPath = fullPath?.includes("/") ? fullPath?.split("/").slice(0, -1).join("/") + "/" + path : path; // TODO: this path is wrong
|
|
489
537
|
const pathError = validatePath(path, isNewCollection, existingPaths, values.id);
|
|
490
538
|
|
|
491
539
|
const parentPaths = !pathError && parentCollectionIds ? navigation.convertIdsToPaths(parentCollectionIds) : undefined;
|
|
492
540
|
const resolvedPath = !pathError ? navigation.resolveIdsFrom(updatedFullPath) : undefined;
|
|
541
|
+
|
|
493
542
|
const getDataWithPath = resolvedPath && getData ? async () => {
|
|
494
|
-
const data = await getData(resolvedPath, parentPaths ?? []);
|
|
543
|
+
const data = await getData!(resolvedPath, parentPaths ?? []);
|
|
495
544
|
if (existingEntities) {
|
|
496
545
|
const existingData = existingEntities.map(e => e.values);
|
|
497
546
|
data.push(...existingData);
|
|
@@ -558,7 +607,16 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
558
607
|
onImportDataSet(importData, propertiesOrder);
|
|
559
608
|
setCurrentView("import_data_mapping");
|
|
560
609
|
} else {
|
|
561
|
-
setCurrentView("
|
|
610
|
+
setCurrentView("general");
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
const aiModifiedPaths = useAIModifiedPaths();
|
|
615
|
+
|
|
616
|
+
const handleAIGenerated = (generatedCollection: EntityCollection, operations?: CollectionOperation[]) => {
|
|
617
|
+
formController.setValues(generatedCollection as PersistedCollection<M>);
|
|
618
|
+
if (operations && aiModifiedPaths) {
|
|
619
|
+
aiModifiedPaths.addModifiedPaths(operations);
|
|
562
620
|
}
|
|
563
621
|
};
|
|
564
622
|
|
|
@@ -566,99 +624,100 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
566
624
|
<Formex value={formController}>
|
|
567
625
|
|
|
568
626
|
<>
|
|
569
|
-
{!isNewCollection && <
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
627
|
+
{!isNewCollection && <div className={cls("px-4 py-2 w-full flex items-center justify-end gap-2 bg-surface-50 dark:bg-surface-950 border-b", defaultBorderMixin)}>
|
|
628
|
+
{generateCollection && (
|
|
629
|
+
<AICollectionGeneratorPopover
|
|
630
|
+
existingCollection={values}
|
|
631
|
+
onGenerated={handleAIGenerated}
|
|
632
|
+
generateCollection={generateCollection}
|
|
633
|
+
/>
|
|
634
|
+
)}
|
|
635
|
+
<Tabs value={currentView}
|
|
636
|
+
onValueChange={(v) => setCurrentView(v as EditorView)}>
|
|
637
|
+
<Tab value={"general"}>
|
|
638
|
+
General
|
|
639
|
+
</Tab>
|
|
640
|
+
<Tab value={"display"}>
|
|
641
|
+
Display
|
|
642
|
+
</Tab>
|
|
643
|
+
<Tab value={"properties"}>
|
|
644
|
+
Properties
|
|
645
|
+
</Tab>
|
|
646
|
+
<Tab value={"extend"}>
|
|
647
|
+
Extend
|
|
648
|
+
</Tab>
|
|
649
|
+
</Tabs>
|
|
650
|
+
</div>}
|
|
585
651
|
|
|
586
652
|
<form noValidate
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
653
|
+
onSubmit={formController.handleSubmit}
|
|
654
|
+
className={cls(
|
|
655
|
+
isNewCollection ? "h-full" : "h-[calc(100%-48px)]",
|
|
656
|
+
"flex-grow flex flex-col relative")}>
|
|
591
657
|
|
|
592
658
|
{currentView === "loading" &&
|
|
593
|
-
<CircularProgressCenter/>}
|
|
659
|
+
<CircularProgressCenter />}
|
|
594
660
|
|
|
595
661
|
{currentView === "extra_view" &&
|
|
596
662
|
path &&
|
|
597
663
|
extraView?.View &&
|
|
598
|
-
<extraView.View path={path}/>}
|
|
664
|
+
<extraView.View path={path} />}
|
|
599
665
|
|
|
600
666
|
{currentView === "welcome" &&
|
|
601
667
|
<CollectionEditorWelcomeView
|
|
602
668
|
path={path}
|
|
603
669
|
onContinue={onWelcomeScreenContinue}
|
|
604
670
|
existingCollectionPaths={existingPaths}
|
|
605
|
-
parentCollection={parentCollection}
|
|
671
|
+
parentCollection={parentCollection}
|
|
672
|
+
generateCollection={generateCollection} />}
|
|
606
673
|
|
|
607
674
|
{currentView === "import_data_mapping" && importConfig &&
|
|
608
675
|
<CollectionEditorImportMapping importConfig={importConfig}
|
|
609
|
-
|
|
610
|
-
|
|
676
|
+
collectionEditable={collectionEditable}
|
|
677
|
+
propertyConfigs={propertyConfigs} />}
|
|
611
678
|
|
|
612
679
|
{currentView === "import_data_preview" && importConfig &&
|
|
613
680
|
<CollectionEditorImportDataPreview importConfig={importConfig}
|
|
614
|
-
|
|
615
|
-
|
|
681
|
+
properties={values.properties as Properties}
|
|
682
|
+
propertiesOrder={values.propertiesOrder as string[]} />}
|
|
616
683
|
|
|
617
684
|
{currentView === "import_data_saving" && importConfig &&
|
|
618
685
|
<ImportSaveInProgress importConfig={importConfig}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
686
|
+
collection={values}
|
|
687
|
+
path={path}
|
|
688
|
+
onImportSuccess={async (importedCollection) => {
|
|
689
|
+
snackbarController.open({
|
|
690
|
+
type: "info",
|
|
691
|
+
message: "Data imported successfully"
|
|
692
|
+
});
|
|
693
|
+
await saveCollection(values);
|
|
694
|
+
handleClose(importedCollection);
|
|
695
|
+
}}
|
|
629
696
|
/>}
|
|
630
697
|
|
|
631
|
-
{currentView === "
|
|
632
|
-
<
|
|
698
|
+
{currentView === "general" &&
|
|
699
|
+
<GeneralSettingsForm
|
|
633
700
|
existingPaths={existingPaths}
|
|
634
701
|
existingIds={existingIds}
|
|
635
|
-
groups={groups}
|
|
636
|
-
parentCollectionIds={parentCollectionIds}
|
|
637
702
|
parentCollection={parentCollection}
|
|
638
|
-
isNewCollection={isNewCollection}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
</div>}
|
|
649
|
-
</CollectionDetailsForm>}
|
|
650
|
-
|
|
651
|
-
{currentView === "custom_actions" && collection &&
|
|
652
|
-
<EntityActionsEditTab collection={collection}/>}
|
|
653
|
-
|
|
654
|
-
{currentView === "subcollections" && collection &&
|
|
655
|
-
<SubcollectionsEditTab
|
|
703
|
+
isNewCollection={isNewCollection} />
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
{currentView === "display" &&
|
|
707
|
+
<DisplaySettingsForm expandKanban={expandKanban} />
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
{currentView === "extend" && collection &&
|
|
711
|
+
<ExtendSettingsForm
|
|
712
|
+
collection={collection}
|
|
656
713
|
parentCollection={parentCollection}
|
|
657
714
|
configController={configController}
|
|
658
|
-
getUser={getUser}
|
|
659
715
|
collectionInference={collectionInference}
|
|
716
|
+
getUser={getUser}
|
|
660
717
|
parentCollectionIds={parentCollectionIds}
|
|
661
|
-
|
|
718
|
+
isMergedCollection={!isNewCollection && isMergedCollection}
|
|
719
|
+
onResetToCode={() => setDeleteRequested(true)} />
|
|
720
|
+
}
|
|
662
721
|
|
|
663
722
|
{currentView === "properties" &&
|
|
664
723
|
<CollectionPropertiesEditorForm
|
|
@@ -683,52 +742,52 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
683
742
|
color={"primary"}
|
|
684
743
|
onClick={() => setCurrentView("extra_view")}>
|
|
685
744
|
{extraView.icon}
|
|
686
|
-
</IconButton>}/>
|
|
745
|
+
</IconButton>} />
|
|
687
746
|
}
|
|
688
747
|
|
|
689
748
|
<DialogActions
|
|
690
749
|
position={"absolute"}>
|
|
691
|
-
{error && <ErrorView error={error}/>}
|
|
750
|
+
{error && <ErrorView error={error} />}
|
|
692
751
|
|
|
693
752
|
{isNewCollection && includeTemplates && currentView === "import_data_mapping" &&
|
|
694
753
|
<Button variant={"text"}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
754
|
+
type="button"
|
|
755
|
+
onClick={() => {
|
|
756
|
+
importConfig.setInUse(false);
|
|
757
|
+
return setCurrentView("welcome");
|
|
758
|
+
}}>
|
|
700
759
|
Back
|
|
701
760
|
</Button>}
|
|
702
761
|
|
|
703
762
|
{isNewCollection && includeTemplates && currentView === "import_data_preview" &&
|
|
704
763
|
<Button variant={"text"}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
764
|
+
type="button"
|
|
765
|
+
onClick={() => {
|
|
766
|
+
setCurrentView("import_data_mapping");
|
|
767
|
+
}}>
|
|
709
768
|
Back
|
|
710
769
|
</Button>}
|
|
711
770
|
|
|
712
|
-
{isNewCollection && includeTemplates && currentView === "
|
|
771
|
+
{isNewCollection && includeTemplates && currentView === "general" &&
|
|
713
772
|
<Button variant={"text"}
|
|
714
|
-
|
|
715
|
-
|
|
773
|
+
type="button"
|
|
774
|
+
onClick={() => setCurrentView("welcome")}>
|
|
716
775
|
Back
|
|
717
776
|
</Button>}
|
|
718
777
|
|
|
719
778
|
{isNewCollection && currentView === "properties" && <Button variant={"text"}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
<ArrowBackIcon/>
|
|
779
|
+
type="button"
|
|
780
|
+
color={"neutral"}
|
|
781
|
+
onClick={() => setCurrentView("general")}>
|
|
782
|
+
<ArrowBackIcon />
|
|
724
783
|
Back
|
|
725
784
|
</Button>}
|
|
726
785
|
|
|
727
786
|
<Button variant={"text"}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
787
|
+
color={"neutral"}
|
|
788
|
+
onClick={() => {
|
|
789
|
+
handleCancel();
|
|
790
|
+
}}>
|
|
732
791
|
Cancel
|
|
733
792
|
</Button>
|
|
734
793
|
|
|
@@ -757,18 +816,18 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
757
816
|
Next
|
|
758
817
|
</Button>}
|
|
759
818
|
|
|
760
|
-
{isNewCollection && (currentView === "
|
|
819
|
+
{isNewCollection && (currentView === "general" || currentView === "properties") &&
|
|
761
820
|
<LoadingButton
|
|
762
821
|
variant={"filled"}
|
|
763
822
|
color="primary"
|
|
764
823
|
type="submit"
|
|
765
824
|
loading={isSubmitting}
|
|
766
|
-
disabled={isSubmitting || (currentView === "
|
|
825
|
+
disabled={isSubmitting || (currentView === "general" && !validValues)}
|
|
767
826
|
startIcon={currentView === "properties"
|
|
768
|
-
? <CheckIcon/>
|
|
827
|
+
? <CheckIcon />
|
|
769
828
|
: undefined}
|
|
770
829
|
>
|
|
771
|
-
{currentView === "
|
|
830
|
+
{currentView === "general" && "Next"}
|
|
772
831
|
{currentView === "properties" && "Create collection"}
|
|
773
832
|
</LoadingButton>}
|
|
774
833
|
|
|
@@ -794,7 +853,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
794
853
|
title={<>Delete the stored config?</>}
|
|
795
854
|
body={<> This will <b>not
|
|
796
855
|
delete any data</b>, only
|
|
797
|
-
the stored config, and reset to the code state.</>}/>
|
|
856
|
+
the stored config, and reset to the code state.</>} />
|
|
798
857
|
|
|
799
858
|
</DialogContent>
|
|
800
859
|
|