@firecms/collection_editor 3.0.1 → 3.1.0-canary.02232f4
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 +15260 -8173
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +15257 -8170
- package/dist/index.umd.js.map +1 -1
- package/dist/locales/de.d.ts +120 -0
- package/dist/locales/en.d.ts +120 -0
- package/dist/locales/es.d.ts +120 -0
- package/dist/locales/fr.d.ts +120 -0
- package/dist/locales/hi.d.ts +120 -0
- package/dist/locales/it.d.ts +120 -0
- package/dist/locales/pt.d.ts +120 -0
- 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 +37 -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 +24 -0
- package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +4 -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 +15 -15
- package/src/ConfigControllerProvider.tsx +82 -47
- package/src/api/generateCollectionApi.ts +119 -0
- package/src/api/index.ts +1 -0
- package/src/index.ts +28 -1
- package/src/locales/de.ts +125 -0
- package/src/locales/en.ts +145 -0
- package/src/locales/es.ts +125 -0
- package/src/locales/fr.ts +125 -0
- package/src/locales/hi.ts +125 -0
- package/src/locales/it.ts +125 -0
- package/src/locales/pt.ts +125 -0
- 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/EditorCollectionAction.tsx +3 -3
- package/src/ui/EditorCollectionActionStart.tsx +1 -2
- package/src/ui/EditorEntityAction.tsx +3 -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 +4 -2
- package/src/ui/NewCollectionCard.tsx +7 -4
- package/src/ui/PropertyAddColumnComponent.tsx +4 -3
- package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +243 -0
- package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +222 -267
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +270 -198
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +138 -71
- package/src/ui/collection_editor/CollectionJsonImportDialog.tsx +171 -0
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +202 -101
- package/src/ui/collection_editor/DisplaySettingsForm.tsx +335 -0
- package/src/ui/collection_editor/EntityActionsEditTab.tsx +106 -97
- package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +8 -10
- package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +5 -7
- package/src/ui/collection_editor/EnumForm.tsx +153 -102
- package/src/ui/collection_editor/ExtendSettingsForm.tsx +94 -0
- package/src/ui/collection_editor/GeneralSettingsForm.tsx +335 -0
- package/src/ui/collection_editor/GetCodeDialog.tsx +63 -41
- package/src/ui/collection_editor/KanbanConfigSection.tsx +209 -0
- package/src/ui/collection_editor/LayoutModeSwitch.tsx +27 -43
- package/src/ui/collection_editor/PropertyEditView.tsx +272 -199
- 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 +169 -163
- package/src/ui/collection_editor/UnsavedChangesDialog.tsx +0 -2
- package/src/ui/collection_editor/ViewModeSwitch.tsx +43 -0
- package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +6 -3
- package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +5 -2
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +0 -2
- package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +4 -1
- package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +6 -4
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +126 -42
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +32 -24
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +8 -9
- package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +128 -53
- package/src/ui/collection_editor/properties/NumberPropertyField.tsx +3 -1
- package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +5 -4
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +47 -52
- package/src/ui/collection_editor/properties/StringPropertyField.tsx +3 -1
- package/src/ui/collection_editor/properties/UrlPropertyField.tsx +12 -10
- package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +23 -4
- package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +866 -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/ArrayPropertyValidation.tsx +5 -2
- package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +7 -5
- package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +10 -7
- package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +11 -9
- package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +5 -2
- package/src/useCollectionEditorPlugin.tsx +53 -22
- package/src/utils/validateCollectionJson.ts +380 -0
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
useCustomizationController,
|
|
23
23
|
useNavigationController,
|
|
24
24
|
User,
|
|
25
|
-
useSnackbarController
|
|
25
|
+
useSnackbarController,
|
|
26
|
+
useTranslation,
|
|
26
27
|
} from "@firecms/core";
|
|
27
28
|
import {
|
|
28
29
|
ArrowBackIcon,
|
|
@@ -42,10 +43,11 @@ import {
|
|
|
42
43
|
Typography
|
|
43
44
|
} from "@firecms/ui";
|
|
44
45
|
import { YupSchema } from "./CollectionYupValidation";
|
|
45
|
-
import {
|
|
46
|
+
import { GeneralSettingsForm } from "./GeneralSettingsForm";
|
|
47
|
+
import { DisplaySettingsForm } from "./DisplaySettingsForm";
|
|
46
48
|
import { CollectionPropertiesEditorForm } from "./CollectionPropertiesEditorForm";
|
|
47
49
|
import { UnsavedChangesDialog } from "./UnsavedChangesDialog";
|
|
48
|
-
import {
|
|
50
|
+
import { ExtendSettingsForm } from "./ExtendSettingsForm";
|
|
49
51
|
import { CollectionsConfigController } from "../../types/config_controller";
|
|
50
52
|
import { CollectionEditorWelcomeView } from "./CollectionEditorWelcomeView";
|
|
51
53
|
import { CollectionInference } from "../../types/collection_inference";
|
|
@@ -57,7 +59,9 @@ import { cleanPropertiesFromImport } from "./import/clean_import_data";
|
|
|
57
59
|
import { PersistedCollection } from "../../types/persisted_collection";
|
|
58
60
|
import { Formex, FormexController, useCreateFormex } from "@firecms/formex";
|
|
59
61
|
import { getFullIdPath } from "./util";
|
|
60
|
-
import {
|
|
62
|
+
import { AICollectionGeneratorPopover } from "./AICollectionGeneratorPopover";
|
|
63
|
+
import { AIModifiedPathsProvider, useAIModifiedPaths } from "./AIModifiedPathsContext";
|
|
64
|
+
import { CollectionOperation, CollectionGenerationCallback } from "../../api/generateCollectionApi";
|
|
61
65
|
|
|
62
66
|
export interface CollectionEditorDialogProps {
|
|
63
67
|
open: boolean;
|
|
@@ -67,6 +71,11 @@ export interface CollectionEditorDialogProps {
|
|
|
67
71
|
path?: string,
|
|
68
72
|
name?: string,
|
|
69
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* A collection to duplicate from. If provided, the new collection will be
|
|
76
|
+
* pre-populated with the same properties (but with empty name, path, and id).
|
|
77
|
+
*/
|
|
78
|
+
copyFrom?: PersistedCollection;
|
|
70
79
|
editedCollectionId?: string;
|
|
71
80
|
fullPath?: string; // full path of this particular collection, like `products/123/locales`
|
|
72
81
|
parentCollectionIds?: string[]; // path ids of the parent collection, like [`products`]
|
|
@@ -84,9 +93,29 @@ export interface CollectionEditorDialogProps {
|
|
|
84
93
|
getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
|
|
85
94
|
parentCollection?: PersistedCollection;
|
|
86
95
|
existingEntities?: Entity<any>[];
|
|
96
|
+
/**
|
|
97
|
+
* Initial view to open when editing: "general", "display", or "properties".
|
|
98
|
+
* For new collections, this is ignored.
|
|
99
|
+
*/
|
|
100
|
+
initialView?: "general" | "display" | "properties";
|
|
101
|
+
/**
|
|
102
|
+
* If true, auto-expand the Kanban configuration section.
|
|
103
|
+
*/
|
|
104
|
+
expandKanban?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Callback function for generating/modifying collections.
|
|
107
|
+
* The plugin is API-agnostic - the consumer provides the implementation.
|
|
108
|
+
*/
|
|
109
|
+
generateCollection?: CollectionGenerationCallback;
|
|
110
|
+
/**
|
|
111
|
+
* Optional analytics callback
|
|
112
|
+
*/
|
|
113
|
+
onAnalyticsEvent?: (event: string, params?: object) => void;
|
|
87
114
|
}
|
|
88
115
|
|
|
89
116
|
export function CollectionEditorDialog(props: CollectionEditorDialogProps) {
|
|
117
|
+
const { t } = useTranslation();
|
|
118
|
+
|
|
90
119
|
|
|
91
120
|
const open = props.open;
|
|
92
121
|
|
|
@@ -117,31 +146,32 @@ export function CollectionEditorDialog(props: CollectionEditorDialogProps) {
|
|
|
117
146
|
maxWidth={"7xl"}
|
|
118
147
|
onOpenChange={(open) => !open ? handleCancel() : undefined}
|
|
119
148
|
>
|
|
120
|
-
<DialogTitle hidden>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
149
|
+
<DialogTitle hidden>{t("collection_editor")}</DialogTitle>
|
|
150
|
+
<AIModifiedPathsProvider>
|
|
151
|
+
{open && <CollectionEditor {...props}
|
|
152
|
+
handleCancel={handleCancel}
|
|
153
|
+
setFormDirty={setFormDirty} />}
|
|
154
|
+
|
|
155
|
+
<UnsavedChangesDialog
|
|
156
|
+
open={unsavedChangesDialogOpen}
|
|
157
|
+
handleOk={() => props.handleClose(undefined)}
|
|
158
|
+
handleCancel={() => setUnsavedChangesDialogOpen(false)}
|
|
159
|
+
body={t("unsaved_changes_in_collection")} />
|
|
160
|
+
</AIModifiedPathsProvider>
|
|
131
161
|
</Dialog>
|
|
132
162
|
);
|
|
133
163
|
}
|
|
134
164
|
|
|
135
165
|
type EditorView = "welcome"
|
|
136
|
-
| "
|
|
166
|
+
| "general"
|
|
167
|
+
| "display"
|
|
137
168
|
| "import_data_mapping"
|
|
138
169
|
| "import_data_preview"
|
|
139
170
|
| "import_data_saving"
|
|
140
171
|
| "properties"
|
|
141
172
|
| "loading"
|
|
142
173
|
| "extra_view"
|
|
143
|
-
| "
|
|
144
|
-
| "custom_actions";
|
|
174
|
+
| "extend";
|
|
145
175
|
|
|
146
176
|
export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
147
177
|
handleCancel: () => void,
|
|
@@ -157,7 +187,9 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
157
187
|
} = navigation;
|
|
158
188
|
|
|
159
189
|
const initialValuesProp = props.initialValues;
|
|
160
|
-
const
|
|
190
|
+
const copyFromProp = props.copyFrom;
|
|
191
|
+
// Skip templates when duplicating (copyFrom is provided)
|
|
192
|
+
const includeTemplates = !copyFromProp && !initialValuesProp?.path && (props.parentCollectionIds ?? []).length === 0;
|
|
161
193
|
const collectionsInThisLevel = (props.parentCollection ? props.parentCollection.subcollections : collections) ?? [];
|
|
162
194
|
const existingPaths = collectionsInThisLevel.map(col => col.path.trim().toLowerCase());
|
|
163
195
|
const existingIds = collectionsInThisLevel.map(col => col.id?.trim().toLowerCase()).filter(Boolean) as string[];
|
|
@@ -194,25 +226,36 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
194
226
|
}
|
|
195
227
|
: undefined;
|
|
196
228
|
|
|
229
|
+
// Build initial values - handle copyFrom for duplication
|
|
197
230
|
const initialValues: PersistedCollection<any> = initialCollection
|
|
198
231
|
? applyPropertyConfigs(initialCollection, propertyConfigs)
|
|
199
|
-
:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
232
|
+
: copyFromProp
|
|
233
|
+
? {
|
|
234
|
+
// When duplicating, copy all properties but clear identifiers
|
|
235
|
+
...copyFromProp,
|
|
236
|
+
id: randomString(16),
|
|
237
|
+
path: "",
|
|
238
|
+
name: "",
|
|
239
|
+
subcollections: undefined, // Don't copy subcollections
|
|
240
|
+
ownerId: authController.user?.uid ?? ""
|
|
241
|
+
}
|
|
242
|
+
: {
|
|
243
|
+
id: initialValuesProp?.path ?? randomString(16),
|
|
244
|
+
path: initialValuesProp?.path ?? "",
|
|
245
|
+
name: initialValuesProp?.name ?? "",
|
|
246
|
+
group: initialValuesProp?.group ?? "",
|
|
247
|
+
properties: {} as PropertiesOrBuilders,
|
|
248
|
+
propertiesOrder: [],
|
|
249
|
+
icon: coolIconKeys[Math.floor(Math.random() * coolIconKeys.length)],
|
|
250
|
+
ownerId: authController.user?.uid ?? ""
|
|
251
|
+
};
|
|
209
252
|
|
|
210
253
|
if (!initialLoadingCompleted) {
|
|
211
|
-
return <CircularProgressCenter/>;
|
|
254
|
+
return <CircularProgressCenter />;
|
|
212
255
|
}
|
|
213
256
|
|
|
214
257
|
if (!props.isNewCollection && (!navigation.initialised || !initialLoadingCompleted)) {
|
|
215
|
-
return <CircularProgressCenter/>;
|
|
258
|
+
return <CircularProgressCenter />;
|
|
216
259
|
}
|
|
217
260
|
|
|
218
261
|
return <CollectionEditorInternal
|
|
@@ -224,48 +267,53 @@ export function CollectionEditor(props: CollectionEditorDialogProps & {
|
|
|
224
267
|
collection={collection}
|
|
225
268
|
setCollection={setCollection}
|
|
226
269
|
groups={groups}
|
|
227
|
-
propertyConfigs={propertyConfigs}/>
|
|
270
|
+
propertyConfigs={propertyConfigs} />
|
|
228
271
|
|
|
229
272
|
}
|
|
230
273
|
|
|
231
274
|
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
|
-
|
|
275
|
+
isNewCollection,
|
|
276
|
+
configController,
|
|
277
|
+
editedCollectionId,
|
|
278
|
+
parentCollectionIds,
|
|
279
|
+
fullPath,
|
|
280
|
+
collectionInference,
|
|
281
|
+
handleClose,
|
|
282
|
+
reservedGroups,
|
|
283
|
+
extraView,
|
|
284
|
+
handleCancel,
|
|
285
|
+
setFormDirty,
|
|
286
|
+
getUser,
|
|
287
|
+
parentCollection,
|
|
288
|
+
getData,
|
|
289
|
+
existingPaths,
|
|
290
|
+
existingIds,
|
|
291
|
+
includeTemplates,
|
|
292
|
+
collection,
|
|
293
|
+
setCollection,
|
|
294
|
+
initialValues,
|
|
295
|
+
propertyConfigs,
|
|
296
|
+
groups,
|
|
297
|
+
existingEntities,
|
|
298
|
+
initialView: initialViewProp,
|
|
299
|
+
expandKanban,
|
|
300
|
+
generateCollection,
|
|
301
|
+
onAnalyticsEvent
|
|
302
|
+
}: CollectionEditorDialogProps & {
|
|
303
|
+
handleCancel: () => void,
|
|
304
|
+
setFormDirty: (dirty: boolean) => void,
|
|
305
|
+
initialValues: PersistedCollection<M>,
|
|
306
|
+
existingPaths: string[],
|
|
307
|
+
existingIds: string[],
|
|
308
|
+
includeTemplates: boolean,
|
|
309
|
+
collection: PersistedCollection<M> | undefined,
|
|
310
|
+
setCollection: (collection: PersistedCollection<M>) => void,
|
|
311
|
+
propertyConfigs: Record<string, PropertyConfig<any>>,
|
|
312
|
+
groups: (string | null)[],
|
|
313
|
+
}
|
|
267
314
|
) {
|
|
268
315
|
|
|
316
|
+
const { t } = useTranslation();
|
|
269
317
|
const importConfig = useImportConfig();
|
|
270
318
|
const navigation = useNavigationController();
|
|
271
319
|
const snackbarController = useSnackbarController();
|
|
@@ -273,7 +321,9 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
273
321
|
// Use this ref to store which properties have errors
|
|
274
322
|
const propertyErrorsRef = useRef({});
|
|
275
323
|
|
|
276
|
-
const initialView = isNewCollection
|
|
324
|
+
const initialView = isNewCollection
|
|
325
|
+
? (includeTemplates ? "welcome" : "general")
|
|
326
|
+
: (initialViewProp ?? "properties");
|
|
277
327
|
const [currentView, setCurrentView] = useState<EditorView>(initialView); // this view can edit either the details view or the properties one
|
|
278
328
|
|
|
279
329
|
const [error, setError] = React.useState<Error | undefined>();
|
|
@@ -296,14 +346,14 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
296
346
|
console.error(e);
|
|
297
347
|
snackbarController.open({
|
|
298
348
|
type: "error",
|
|
299
|
-
message: "
|
|
349
|
+
message: t("error_persisting_collection", { error: e.message ?? t("details_in_console") })
|
|
300
350
|
});
|
|
301
351
|
return false;
|
|
302
352
|
});
|
|
303
353
|
};
|
|
304
354
|
|
|
305
355
|
const setNextMode = () => {
|
|
306
|
-
if (currentView === "
|
|
356
|
+
if (currentView === "general") {
|
|
307
357
|
if (importConfig.inUse) {
|
|
308
358
|
setCurrentView("import_data_saving");
|
|
309
359
|
} else if (extraView) {
|
|
@@ -312,22 +362,29 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
312
362
|
setCurrentView("properties");
|
|
313
363
|
}
|
|
314
364
|
} else if (currentView === "welcome") {
|
|
315
|
-
setCurrentView("
|
|
365
|
+
setCurrentView("general");
|
|
316
366
|
} else if (currentView === "import_data_mapping") {
|
|
317
367
|
setCurrentView("import_data_preview");
|
|
318
368
|
} else if (currentView === "import_data_preview") {
|
|
319
|
-
setCurrentView("
|
|
369
|
+
setCurrentView("general");
|
|
320
370
|
} else if (currentView === "extra_view") {
|
|
321
371
|
setCurrentView("properties");
|
|
322
372
|
} else {
|
|
323
|
-
setCurrentView("
|
|
373
|
+
setCurrentView("general");
|
|
324
374
|
}
|
|
325
375
|
|
|
326
376
|
};
|
|
327
377
|
|
|
328
378
|
const doCollectionInference = collectionInference ? (collection: PersistedCollection<any>) => {
|
|
329
379
|
if (!collectionInference) return undefined;
|
|
330
|
-
return collectionInference?.(
|
|
380
|
+
return collectionInference?.(
|
|
381
|
+
collection.path,
|
|
382
|
+
collection.collectionGroup ?? false,
|
|
383
|
+
parentPaths ?? [],
|
|
384
|
+
collection.databaseId,
|
|
385
|
+
collection.initialFilter,
|
|
386
|
+
collection.initialSort
|
|
387
|
+
);
|
|
331
388
|
} : undefined;
|
|
332
389
|
|
|
333
390
|
const inferCollectionFromData = async (newCollection: PersistedCollection<M>) => {
|
|
@@ -370,7 +427,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
370
427
|
console.error(e);
|
|
371
428
|
snackbarController.open({
|
|
372
429
|
type: "error",
|
|
373
|
-
message: "
|
|
430
|
+
message: t("error_inferring_collection", { error: e.message ?? t("details_in_console") })
|
|
374
431
|
});
|
|
375
432
|
return newCollection;
|
|
376
433
|
}
|
|
@@ -382,6 +439,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
382
439
|
|
|
383
440
|
if (!isNewCollection) {
|
|
384
441
|
saveCollection(newCollectionState).then(() => {
|
|
442
|
+
aiModifiedPaths?.clearAllPaths();
|
|
385
443
|
formexController.resetForm();
|
|
386
444
|
handleClose(newCollectionState);
|
|
387
445
|
});
|
|
@@ -391,7 +449,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
391
449
|
if (currentView === "welcome") {
|
|
392
450
|
setNextMode();
|
|
393
451
|
formexController.resetForm({ values: newCollectionState });
|
|
394
|
-
} else if (currentView === "
|
|
452
|
+
} else if (currentView === "general") {
|
|
395
453
|
if (extraView || importConfig.inUse) {
|
|
396
454
|
formexController.resetForm({ values: newCollectionState });
|
|
397
455
|
setNextMode();
|
|
@@ -406,8 +464,8 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
406
464
|
}
|
|
407
465
|
});
|
|
408
466
|
}).finally(() => {
|
|
409
|
-
|
|
410
|
-
|
|
467
|
+
setNextMode();
|
|
468
|
+
});
|
|
411
469
|
} else {
|
|
412
470
|
formexController.resetForm({ values: newCollectionState });
|
|
413
471
|
setNextMode();
|
|
@@ -432,7 +490,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
432
490
|
} catch (e: any) {
|
|
433
491
|
snackbarController.open({
|
|
434
492
|
type: "error",
|
|
435
|
-
message: "
|
|
493
|
+
message: t("error_persisting_collection", { error: e.message ?? t("details_in_console") })
|
|
436
494
|
});
|
|
437
495
|
console.error(e);
|
|
438
496
|
formexController.resetForm({ values: newCollectionState });
|
|
@@ -442,7 +500,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
442
500
|
const validation = (col: PersistedCollection) => {
|
|
443
501
|
|
|
444
502
|
let errors: Record<string, any> = {};
|
|
445
|
-
const schema = (currentView === "properties" || currentView === "
|
|
503
|
+
const schema = (currentView === "properties" || currentView === "extend" || currentView === "general") && YupSchema;
|
|
446
504
|
if (schema) {
|
|
447
505
|
try {
|
|
448
506
|
schema.validateSync(col, { abortEarly: false });
|
|
@@ -455,12 +513,12 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
455
513
|
if (currentView === "properties") {
|
|
456
514
|
errors = { ...errors, ...propertyErrorsRef.current };
|
|
457
515
|
}
|
|
458
|
-
if (currentView === "
|
|
459
|
-
const pathError = validatePath(col.path, isNewCollection, existingPaths, col.id);
|
|
516
|
+
if (currentView === "general") {
|
|
517
|
+
const pathError = validatePath(t, col.path, isNewCollection, existingPaths, col.id);
|
|
460
518
|
if (pathError) {
|
|
461
519
|
errors.path = pathError;
|
|
462
520
|
}
|
|
463
|
-
const idError = validateId(col.id, isNewCollection, existingPaths, existingIds);
|
|
521
|
+
const idError = validateId(t, col.id, isNewCollection, existingPaths, existingIds);
|
|
464
522
|
if (idError) {
|
|
465
523
|
errors.id = idError;
|
|
466
524
|
}
|
|
@@ -483,15 +541,15 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
483
541
|
submitCount
|
|
484
542
|
} = formController;
|
|
485
543
|
|
|
486
|
-
// TODO: getting data is only working in root collections with this code
|
|
487
544
|
const path = values.path;
|
|
488
545
|
const updatedFullPath = fullPath?.includes("/") ? fullPath?.split("/").slice(0, -1).join("/") + "/" + path : path; // TODO: this path is wrong
|
|
489
|
-
const pathError = validatePath(path, isNewCollection, existingPaths, values.id);
|
|
546
|
+
const pathError = validatePath(t, path, isNewCollection, existingPaths, values.id);
|
|
490
547
|
|
|
491
548
|
const parentPaths = !pathError && parentCollectionIds ? navigation.convertIdsToPaths(parentCollectionIds) : undefined;
|
|
492
549
|
const resolvedPath = !pathError ? navigation.resolveIdsFrom(updatedFullPath) : undefined;
|
|
550
|
+
|
|
493
551
|
const getDataWithPath = resolvedPath && getData ? async () => {
|
|
494
|
-
const data = await getData(resolvedPath, parentPaths ?? []);
|
|
552
|
+
const data = await getData!(resolvedPath, parentPaths ?? []);
|
|
495
553
|
if (existingEntities) {
|
|
496
554
|
const existingData = existingEntities.map(e => e.values);
|
|
497
555
|
data.push(...existingData);
|
|
@@ -547,7 +605,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
547
605
|
setDeleteRequested(false);
|
|
548
606
|
handleCancel();
|
|
549
607
|
snackbarController.open({
|
|
550
|
-
message: "
|
|
608
|
+
message: t("collection_deleted"),
|
|
551
609
|
type: "success"
|
|
552
610
|
});
|
|
553
611
|
});
|
|
@@ -558,7 +616,16 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
558
616
|
onImportDataSet(importData, propertiesOrder);
|
|
559
617
|
setCurrentView("import_data_mapping");
|
|
560
618
|
} else {
|
|
561
|
-
setCurrentView("
|
|
619
|
+
setCurrentView("general");
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
const aiModifiedPaths = useAIModifiedPaths();
|
|
624
|
+
|
|
625
|
+
const handleAIGenerated = (generatedCollection: EntityCollection, operations?: CollectionOperation[]) => {
|
|
626
|
+
formController.setValues(generatedCollection as PersistedCollection<M>);
|
|
627
|
+
if (operations && aiModifiedPaths) {
|
|
628
|
+
aiModifiedPaths.addModifiedPaths(operations);
|
|
562
629
|
}
|
|
563
630
|
};
|
|
564
631
|
|
|
@@ -566,99 +633,102 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
566
633
|
<Formex value={formController}>
|
|
567
634
|
|
|
568
635
|
<>
|
|
569
|
-
{!isNewCollection && <
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
<
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
636
|
+
{!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)}>
|
|
637
|
+
{generateCollection && (
|
|
638
|
+
<AICollectionGeneratorPopover
|
|
639
|
+
existingCollection={values}
|
|
640
|
+
onGenerated={handleAIGenerated}
|
|
641
|
+
generateCollection={generateCollection}
|
|
642
|
+
onAnalyticsEvent={onAnalyticsEvent}
|
|
643
|
+
/>
|
|
644
|
+
)}
|
|
645
|
+
<Tabs value={currentView}
|
|
646
|
+
onValueChange={(v) => setCurrentView(v as EditorView)}>
|
|
647
|
+
<Tab value={"general"}>
|
|
648
|
+
{t("tab_general")}
|
|
649
|
+
</Tab>
|
|
650
|
+
<Tab value={"display"}>
|
|
651
|
+
{t("tab_display")}
|
|
652
|
+
</Tab>
|
|
653
|
+
<Tab value={"properties"}>
|
|
654
|
+
{t("tab_properties")}
|
|
655
|
+
</Tab>
|
|
656
|
+
<Tab value={"extend"}>
|
|
657
|
+
{t("tab_extend")}
|
|
658
|
+
</Tab>
|
|
659
|
+
</Tabs>
|
|
660
|
+
</div>}
|
|
585
661
|
|
|
586
662
|
<form noValidate
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
663
|
+
onSubmit={formController.handleSubmit}
|
|
664
|
+
className={cls(
|
|
665
|
+
isNewCollection ? "h-full" : "h-[calc(100%-48px)]",
|
|
666
|
+
"flex-grow flex flex-col relative")}>
|
|
591
667
|
|
|
592
668
|
{currentView === "loading" &&
|
|
593
|
-
<CircularProgressCenter/>}
|
|
669
|
+
<CircularProgressCenter />}
|
|
594
670
|
|
|
595
671
|
{currentView === "extra_view" &&
|
|
596
672
|
path &&
|
|
597
673
|
extraView?.View &&
|
|
598
|
-
<extraView.View path={path}/>}
|
|
674
|
+
<extraView.View path={path} />}
|
|
599
675
|
|
|
600
676
|
{currentView === "welcome" &&
|
|
601
677
|
<CollectionEditorWelcomeView
|
|
602
678
|
path={path}
|
|
603
679
|
onContinue={onWelcomeScreenContinue}
|
|
604
680
|
existingCollectionPaths={existingPaths}
|
|
605
|
-
parentCollection={parentCollection}
|
|
681
|
+
parentCollection={parentCollection}
|
|
682
|
+
generateCollection={generateCollection}
|
|
683
|
+
onAnalyticsEvent={onAnalyticsEvent} />}
|
|
606
684
|
|
|
607
685
|
{currentView === "import_data_mapping" && importConfig &&
|
|
608
686
|
<CollectionEditorImportMapping importConfig={importConfig}
|
|
609
|
-
|
|
610
|
-
|
|
687
|
+
collectionEditable={collectionEditable}
|
|
688
|
+
propertyConfigs={propertyConfigs} />}
|
|
611
689
|
|
|
612
690
|
{currentView === "import_data_preview" && importConfig &&
|
|
613
691
|
<CollectionEditorImportDataPreview importConfig={importConfig}
|
|
614
|
-
|
|
615
|
-
|
|
692
|
+
properties={values.properties as Properties}
|
|
693
|
+
propertiesOrder={values.propertiesOrder as string[]} />}
|
|
616
694
|
|
|
617
695
|
{currentView === "import_data_saving" && importConfig &&
|
|
618
696
|
<ImportSaveInProgress importConfig={importConfig}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
697
|
+
collection={values}
|
|
698
|
+
path={path}
|
|
699
|
+
onImportSuccess={async (importedCollection) => {
|
|
700
|
+
snackbarController.open({
|
|
701
|
+
type: "info",
|
|
702
|
+
message: t("data_imported_successfully_msg")
|
|
703
|
+
});
|
|
704
|
+
await saveCollection(values);
|
|
705
|
+
handleClose(importedCollection);
|
|
706
|
+
}}
|
|
629
707
|
/>}
|
|
630
708
|
|
|
631
|
-
{currentView === "
|
|
632
|
-
<
|
|
709
|
+
{currentView === "general" &&
|
|
710
|
+
<GeneralSettingsForm
|
|
633
711
|
existingPaths={existingPaths}
|
|
634
712
|
existingIds={existingIds}
|
|
635
|
-
groups={groups}
|
|
636
|
-
parentCollectionIds={parentCollectionIds}
|
|
637
713
|
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
|
|
714
|
+
isNewCollection={isNewCollection} />
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
{currentView === "display" &&
|
|
718
|
+
<DisplaySettingsForm expandKanban={expandKanban} />
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
{currentView === "extend" && collection &&
|
|
722
|
+
<ExtendSettingsForm
|
|
723
|
+
collection={collection}
|
|
656
724
|
parentCollection={parentCollection}
|
|
657
725
|
configController={configController}
|
|
658
|
-
getUser={getUser}
|
|
659
726
|
collectionInference={collectionInference}
|
|
727
|
+
getUser={getUser}
|
|
660
728
|
parentCollectionIds={parentCollectionIds}
|
|
661
|
-
|
|
729
|
+
isMergedCollection={!isNewCollection && isMergedCollection}
|
|
730
|
+
onResetToCode={() => setDeleteRequested(true)} />
|
|
731
|
+
}
|
|
662
732
|
|
|
663
733
|
{currentView === "properties" &&
|
|
664
734
|
<CollectionPropertiesEditorForm
|
|
@@ -683,58 +753,58 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
683
753
|
color={"primary"}
|
|
684
754
|
onClick={() => setCurrentView("extra_view")}>
|
|
685
755
|
{extraView.icon}
|
|
686
|
-
</IconButton>}/>
|
|
756
|
+
</IconButton>} />
|
|
687
757
|
}
|
|
688
758
|
|
|
689
759
|
<DialogActions
|
|
690
760
|
position={"absolute"}>
|
|
691
|
-
{error && <ErrorView error={error}/>}
|
|
761
|
+
{error && <ErrorView error={error} />}
|
|
692
762
|
|
|
693
763
|
{isNewCollection && includeTemplates && currentView === "import_data_mapping" &&
|
|
694
764
|
<Button variant={"text"}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
765
|
+
type="button"
|
|
766
|
+
onClick={() => {
|
|
767
|
+
importConfig.setInUse(false);
|
|
768
|
+
return setCurrentView("welcome");
|
|
769
|
+
}}>
|
|
770
|
+
{t("back")}
|
|
701
771
|
</Button>}
|
|
702
772
|
|
|
703
773
|
{isNewCollection && includeTemplates && currentView === "import_data_preview" &&
|
|
704
774
|
<Button variant={"text"}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
775
|
+
type="button"
|
|
776
|
+
onClick={() => {
|
|
777
|
+
setCurrentView("import_data_mapping");
|
|
778
|
+
}}>
|
|
779
|
+
{t("back")}
|
|
710
780
|
</Button>}
|
|
711
781
|
|
|
712
|
-
{isNewCollection && includeTemplates && currentView === "
|
|
782
|
+
{isNewCollection && includeTemplates && currentView === "general" &&
|
|
713
783
|
<Button variant={"text"}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
784
|
+
type="button"
|
|
785
|
+
onClick={() => setCurrentView("welcome")}>
|
|
786
|
+
{t("back")}
|
|
717
787
|
</Button>}
|
|
718
788
|
|
|
719
789
|
{isNewCollection && currentView === "properties" && <Button variant={"text"}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
<ArrowBackIcon/>
|
|
724
|
-
|
|
790
|
+
type="button"
|
|
791
|
+
color={"neutral"}
|
|
792
|
+
onClick={() => setCurrentView("general")}>
|
|
793
|
+
<ArrowBackIcon />
|
|
794
|
+
{t("back")}
|
|
725
795
|
</Button>}
|
|
726
796
|
|
|
727
797
|
<Button variant={"text"}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
798
|
+
color={"neutral"}
|
|
799
|
+
onClick={() => {
|
|
800
|
+
handleCancel();
|
|
801
|
+
}}>
|
|
802
|
+
{t("cancel")}
|
|
733
803
|
</Button>
|
|
734
804
|
|
|
735
805
|
{currentView === "welcome" &&
|
|
736
806
|
<Button variant={"text"} onClick={() => onWelcomeScreenContinue()}>
|
|
737
|
-
|
|
807
|
+
{t("continue_from_scratch")}
|
|
738
808
|
</Button>}
|
|
739
809
|
|
|
740
810
|
{isNewCollection && currentView === "import_data_mapping" &&
|
|
@@ -743,7 +813,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
743
813
|
color="primary"
|
|
744
814
|
onClick={onImportMappingComplete}
|
|
745
815
|
>
|
|
746
|
-
|
|
816
|
+
{t("next")}
|
|
747
817
|
</Button>}
|
|
748
818
|
|
|
749
819
|
{isNewCollection && currentView === "import_data_preview" &&
|
|
@@ -754,22 +824,22 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
754
824
|
setNextMode();
|
|
755
825
|
}}
|
|
756
826
|
>
|
|
757
|
-
|
|
827
|
+
{t("next")}
|
|
758
828
|
</Button>}
|
|
759
829
|
|
|
760
|
-
{isNewCollection && (currentView === "
|
|
830
|
+
{isNewCollection && (currentView === "general" || currentView === "properties") &&
|
|
761
831
|
<LoadingButton
|
|
762
832
|
variant={"filled"}
|
|
763
833
|
color="primary"
|
|
764
834
|
type="submit"
|
|
765
835
|
loading={isSubmitting}
|
|
766
|
-
disabled={isSubmitting || (currentView === "
|
|
836
|
+
disabled={isSubmitting || (currentView === "general" && !validValues)}
|
|
767
837
|
startIcon={currentView === "properties"
|
|
768
|
-
? <CheckIcon/>
|
|
838
|
+
? <CheckIcon />
|
|
769
839
|
: undefined}
|
|
770
840
|
>
|
|
771
|
-
{currentView === "
|
|
772
|
-
{currentView === "properties" && "
|
|
841
|
+
{currentView === "general" && t("next")}
|
|
842
|
+
{currentView === "properties" && t("create_collection")}
|
|
773
843
|
</LoadingButton>}
|
|
774
844
|
|
|
775
845
|
{!isNewCollection && <LoadingButton
|
|
@@ -778,7 +848,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
778
848
|
type="submit"
|
|
779
849
|
loading={isSubmitting}
|
|
780
850
|
>
|
|
781
|
-
|
|
851
|
+
{t("update_collection")}
|
|
782
852
|
</LoadingButton>}
|
|
783
853
|
|
|
784
854
|
</DialogActions>
|
|
@@ -791,10 +861,8 @@ function CollectionEditorInternal<M extends Record<string, any>>({
|
|
|
791
861
|
open={deleteRequested}
|
|
792
862
|
onAccept={deleteCollection}
|
|
793
863
|
onCancel={() => setDeleteRequested(false)}
|
|
794
|
-
title={<>
|
|
795
|
-
body={<>
|
|
796
|
-
delete any data</b>, only
|
|
797
|
-
the stored config, and reset to the code state.</>}/>
|
|
864
|
+
title={<>{t("delete_stored_config")}</>}
|
|
865
|
+
body={<>{t("delete_stored_config_body")}</>} />
|
|
798
866
|
|
|
799
867
|
</DialogContent>
|
|
800
868
|
|
|
@@ -808,7 +876,9 @@ function applyPropertyConfigs<M extends Record<string, any> = any>(collection: P
|
|
|
808
876
|
const propertiesResult: PropertiesOrBuilders<any> = {};
|
|
809
877
|
if (properties) {
|
|
810
878
|
Object.keys(properties).forEach((key) => {
|
|
811
|
-
|
|
879
|
+
const prop = properties[key];
|
|
880
|
+
if (prop == null) return;
|
|
881
|
+
propertiesResult[key] = applyPropertiesConfig(prop as PropertyOrBuilder, propertyConfigs);
|
|
812
882
|
});
|
|
813
883
|
}
|
|
814
884
|
|
|
@@ -820,7 +890,7 @@ function applyPropertyConfigs<M extends Record<string, any> = any>(collection: P
|
|
|
820
890
|
|
|
821
891
|
function applyPropertiesConfig(property: PropertyOrBuilder, propertyConfigs: Record<string, PropertyConfig<any>>) {
|
|
822
892
|
let internalProperty = property;
|
|
823
|
-
if (propertyConfigs && typeof internalProperty === "object" && internalProperty.propertyConfig) {
|
|
893
|
+
if (propertyConfigs && internalProperty && typeof internalProperty === "object" && internalProperty.propertyConfig) {
|
|
824
894
|
const propertyConfig = propertyConfigs[internalProperty.propertyConfig];
|
|
825
895
|
if (propertyConfig && isPropertyBuilder(propertyConfig.property)) {
|
|
826
896
|
internalProperty = propertyConfig.property;
|
|
@@ -847,30 +917,32 @@ function applyPropertiesConfig(property: PropertyOrBuilder, propertyConfigs: Rec
|
|
|
847
917
|
|
|
848
918
|
}
|
|
849
919
|
|
|
850
|
-
|
|
920
|
+
type TranslateFn = (key: string, params?: Record<string, string>) => string;
|
|
921
|
+
|
|
922
|
+
const validatePath = (t: TranslateFn, value: string, isNewCollection: boolean, existingPaths: string[], idValue?: string) => {
|
|
851
923
|
let error;
|
|
852
924
|
if (!value) {
|
|
853
|
-
error = "
|
|
925
|
+
error = t("must_specify_path");
|
|
854
926
|
}
|
|
855
927
|
// if (isNewCollection && existingIds?.includes(value.trim().toLowerCase()))
|
|
856
928
|
// error = "There is already a collection which uses this path as an id";
|
|
857
929
|
if (isNewCollection && existingPaths?.includes(value.trim().toLowerCase()) && !idValue)
|
|
858
|
-
error = "
|
|
930
|
+
error = t("collection_path_already_exists");
|
|
859
931
|
|
|
860
932
|
const subpaths = removeInitialAndTrailingSlashes(value).split("/");
|
|
861
933
|
if (subpaths.length % 2 === 0) {
|
|
862
|
-
error =
|
|
934
|
+
error = t("collection_path_odd_segments", { path: value });
|
|
863
935
|
}
|
|
864
936
|
return error;
|
|
865
937
|
};
|
|
866
938
|
|
|
867
|
-
const validateId = (value: string, isNewCollection: boolean, existingPaths: string[], existingIds: string[]) => {
|
|
939
|
+
const validateId = (t: TranslateFn, value: string, isNewCollection: boolean, existingPaths: string[], existingIds: string[]) => {
|
|
868
940
|
if (!value) return undefined;
|
|
869
941
|
let error;
|
|
870
942
|
if (isNewCollection && existingPaths?.includes(value.trim().toLowerCase()))
|
|
871
|
-
error = "
|
|
943
|
+
error = t("collection_uses_path_as_id");
|
|
872
944
|
if (isNewCollection && existingIds?.includes(value.trim().toLowerCase()))
|
|
873
|
-
error = "
|
|
945
|
+
error = t("collection_uses_this_id");
|
|
874
946
|
// if (error) {
|
|
875
947
|
// setAdvancedPanelExpanded(true);
|
|
876
948
|
// }
|