@firecms/collection_editor 3.0.0-alpha.17 → 3.0.0-alpha.19

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.
Files changed (64) hide show
  1. package/package.json +4 -3
  2. package/src/ConfigControllerProvider.tsx +177 -0
  3. package/src/components/EditorCollectionAction.tsx +95 -0
  4. package/src/components/HomePageEditorCollectionAction.tsx +81 -0
  5. package/src/components/NewCollectionCard.tsx +45 -0
  6. package/src/components/RootCollectionSuggestions.tsx +53 -0
  7. package/src/components/collection_editor/CollectionDetailsForm.tsx +312 -0
  8. package/src/components/collection_editor/CollectionEditorDialog.tsx +640 -0
  9. package/src/components/collection_editor/CollectionEditorWelcomeView.tsx +212 -0
  10. package/src/components/collection_editor/CollectionPropertiesEditorForm.tsx +450 -0
  11. package/src/components/collection_editor/CollectionYupValidation.tsx +6 -0
  12. package/src/components/collection_editor/EntityCustomViewsSelectDialog.tsx +29 -0
  13. package/src/components/collection_editor/EnumForm.tsx +354 -0
  14. package/src/components/collection_editor/PropertyEditView.tsx +535 -0
  15. package/src/components/collection_editor/PropertyFieldPreview.tsx +205 -0
  16. package/src/components/collection_editor/PropertySelectItem.tsx +31 -0
  17. package/src/components/collection_editor/PropertyTree.tsx +228 -0
  18. package/src/components/collection_editor/SelectIcons.tsx +72 -0
  19. package/src/components/collection_editor/SubcollectionsEditTab.tsx +239 -0
  20. package/src/components/collection_editor/UnsavedChangesDialog.tsx +47 -0
  21. package/src/components/collection_editor/import/CollectionEditorImportDataPreview.tsx +37 -0
  22. package/src/components/collection_editor/import/CollectionEditorImportMapping.tsx +236 -0
  23. package/src/components/collection_editor/import/clean_import_data.ts +53 -0
  24. package/src/components/collection_editor/properties/BlockPropertyField.tsx +131 -0
  25. package/src/components/collection_editor/properties/BooleanPropertyField.tsx +36 -0
  26. package/src/components/collection_editor/properties/CommonPropertyFields.tsx +112 -0
  27. package/src/components/collection_editor/properties/DateTimePropertyField.tsx +86 -0
  28. package/src/components/collection_editor/properties/EnumPropertyField.tsx +116 -0
  29. package/src/components/collection_editor/properties/FieldHelperView.tsx +13 -0
  30. package/src/components/collection_editor/properties/KeyValuePropertyField.tsx +20 -0
  31. package/src/components/collection_editor/properties/MapPropertyField.tsx +154 -0
  32. package/src/components/collection_editor/properties/NumberPropertyField.tsx +38 -0
  33. package/src/components/collection_editor/properties/ReferencePropertyField.tsx +184 -0
  34. package/src/components/collection_editor/properties/RepeatPropertyField.tsx +115 -0
  35. package/src/components/collection_editor/properties/StoragePropertyField.tsx +194 -0
  36. package/src/components/collection_editor/properties/StringPropertyField.tsx +85 -0
  37. package/src/components/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +36 -0
  38. package/src/components/collection_editor/properties/validation/ArrayPropertyValidation.tsx +50 -0
  39. package/src/components/collection_editor/properties/validation/GeneralPropertyValidation.tsx +49 -0
  40. package/src/components/collection_editor/properties/validation/NumberPropertyValidation.tsx +99 -0
  41. package/src/components/collection_editor/properties/validation/StringPropertyValidation.tsx +131 -0
  42. package/src/components/collection_editor/properties/validation/ValidationPanel.tsx +28 -0
  43. package/src/components/collection_editor/templates/blog_template.ts +115 -0
  44. package/src/components/collection_editor/templates/products_template.ts +89 -0
  45. package/src/components/collection_editor/templates/users_template.ts +34 -0
  46. package/src/components/collection_editor/util.ts +21 -0
  47. package/src/components/collection_editor/utils/supported_fields.tsx +28 -0
  48. package/src/components/collection_editor/utils/update_property_for_widget.ts +258 -0
  49. package/src/components/collection_editor/utils/useTraceUpdate.tsx +23 -0
  50. package/src/index.ts +31 -0
  51. package/src/types/collection_editor_controller.tsx +31 -0
  52. package/src/types/collection_inference.ts +3 -0
  53. package/src/types/config_controller.tsx +30 -0
  54. package/src/types/config_permissions.ts +20 -0
  55. package/src/types/persisted_collection.ts +7 -0
  56. package/src/useCollectionEditorController.tsx +9 -0
  57. package/src/useCollectionEditorPlugin.tsx +103 -0
  58. package/src/useCollectionsConfigController.tsx +9 -0
  59. package/src/utils/arrays.ts +3 -0
  60. package/src/utils/entities.ts +38 -0
  61. package/src/utils/icons.ts +17 -0
  62. package/src/utils/join_collections.ts +144 -0
  63. package/src/utils/synonyms.ts +1952 -0
  64. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,535 @@
