@firecms/collection_editor 3.0.0-beta.2-pre.2 → 3.0.0-beta.2-pre.4
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/index.es.js +2532 -2386
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collection_editor_controller.d.ts +3 -2
- package/dist/types/config_controller.d.ts +3 -3
- package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +3 -5
- package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +2 -2
- package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -2
- package/dist/ui/collection_editor/EnumForm.d.ts +1 -2
- package/dist/ui/collection_editor/PropertyEditView.d.ts +5 -5
- package/dist/ui/collection_editor/PropertyTree.d.ts +14 -13
- package/dist/ui/collection_editor/SwitchControl.d.ts +8 -0
- package/dist/ui/collection_editor/properties/CommonPropertyFields.d.ts +0 -1
- package/dist/ui/collection_editor/util.d.ts +1 -0
- package/package.json +6 -5
- package/src/ConfigControllerProvider.tsx +24 -22
- package/src/types/collection_editor_controller.tsx +4 -3
- package/src/types/config_controller.tsx +3 -3
- package/src/ui/CollectionViewHeaderAction.tsx +1 -1
- package/src/ui/EditorCollectionAction.tsx +3 -3
- package/src/ui/HomePageEditorCollectionAction.tsx +2 -2
- package/src/ui/MissingReferenceWidget.tsx +2 -1
- package/src/ui/NewCollectionButton.tsx +3 -3
- package/src/ui/NewCollectionCard.tsx +2 -1
- package/src/ui/PropertyAddColumnComponent.tsx +1 -1
- package/src/ui/RootCollectionSuggestions.tsx +3 -2
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +2 -2
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +420 -374
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +19 -12
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +26 -18
- package/src/ui/collection_editor/EnumForm.tsx +118 -114
- package/src/ui/collection_editor/GetCodeDialog.tsx +1 -1
- package/src/ui/collection_editor/PropertyEditView.tsx +199 -142
- package/src/ui/collection_editor/PropertyFieldPreview.tsx +5 -1
- package/src/ui/collection_editor/PropertyTree.tsx +132 -113
- package/src/ui/collection_editor/SubcollectionsEditTab.tsx +18 -11
- package/src/ui/collection_editor/SwitchControl.tsx +39 -0
- package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +10 -2
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +2 -2
- package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +13 -9
- package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +11 -37
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +2 -2
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +3 -6
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +2 -2
- package/src/ui/collection_editor/properties/NumberPropertyField.tsx +2 -2
- package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +11 -14
- package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +10 -9
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +15 -9
- package/src/ui/collection_editor/properties/StringPropertyField.tsx +2 -2
- package/src/ui/collection_editor/properties/UrlPropertyField.tsx +2 -2
- package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +27 -18
- package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +2 -2
- package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +27 -16
- package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +33 -18
- package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +99 -80
- package/src/ui/collection_editor/util.ts +7 -0
- package/src/ui/collection_editor/utils/strings.ts +2 -1
- package/src/useCollectionEditorPlugin.tsx +1 -16
|
@@ -1,124 +1,143 @@
|
|
|
1
|
+
import React, { useCallback } from "react";
|
|
2
|
+
import equal from "react-fast-compare"
|
|
3
|
+
|
|
1
4
|
import {
|
|
2
5
|
AdditionalFieldDelegate,
|
|
3
6
|
CMSType,
|
|
4
7
|
ErrorBoundary,
|
|
5
8
|
isPropertyBuilder,
|
|
6
9
|
PropertiesOrBuilders,
|
|
7
|
-
PropertyOrBuilder
|
|
10
|
+
PropertyOrBuilder
|
|
8
11
|
} from "@firecms/core";
|
|
9
12
|
import { AutoAwesomeIcon, defaultBorderMixin, DragHandleIcon, IconButton, RemoveIcon, Tooltip } from "@firecms/ui";
|
|
10
13
|
import { NonEditablePropertyPreview, PropertyFieldPreview } from "./PropertyFieldPreview";
|
|
11
14
|
import { DragDropContext, Draggable, DraggableProvided, Droppable } from "@hello-pangea/dnd";
|
|
12
|
-
import { getFullId,
|
|
13
|
-
import { getIn } from "formik";
|
|
15
|
+
import { getFullId, getFullIdPath } from "./util";
|
|
14
16
|
import { editableProperty } from "../../utils/entities";
|
|
15
|
-
import { useCallback } from "react";
|
|
16
|
-
|
|
17
|
-
export function PropertyTree<M extends {
|
|
18
|
-
[Key: string]: CMSType
|
|
19
|
-
}>({
|
|
20
|
-
namespace,
|
|
21
|
-
selectedPropertyKey,
|
|
22
|
-
onPropertyClick,
|
|
23
|
-
properties,
|
|
24
|
-
propertiesOrder: propertiesOrderProp,
|
|
25
|
-
additionalFields,
|
|
26
|
-
errors,
|
|
27
|
-
onPropertyMove,
|
|
28
|
-
onPropertyRemove,
|
|
29
|
-
className,
|
|
30
|
-
inferredPropertyKeys,
|
|
31
|
-
collectionEditable,
|
|
32
|
-
}: {
|
|
33
|
-
namespace?: string;
|
|
34
|
-
selectedPropertyKey?: string;
|
|
35
|
-
onPropertyClick?: (propertyKey: string, namespace?: string) => void;
|
|
36
|
-
properties: PropertiesOrBuilders<M>;
|
|
37
|
-
propertiesOrder?: string[];
|
|
38
|
-
additionalFields?: AdditionalFieldDelegate<M>[];
|
|
39
|
-
errors: Record<string, any>;
|
|
40
|
-
onPropertyMove?: (propertiesOrder: string[], namespace?: string) => void;
|
|
41
|
-
onPropertyRemove?: (propertyKey: string, namespace?: string) => void;
|
|
42
|
-
className?: string;
|
|
43
|
-
inferredPropertyKeys?: string[];
|
|
44
|
-
collectionEditable: boolean;
|
|
45
|
-
}) {
|
|
46
17
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
18
|
+
export const PropertyTree = React.memo(
|
|
19
|
+
function PropertyTree<M extends {
|
|
20
|
+
[Key: string]: CMSType
|
|
21
|
+
}>({
|
|
22
|
+
namespace,
|
|
23
|
+
selectedPropertyKey,
|
|
24
|
+
onPropertyClick,
|
|
25
|
+
properties,
|
|
26
|
+
propertiesOrder: propertiesOrderProp,
|
|
27
|
+
additionalFields,
|
|
28
|
+
errors,
|
|
29
|
+
onPropertyMove,
|
|
30
|
+
onPropertyRemove,
|
|
31
|
+
className,
|
|
32
|
+
inferredPropertyKeys,
|
|
33
|
+
collectionEditable
|
|
34
|
+
}: {
|
|
35
|
+
namespace?: string;
|
|
36
|
+
selectedPropertyKey?: string;
|
|
37
|
+
onPropertyClick?: (propertyKey: string, namespace?: string) => void;
|
|
38
|
+
properties: PropertiesOrBuilders<M>;
|
|
39
|
+
propertiesOrder?: string[];
|
|
40
|
+
additionalFields?: AdditionalFieldDelegate<M>[];
|
|
41
|
+
errors: Record<string, any>;
|
|
42
|
+
onPropertyMove?: (propertiesOrder: string[], namespace?: string) => void;
|
|
43
|
+
onPropertyRemove?: (propertyKey: string, namespace?: string) => void;
|
|
44
|
+
className?: string;
|
|
45
|
+
inferredPropertyKeys?: string[];
|
|
46
|
+
collectionEditable: boolean;
|
|
47
|
+
}) {
|
|
48
|
+
|
|
49
|
+
const propertiesOrder = propertiesOrderProp ?? Object.keys(properties);
|
|
50
|
+
|
|
51
|
+
const onDragEnd = useCallback((result: any) => {
|
|
52
|
+
// dropped outside the list
|
|
53
|
+
if (!result.destination) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const startIndex = result.source.index;
|
|
57
|
+
const endIndex = result.destination.index;
|
|
58
|
+
|
|
59
|
+
const newPropertiesOrder = Array.from(propertiesOrder);
|
|
60
|
+
const [removed] = newPropertiesOrder.splice(startIndex, 1);
|
|
61
|
+
newPropertiesOrder.splice(endIndex, 0, removed);
|
|
62
|
+
if (onPropertyMove)
|
|
63
|
+
onPropertyMove(newPropertiesOrder, namespace);
|
|
64
|
+
}, [namespace, onPropertyMove, propertiesOrder])
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<>
|
|
68
|
+
|
|
69
|
+
<DragDropContext onDragEnd={onDragEnd}>
|
|
70
|
+
<Droppable droppableId={`droppable_${namespace}`}>
|
|
71
|
+
{(droppableProvided, droppableSnapshot) => (
|
|
72
|
+
<div
|
|
73
|
+
{...droppableProvided.droppableProps}
|
|
74
|
+
ref={droppableProvided.innerRef}
|
|
75
|
+
className={className}>
|
|
76
|
+
{propertiesOrder && propertiesOrder
|
|
77
|
+
.map((propertyKey: string, index: number) => {
|
|
78
|
+
const property = properties[propertyKey] as PropertyOrBuilder;
|
|
79
|
+
const additionalField = additionalFields?.find(field => field.key === propertyKey);
|
|
80
|
+
|
|
81
|
+
if (!property && !additionalField) {
|
|
82
|
+
console.warn(`Property ${propertyKey} not found in properties or additionalFields`);
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return (
|
|
86
|
+
<Draggable
|
|
87
|
+
key={`array_field_${namespace}_${propertyKey}}`}
|
|
88
|
+
draggableId={`array_field_${namespace}_${propertyKey}}`}
|
|
89
|
+
index={index}>
|
|
90
|
+
{(provided, snapshot) => {
|
|
91
|
+
return (
|
|
92
|
+
<ErrorBoundary>
|
|
93
|
+
<PropertyTreeEntry
|
|
94
|
+
propertyKey={propertyKey as string}
|
|
95
|
+
propertyOrBuilder={property}
|
|
96
|
+
additionalField={additionalField}
|
|
97
|
+
provided={provided}
|
|
98
|
+
errors={errors}
|
|
99
|
+
namespace={namespace}
|
|
100
|
+
inferredPropertyKeys={inferredPropertyKeys}
|
|
101
|
+
onPropertyMove={onPropertyMove}
|
|
102
|
+
onPropertyRemove={onPropertyRemove}
|
|
103
|
+
onPropertyClick={snapshot.isDragging ? undefined : onPropertyClick}
|
|
104
|
+
selectedPropertyKey={selectedPropertyKey}
|
|
105
|
+
collectionEditable={collectionEditable}
|
|
106
|
+
/>
|
|
107
|
+
</ErrorBoundary>
|
|
108
|
+
);
|
|
109
|
+
}}
|
|
110
|
+
</Draggable>);
|
|
111
|
+
}).filter(Boolean)}
|
|
112
|
+
|
|
113
|
+
{droppableProvided.placeholder}
|
|
114
|
+
|
|
115
|
+
</div>
|
|
116
|
+
)}
|
|
117
|
+
</Droppable>
|
|
118
|
+
</DragDropContext>
|
|
119
|
+
|
|
120
|
+
</>
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
(prevProps, nextProps) => {
|
|
124
|
+
|
|
125
|
+
const isSelected = nextProps.selectedPropertyKey?.startsWith(nextProps.namespace ?? "");
|
|
126
|
+
const wasSelected = prevProps.selectedPropertyKey?.startsWith(prevProps.namespace ?? "");
|
|
127
|
+
if (isSelected || wasSelected)
|
|
128
|
+
return false;
|
|
129
|
+
|
|
130
|
+
return equal(prevProps.properties, nextProps.properties) &&
|
|
131
|
+
prevProps.propertiesOrder === nextProps.propertiesOrder &&
|
|
132
|
+
equal(prevProps.additionalFields, nextProps.additionalFields) &&
|
|
133
|
+
equal(prevProps.errors, nextProps.errors) &&
|
|
134
|
+
equal(prevProps.onPropertyClick, nextProps.onPropertyClick) &&
|
|
135
|
+
// equal(prevProps.onPropertyMove, nextProps.onPropertyMove) &&
|
|
136
|
+
// equal(prevProps.onPropertyRemove, nextProps.onPropertyRemove) &&
|
|
137
|
+
prevProps.namespace === nextProps.namespace &&
|
|
138
|
+
prevProps.collectionEditable === nextProps.collectionEditable;
|
|
139
|
+
}
|
|
140
|
+
);
|
|
122
141
|
|
|
123
142
|
export function PropertyTreeEntry({
|
|
124
143
|
propertyKey,
|
|
@@ -132,7 +151,7 @@ export function PropertyTreeEntry({
|
|
|
132
151
|
onPropertyMove,
|
|
133
152
|
onPropertyRemove,
|
|
134
153
|
inferredPropertyKeys,
|
|
135
|
-
collectionEditable
|
|
154
|
+
collectionEditable
|
|
136
155
|
}: {
|
|
137
156
|
propertyKey: string;
|
|
138
157
|
namespace?: string;
|
|
@@ -149,8 +168,9 @@ export function PropertyTreeEntry({
|
|
|
149
168
|
}) {
|
|
150
169
|
|
|
151
170
|
const isPropertyInferred = inferredPropertyKeys?.includes(namespace ? `${namespace}.${propertyKey}` : propertyKey);
|
|
152
|
-
|
|
153
171
|
const fullId = getFullId(propertyKey, namespace);
|
|
172
|
+
const fullIdPath = getFullIdPath(propertyKey, namespace);
|
|
173
|
+
const hasError = fullIdPath in errors;
|
|
154
174
|
|
|
155
175
|
let subtree;
|
|
156
176
|
if (typeof propertyOrBuilder === "object") {
|
|
@@ -170,7 +190,7 @@ export function PropertyTreeEntry({
|
|
|
170
190
|
}
|
|
171
191
|
}
|
|
172
192
|
|
|
173
|
-
const hasError = fullId ? getIn(errors, idToPropertiesPath(fullId)) : false;
|
|
193
|
+
// const hasError = fullId ? getIn(errors, idToPropertiesPath(fullId)) : false;
|
|
174
194
|
const selected = selectedPropertyKey === fullId;
|
|
175
195
|
const editable = propertyOrBuilder && ((collectionEditable && !isPropertyBuilder(propertyOrBuilder)) || editableProperty(propertyOrBuilder));
|
|
176
196
|
|
|
@@ -225,7 +245,6 @@ export function PropertyTreeEntry({
|
|
|
225
245
|
</Tooltip>}
|
|
226
246
|
</div>
|
|
227
247
|
|
|
228
|
-
|
|
229
248
|
{subtree && <div className={"ml-16"}>{subtree}</div>}
|
|
230
249
|
</div>
|
|
231
250
|
);
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
} from "@firecms/core";
|
|
10
10
|
import {
|
|
11
11
|
AddIcon,
|
|
12
|
+
Alert,
|
|
12
13
|
Button,
|
|
13
14
|
Container,
|
|
14
15
|
DeleteIcon,
|
|
15
16
|
IconButton,
|
|
16
|
-
InfoLabel,
|
|
17
17
|
Paper,
|
|
18
18
|
Table,
|
|
19
19
|
TableBody,
|
|
@@ -22,12 +22,12 @@ import {
|
|
|
22
22
|
Tooltip,
|
|
23
23
|
Typography,
|
|
24
24
|
} from "@firecms/ui";
|
|
25
|
-
import { useFormikContext } from "formik";
|
|
26
25
|
import { CollectionEditorDialog } from "./CollectionEditorDialog";
|
|
27
26
|
import { CollectionsConfigController } from "../../types/config_controller";
|
|
28
27
|
import { PersistedCollection } from "../../types/persisted_collection";
|
|
29
28
|
import { CollectionInference } from "../../types/collection_inference";
|
|
30
29
|
import { EntityCustomViewsSelectDialog } from "./EntityCustomViewsSelectDialog";
|
|
30
|
+
import { useFormex } from "@firecms/formex";
|
|
31
31
|
|
|
32
32
|
export function SubcollectionsEditTab({
|
|
33
33
|
collection,
|
|
@@ -59,7 +59,7 @@ export function SubcollectionsEditTab({
|
|
|
59
59
|
const {
|
|
60
60
|
values,
|
|
61
61
|
setFieldValue,
|
|
62
|
-
} =
|
|
62
|
+
} = useFormex<EntityCollection>();
|
|
63
63
|
|
|
64
64
|
const subcollections = collection.subcollections ?? [];
|
|
65
65
|
const resolvedEntityViews = values.entityViews?.filter(e => typeof e === "string")
|
|
@@ -101,7 +101,7 @@ export function SubcollectionsEditTab({
|
|
|
101
101
|
onClick={(e) => {
|
|
102
102
|
e.preventDefault();
|
|
103
103
|
e.stopPropagation();
|
|
104
|
-
setSubcollectionToDelete(subcollection.
|
|
104
|
+
setSubcollectionToDelete(subcollection.id);
|
|
105
105
|
}}
|
|
106
106
|
color="inherit">
|
|
107
107
|
<DeleteIcon size={"small"}/>
|
|
@@ -180,9 +180,14 @@ export function SubcollectionsEditTab({
|
|
|
180
180
|
</>}
|
|
181
181
|
|
|
182
182
|
{totalEntityViews === 0 &&
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
<Alert action={<Button variant="text"
|
|
184
|
+
size={"small"}
|
|
185
|
+
href={"https://firecms.co/docs/customization_quickstart"}
|
|
186
|
+
component={"a"}
|
|
187
|
+
rel="noopener noreferrer"
|
|
188
|
+
target="_blank">More info</Button>}>
|
|
189
|
+
Define your own custom views by uploading it with the CLI.
|
|
190
|
+
</Alert>
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
<Button
|
|
@@ -204,10 +209,12 @@ export function SubcollectionsEditTab({
|
|
|
204
209
|
{subcollectionToDelete &&
|
|
205
210
|
<DeleteConfirmationDialog open={Boolean(subcollectionToDelete)}
|
|
206
211
|
onAccept={() => {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
parentCollectionIds: [...(parentCollectionIds ?? []), collection.
|
|
210
|
-
}
|
|
212
|
+
const props = {
|
|
213
|
+
id: subcollectionToDelete,
|
|
214
|
+
parentCollectionIds: [...(parentCollectionIds ?? []), collection.id]
|
|
215
|
+
};
|
|
216
|
+
console.debug("Deleting subcollection", props)
|
|
217
|
+
configController.deleteCollection(props);
|
|
211
218
|
setSubcollectionToDelete(undefined);
|
|
212
219
|
}}
|
|
213
220
|
onCancel={() => setSubcollectionToDelete(undefined)}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { BooleanSwitchWithLabel, Tooltip } from "@firecms/ui";
|
|
4
|
+
import { FormexFieldProps } from "@firecms/formex";
|
|
5
|
+
|
|
6
|
+
export function SwitchControl({
|
|
7
|
+
field,
|
|
8
|
+
form,
|
|
9
|
+
label,
|
|
10
|
+
tooltip,
|
|
11
|
+
disabled,
|
|
12
|
+
size = "small",
|
|
13
|
+
allowIndeterminate
|
|
14
|
+
}: FormexFieldProps & {
|
|
15
|
+
label: string,
|
|
16
|
+
tooltip?: string,
|
|
17
|
+
disabled?: boolean,
|
|
18
|
+
size?: "small" | "medium",
|
|
19
|
+
allowIndeterminate?: boolean
|
|
20
|
+
}) {
|
|
21
|
+
|
|
22
|
+
const formControlLabel = <BooleanSwitchWithLabel
|
|
23
|
+
label={label}
|
|
24
|
+
size={size}
|
|
25
|
+
position={"start"}
|
|
26
|
+
value={field.value}
|
|
27
|
+
disabled={disabled}
|
|
28
|
+
allowIndeterminate={allowIndeterminate}
|
|
29
|
+
onValueChange={(checked:boolean | null) => form.setFieldValue(field.name, checked)}/>;
|
|
30
|
+
|
|
31
|
+
if (tooltip)
|
|
32
|
+
return (
|
|
33
|
+
<Tooltip
|
|
34
|
+
title={tooltip}>
|
|
35
|
+
{formControlLabel}
|
|
36
|
+
</Tooltip>
|
|
37
|
+
);
|
|
38
|
+
return formControlLabel;
|
|
39
|
+
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ImportConfig,
|
|
5
5
|
ImportNewPropertyFieldPreview
|
|
6
6
|
} from "@firecms/data_import_export";
|
|
7
|
-
import { getIn,
|
|
7
|
+
import { getIn, useFormex } from "@firecms/formex";
|
|
8
8
|
|
|
9
9
|
import { PropertyConfigBadge, getFieldConfig, getFieldId, Properties, Property, PropertyConfig, } from "@firecms/core";
|
|
10
10
|
import { Container, Select, Tooltip, Typography } from "@firecms/ui";
|
|
@@ -28,11 +28,19 @@ export function CollectionEditorImportMapping({
|
|
|
28
28
|
collectionEditable: boolean
|
|
29
29
|
}) {
|
|
30
30
|
|
|
31
|
+
// const {
|
|
32
|
+
// values,
|
|
33
|
+
// setFieldValue,
|
|
34
|
+
// setFieldTouched,
|
|
35
|
+
// setValues,
|
|
36
|
+
// submitCount
|
|
37
|
+
// } = useFormex();
|
|
38
|
+
|
|
31
39
|
const {
|
|
32
40
|
setFieldValue,
|
|
33
41
|
setFieldTouched,
|
|
34
42
|
values
|
|
35
|
-
} =
|
|
43
|
+
} = useFormex<PersistedCollection>();
|
|
36
44
|
const [selectedProperty, setSelectedProperty] = useState<PropertyWithId | undefined>(undefined);
|
|
37
45
|
|
|
38
46
|
const currentPropertiesOrderRef = React.useRef<{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useState } from "react";
|
|
2
2
|
import { AddIcon, Button, Paper, Typography } from "@firecms/ui";
|
|
3
|
-
import { getIn,
|
|
3
|
+
import { getIn, useFormex } from "@firecms/formex";
|
|
4
4
|
import { PropertyFormDialog } from "../PropertyEditView";
|
|
5
5
|
import { getFullId, idToPropertiesPath, namespaceToPropertiesOrderPath } from "../util";
|
|
6
6
|
import { PropertyTree } from "../PropertyTree";
|
|
@@ -17,7 +17,7 @@ export function BlockPropertyField({ disabled, getData, allowDataInference, prop
|
|
|
17
17
|
const {
|
|
18
18
|
values,
|
|
19
19
|
setFieldValue
|
|
20
|
-
} =
|
|
20
|
+
} = useFormex<ArrayProperty>();
|
|
21
21
|
|
|
22
22
|
const [propertyDialogOpen, setPropertyDialogOpen] = useState<boolean>(false);
|
|
23
23
|
const [selectedPropertyKey, setSelectedPropertyKey] = useState<string | undefined>();
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { Field, FormexFieldProps, getIn, useFormex } from "@firecms/formex";
|
|
3
3
|
|
|
4
4
|
import { GeneralPropertyValidation } from "./validation/GeneralPropertyValidation";
|
|
5
5
|
import { ValidationPanel } from "./validation/ValidationPanel";
|
|
6
|
-
import { SwitchControl } from "
|
|
6
|
+
import { SwitchControl } from "../SwitchControl";
|
|
7
7
|
|
|
8
8
|
export function BooleanPropertyField({ disabled }: {
|
|
9
9
|
disabled: boolean;
|
|
10
10
|
}) {
|
|
11
|
-
const { values } =
|
|
11
|
+
const { values } = useFormex();
|
|
12
12
|
const defaultValue = getIn(values, "defaultValue");
|
|
13
13
|
|
|
14
14
|
return (
|
|
@@ -23,12 +23,16 @@ export function BooleanPropertyField({ disabled }: {
|
|
|
23
23
|
|
|
24
24
|
<div className={"col-span-12"}>
|
|
25
25
|
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
<Field
|
|
27
|
+
name={"defaultValue"}>
|
|
28
|
+
{({ field, form }: FormexFieldProps) => {
|
|
29
|
+
return <SwitchControl
|
|
30
|
+
label={defaultValue === null || defaultValue === undefined ? "Default value not set" : ("Default value is " + defaultValue.toString())}
|
|
31
|
+
disabled={disabled}
|
|
32
|
+
allowIndeterminate={true} field={field}
|
|
33
|
+
form={form}/>
|
|
34
|
+
}}
|
|
35
|
+
</Field>
|
|
32
36
|
|
|
33
37
|
</div>
|
|
34
38
|
</>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Field, getIn,
|
|
1
|
+
import { Field, getIn, useFormex } from "@firecms/formex";
|
|
2
2
|
import { DebouncedTextField } from "@firecms/ui";
|
|
3
3
|
import { PropertyWithId } from "../PropertyEditView";
|
|
4
4
|
import React from "react";
|
|
@@ -8,7 +8,6 @@ import { toSnakeCase, unslugify } from "@firecms/core";
|
|
|
8
8
|
type CommonPropertyFieldsProps = {
|
|
9
9
|
showErrors: boolean,
|
|
10
10
|
disabledId: boolean,
|
|
11
|
-
existingPropertyKeys?: string[];
|
|
12
11
|
disabled: boolean;
|
|
13
12
|
isNewProperty: boolean;
|
|
14
13
|
autoUpdateId: boolean;
|
|
@@ -18,7 +17,6 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
|
|
|
18
17
|
function CommonPropertyFields({
|
|
19
18
|
showErrors,
|
|
20
19
|
disabledId,
|
|
21
|
-
existingPropertyKeys,
|
|
22
20
|
disabled,
|
|
23
21
|
autoUpdateId,
|
|
24
22
|
isNewProperty
|
|
@@ -29,8 +27,9 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
|
|
|
29
27
|
values,
|
|
30
28
|
setFieldValue,
|
|
31
29
|
setFieldTouched,
|
|
32
|
-
touched
|
|
33
|
-
|
|
30
|
+
touched,
|
|
31
|
+
validate
|
|
32
|
+
} = useFormex<PropertyWithId>();
|
|
34
33
|
|
|
35
34
|
const name = "name";
|
|
36
35
|
const nameError = showErrors && getIn(errors, name);
|
|
@@ -46,20 +45,20 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
|
|
|
46
45
|
|
|
47
46
|
<div>
|
|
48
47
|
<Field
|
|
48
|
+
name={name}
|
|
49
49
|
inputRef={ref}
|
|
50
50
|
as={DebouncedTextField}
|
|
51
51
|
value={values[name]}
|
|
52
52
|
onChange={(e: any) => {
|
|
53
53
|
const newNameValue = e.target.value;
|
|
54
|
-
setFieldValue(name, newNameValue);
|
|
55
|
-
setFieldTouched(name, true, true);
|
|
56
54
|
const idTouched = getIn(touched, id);
|
|
57
55
|
if (!idTouched && autoUpdateId) {
|
|
58
|
-
setFieldValue(id, newNameValue ? toSnakeCase(newNameValue) : "")
|
|
56
|
+
setFieldValue(id, newNameValue ? toSnakeCase(newNameValue) : "", false)
|
|
59
57
|
}
|
|
58
|
+
setFieldValue(name, newNameValue, true);
|
|
59
|
+
setFieldTouched(name, true);
|
|
60
60
|
}}
|
|
61
61
|
style={{ fontSize: 20 }}
|
|
62
|
-
validate={validateName}
|
|
63
62
|
placeholder={"Field name"}
|
|
64
63
|
required
|
|
65
64
|
disabled={disabled}
|
|
@@ -72,19 +71,19 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
|
|
|
72
71
|
|
|
73
72
|
<div>
|
|
74
73
|
<Field
|
|
74
|
+
name={id}
|
|
75
75
|
as={DebouncedTextField}
|
|
76
76
|
label={"ID"}
|
|
77
77
|
value={values[id]}
|
|
78
78
|
onChange={(e: any) => {
|
|
79
79
|
const newIdValue = e.target.value;
|
|
80
|
-
setFieldValue(id, newIdValue);
|
|
81
|
-
setFieldTouched(id, true, true);
|
|
82
80
|
const nameTouched = getIn(touched, name);
|
|
83
81
|
if (!nameTouched && autoUpdateId) {
|
|
84
82
|
setFieldValue(name, newIdValue ? unslugify(newIdValue) : "")
|
|
85
83
|
}
|
|
84
|
+
setFieldValue(id, newIdValue, true);
|
|
85
|
+
setFieldTouched(id, true);
|
|
86
86
|
}}
|
|
87
|
-
validate={() => validateId(values[id], existingPropertyKeys)}
|
|
88
87
|
disabled={disabledId || disabled}
|
|
89
88
|
required
|
|
90
89
|
size="small"
|
|
@@ -110,28 +109,3 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
|
|
|
110
109
|
|
|
111
110
|
}
|
|
112
111
|
);
|
|
113
|
-
|
|
114
|
-
const idRegEx = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
115
|
-
|
|
116
|
-
function validateId(value?: string, existingPropertyKeys?: string[]) {
|
|
117
|
-
|
|
118
|
-
let error;
|
|
119
|
-
if (!value) {
|
|
120
|
-
error = "You must specify an id for the field";
|
|
121
|
-
}
|
|
122
|
-
if (value && !value.match(idRegEx)) {
|
|
123
|
-
error = "The id can only contain letters, numbers and underscores (_), and not start with a number";
|
|
124
|
-
}
|
|
125
|
-
if (value && existingPropertyKeys && existingPropertyKeys.includes(value)) {
|
|
126
|
-
error = "There is another field with this ID already";
|
|
127
|
-
}
|
|
128
|
-
return error;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function validateName(value: string) {
|
|
132
|
-
let error;
|
|
133
|
-
if (!value) {
|
|
134
|
-
error = "You must specify a title for the field";
|
|
135
|
-
}
|
|
136
|
-
return error;
|
|
137
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { getIn,
|
|
2
|
+
import { getIn, useFormex } from "@firecms/formex";
|
|
3
3
|
import { NumberProperty, StringProperty } from "@firecms/core";
|
|
4
4
|
import { Select, SelectItem } from "@firecms/ui";
|
|
5
5
|
import { GeneralPropertyValidation } from "./validation/GeneralPropertyValidation";
|
|
@@ -15,7 +15,7 @@ export function DateTimePropertyField({ disabled }: {
|
|
|
15
15
|
errors,
|
|
16
16
|
touched,
|
|
17
17
|
setFieldValue
|
|
18
|
-
} =
|
|
18
|
+
} = useFormex<StringProperty | NumberProperty>();
|
|
19
19
|
|
|
20
20
|
const modePath = "mode";
|
|
21
21
|
const modeValue: string | undefined = getIn(values, modePath);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
|
-
import { getIn,
|
|
2
|
+
import { getIn, useFormex } from "@firecms/formex";
|
|
3
3
|
import { EnumValueConfig, resolveEnumValues, useSnackbarController } from "@firecms/core";
|
|
4
4
|
import { Select, SelectItem } from "@firecms/ui";
|
|
5
5
|
import { EnumForm } from "../EnumForm";
|
|
@@ -26,12 +26,9 @@ export function EnumPropertyField({
|
|
|
26
26
|
|
|
27
27
|
const {
|
|
28
28
|
values,
|
|
29
|
-
handleChange,
|
|
30
|
-
errors,
|
|
31
|
-
touched,
|
|
32
29
|
setFieldError,
|
|
33
30
|
setFieldValue
|
|
34
|
-
} =
|
|
31
|
+
} = useFormex<PropertyWithId>();
|
|
35
32
|
|
|
36
33
|
const snackbarContext = useSnackbarController();
|
|
37
34
|
|
|
@@ -70,7 +67,7 @@ export function EnumPropertyField({
|
|
|
70
67
|
disabled={disabled}
|
|
71
68
|
allowDataInference={allowDataInference}
|
|
72
69
|
onError={(hasError) => {
|
|
73
|
-
setFieldError(enumValuesPath, hasError ? "" : undefined);
|
|
70
|
+
setFieldError(enumValuesPath, hasError ? "This enum property is missing some values" : undefined);
|
|
74
71
|
}}
|
|
75
72
|
getData={getData
|
|
76
73
|
? () => getData()
|