@firecms/core 3.0.0-canary.66 → 3.0.0-canary.68
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/core/EntityEditView.d.ts +17 -3
- package/dist/form/PropertiesForm.d.ts +8 -0
- package/dist/form/components/FieldHelperText.d.ts +3 -3
- package/dist/form/components/StorageItemPreview.d.ts +2 -4
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +2 -4
- package/dist/form/index.d.ts +0 -2
- package/dist/index.es.js +4271 -4322
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collections.d.ts +14 -0
- package/dist/types/fields.d.ts +31 -30
- package/dist/types/plugins.d.ts +2 -2
- package/dist/types/properties.d.ts +1 -1
- package/dist/util/storage.d.ts +23 -2
- package/dist/util/useStorageUploadController.d.ts +1 -1
- package/package.json +4 -4
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -1
- package/src/core/EntityEditView.tsx +662 -120
- package/src/core/EntitySidePanel.tsx +0 -1
- package/src/form/PropertiesForm.tsx +81 -0
- package/src/form/PropertyFieldBinding.tsx +28 -5
- package/src/form/components/FieldHelperText.tsx +3 -3
- package/src/form/components/StorageItemPreview.tsx +0 -4
- package/src/form/field_bindings/MapFieldBinding.tsx +10 -3
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -7
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +3 -26
- package/src/form/index.tsx +4 -4
- package/src/form/validation.ts +1 -17
- package/src/types/collections.ts +14 -0
- package/src/types/customization_controller.tsx +0 -1
- package/src/types/fields.tsx +33 -33
- package/src/types/plugins.tsx +2 -2
- package/src/types/properties.ts +1 -1
- package/src/util/entities.ts +1 -0
- package/src/util/permissions.ts +1 -0
- package/src/util/storage.ts +75 -21
- package/src/util/useStorageUploadController.tsx +21 -3
- package/dist/form/EntityForm.d.ts +0 -77
- package/src/form/EntityForm.tsx +0 -735
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { FormContext, PropertiesOrBuilders, PropertyFieldBindingProps } from "../types";
|
|
2
|
+
import { Tooltip } from "@firecms/ui";
|
|
3
|
+
import { PropertyIdCopyTooltipContent } from "../components/PropertyIdCopyTooltipContent";
|
|
4
|
+
import { PropertyFieldBinding } from "./PropertyFieldBinding";
|
|
5
|
+
import { ErrorBoundary } from "../components";
|
|
6
|
+
import { isHidden, isReadOnly, resolveProperties } from "../util";
|
|
7
|
+
import { FormexController } from "@firecms/formex";
|
|
8
|
+
|
|
9
|
+
export type PropertiesFormProps<M extends Record<string, any> = Record<string, any>> = {
|
|
10
|
+
properties: PropertiesOrBuilders<M>;
|
|
11
|
+
propertiesOrder?: string[];
|
|
12
|
+
formex: FormexController<M>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function PropertiesForm<M extends Record<string, any> = Record<string, any>>({
|
|
16
|
+
properties,
|
|
17
|
+
propertiesOrder,
|
|
18
|
+
formex
|
|
19
|
+
}: PropertiesFormProps<M>) {
|
|
20
|
+
|
|
21
|
+
const resolvedProperties = resolveProperties({ properties });
|
|
22
|
+
|
|
23
|
+
const formContext: FormContext<M> = {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
setFieldValue: useCallback(formex.setFieldValue, []),
|
|
26
|
+
values: formex.values ?? {},
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
save: useCallback(() => {
|
|
29
|
+
throw new Error("Not implemented. You currently can't call save from a custom field, within a PropertiesForm (it works in standard Entity forms)");
|
|
30
|
+
}, []),
|
|
31
|
+
formex
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const formFields = (
|
|
35
|
+
<div className={"flex flex-col gap-8"}>
|
|
36
|
+
{(propertiesOrder ?? Object.keys(resolvedProperties))
|
|
37
|
+
.map((key) => {
|
|
38
|
+
|
|
39
|
+
const property = resolvedProperties[key];
|
|
40
|
+
if (!property) {
|
|
41
|
+
console.warn(`Property ${key} not found in collection PropertiesForm`);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const disabled = formex.isSubmitting || isReadOnly(property) || Boolean(property.disabled);
|
|
46
|
+
const hidden = isHidden(property);
|
|
47
|
+
if (hidden) return null;
|
|
48
|
+
const cmsFormFieldProps: PropertyFieldBindingProps<any, M> = {
|
|
49
|
+
propertyKey: key,
|
|
50
|
+
disabled,
|
|
51
|
+
property,
|
|
52
|
+
includeDescription: property.description || property.longDescription,
|
|
53
|
+
context: formContext,
|
|
54
|
+
tableMode: false,
|
|
55
|
+
partOfArray: false,
|
|
56
|
+
partOfBlock: false,
|
|
57
|
+
autoFocus: false
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div id={`form_field_${key}`}
|
|
62
|
+
key={`field_${key}`}>
|
|
63
|
+
<ErrorBoundary>
|
|
64
|
+
<Tooltip title={<PropertyIdCopyTooltipContent propertyId={key}/>}
|
|
65
|
+
delayDuration={800}
|
|
66
|
+
side={"left"}
|
|
67
|
+
align={"start"}
|
|
68
|
+
sideOffset={16}>
|
|
69
|
+
<PropertyFieldBinding {...cmsFormFieldProps}/>
|
|
70
|
+
</Tooltip>
|
|
71
|
+
</ErrorBoundary>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
})
|
|
75
|
+
.filter(Boolean)}
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return <div></div>
|
|
81
|
+
}
|
|
@@ -110,7 +110,12 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
|
|
|
110
110
|
} else {
|
|
111
111
|
const propertyConfig = getFieldConfig(resolvedProperty, customizationController.propertyConfigs);
|
|
112
112
|
if (!propertyConfig) {
|
|
113
|
-
console.log("INTERNAL: Could not find field config for property", {
|
|
113
|
+
console.log("INTERNAL: Could not find field config for property", {
|
|
114
|
+
propertyKey,
|
|
115
|
+
resolvedProperty,
|
|
116
|
+
fields: customizationController.propertyConfigs,
|
|
117
|
+
propertyConfig
|
|
118
|
+
});
|
|
114
119
|
throw new Error(`INTERNAL: Could not find field config for property ${propertyKey}`);
|
|
115
120
|
}
|
|
116
121
|
const configProperty = resolveProperty({
|
|
@@ -194,7 +199,14 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
|
|
|
194
199
|
(fieldProps.form.submitCount > 0 || property.validation?.unique) &&
|
|
195
200
|
(!Array.isArray(error) || !!error.filter((e: any) => !!e).length);
|
|
196
201
|
|
|
197
|
-
const WrappedComponent: ComponentType<FieldProps<T, any, M>> | null = useWrappedComponent(
|
|
202
|
+
const WrappedComponent: ComponentType<FieldProps<T, any, M>> | null = useWrappedComponent({
|
|
203
|
+
path: context.path,
|
|
204
|
+
collection: context.collection,
|
|
205
|
+
propertyKey: propertyKey,
|
|
206
|
+
property: property,
|
|
207
|
+
Component: Component,
|
|
208
|
+
plugins: plugins
|
|
209
|
+
});
|
|
198
210
|
const UsedComponent: ComponentType<FieldProps<T>> = WrappedComponent ?? Component;
|
|
199
211
|
|
|
200
212
|
const isSubmitting = fieldProps.form.isSubmitting;
|
|
@@ -264,13 +276,24 @@ const shouldPropertyReRender = (property: PropertyOrBuilder | ResolvedProperty,
|
|
|
264
276
|
}
|
|
265
277
|
}
|
|
266
278
|
|
|
267
|
-
|
|
268
|
-
path
|
|
269
|
-
collection
|
|
279
|
+
interface UseWrappedComponentParams<T extends CMSType = CMSType, M extends Record<string, any> = any> {
|
|
280
|
+
path?: string,
|
|
281
|
+
collection?: EntityCollection<M>,
|
|
270
282
|
propertyKey: string,
|
|
271
283
|
property: ResolvedProperty<T>,
|
|
272
284
|
Component: ComponentType<FieldProps<T, any, M>>,
|
|
273
285
|
plugins?: FireCMSPlugin[]
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function useWrappedComponent<T extends CMSType = CMSType, M extends Record<string, any> = any>(
|
|
289
|
+
{
|
|
290
|
+
path,
|
|
291
|
+
collection,
|
|
292
|
+
propertyKey,
|
|
293
|
+
property,
|
|
294
|
+
Component,
|
|
295
|
+
plugins
|
|
296
|
+
}: UseWrappedComponentParams<T, M>
|
|
274
297
|
): ComponentType<FieldProps<T, any, M>> | null {
|
|
275
298
|
|
|
276
299
|
const wrapperRef = useRef<ComponentType<FieldProps<T, any, M>> | null>((() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ResolvedProperty } from "../../types";
|
|
1
|
+
import { Property, ResolvedProperty } from "../../types";
|
|
2
2
|
import { IconButton, InfoIcon, Tooltip, Typography } from "@firecms/ui";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -13,8 +13,8 @@ export function FieldHelperText({
|
|
|
13
13
|
disabled
|
|
14
14
|
}: {
|
|
15
15
|
error?: string,
|
|
16
|
-
showError
|
|
17
|
-
property: ResolvedProperty,
|
|
16
|
+
showError?: boolean,
|
|
17
|
+
property: ResolvedProperty | Property,
|
|
18
18
|
includeDescription?: boolean,
|
|
19
19
|
disabled?: boolean,
|
|
20
20
|
}
|
|
@@ -10,22 +10,18 @@ interface StorageItemPreviewProps {
|
|
|
10
10
|
name: string;
|
|
11
11
|
property: ResolvedStringProperty;
|
|
12
12
|
value: string,
|
|
13
|
-
entity: Entity<any>,
|
|
14
13
|
onRemove: (value: string) => void;
|
|
15
14
|
size: PreviewSize;
|
|
16
15
|
disabled: boolean;
|
|
17
|
-
collection: EntityCollection;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
export function StorageItemPreview({
|
|
21
19
|
name,
|
|
22
20
|
property,
|
|
23
21
|
value,
|
|
24
|
-
entity,
|
|
25
22
|
onRemove,
|
|
26
23
|
disabled,
|
|
27
24
|
size,
|
|
28
|
-
collection
|
|
29
25
|
}: StorageItemPreviewProps) {
|
|
30
26
|
|
|
31
27
|
return (
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
CMSType,
|
|
4
|
+
FieldProps,
|
|
5
|
+
FormContext,
|
|
6
|
+
MapProperty,
|
|
7
|
+
Properties,
|
|
8
|
+
ResolvedProperties,
|
|
9
|
+
ResolvedProperty
|
|
10
|
+
} from "../../types";
|
|
3
11
|
|
|
4
12
|
import { ErrorBoundary } from "../../components";
|
|
5
13
|
import { getIconForProperty, isHidden, pick } from "../../util";
|
|
@@ -21,7 +29,6 @@ export function MapFieldBinding({
|
|
|
21
29
|
error,
|
|
22
30
|
disabled,
|
|
23
31
|
property,
|
|
24
|
-
setValue,
|
|
25
32
|
partOfBlock,
|
|
26
33
|
tableMode,
|
|
27
34
|
includeDescription,
|
|
@@ -101,7 +108,7 @@ export function MapFieldBinding({
|
|
|
101
108
|
{(tableMode || partOfBlock) && mapFormView}
|
|
102
109
|
|
|
103
110
|
<FieldHelperText includeDescription={includeDescription}
|
|
104
|
-
showError={showError}
|
|
111
|
+
showError={showError ?? false}
|
|
105
112
|
error={error ? (typeof error === "string" ? error : "A property of this map has an error") : undefined}
|
|
106
113
|
disabled={disabled}
|
|
107
114
|
property={property}/>
|
|
@@ -30,12 +30,6 @@ export function ReadOnlyFieldBinding({
|
|
|
30
30
|
if (!context.entityId)
|
|
31
31
|
throw new Error("ReadOnlyFieldBinding: Entity id is null");
|
|
32
32
|
|
|
33
|
-
const entity: Entity<any> = {
|
|
34
|
-
id: context.entityId!,
|
|
35
|
-
values: context.values,
|
|
36
|
-
path: context.path
|
|
37
|
-
};
|
|
38
|
-
|
|
39
33
|
return (
|
|
40
34
|
|
|
41
35
|
<>
|
|
@@ -53,7 +47,6 @@ export function ReadOnlyFieldBinding({
|
|
|
53
47
|
<PropertyPreview propertyKey={propertyKey}
|
|
54
48
|
value={value}
|
|
55
49
|
property={property}
|
|
56
|
-
// entity={entity}
|
|
57
50
|
size={"medium"}/>
|
|
58
51
|
</ErrorBoundary>
|
|
59
52
|
|
|
@@ -3,7 +3,6 @@ import React, { useCallback } from "react";
|
|
|
3
3
|
import {
|
|
4
4
|
ArrayProperty,
|
|
5
5
|
Entity,
|
|
6
|
-
EntityCollection,
|
|
7
6
|
FieldProps,
|
|
8
7
|
ResolvedArrayProperty,
|
|
9
8
|
ResolvedStringProperty,
|
|
@@ -81,7 +80,7 @@ export function StorageUploadFieldBinding({
|
|
|
81
80
|
propertyKey,
|
|
82
81
|
value,
|
|
83
82
|
storageSource,
|
|
84
|
-
disabled,
|
|
83
|
+
disabled: disabled ?? false,
|
|
85
84
|
onChange: setValue
|
|
86
85
|
});
|
|
87
86
|
|
|
@@ -91,12 +90,6 @@ export function StorageUploadFieldBinding({
|
|
|
91
90
|
setValue
|
|
92
91
|
});
|
|
93
92
|
|
|
94
|
-
const entity: Entity<any> = {
|
|
95
|
-
id: context.entityId,
|
|
96
|
-
values: context.values,
|
|
97
|
-
path: context.path
|
|
98
|
-
};
|
|
99
|
-
|
|
100
93
|
return (
|
|
101
94
|
|
|
102
95
|
<>
|
|
@@ -109,15 +102,13 @@ export function StorageUploadFieldBinding({
|
|
|
109
102
|
|
|
110
103
|
<StorageUpload
|
|
111
104
|
value={internalValue}
|
|
112
|
-
collection={context.collection}
|
|
113
105
|
name={propertyKey}
|
|
114
|
-
disabled={disabled}
|
|
115
|
-
autoFocus={autoFocus}
|
|
106
|
+
disabled={disabled ?? false}
|
|
107
|
+
autoFocus={autoFocus ?? false}
|
|
116
108
|
property={property}
|
|
117
109
|
onChange={setValue}
|
|
118
110
|
setInternalValue={setInternalValue}
|
|
119
111
|
onFilesAdded={onFilesAdded}
|
|
120
|
-
entity={entity}
|
|
121
112
|
onFileUploadComplete={onFileUploadComplete}
|
|
122
113
|
storagePathBuilder={storagePathBuilder}
|
|
123
114
|
storage={storage}
|
|
@@ -135,7 +126,6 @@ export function StorageUploadFieldBinding({
|
|
|
135
126
|
|
|
136
127
|
function FileDropComponent({
|
|
137
128
|
storage,
|
|
138
|
-
collection,
|
|
139
129
|
disabled,
|
|
140
130
|
isDraggingOver,
|
|
141
131
|
onFilesAdded,
|
|
@@ -144,7 +134,6 @@ function FileDropComponent({
|
|
|
144
134
|
autoFocus,
|
|
145
135
|
internalValue,
|
|
146
136
|
property,
|
|
147
|
-
entity,
|
|
148
137
|
onClear,
|
|
149
138
|
metadata,
|
|
150
139
|
storagePathBuilder,
|
|
@@ -154,7 +143,6 @@ function FileDropComponent({
|
|
|
154
143
|
helpText
|
|
155
144
|
}: {
|
|
156
145
|
storage: StorageConfig,
|
|
157
|
-
collection: EntityCollection,
|
|
158
146
|
disabled: boolean,
|
|
159
147
|
isDraggingOver: boolean,
|
|
160
148
|
droppableProvided: any,
|
|
@@ -165,7 +153,6 @@ function FileDropComponent({
|
|
|
165
153
|
property: ResolvedStringProperty,
|
|
166
154
|
onClear: (clearedStoragePathOrDownloadUrl: string) => void,
|
|
167
155
|
metadata: any,
|
|
168
|
-
entity: Entity<any>;
|
|
169
156
|
storagePathBuilder: (file: File) => string,
|
|
170
157
|
onFileUploadComplete: (uploadedPath: string, entry: StorageFieldItem, fileMetadata?: any) => Promise<void>,
|
|
171
158
|
size: PreviewSize,
|
|
@@ -235,11 +222,9 @@ function FileDropComponent({
|
|
|
235
222
|
if (entry.storagePathOrDownloadUrl) {
|
|
236
223
|
child = (
|
|
237
224
|
<StorageItemPreview
|
|
238
|
-
collection={collection}
|
|
239
225
|
name={`storage_preview_${entry.storagePathOrDownloadUrl}`}
|
|
240
226
|
property={property}
|
|
241
227
|
disabled={disabled}
|
|
242
|
-
entity={entity}
|
|
243
228
|
value={entry.storagePathOrDownloadUrl}
|
|
244
229
|
onRemove={onClear}
|
|
245
230
|
size={entry.size}/>
|
|
@@ -299,7 +284,6 @@ function FileDropComponent({
|
|
|
299
284
|
|
|
300
285
|
export interface StorageUploadProps {
|
|
301
286
|
value: StorageFieldItem[];
|
|
302
|
-
collection: EntityCollection;
|
|
303
287
|
setInternalValue: (v: StorageFieldItem[]) => void;
|
|
304
288
|
name: string;
|
|
305
289
|
property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
|
|
@@ -307,7 +291,6 @@ export interface StorageUploadProps {
|
|
|
307
291
|
multipleFilesSupported: boolean;
|
|
308
292
|
autoFocus: boolean;
|
|
309
293
|
disabled: boolean;
|
|
310
|
-
entity: Entity<any>;
|
|
311
294
|
storage: StorageConfig;
|
|
312
295
|
onFilesAdded: (acceptedFiles: File[]) => void;
|
|
313
296
|
storagePathBuilder: (file: File) => string;
|
|
@@ -315,7 +298,6 @@ export interface StorageUploadProps {
|
|
|
315
298
|
}
|
|
316
299
|
|
|
317
300
|
export function StorageUpload({
|
|
318
|
-
collection,
|
|
319
301
|
property,
|
|
320
302
|
name,
|
|
321
303
|
value,
|
|
@@ -327,7 +309,6 @@ export function StorageUpload({
|
|
|
327
309
|
onFilesAdded,
|
|
328
310
|
autoFocus,
|
|
329
311
|
storage,
|
|
330
|
-
entity,
|
|
331
312
|
storagePathBuilder,
|
|
332
313
|
}: StorageUploadProps) {
|
|
333
314
|
|
|
@@ -408,11 +389,9 @@ export function StorageUpload({
|
|
|
408
389
|
className="rounded"
|
|
409
390
|
>
|
|
410
391
|
<StorageItemPreview
|
|
411
|
-
collection={collection}
|
|
412
392
|
name={`storage_preview_${entry.storagePathOrDownloadUrl}`}
|
|
413
393
|
property={renderProperty}
|
|
414
394
|
disabled={true}
|
|
415
|
-
entity={entity}
|
|
416
395
|
value={entry.storagePathOrDownloadUrl as string}
|
|
417
396
|
onRemove={onClear}
|
|
418
397
|
size={entry.size}/>
|
|
@@ -422,7 +401,6 @@ export function StorageUpload({
|
|
|
422
401
|
>
|
|
423
402
|
{(provided, snapshot) => {
|
|
424
403
|
return <FileDropComponent storage={storage}
|
|
425
|
-
collection={collection}
|
|
426
404
|
disabled={disabled}
|
|
427
405
|
isDraggingOver={snapshot.isDraggingOver}
|
|
428
406
|
droppableProvided={provided}
|
|
@@ -431,7 +409,6 @@ export function StorageUpload({
|
|
|
431
409
|
autoFocus={autoFocus}
|
|
432
410
|
internalValue={value}
|
|
433
411
|
property={renderProperty}
|
|
434
|
-
entity={entity}
|
|
435
412
|
onClear={onClear}
|
|
436
413
|
metadata={metadata}
|
|
437
414
|
storagePathBuilder={storagePathBuilder}
|
package/src/form/index.tsx
CHANGED
|
@@ -34,10 +34,10 @@ export {
|
|
|
34
34
|
|
|
35
35
|
export * from "./components";
|
|
36
36
|
|
|
37
|
-
export type { EntityFormProps } from "./EntityForm";
|
|
38
|
-
export {
|
|
39
|
-
|
|
40
|
-
} from "./EntityForm";
|
|
37
|
+
// export type { EntityFormProps } from "./EntityForm";
|
|
38
|
+
// export {
|
|
39
|
+
// EntityForm
|
|
40
|
+
// } from "./EntityForm";
|
|
41
41
|
|
|
42
42
|
export { PropertyFieldBinding } from "./PropertyFieldBinding";
|
|
43
43
|
export * from "./useClearRestoreValue";
|
package/src/form/validation.ts
CHANGED
|
@@ -112,23 +112,7 @@ export function getYupMapObjectSchema({
|
|
|
112
112
|
if (validation?.required) {
|
|
113
113
|
return shape.required(validation?.requiredMessage ? validation.requiredMessage : "Required").nullable(true);
|
|
114
114
|
}
|
|
115
|
-
return shape.nullable(true);
|
|
116
|
-
// const object: ObjectSchema<any> = yup.object().shape(objectSchema);
|
|
117
|
-
// return validation?.required
|
|
118
|
-
// ? object.required(validation?.requiredMessage ? validation.requiredMessage : "Required").nullable(true)
|
|
119
|
-
// : yup.object().optional().default(undefined).notRequired().nullable(true).test(
|
|
120
|
-
// "empty-check",
|
|
121
|
-
// "Optional map can be empty",
|
|
122
|
-
// (o: any, testContext: any) => {
|
|
123
|
-
// try {
|
|
124
|
-
// if (!o || Object.keys(o).length === 0) return true;
|
|
125
|
-
// return object.validateSync(o);
|
|
126
|
-
// } catch (e) {
|
|
127
|
-
// testContext.createError(e);
|
|
128
|
-
// console.error(e);
|
|
129
|
-
// return false;
|
|
130
|
-
// }
|
|
131
|
-
// });
|
|
115
|
+
return yup.object().shape(shape.fields).default(undefined).notRequired().nullable(true);
|
|
132
116
|
}
|
|
133
117
|
|
|
134
118
|
function getYupStringSchema({
|
package/src/types/collections.ts
CHANGED
|
@@ -477,8 +477,22 @@ export interface AdditionalFieldDelegate<M extends Record<string, any> = any,
|
|
|
477
477
|
*/
|
|
478
478
|
export type EntityCustomView<M extends Record<string, any> = any> =
|
|
479
479
|
{
|
|
480
|
+
/**
|
|
481
|
+
* Key of this custom view.
|
|
482
|
+
*/
|
|
480
483
|
key: string,
|
|
484
|
+
/**
|
|
485
|
+
* Name of this custom view.
|
|
486
|
+
*/
|
|
481
487
|
name: string,
|
|
488
|
+
/**
|
|
489
|
+
* If set to true, the actions of the entity will be included in the
|
|
490
|
+
* bottom of the panel (save buttons, delete buttons, etc.)
|
|
491
|
+
*/
|
|
492
|
+
includeActions?: boolean;
|
|
493
|
+
/**
|
|
494
|
+
* Builder for rendering the custom view
|
|
495
|
+
*/
|
|
482
496
|
Builder?: React.ComponentType<EntityCustomViewParams<M>>;
|
|
483
497
|
}
|
|
484
498
|
|
package/src/types/fields.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { EntityValues } from "./entities";
|
|
2
1
|
import { CMSType, PropertyOrBuilder } from "./properties";
|
|
3
2
|
import { ResolvedEntityCollection, ResolvedProperty } from "./resolved_entities";
|
|
3
|
+
import { FormexController } from "@firecms/formex";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* When building a custom field you need to create a React component that takes
|
|
@@ -21,11 +21,6 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
21
21
|
*/
|
|
22
22
|
value: T;
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* Initial value of this field
|
|
26
|
-
*/
|
|
27
|
-
// initialValue: T | undefined;
|
|
28
|
-
|
|
29
24
|
/**
|
|
30
25
|
* Set value of field directly
|
|
31
26
|
*/
|
|
@@ -42,7 +37,7 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
42
37
|
/**
|
|
43
38
|
* Is the form currently submitting
|
|
44
39
|
*/
|
|
45
|
-
isSubmitting
|
|
40
|
+
isSubmitting?: boolean;
|
|
46
41
|
|
|
47
42
|
/**
|
|
48
43
|
* Should this field show the error indicator.
|
|
@@ -50,19 +45,19 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
50
45
|
* filled) but we don't want to show the error until the user has tried
|
|
51
46
|
* saving.
|
|
52
47
|
*/
|
|
53
|
-
showError
|
|
48
|
+
showError?: boolean;
|
|
54
49
|
|
|
55
50
|
/**
|
|
56
51
|
* Is there an error in this field. The error field has the same shape as
|
|
57
52
|
* the field, replacing values with a string containing the error.
|
|
58
53
|
* It takes the value `null` if there is no error
|
|
59
54
|
*/
|
|
60
|
-
error
|
|
55
|
+
error?: any | null;
|
|
61
56
|
|
|
62
57
|
/**
|
|
63
58
|
* Has this field been touched
|
|
64
59
|
*/
|
|
65
|
-
touched
|
|
60
|
+
touched?: boolean;
|
|
66
61
|
|
|
67
62
|
/**
|
|
68
63
|
* Property related to this field
|
|
@@ -72,38 +67,38 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
72
67
|
/**
|
|
73
68
|
* Should this field include a description
|
|
74
69
|
*/
|
|
75
|
-
includeDescription
|
|
70
|
+
includeDescription?: boolean;
|
|
76
71
|
|
|
77
72
|
/**
|
|
78
73
|
* Flag to indicate that the underlying value has been updated in the
|
|
79
74
|
* datasource
|
|
80
75
|
*/
|
|
81
|
-
underlyingValueHasChanged
|
|
76
|
+
underlyingValueHasChanged?: boolean;
|
|
82
77
|
|
|
83
78
|
/**
|
|
84
79
|
* Is this field part of an array
|
|
85
80
|
*/
|
|
86
|
-
partOfArray
|
|
81
|
+
partOfArray?: boolean;
|
|
87
82
|
|
|
88
83
|
/**
|
|
89
84
|
* Is this field part of a block (oneOf array)
|
|
90
85
|
*/
|
|
91
|
-
partOfBlock
|
|
86
|
+
partOfBlock?: boolean;
|
|
92
87
|
|
|
93
88
|
/**
|
|
94
89
|
* Is this field being rendered in the entity table popup
|
|
95
90
|
*/
|
|
96
|
-
tableMode
|
|
91
|
+
tableMode?: boolean;
|
|
97
92
|
|
|
98
93
|
/**
|
|
99
94
|
* Should this field autofocus on mount
|
|
100
95
|
*/
|
|
101
|
-
autoFocus
|
|
96
|
+
autoFocus?: boolean;
|
|
102
97
|
|
|
103
98
|
/**
|
|
104
99
|
* Additional properties set by the developer
|
|
105
100
|
*/
|
|
106
|
-
customProps
|
|
101
|
+
customProps?: CustomProps
|
|
107
102
|
|
|
108
103
|
/**
|
|
109
104
|
* Additional values related to the state of the form or the entity
|
|
@@ -113,7 +108,7 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
113
108
|
/**
|
|
114
109
|
* Flag to indicate if this field should be disabled
|
|
115
110
|
*/
|
|
116
|
-
disabled
|
|
111
|
+
disabled?: boolean;
|
|
117
112
|
|
|
118
113
|
}
|
|
119
114
|
|
|
@@ -124,37 +119,42 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
124
119
|
export interface FormContext<M extends Record<string, any> = any> {
|
|
125
120
|
|
|
126
121
|
/**
|
|
127
|
-
*
|
|
122
|
+
* Current values of the entity
|
|
128
123
|
*/
|
|
129
|
-
|
|
124
|
+
values: M;
|
|
130
125
|
|
|
131
126
|
/**
|
|
132
|
-
*
|
|
127
|
+
* Update the value of a field
|
|
128
|
+
* @param key
|
|
129
|
+
* @param value
|
|
130
|
+
* @param shouldValidate
|
|
133
131
|
*/
|
|
134
|
-
|
|
132
|
+
setFieldValue: (key: string, value: any, shouldValidate?: boolean) => void;
|
|
135
133
|
|
|
136
134
|
/**
|
|
137
|
-
*
|
|
135
|
+
* Save the entity.
|
|
138
136
|
*/
|
|
139
|
-
|
|
137
|
+
save: (values: M) => void;
|
|
140
138
|
|
|
141
139
|
/**
|
|
142
|
-
*
|
|
140
|
+
* Collection of the entity being modified
|
|
143
141
|
*/
|
|
144
|
-
|
|
142
|
+
collection?: ResolvedEntityCollection<M>;
|
|
145
143
|
|
|
146
144
|
/**
|
|
147
|
-
*
|
|
148
|
-
* @param key
|
|
149
|
-
* @param value
|
|
150
|
-
* @param shouldValidate
|
|
145
|
+
* Entity id, it can be null if it's a new entity
|
|
151
146
|
*/
|
|
152
|
-
|
|
147
|
+
entityId?: string;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Path this entity is located at
|
|
151
|
+
*/
|
|
152
|
+
path?: string;
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
*
|
|
155
|
+
* This is the underlying formex controller that powers the form
|
|
156
156
|
*/
|
|
157
|
-
|
|
157
|
+
formex: FormexController<M>;
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
/**
|
package/src/types/plugins.tsx
CHANGED
|
@@ -194,8 +194,8 @@ export type PluginFieldBuilderParams<T extends CMSType = CMSType, M extends Reco
|
|
|
194
194
|
property: Property<T> | ResolvedProperty<T>;
|
|
195
195
|
Field: React.ComponentType<FieldProps<T, any, M>>;
|
|
196
196
|
plugin: FireCMSPlugin;
|
|
197
|
-
path
|
|
198
|
-
collection
|
|
197
|
+
path?: string;
|
|
198
|
+
collection?: EC;
|
|
199
199
|
};
|
|
200
200
|
|
|
201
201
|
export interface PluginGenericProps<UserType extends User = User> {
|
package/src/types/properties.ts
CHANGED
package/src/util/entities.ts
CHANGED
|
@@ -152,6 +152,7 @@ export function traverseValuesProperties<M extends Record<string, any>>(
|
|
|
152
152
|
.map(([key, property]) => {
|
|
153
153
|
const inputValue = inputValues && (inputValues)[key];
|
|
154
154
|
const updatedValue = traverseValueProperty(inputValue, property as Property, operation);
|
|
155
|
+
if (updatedValue === null) return null;
|
|
155
156
|
if (updatedValue === undefined) return undefined;
|
|
156
157
|
return ({ [key]: updatedValue });
|
|
157
158
|
})
|
package/src/util/permissions.ts
CHANGED
|
@@ -49,6 +49,7 @@ export function canCreateEntity<M extends Record<string, any>, UserType extends
|
|
|
49
49
|
authController: AuthController<UserType>,
|
|
50
50
|
path: string,
|
|
51
51
|
entity: Entity<M> | null): boolean {
|
|
52
|
+
if (collection.collectionGroup) return false;
|
|
52
53
|
return resolvePermissions(collection, authController, path, entity)?.create ?? DEFAULT_PERMISSIONS.create;
|
|
53
54
|
}
|
|
54
55
|
|