1
+ import React, { useDeferredValue, useEffect, useRef, useState } from "react";
2
+ import equal from "react-fast-compare"
3
+
4
+ import { Form, Formik, FormikErrors, FormikProps, getIn } from "formik";
5
+ import {
6
+ Button,
7
+ cn,
8
+ DEFAULT_FIELD_CONFIGS,
9
+ DeleteConfirmationDialog,
10
+ DeleteIcon,
11
+ Dialog,
12
+ DialogActions,
13
+ DialogContent,
14
+ FieldConfig,
15
+ FieldConfigBadge,
16
+ FieldConfigId,
17
+ getFieldId,
18
+ IconButton,
19
+ InfoLabel,
20
+ isPropertyBuilder, Property,
21
+ Select,
22
+ toSnakeCase,
23
+ Typography
24
+ } from "@firecms/core";
25
+ import { EnumPropertyField } from "./properties/EnumPropertyField";
26
+ import { StoragePropertyField } from "./properties/StoragePropertyField";
27
+ import { MapPropertyField } from "./properties/MapPropertyField";
28
+ import { RepeatPropertyField } from "./properties/RepeatPropertyField";
29
+ import { CommonPropertyFields } from "./properties/CommonPropertyFields";
30
+ import { StringPropertyField } from "./properties/StringPropertyField";
31
+ import { BooleanPropertyField } from "./properties/BooleanPropertyField";
32
+ import { BlockPropertyField } from "./properties/BlockPropertyField";
33
+ import { NumberPropertyField } from "./properties/NumberPropertyField";
34
+ import { ReferencePropertyField } from "./properties/ReferencePropertyField";
35
+ import { DateTimePropertyField } from "./properties/DateTimePropertyField";
36
+ import { AdvancedPropertyValidation } from "./properties/advanced/AdvancedPropertyValidation";
37
+ import { editableProperty } from "../../utils/entities";
38
+ import { KeyValuePropertyField } from "./properties/KeyValuePropertyField";
39
+ import { updatePropertyFromWidget } from "./utils/update_property_for_widget";
40
+ import { PropertySelectItem } from "./PropertySelectItem";
41
+
42
+ export type PropertyWithId = Property & {
43
+ id?: string
44
+ };
45
+
46
+ export type OnPropertyChangedParams = {
47
+ id?: string,
48
+ property: Property,
49
+ namespace?: string,
50
+ previousId?: string
51
+ };
52
+
53
+ export type PropertyFormProps = {
54
+ includeIdAndName?: boolean;
55
+ existing: boolean;
56
+ autoUpdateId?: boolean;
57
+ autoOpenTypeSelect: boolean;
58
+ inArray: boolean;
59
+ propertyKey?: string;
60
+ propertyNamespace?: string;
61
+ property?: Property;
62
+ onPropertyChanged?: (params: OnPropertyChangedParams) => void;
63
+ onPropertyChangedImmediate?: boolean;
64
+ onDelete?: (id?: string, namespace?: string) => void;
65
+ onError?: (id: string, namespace?: string, error?: FormikErrors<any>) => void;
66
+ initialErrors?: FormikErrors<any>;
67
+ forceShowErrors?: boolean;
68
+ existingPropertyKeys?: string[];
69
+ allowDataInference: boolean;
70
+ getData?: () => Promise<object[]>;
71
+ getHelpers?: (formikProps: FormikProps<PropertyWithId>) => void;
72
+ customFields: Record<string, FieldConfig>;
73
+ };
74
+
75
+ export const PropertyForm = React.memo(
76
+ function PropertyForm({
77
+ includeIdAndName = true,
78
+ autoOpenTypeSelect,
79
+ existing,
80
+ autoUpdateId,
81
+ inArray,
82
+ propertyKey,
83
+ propertyNamespace,
84
+ property,
85
+ onPropertyChanged,
86
+ onPropertyChangedImmediate = true,
87
+ onDelete,
88
+ onError,
89
+ initialErrors,
90
+ forceShowErrors,
91
+ existingPropertyKeys,
92
+ allowDataInference,
93
+ getHelpers,
94
+ getData,
95
+ customFields
96
+ }: PropertyFormProps) {
97
+
98
+ const initialValue: PropertyWithId = {
99
+ id: "",
100
+ name: ""
101
+ } as PropertyWithId;
102
+
103
+ const disabled = (property && !editableProperty(property)) ?? false;
104
+
105
+ const lastSubmittedProperty = useRef<OnPropertyChangedParams | undefined>(property ? {
106
+ id: propertyKey,
107
+ previousId: propertyKey,
108
+ property
109
+ } : undefined);
110
+
111
+ const doOnPropertyChanged = ({
112
+ id,
113
+ property
114
+ }: OnPropertyChangedParams) => {
115
+ const params = {
116
+ id,
117
+ previousId: lastSubmittedProperty.current?.id,
118
+ property,
119
+ namespace: propertyNamespace
120
+ };
121
+ lastSubmittedProperty.current = params;
122
+ onPropertyChanged?.(params);
123
+ };
124
+
125
+ return <Formik
126
+ key={`property_view_${propertyKey}`}
127
+ initialErrors={initialErrors}
128
+ initialValues={property
129
+ ? { id: propertyKey, ...property } as PropertyWithId
130
+ : initialValue}
131
+ onSubmit={(newPropertyWithId: PropertyWithId, helpers) => {
132
+ console.log("Submitting property", newPropertyWithId)
133
+ const {
134
+ id,
135
+ ...property
136
+ } = newPropertyWithId;
137
+ doOnPropertyChanged({
138
+ id,
139
+ property
140
+ });
141
+ if (!existing)
142
+ helpers.resetForm({ values: initialValue });
143
+ }}
144
+ // validate={(values) => {
145
+ // console.log("validate property", values)
146
+ // const errors: any = {};
147
+ // if (!values?.dataType || !getFieldConfig(values)) {
148
+ // errors.selectedWidget = "Required";
149
+ // }
150
+ // if (existingPropertyKeys && values?.id && existingPropertyKeys.includes(values?.id)) {
151
+ // errors.id = "";
152
+ // }
153
+ // console.log("errors", errors)
154
+ // return errors;
155
+ // }}
156
+ >
157
+ {(props) => {
158
+
159
+ // eslint-disable-next-line react-hooks/rules-of-hooks
160
+ useEffect(() => {
161
+ getHelpers?.(props);
162
+ }, [props]);
163
+
164
+ return <PropertyEditView
165
+ onPropertyChanged={onPropertyChangedImmediate
166
+ ? doOnPropertyChanged
167
+ : undefined}
168
+ onDelete={onDelete}
169
+ includeIdAndTitle={includeIdAndName}
170
+ propertyNamespace={propertyNamespace}
171
+ onError={onError}
172
+ showErrors={forceShowErrors || props.submitCount > 0}
173
+ existing={existing}
174
+ autoUpdateId={autoUpdateId}
175
+ inArray={inArray}
176
+ autoOpenTypeSelect={autoOpenTypeSelect}
177
+ existingPropertyKeys={existingPropertyKeys}
178
+ disabled={disabled}
179
+ getData={getData}
180
+ allowDataInference={allowDataInference}
181
+ customFields={customFields}
182
+ {...props}/>;
183
+
184
+ }}
185
+
186
+ </Formik>
187
+ }, (a, b) =>
188
+ a.getData === b.getData &&
189
+ a.includeIdAndName === b.includeIdAndName &&
190
+ a.autoOpenTypeSelect === b.autoOpenTypeSelect &&
191
+ a.autoUpdateId === b.autoUpdateId &&
192
+ a.existing === b.existing
193
+ );
194
+
195
+ export function PropertyFormDialog({
196
+ open,
197
+ onCancel,
198
+ onOkClicked,
199
+ onPropertyChanged,
200
+ getData,
201
+ ...formProps
202
+ }: PropertyFormProps & {
203
+ open?: boolean;
204
+ onOkClicked?: () => void;
205
+ onCancel?: () => void;
206
+ }) {
207
+ const helpersRef = useRef<FormikProps<PropertyWithId>>();
208
+ const getHelpers = (helpers: FormikProps<PropertyWithId>) => {
209
+ helpersRef.current = helpers;
210
+ };
211
+
212
+ return <Dialog
213
+ open={open ?? false}
214
+ maxWidth={"xl"}
215
+ fullWidth={true}
216
+ >
217
+ <Form noValidate style={{ height: "100%" }}>
218
+
219
+ <DialogContent>
220
+ <PropertyForm {...formProps}
221
+ onPropertyChanged={(params) => {
222
+ onPropertyChanged?.(params);
223
+ onOkClicked?.();
224
+ }}
225
+ onPropertyChangedImmediate={false}
226
+ getHelpers={getHelpers}
227
+ getData={getData}
228
+ />
229
+ </DialogContent>
230
+
231
+ <DialogActions>
232
+
233
+ {onCancel && <Button
234
+ variant={"text"}
235
+ onClick={() => {
236
+ onCancel();
237
+ helpersRef.current?.resetForm();
238
+ }}>
239
+ Cancel
240
+ </Button>}
241
+
242
+ <Button variant="outlined"
243
+ color="primary"
244
+ onClick={() => helpersRef.current?.submitForm()}>
245
+ Ok
246
+ </Button>
247
+ </DialogActions>
248
+ </Form>
249
+ </Dialog>;
250
+
251
+ }
252
+
253
+ function PropertyEditView({
254
+ values,
255
+ errors,
256
+ touched,
257
+ setValues,
258
+ setFieldValue,
259
+ existing,
260
+ autoUpdateId = false,
261
+ autoOpenTypeSelect,
262
+ includeIdAndTitle,
263
+ onPropertyChanged,
264
+ onDelete,
265
+ propertyNamespace,
266
+ onError,
267
+ showErrors,
268
+ disabled,
269
+ inArray,
270
+ existingPropertyKeys,
271
+ getData,
272
+ allowDataInference,
273
+ customFields
274
+ }: {
275
+ includeIdAndTitle?: boolean;
276
+ existing: boolean;
277
+ autoUpdateId?: boolean;
278
+ autoOpenTypeSelect: boolean;
279
+ propertyNamespace?: string;
280
+ onPropertyChanged?: (params: OnPropertyChangedParams) => void;
281
+ onDelete?: (id?: string, namespace?: string) => void;
282
+ onError?: (id: string, namespace?: string, error?: FormikErrors<any>) => void;
283
+ showErrors: boolean;
284
+ inArray: boolean;
285
+ disabled: boolean;
286
+ existingPropertyKeys?: string[];
287
+ getData?: () => Promise<object[]>;
288
+ allowDataInference: boolean;
289
+ customFields: Record<string, FieldConfig>;
290
+ } & FormikProps<PropertyWithId>) {
291
+
292
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
293
+ const [selectedFieldConfigId, setSelectedFieldConfigId] = useState<string | undefined>(values?.dataType ? getFieldId(values) : undefined);
294
+
295
+ const allSupportedFields = Object.entries(customFields).concat(Object.entries(DEFAULT_FIELD_CONFIGS));
296
+
297
+ const displayedWidgets = inArray
298
+ ? allSupportedFields.filter(([_, fieldConfig]) => !isPropertyBuilder(fieldConfig.property) && fieldConfig.property?.dataType !== "array")
299
+ : allSupportedFields;
300
+
301
+ const deferredValues = useDeferredValue(values);
302
+ const nameFieldRef = useRef<HTMLInputElement>(null);
303
+
304
+ const lastSubmittedProperty = useRef<object>(values);
305
+
306
+ const id = "id";
307
+
308
+ const selectedWidgetError = showErrors && getIn(errors, "selectedWidget");
309
+
310
+ useEffect(() => {
311
+ const idTouched = getIn(touched, id);
312
+ if (!idTouched && autoUpdateId && values?.name) {
313
+ setFieldValue(id, toSnakeCase(values.name))
314
+ }
315
+ }, [autoUpdateId, touched, values?.name]);
316
+
317
+ useEffect(() => {
318
+ if (onPropertyChanged) {
319
+ if ((!includeIdAndTitle || deferredValues.id)) {
320
+ const {
321
+ id,
322
+ ...property
323
+ } = deferredValues;
324
+ if (!equal(deferredValues, lastSubmittedProperty.current)) {
325
+ onPropertyChanged({
326
+ id,
327
+ property,
328
+ namespace: propertyNamespace
329
+ });
330
+ lastSubmittedProperty.current = deferredValues;
331
+ }
332
+ }
333
+ }
334
+ }, [deferredValues, includeIdAndTitle, onPropertyChanged, propertyNamespace]);
335
+
336
+ useEffect(() => {
337
+ if (values?.id && onError && Object.keys(errors).length > 0) {
338
+ onError(values?.id, propertyNamespace, errors);
339
+ }
340
+ }, [errors, onError, propertyNamespace, values?.id]);
341
+
342
+ const onWidgetSelectChanged = (newSelectedWidgetId: FieldConfigId) => {
343
+ setSelectedFieldConfigId(newSelectedWidgetId);
344
+ setValues(updatePropertyFromWidget(values, newSelectedWidgetId, customFields));
345
+ // Ugly hack to autofocus the name field
346
+ setTimeout(() => {
347
+ nameFieldRef.current?.focus();
348
+ }, 0);
349
+ };
350
+
351
+ let childComponent;
352
+ if (selectedFieldConfigId === "text_field" ||
353
+ selectedFieldConfigId === "multiline" ||
354
+ selectedFieldConfigId === "markdown" ||
355
+ selectedFieldConfigId === "url" ||
356
+ selectedFieldConfigId === "email") {
357
+ childComponent =
358
+ <StringPropertyField widgetId={selectedFieldConfigId}
359
+ disabled={disabled}
360
+ showErrors={showErrors}/>;
361
+ } else if (selectedFieldConfigId === "select" ||
362
+ selectedFieldConfigId === "number_select") {
363
+ childComponent = <EnumPropertyField
364
+ multiselect={false}
365
+ allowDataInference={allowDataInference}
366
+ updateIds={!existing}
367
+ disabled={disabled}
368
+ getData={getData}
369
+ showErrors={showErrors}/>;
370
+ } else if (selectedFieldConfigId === "multi_select" ||
371
+ selectedFieldConfigId === "multi_number_select") {
372
+ childComponent = <EnumPropertyField
373
+ multiselect={true}
374
+ updateIds={!existing}
375
+ disabled={disabled}
376
+ allowDataInference={allowDataInference}
377
+ getData={getData}
378
+ showErrors={showErrors}/>;
379
+ } else if (selectedFieldConfigId === "file_upload") {
380
+ childComponent =
381
+ <StoragePropertyField existing={existing}
382
+ multiple={false}
383
+ disabled={disabled}/>;
384
+ } else if (selectedFieldConfigId === "multi_file_upload") {
385
+ childComponent =
386
+ <StoragePropertyField existing={existing}
387
+ multiple={true}
388
+ disabled={disabled}/>;
389
+ } else if (selectedFieldConfigId === "switch") {
390
+ childComponent = <BooleanPropertyField disabled={disabled}/>;
391
+ } else if (selectedFieldConfigId === "number_input") {
392
+ childComponent = <NumberPropertyField disabled={disabled}/>;
393
+ } else if (selectedFieldConfigId === "group") {
394
+ childComponent =
395
+ <MapPropertyField disabled={disabled} getData={getData} allowDataInference={allowDataInference} customFields={customFields}/>;
396
+ } else if (selectedFieldConfigId === "block") {
397
+ childComponent =
398
+ <BlockPropertyField disabled={disabled} getData={getData} allowDataInference={allowDataInference} customFields={customFields}/>;
399
+ } else if (selectedFieldConfigId === "reference") {
400
+ childComponent =
401
+ <ReferencePropertyField showErrors={showErrors}
402
+ existing={existing}
403
+ multiple={false}
404
+ disabled={disabled}/>;
405
+ } else if (selectedFieldConfigId === "date_time") {
406
+ childComponent = <DateTimePropertyField disabled={disabled}/>;
407
+ } else if (selectedFieldConfigId === "multi_references") {
408
+ childComponent =
409
+ <ReferencePropertyField showErrors={showErrors}
410
+ existing={existing}
411
+ multiple={true}
412
+ disabled={disabled}/>;
413
+ } else if (selectedFieldConfigId === "repeat") {
414
+ childComponent =
415
+ <RepeatPropertyField showErrors={showErrors}
416
+ existing={existing}
417
+ getData={getData}
418
+ allowDataInference={allowDataInference}
419
+ disabled={disabled}
420
+ customFields={customFields}/>;
421
+ } else if (selectedFieldConfigId === "key_value") {
422
+ childComponent =
423
+ <KeyValuePropertyField disabled={disabled}/>;
424
+ } else {
425
+ childComponent = null;
426
+ }
427
+
428
+ return (
429
+ <>
430
+ {disabled && <InfoLabel mode={"warn"}>
431
+ <Typography>This property can&apos;t be edited</Typography>
432
+ <Typography variant={"caption"}>
433
+ You may not have permission to
434
+ edit it or it is defined in code with no <code>editable</code> flag
435
+ </Typography>
436
+ </InfoLabel>}
437
+
438
+ <div className="flex mt-2 justify-between">
439
+ <Select
440
+ className={"w-full"}
441
+ error={Boolean(selectedWidgetError)}
442
+ value={selectedFieldConfigId ?? ""}
443
+ placeholder={"Select a property widget"}
444
+ open={autoOpenTypeSelect}
445
+ position={"item-aligned"}
446
+ disabled={disabled}
447
+ renderValue={(value) => {
448
+ if (!value) {
449
+ return <em>Select a property
450
+ widget</em>;
451
+ }
452
+ const key = value as FieldConfigId;
453
+ const fieldConfig = DEFAULT_FIELD_CONFIGS[key] ?? customFields[key];
454
+ const baseProperty = fieldConfig.property;
455
+ const optionDisabled = isPropertyBuilder(baseProperty) || (existing && baseProperty.dataType !== values?.dataType);
456
+ return <div
457
+ onClick={(e) => {
458
+ if (optionDisabled) {
459
+ e.stopPropagation();
460
+ e.preventDefault();
461
+ }
462
+ }}
463
+ className={cn(
464
+ "flex items-center",
465
+ optionDisabled ? "w-full pointer-events-none opacity-50" : "")}>
466
+ <div className={"mr-8"}>
467
+ <FieldConfigBadge fieldConfig={fieldConfig}/>
468
+ </div>
469
+ <div className={"flex flex-col items-start text-base text-left"}>
470
+ <div>{fieldConfig.name}</div>
471
+ <Typography variant={"caption"}
472
+ color={"disabled"}>
473
+ {optionDisabled ? "You can only switch to widgets that use the same data type" : fieldConfig.description}
474
+ </Typography>
475
+ </div>
476
+ </div>
477
+ }}
478
+ onValueChange={(value) => {
479
+ onWidgetSelectChanged(value as FieldConfigId);
480
+ }}>
481
+ {displayedWidgets.map(([key, fieldConfig]) => {
482
+ const baseProperty = fieldConfig.property;
483
+ const optionDisabled = existing && !isPropertyBuilder(baseProperty) && baseProperty.dataType !== values?.dataType;
484
+ return <PropertySelectItem
485
+ key={key}
486
+ value={key}
487
+ optionDisabled={optionDisabled}
488
+ fieldConfig={fieldConfig}
489
+ existing={existing}/>;
490
+ })}
491
+ </Select>
492
+
493
+ {selectedWidgetError &&
494
+ <Typography variant="caption" color={"error"}>Required</Typography>}
495
+
496
+ {onDelete && values?.id &&
497
+ <IconButton
498
+ variant={"ghost"}
499
+ className="m-4"
500
+ disabled={disabled}
501
+ onClick={() => setDeleteDialogOpen(true)}>
502
+ <DeleteIcon/>
503
+ </IconButton>}
504
+ </div>
505
+
506
+ <div className={"grid grid-cols-12 gap-y-12 mt-8 mb-8"}>
507
+ {includeIdAndTitle &&
508
+ <CommonPropertyFields showErrors={showErrors}
509
+ disabledId={existing}
510
+ isNewProperty={!existing}
511
+ existingPropertyKeys={existingPropertyKeys}
512
+ disabled={disabled}
513
+ ref={nameFieldRef}/>}
514
+
515
+ {childComponent}
516
+
517
+ <div className={"col-span-12"}>
518
+ <AdvancedPropertyValidation disabled={disabled}/>
519
+ </div>
520
+ </div>
521
+
522
+ {onDelete &&
523
+ <DeleteConfirmationDialog open={deleteDialogOpen}
524
+ onAccept={() => onDelete(values?.id, propertyNamespace)}
525
+ onCancel={() => setDeleteDialogOpen(false)}
526
+ title={<div>Delete this property?</div>}
527
+ body={
528
+ <div> This will <b>not delete any
529
+ data</b>, only modify the
530
+ collection.</div>
531
+ }/>}
532
+
533
+ </>
534
+ );
535
+ }