@firecms/collection_editor 3.0.0-canary.15 → 3.0.0-canary.151
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/LICENSE +114 -21
- package/dist/ConfigControllerProvider.d.ts +11 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +4921 -3536
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +6846 -3
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collection_editor_controller.d.ts +14 -2
- package/dist/types/collection_inference.d.ts +1 -1
- package/dist/types/config_permissions.d.ts +2 -2
- package/dist/types/persisted_collection.d.ts +1 -1
- package/dist/ui/CollectionViewHeaderAction.d.ts +3 -2
- package/dist/ui/EditorCollectionActionStart.d.ts +2 -0
- package/dist/ui/PropertyAddColumnComponent.d.ts +3 -1
- package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +4 -3
- package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +1 -1
- package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -1
- package/dist/ui/collection_editor/PropertyEditView.d.ts +8 -0
- package/dist/ui/collection_editor/PropertyTree.d.ts +9 -9
- package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +1 -1
- package/dist/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +7 -0
- package/dist/ui/collection_editor/properties/MarkdownPropertyField.d.ts +4 -0
- package/dist/ui/collection_editor/properties/StringPropertyField.d.ts +1 -1
- package/dist/useCollectionEditorPlugin.d.ts +17 -11
- package/dist/utils/collections.d.ts +6 -0
- package/package.json +21 -35
- package/src/ConfigControllerProvider.tsx +75 -63
- package/src/index.ts +1 -0
- package/src/types/collection_editor_controller.tsx +14 -4
- package/src/types/collection_inference.ts +1 -1
- package/src/types/config_permissions.ts +1 -1
- package/src/types/persisted_collection.ts +2 -3
- package/src/ui/CollectionViewHeaderAction.tsx +10 -5
- package/src/ui/EditorCollectionAction.tsx +10 -63
- package/src/ui/EditorCollectionActionStart.tsx +88 -0
- package/src/ui/HomePageEditorCollectionAction.tsx +18 -13
- package/src/ui/NewCollectionButton.tsx +12 -10
- package/src/ui/NewCollectionCard.tsx +3 -3
- package/src/ui/PropertyAddColumnComponent.tsx +11 -6
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +70 -9
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +61 -34
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +8 -7
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +37 -34
- package/src/ui/collection_editor/EnumForm.tsx +5 -2
- package/src/ui/collection_editor/GetCodeDialog.tsx +52 -21
- package/src/ui/collection_editor/PropertyEditView.tsx +255 -80
- package/src/ui/collection_editor/PropertyFieldPreview.tsx +4 -7
- package/src/ui/collection_editor/PropertyTree.tsx +7 -5
- package/src/ui/collection_editor/SubcollectionsEditTab.tsx +26 -19
- package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +25 -9
- package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +40 -9
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +32 -20
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +50 -47
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +1 -1
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +7 -6
- package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +139 -0
- package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -1
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +32 -17
- package/src/ui/collection_editor/properties/StringPropertyField.tsx +1 -10
- package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +2 -2
- package/src/ui/collection_editor/templates/pages_template.ts +1 -6
- package/src/useCollectionEditorPlugin.tsx +41 -31
- package/src/utils/collections.ts +30 -0
- package/dist/ui/RootCollectionSuggestions.d.ts +0 -3
- package/dist/ui/collection_editor/PropertySelectItem.d.ts +0 -8
- package/src/ui/RootCollectionSuggestions.tsx +0 -63
- package/src/ui/collection_editor/PropertySelectItem.tsx +0 -32
|
@@ -3,29 +3,35 @@ import equal from "react-fast-compare"
|
|
|
3
3
|
|
|
4
4
|
import { Formex, FormexController, getIn, useCreateFormex } from "@firecms/formex";
|
|
5
5
|
import {
|
|
6
|
+
ConfirmationDialog,
|
|
6
7
|
DEFAULT_FIELD_CONFIGS,
|
|
7
|
-
DeleteConfirmationDialog,
|
|
8
|
-
PropertyConfigId,
|
|
9
8
|
getFieldConfig,
|
|
10
|
-
getFieldId,
|
|
9
|
+
getFieldId, isEmptyObject,
|
|
11
10
|
isPropertyBuilder,
|
|
12
11
|
isValidRegExp,
|
|
13
12
|
mergeDeep,
|
|
14
13
|
Property,
|
|
15
14
|
PropertyConfig,
|
|
16
15
|
PropertyConfigBadge,
|
|
16
|
+
PropertyConfigId,
|
|
17
17
|
} from "@firecms/core";
|
|
18
18
|
import {
|
|
19
19
|
Button,
|
|
20
|
-
|
|
20
|
+
Card,
|
|
21
|
+
cls,
|
|
21
22
|
DeleteIcon,
|
|
22
23
|
Dialog,
|
|
23
24
|
DialogActions,
|
|
24
25
|
DialogContent,
|
|
26
|
+
DialogTitle,
|
|
27
|
+
fieldBackgroundDisabledMixin,
|
|
28
|
+
fieldBackgroundHoverMixin,
|
|
29
|
+
fieldBackgroundMixin,
|
|
25
30
|
IconButton,
|
|
26
31
|
InfoLabel,
|
|
27
|
-
|
|
28
|
-
Typography
|
|
32
|
+
Tooltip,
|
|
33
|
+
Typography,
|
|
34
|
+
WarningOffIcon
|
|
29
35
|
} from "@firecms/ui";
|
|
30
36
|
import { EnumPropertyField } from "./properties/EnumPropertyField";
|
|
31
37
|
import { StoragePropertyField } from "./properties/StoragePropertyField";
|
|
@@ -42,9 +48,9 @@ import { AdvancedPropertyValidation } from "./properties/advanced/AdvancedProper
|
|
|
42
48
|
import { editableProperty } from "../../utils/entities";
|
|
43
49
|
import { KeyValuePropertyField } from "./properties/KeyValuePropertyField";
|
|
44
50
|
import { updatePropertyFromWidget } from "./utils/update_property_for_widget";
|
|
45
|
-
import { PropertySelectItem } from "./PropertySelectItem";
|
|
46
51
|
import { UrlPropertyField } from "./properties/UrlPropertyField";
|
|
47
52
|
import { supportedFields } from "./utils/supported_fields";
|
|
53
|
+
import { MarkdownPropertyField } from "./properties/MarkdownPropertyField";
|
|
48
54
|
|
|
49
55
|
export type PropertyWithId = Property & {
|
|
50
56
|
id?: string
|
|
@@ -68,6 +74,7 @@ export type PropertyFormProps = {
|
|
|
68
74
|
property?: Property;
|
|
69
75
|
onPropertyChanged?: (params: OnPropertyChangedParams) => void;
|
|
70
76
|
onPropertyChangedImmediate?: boolean;
|
|
77
|
+
onDismiss?: () => void;
|
|
71
78
|
onDelete?: (id?: string, namespace?: string) => void;
|
|
72
79
|
onError?: (id: string, namespace?: string, error?: Record<string, any>) => void;
|
|
73
80
|
initialErrors?: Record<string, any>;
|
|
@@ -95,6 +102,7 @@ export const PropertyForm = React.memo(
|
|
|
95
102
|
property,
|
|
96
103
|
onPropertyChanged,
|
|
97
104
|
onPropertyChangedImmediate = true,
|
|
105
|
+
onDismiss,
|
|
98
106
|
onDelete,
|
|
99
107
|
onError,
|
|
100
108
|
initialErrors,
|
|
@@ -134,6 +142,7 @@ export const PropertyForm = React.memo(
|
|
|
134
142
|
};
|
|
135
143
|
|
|
136
144
|
const formexController = useCreateFormex<PropertyWithId>({
|
|
145
|
+
debugId: "PROPERTY_FORM",
|
|
137
146
|
initialValues: property
|
|
138
147
|
? { id: propertyKey, ...property } as PropertyWithId
|
|
139
148
|
: initialValue,
|
|
@@ -148,7 +157,10 @@ export const PropertyForm = React.memo(
|
|
|
148
157
|
} = newPropertyWithId;
|
|
149
158
|
doOnPropertyChanged({
|
|
150
159
|
id,
|
|
151
|
-
property: {
|
|
160
|
+
property: {
|
|
161
|
+
...property,
|
|
162
|
+
editable: property.editable ?? true
|
|
163
|
+
}
|
|
152
164
|
});
|
|
153
165
|
if (!existingProperty)
|
|
154
166
|
controller.resetForm({ values: initialValue });
|
|
@@ -209,6 +221,7 @@ export const PropertyForm = React.memo(
|
|
|
209
221
|
includeIdAndTitle={includeIdAndName}
|
|
210
222
|
propertyNamespace={propertyNamespace}
|
|
211
223
|
onError={onError}
|
|
224
|
+
onDismiss={onDismiss}
|
|
212
225
|
showErrors={forceShowErrors || formexController.submitCount > 0}
|
|
213
226
|
existing={existingProperty}
|
|
214
227
|
autoUpdateId={autoUpdateId}
|
|
@@ -228,6 +241,7 @@ export const PropertyForm = React.memo(
|
|
|
228
241
|
a.includeIdAndName === b.includeIdAndName &&
|
|
229
242
|
a.autoOpenTypeSelect === b.autoOpenTypeSelect &&
|
|
230
243
|
a.autoUpdateId === b.autoUpdateId &&
|
|
244
|
+
a.existingPropertyKeys === b.existingPropertyKeys &&
|
|
231
245
|
a.existingProperty === b.existingProperty
|
|
232
246
|
);
|
|
233
247
|
|
|
@@ -263,6 +277,7 @@ export function PropertyFormDialog({
|
|
|
263
277
|
}}>
|
|
264
278
|
<DialogContent>
|
|
265
279
|
<PropertyForm {...formProps}
|
|
280
|
+
onDismiss={onCancel}
|
|
266
281
|
onPropertyChanged={(params) => {
|
|
267
282
|
onPropertyChanged?.(params);
|
|
268
283
|
onOkClicked?.();
|
|
@@ -307,6 +322,7 @@ function PropertyEditFormFields({
|
|
|
307
322
|
onPropertyChanged,
|
|
308
323
|
onDelete,
|
|
309
324
|
propertyNamespace,
|
|
325
|
+
onDismiss,
|
|
310
326
|
onError,
|
|
311
327
|
showErrors,
|
|
312
328
|
disabled,
|
|
@@ -321,6 +337,7 @@ function PropertyEditFormFields({
|
|
|
321
337
|
autoUpdateId?: boolean;
|
|
322
338
|
autoOpenTypeSelect: boolean;
|
|
323
339
|
propertyNamespace?: string;
|
|
340
|
+
onDismiss?: () => void;
|
|
324
341
|
onPropertyChanged?: (params: OnPropertyChangedParams) => void;
|
|
325
342
|
onDelete?: (id?: string, namespace?: string) => void;
|
|
326
343
|
onError?: (id: string, namespace?: string, error?: Record<string, any>) => void;
|
|
@@ -337,12 +354,6 @@ function PropertyEditFormFields({
|
|
|
337
354
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
338
355
|
const [selectedFieldConfigId, setSelectedFieldConfigId] = useState<string | undefined>(values?.dataType ? getFieldId(values) : undefined);
|
|
339
356
|
|
|
340
|
-
const allSupportedFields = Object.entries(supportedFields).concat(Object.entries(propertyConfigs));
|
|
341
|
-
|
|
342
|
-
const displayedWidgets = inArray
|
|
343
|
-
? allSupportedFields.filter(([_, propertyConfig]) => !isPropertyBuilder(propertyConfig.property) && propertyConfig.property?.dataType !== "array")
|
|
344
|
-
: allSupportedFields;
|
|
345
|
-
|
|
346
357
|
const deferredValues = useDeferredValue(values);
|
|
347
358
|
const nameFieldRef = useRef<HTMLInputElement>(null);
|
|
348
359
|
|
|
@@ -367,13 +378,13 @@ function PropertyEditFormFields({
|
|
|
367
378
|
}
|
|
368
379
|
}
|
|
369
380
|
}
|
|
370
|
-
}, [deferredValues, includeIdAndTitle,
|
|
381
|
+
}, [deferredValues, includeIdAndTitle, propertyNamespace]);
|
|
371
382
|
|
|
372
383
|
useEffect(() => {
|
|
373
|
-
if (values?.id && onError) {
|
|
384
|
+
if (values?.id && onError && !isEmptyObject(errors)) {
|
|
374
385
|
onError(values?.id, propertyNamespace, errors);
|
|
375
386
|
}
|
|
376
|
-
}, [errors,
|
|
387
|
+
}, [errors, propertyNamespace, values?.id]);
|
|
377
388
|
|
|
378
389
|
const onWidgetSelectChanged = (newSelectedWidgetId: PropertyConfigId) => {
|
|
379
390
|
setSelectedFieldConfigId(newSelectedWidgetId);
|
|
@@ -387,7 +398,6 @@ function PropertyEditFormFields({
|
|
|
387
398
|
let childComponent;
|
|
388
399
|
if (selectedFieldConfigId === "text_field" ||
|
|
389
400
|
selectedFieldConfigId === "multiline" ||
|
|
390
|
-
selectedFieldConfigId === "markdown" ||
|
|
391
401
|
selectedFieldConfigId === "email") {
|
|
392
402
|
childComponent =
|
|
393
403
|
<StringPropertyField widgetId={selectedFieldConfigId}
|
|
@@ -397,6 +407,10 @@ function PropertyEditFormFields({
|
|
|
397
407
|
childComponent =
|
|
398
408
|
<UrlPropertyField disabled={disabled}
|
|
399
409
|
showErrors={showErrors}/>;
|
|
410
|
+
} else if (selectedFieldConfigId === "markdown") {
|
|
411
|
+
childComponent =
|
|
412
|
+
<MarkdownPropertyField disabled={disabled}
|
|
413
|
+
showErrors={showErrors}/>;
|
|
400
414
|
} else if (selectedFieldConfigId === "select" ||
|
|
401
415
|
selectedFieldConfigId === "number_select") {
|
|
402
416
|
childComponent = <EnumPropertyField
|
|
@@ -481,62 +495,22 @@ function PropertyEditFormFields({
|
|
|
481
495
|
|
|
482
496
|
<div className="flex mt-2 justify-between">
|
|
483
497
|
<div className={"w-full flex flex-col gap-2"}>
|
|
484
|
-
<
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
placeholder={"Select a property widget"}
|
|
498
|
+
<WidgetSelectView
|
|
499
|
+
initialProperty={values}
|
|
500
|
+
value={selectedFieldConfigId as PropertyConfigId}
|
|
501
|
+
onValueChange={(value) => onWidgetSelectChanged(value as PropertyConfigId)}
|
|
489
502
|
open={selectOpen}
|
|
490
|
-
onOpenChange={
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
renderValue={(value) => {
|
|
494
|
-
if (!value) {
|
|
495
|
-
return <em>Select a property
|
|
496
|
-
widget</em>;
|
|
503
|
+
onOpenChange={(open, hasValue) => {
|
|
504
|
+
if (!hasValue) {
|
|
505
|
+
onDismiss?.();
|
|
497
506
|
}
|
|
498
|
-
|
|
499
|
-
const propertyConfig = DEFAULT_FIELD_CONFIGS[key] ?? propertyConfigs[key];
|
|
500
|
-
const baseProperty = propertyConfig.property;
|
|
501
|
-
const baseFieldConfig = baseProperty && !isPropertyBuilder(baseProperty) ? getFieldConfig(baseProperty, propertyConfigs) : undefined;
|
|
502
|
-
const optionDisabled = isPropertyBuilder(baseProperty) || (existing && baseProperty.dataType !== values?.dataType);
|
|
503
|
-
const computedFieldConfig = baseFieldConfig ? mergeDeep(baseFieldConfig, propertyConfig) : propertyConfig;
|
|
504
|
-
return <div
|
|
505
|
-
onClick={(e) => {
|
|
506
|
-
if (optionDisabled) {
|
|
507
|
-
e.stopPropagation();
|
|
508
|
-
e.preventDefault();
|
|
509
|
-
}
|
|
510
|
-
}}
|
|
511
|
-
className={cn(
|
|
512
|
-
"flex items-center",
|
|
513
|
-
optionDisabled ? "w-full pointer-events-none opacity-50" : "")}>
|
|
514
|
-
<div className={"mr-8"}>
|
|
515
|
-
<PropertyConfigBadge propertyConfig={computedFieldConfig}/>
|
|
516
|
-
</div>
|
|
517
|
-
<div className={"flex flex-col items-start text-base text-left"}>
|
|
518
|
-
<div>{computedFieldConfig.name}</div>
|
|
519
|
-
<Typography variant={"caption"}
|
|
520
|
-
color={"disabled"}>
|
|
521
|
-
{optionDisabled ? "You can only switch to widgets that use the same data type" : computedFieldConfig.description}
|
|
522
|
-
</Typography>
|
|
523
|
-
</div>
|
|
524
|
-
</div>
|
|
507
|
+
setSelectOpen(open);
|
|
525
508
|
}}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
}
|
|
529
|
-
{
|
|
530
|
-
|
|
531
|
-
const optionDisabled = existing && !isPropertyBuilder(baseProperty) && baseProperty.dataType !== values?.dataType;
|
|
532
|
-
return <PropertySelectItem
|
|
533
|
-
key={key}
|
|
534
|
-
value={key}
|
|
535
|
-
optionDisabled={optionDisabled}
|
|
536
|
-
propertyConfig={propertyConfig}
|
|
537
|
-
existing={existing}/>;
|
|
538
|
-
})}
|
|
539
|
-
</Select>
|
|
509
|
+
disabled={disabled}
|
|
510
|
+
showError={Boolean(selectedWidgetError)}
|
|
511
|
+
existing={existing}
|
|
512
|
+
propertyConfigs={propertyConfigs}
|
|
513
|
+
inArray={inArray}/>
|
|
540
514
|
|
|
541
515
|
{selectedWidgetError &&
|
|
542
516
|
<Typography variant="caption"
|
|
@@ -575,15 +549,15 @@ function PropertyEditFormFields({
|
|
|
575
549
|
</div>
|
|
576
550
|
|
|
577
551
|
{onDelete &&
|
|
578
|
-
<
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
552
|
+
<ConfirmationDialog open={deleteDialogOpen}
|
|
553
|
+
onAccept={() => onDelete(values?.id, propertyNamespace)}
|
|
554
|
+
onCancel={() => setDeleteDialogOpen(false)}
|
|
555
|
+
title={<div>Delete this property?</div>}
|
|
556
|
+
body={
|
|
557
|
+
<div> This will <b>not delete any
|
|
558
|
+
data</b>, only modify the
|
|
559
|
+
collection.</div>
|
|
560
|
+
}/>}
|
|
587
561
|
|
|
588
562
|
</>
|
|
589
563
|
);
|
|
@@ -613,3 +587,204 @@ function validateName(value: string) {
|
|
|
613
587
|
}
|
|
614
588
|
return error;
|
|
615
589
|
}
|
|
590
|
+
|
|
591
|
+
const WIDGET_TYPE_MAP: Record<PropertyConfigId, string> = {
|
|
592
|
+
text_field: "Text",
|
|
593
|
+
multiline: "Text",
|
|
594
|
+
markdown: "Text",
|
|
595
|
+
url: "Text",
|
|
596
|
+
email: "Text",
|
|
597
|
+
switch: "Boolean",
|
|
598
|
+
select: "Select",
|
|
599
|
+
multi_select: "Select",
|
|
600
|
+
number_input: "Number",
|
|
601
|
+
number_select: "Select",
|
|
602
|
+
multi_number_select: "Select",
|
|
603
|
+
file_upload: "File",
|
|
604
|
+
multi_file_upload: "File",
|
|
605
|
+
reference: "Reference",
|
|
606
|
+
multi_references: "Reference",
|
|
607
|
+
date_time: "Date",
|
|
608
|
+
group: "Group",
|
|
609
|
+
key_value: "Group",
|
|
610
|
+
repeat: "Array",
|
|
611
|
+
custom_array: "Array",
|
|
612
|
+
block: "Group"
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
function WidgetSelectView({
|
|
616
|
+
initialProperty,
|
|
617
|
+
value,
|
|
618
|
+
onValueChange,
|
|
619
|
+
open,
|
|
620
|
+
onOpenChange,
|
|
621
|
+
disabled,
|
|
622
|
+
showError,
|
|
623
|
+
existing,
|
|
624
|
+
propertyConfigs,
|
|
625
|
+
inArray
|
|
626
|
+
}: {
|
|
627
|
+
initialProperty?: PropertyWithId,
|
|
628
|
+
value?: PropertyConfigId,
|
|
629
|
+
onValueChange: (value: string) => void,
|
|
630
|
+
showError: boolean,
|
|
631
|
+
open: boolean,
|
|
632
|
+
onOpenChange: (open: boolean, hasValue: boolean) => void,
|
|
633
|
+
disabled: boolean,
|
|
634
|
+
existing: boolean,
|
|
635
|
+
propertyConfigs: Record<string, PropertyConfig>,
|
|
636
|
+
inArray?: boolean
|
|
637
|
+
}) {
|
|
638
|
+
|
|
639
|
+
const allSupportedFields = Object.entries(supportedFields).concat(Object.entries(propertyConfigs));
|
|
640
|
+
|
|
641
|
+
const displayedWidgets = (inArray
|
|
642
|
+
? allSupportedFields.filter(([_, propertyConfig]) => !isPropertyBuilder(propertyConfig.property) && propertyConfig.property?.dataType !== "array")
|
|
643
|
+
: allSupportedFields)
|
|
644
|
+
.map(([key, propertyConfig]) => ({
|
|
645
|
+
[key]: propertyConfig
|
|
646
|
+
}))
|
|
647
|
+
.reduce((a, b) => {
|
|
648
|
+
return {
|
|
649
|
+
...a,
|
|
650
|
+
...b
|
|
651
|
+
}
|
|
652
|
+
}, {});
|
|
653
|
+
|
|
654
|
+
const key = value;
|
|
655
|
+
const propertyConfig = key ? (DEFAULT_FIELD_CONFIGS[key] ?? propertyConfigs[key]) : undefined;
|
|
656
|
+
const baseProperty = propertyConfig?.property;
|
|
657
|
+
const baseFieldConfig = baseProperty && !isPropertyBuilder(baseProperty) ? getFieldConfig(baseProperty, propertyConfigs) : undefined;
|
|
658
|
+
const computedFieldConfig = baseFieldConfig && propertyConfig ? mergeDeep(baseFieldConfig, propertyConfig) : propertyConfig;
|
|
659
|
+
|
|
660
|
+
const groups: string[] = [...new Set(Object.keys(displayedWidgets).map(key => {
|
|
661
|
+
const group = WIDGET_TYPE_MAP[key as PropertyConfigId];
|
|
662
|
+
if (group) {
|
|
663
|
+
return group;
|
|
664
|
+
}
|
|
665
|
+
return "Custom/Other"
|
|
666
|
+
}))];
|
|
667
|
+
|
|
668
|
+
return <>
|
|
669
|
+
<div
|
|
670
|
+
onClick={() => {
|
|
671
|
+
if (!disabled) {
|
|
672
|
+
onOpenChange(!open, Boolean(value));
|
|
673
|
+
}
|
|
674
|
+
}}
|
|
675
|
+
className={cls(
|
|
676
|
+
"select-none rounded-md text-sm p-4",
|
|
677
|
+
fieldBackgroundMixin,
|
|
678
|
+
disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
|
|
679
|
+
"relative flex items-center",
|
|
680
|
+
)}>
|
|
681
|
+
{!value && <em>Select a property widget</em>}
|
|
682
|
+
{value && computedFieldConfig && <div
|
|
683
|
+
className={cls(
|
|
684
|
+
"flex items-center")}>
|
|
685
|
+
<div className={"mr-8"}>
|
|
686
|
+
<PropertyConfigBadge propertyConfig={computedFieldConfig}/>
|
|
687
|
+
</div>
|
|
688
|
+
<div className={"flex flex-col items-start text-base text-left"}>
|
|
689
|
+
<div>{computedFieldConfig.name}</div>
|
|
690
|
+
<Typography variant={"caption"}
|
|
691
|
+
color={"secondary"}>
|
|
692
|
+
{computedFieldConfig.description}
|
|
693
|
+
</Typography>
|
|
694
|
+
</div>
|
|
695
|
+
</div>}
|
|
696
|
+
</div>
|
|
697
|
+
<Dialog open={open}
|
|
698
|
+
onOpenChange={(open) => onOpenChange(open, Boolean(value))}
|
|
699
|
+
maxWidth={"4xl"}>
|
|
700
|
+
<DialogTitle>
|
|
701
|
+
Select a property widget
|
|
702
|
+
</DialogTitle>
|
|
703
|
+
<DialogContent>
|
|
704
|
+
<div>
|
|
705
|
+
{groups.map(group => {
|
|
706
|
+
return <div key={group} className={"mt-4"}>
|
|
707
|
+
<Typography variant={"label"}>{group}</Typography>
|
|
708
|
+
<div className={"grid grid-cols-1 md:grid-cols-2 gap-x-4 gap-y-2 mt-4"}>
|
|
709
|
+
{Object.entries(displayedWidgets).map(([key, propertyConfig]) => {
|
|
710
|
+
const groupKey = WIDGET_TYPE_MAP[key as PropertyConfigId];
|
|
711
|
+
if (groupKey === group) {
|
|
712
|
+
return <WidgetSelectViewItem
|
|
713
|
+
key={key}
|
|
714
|
+
initialProperty={initialProperty}
|
|
715
|
+
onClick={() => {
|
|
716
|
+
onValueChange(key);
|
|
717
|
+
onOpenChange(false, true);
|
|
718
|
+
}}
|
|
719
|
+
propertyConfig={propertyConfig}
|
|
720
|
+
existing={existing}/>;
|
|
721
|
+
}
|
|
722
|
+
return null;
|
|
723
|
+
})}
|
|
724
|
+
</div>
|
|
725
|
+
</div>;
|
|
726
|
+
})}
|
|
727
|
+
{/*{displayedWidgets.map(([key, propertyConfig]) => {*/}
|
|
728
|
+
{/* return <WidgetSelectViewItem*/}
|
|
729
|
+
{/* key={key}*/}
|
|
730
|
+
{/* initialProperty={initialProperty}*/}
|
|
731
|
+
{/* onClick={() => {*/}
|
|
732
|
+
{/* onValueChange(key);*/}
|
|
733
|
+
{/* onOpenChange(false);*/}
|
|
734
|
+
{/* }}*/}
|
|
735
|
+
{/* propertyConfig={propertyConfig}*/}
|
|
736
|
+
{/* existing={existing}/>;*/}
|
|
737
|
+
{/*})}*/}
|
|
738
|
+
</div>
|
|
739
|
+
</DialogContent>
|
|
740
|
+
</Dialog>
|
|
741
|
+
</>;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
export interface PropertySelectItemProps {
|
|
745
|
+
onClick?: () => void;
|
|
746
|
+
initialProperty?: PropertyWithId;
|
|
747
|
+
propertyConfig: PropertyConfig;
|
|
748
|
+
existing: boolean;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
export function WidgetSelectViewItem({
|
|
752
|
+
onClick,
|
|
753
|
+
initialProperty,
|
|
754
|
+
// optionDisabled,
|
|
755
|
+
propertyConfig,
|
|
756
|
+
existing
|
|
757
|
+
}: PropertySelectItemProps) {
|
|
758
|
+
const baseProperty = propertyConfig.property;
|
|
759
|
+
const shouldWarnChangingDataType = existing && !isPropertyBuilder(baseProperty) && baseProperty.dataType !== initialProperty?.dataType;
|
|
760
|
+
|
|
761
|
+
return <Card
|
|
762
|
+
onClick={onClick}
|
|
763
|
+
className={"flex flex-row items-center px-4 py-2"}>
|
|
764
|
+
<div
|
|
765
|
+
className={cls(
|
|
766
|
+
"flex flex-row items-center text-base min-h-[48px]",
|
|
767
|
+
)}>
|
|
768
|
+
<div className={"mr-8"}>
|
|
769
|
+
<PropertyConfigBadge propertyConfig={propertyConfig} disabled={shouldWarnChangingDataType}/>
|
|
770
|
+
</div>
|
|
771
|
+
<div>
|
|
772
|
+
<div className={"flex flex-row gap-2 items-center"}>
|
|
773
|
+
{shouldWarnChangingDataType && <Tooltip
|
|
774
|
+
title={"This widget uses a different data type than the initially selected widget. This can cause errors with existing data."}>
|
|
775
|
+
<WarningOffIcon size="smallest" className={"w-4"}/>
|
|
776
|
+
</Tooltip>}
|
|
777
|
+
<Typography
|
|
778
|
+
color={shouldWarnChangingDataType ? "secondary" : undefined}>{propertyConfig.name}</Typography>
|
|
779
|
+
</div>
|
|
780
|
+
|
|
781
|
+
<Typography variant={"caption"}
|
|
782
|
+
color={"secondary"}
|
|
783
|
+
className={"max-w-sm"}>
|
|
784
|
+
{propertyConfig.description}
|
|
785
|
+
</Typography>
|
|
786
|
+
|
|
787
|
+
</div>
|
|
788
|
+
</div>
|
|
789
|
+
</Card>
|
|
790
|
+
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
cardClickableMixin,
|
|
12
12
|
cardMixin,
|
|
13
13
|
cardSelectedMixin,
|
|
14
|
-
|
|
14
|
+
cls,
|
|
15
15
|
FunctionsIcon,
|
|
16
16
|
Paper,
|
|
17
17
|
RemoveCircleIcon,
|
|
@@ -45,9 +45,6 @@ export function PropertyFieldPreview({
|
|
|
45
45
|
? "border-red-500 dark:border-red-500 border-opacity-100 dark:border-opacity-100 ring-0 dark:ring-0"
|
|
46
46
|
: (selected ? "border-primary" : "border-transparent");
|
|
47
47
|
|
|
48
|
-
if(hasError)
|
|
49
|
-
console.log("PropertyFieldPreview", property)
|
|
50
|
-
|
|
51
48
|
return <ErrorBoundary>
|
|
52
49
|
<div
|
|
53
50
|
onClick={onClick}
|
|
@@ -56,7 +53,7 @@ export function PropertyFieldPreview({
|
|
|
56
53
|
<PropertyConfigBadge propertyConfig={propertyConfig}/>
|
|
57
54
|
</div>
|
|
58
55
|
<Paper
|
|
59
|
-
className={
|
|
56
|
+
className={cls(
|
|
60
57
|
"border",
|
|
61
58
|
"pl-2 w-full flex flex-row gap-4 items-center",
|
|
62
59
|
cardMixin,
|
|
@@ -133,13 +130,13 @@ export function NonEditablePropertyPreview({
|
|
|
133
130
|
<div className={"relative m-4"}>
|
|
134
131
|
{propertyConfig && <PropertyConfigBadge propertyConfig={propertyConfig}/>}
|
|
135
132
|
{!propertyConfig && <div
|
|
136
|
-
className={"h-8 w-8 p-1 rounded-full shadow text-white bg-
|
|
133
|
+
className={"h-8 w-8 p-1 rounded-full shadow text-white bg-surface-500"}>
|
|
137
134
|
<FunctionsIcon color={"inherit"} size={"medium"}/>
|
|
138
135
|
</div>}
|
|
139
136
|
<RemoveCircleIcon color={"disabled"} size={"small"} className={"absolute -right-2 -top-2"}/>
|
|
140
137
|
</div>
|
|
141
138
|
<Paper
|
|
142
|
-
className={
|
|
139
|
+
className={cls(
|
|
143
140
|
"pl-2 w-full flex flex-row gap-4 items-center",
|
|
144
141
|
cardMixin,
|
|
145
142
|
onClick ? cardClickableMixin : "",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import equal from "react-fast-compare"
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -48,7 +48,7 @@ export const PropertyTree = React.memo(
|
|
|
48
48
|
|
|
49
49
|
const propertiesOrder = propertiesOrderProp ?? Object.keys(properties);
|
|
50
50
|
|
|
51
|
-
const onDragEnd =
|
|
51
|
+
const onDragEnd = (result: any) => {
|
|
52
52
|
// dropped outside the list
|
|
53
53
|
if (!result.destination) {
|
|
54
54
|
return;
|
|
@@ -61,7 +61,7 @@ export const PropertyTree = React.memo(
|
|
|
61
61
|
newPropertiesOrder.splice(endIndex, 0, removed);
|
|
62
62
|
if (onPropertyMove)
|
|
63
63
|
onPropertyMove(newPropertiesOrder, namespace);
|
|
64
|
-
}
|
|
64
|
+
}
|
|
65
65
|
|
|
66
66
|
return (
|
|
67
67
|
<>
|
|
@@ -227,7 +227,8 @@ export function PropertyTreeEntry({
|
|
|
227
227
|
<AutoAwesomeIcon size="small" className={"p-2"}/>
|
|
228
228
|
</Tooltip>}
|
|
229
229
|
|
|
230
|
-
{onPropertyRemove && <Tooltip title={"Remove"}
|
|
230
|
+
{onPropertyRemove && <Tooltip title={"Remove"}
|
|
231
|
+
asChild={true}>
|
|
231
232
|
<IconButton size="small"
|
|
232
233
|
color="inherit"
|
|
233
234
|
onClick={() => onPropertyRemove(propertyKey, namespace)}>
|
|
@@ -235,7 +236,8 @@ export function PropertyTreeEntry({
|
|
|
235
236
|
</IconButton>
|
|
236
237
|
</Tooltip>}
|
|
237
238
|
|
|
238
|
-
{onPropertyMove && <Tooltip title={"Move"}
|
|
239
|
+
{onPropertyMove && <Tooltip title={"Move"}
|
|
240
|
+
asChild={true}>
|
|
239
241
|
<IconButton
|
|
240
242
|
component={"span"}
|
|
241
243
|
size="small"
|