@firecms/core 3.0.0-beta.7 → 3.0.0-beta.8
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/app/AppBar.d.ts +12 -0
- package/dist/app/Drawer.d.ts +17 -0
- package/dist/app/Scaffold.d.ts +30 -0
- package/dist/app/index.d.ts +4 -0
- package/dist/app/useApp.d.ts +16 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +4 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +2 -7
- package/dist/core/DefaultDrawer.d.ts +19 -0
- package/dist/core/EntityEditView.d.ts +17 -3
- package/dist/core/NavigationRoutes.d.ts +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/form/PropertiesForm.d.ts +8 -0
- package/dist/form/components/FieldHelperText.d.ts +3 -3
- package/dist/form/components/StorageItemPreview.d.ts +4 -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.d.ts +1 -0
- package/dist/index.es.js +5595 -5574
- 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/preview/PropertyPreviewProps.d.ts +5 -0
- package/dist/preview/components/StorageThumbnail.d.ts +2 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
- package/dist/types/auth.d.ts +1 -1
- package/dist/types/collections.d.ts +14 -0
- package/dist/types/datasource.d.ts +18 -8
- package/dist/types/fields.d.ts +31 -30
- package/dist/types/plugins.d.ts +11 -3
- package/dist/types/properties.d.ts +7 -2
- package/dist/util/icons.d.ts +2 -2
- package/dist/util/storage.d.ts +23 -2
- package/dist/util/useStorageUploadController.d.ts +1 -1
- package/package.json +13 -22
- package/src/app/AppBar.tsx +18 -0
- package/src/app/Drawer.tsx +25 -0
- package/src/{core → app}/Scaffold.tsx +61 -107
- package/src/app/index.ts +4 -0
- package/src/app/useApp.tsx +32 -0
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +7 -9
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -1
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +7 -4
- package/src/components/VirtualTable/VirtualTable.tsx +3 -1
- package/src/components/VirtualTable/VirtualTableProps.tsx +5 -0
- package/src/components/common/useTableSearchHelper.ts +52 -12
- package/src/components/index.tsx +1 -1
- package/src/contexts/DialogsProvider.tsx +2 -2
- package/src/{components/FireCMSAppBar.tsx → core/DefaultAppBar.tsx} +26 -28
- package/src/core/DefaultDrawer.tsx +177 -0
- package/src/core/EntityEditView.tsx +669 -129
- package/src/core/EntitySidePanel.tsx +0 -1
- package/src/core/NavigationRoutes.tsx +3 -3
- package/src/core/index.tsx +2 -2
- package/src/form/PropertiesForm.tsx +81 -0
- package/src/form/PropertyFieldBinding.tsx +29 -5
- package/src/form/components/FieldHelperText.tsx +3 -3
- package/src/form/components/StorageItemPreview.tsx +19 -10
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +8 -5
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -4
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +40 -35
- package/src/form/field_bindings/MapFieldBinding.tsx +11 -3
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -7
- package/src/form/field_bindings/RepeatFieldBinding.tsx +10 -7
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +6 -35
- package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -1
- package/src/form/index.tsx +4 -4
- package/src/form/validation.ts +1 -17
- package/src/index.ts +1 -0
- package/src/internal/useBuildDataSource.ts +12 -0
- package/src/preview/PropertyPreview.tsx +5 -2
- package/src/preview/PropertyPreviewProps.tsx +6 -0
- package/src/preview/components/ImagePreview.tsx +21 -33
- package/src/preview/components/ReferencePreview.tsx +2 -1
- package/src/preview/components/StorageThumbnail.tsx +5 -1
- package/src/preview/components/UrlComponentPreview.tsx +44 -11
- package/src/types/auth.tsx +1 -1
- package/src/types/collections.ts +14 -0
- package/src/types/customization_controller.tsx +0 -1
- package/src/types/datasource.ts +20 -16
- package/src/types/fields.tsx +33 -33
- package/src/types/plugins.tsx +12 -3
- package/src/types/properties.ts +7 -2
- package/src/util/entities.ts +4 -3
- package/src/util/objects.ts +17 -7
- package/src/util/permissions.ts +1 -0
- package/src/util/storage.ts +75 -21
- package/src/util/useStorageUploadController.tsx +21 -3
- package/dist/core/Drawer.d.ts +0 -16
- package/dist/core/Scaffold.d.ts +0 -51
- package/dist/form/EntityForm.d.ts +0 -77
- package/src/core/Drawer.tsx +0 -139
- package/src/form/EntityForm.tsx +0 -736
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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
2
|
|
|
3
3
|
import { FireCMSContext } from "./firecms_context";
|
|
4
|
-
import { CollectionActionsProps, EntityCollection } from "./collections";
|
|
4
|
+
import { CollectionActionsProps, EntityCollection, EntityTableController } from "./collections";
|
|
5
5
|
import { User } from "./user";
|
|
6
6
|
import { FieldProps, FormContext } from "./fields";
|
|
7
7
|
import { CMSType, Property } from "./properties";
|
|
@@ -98,6 +98,13 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
98
98
|
CollectionActionsStart?: React.ComponentType<CollectionActionsProps<any, any, EC> & COL_ACTIONS_START__PROPS> | React.ComponentType<CollectionActionsProps<any, any, EC> & COL_ACTIONS_START__PROPS>[];
|
|
99
99
|
collectionActionsStartProps?: COL_ACTIONS_START__PROPS;
|
|
100
100
|
|
|
101
|
+
blockSearch?: (props: {
|
|
102
|
+
context: FireCMSContext,
|
|
103
|
+
path: string,
|
|
104
|
+
collection: EC,
|
|
105
|
+
parentCollectionIds?: string[]
|
|
106
|
+
}) => boolean;
|
|
107
|
+
|
|
101
108
|
showTextSearchBar?: (props: {
|
|
102
109
|
context: FireCMSContext,
|
|
103
110
|
path: string,
|
|
@@ -123,6 +130,7 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
123
130
|
parentCollectionIds: string[],
|
|
124
131
|
onHover: boolean,
|
|
125
132
|
collection: EC;
|
|
133
|
+
tableController: EntityTableController;
|
|
126
134
|
}>;
|
|
127
135
|
|
|
128
136
|
/**
|
|
@@ -133,6 +141,7 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
133
141
|
fullPath: string,
|
|
134
142
|
parentCollectionIds: string[],
|
|
135
143
|
collection: EC;
|
|
144
|
+
tableController: EntityTableController;
|
|
136
145
|
}>;
|
|
137
146
|
}
|
|
138
147
|
|
|
@@ -194,8 +203,8 @@ export type PluginFieldBuilderParams<T extends CMSType = CMSType, M extends Reco
|
|
|
194
203
|
property: Property<T> | ResolvedProperty<T>;
|
|
195
204
|
Field: React.ComponentType<FieldProps<T, any, M>>;
|
|
196
205
|
plugin: FireCMSPlugin;
|
|
197
|
-
path
|
|
198
|
-
collection
|
|
206
|
+
path?: string;
|
|
207
|
+
collection?: EC;
|
|
199
208
|
};
|
|
200
209
|
|
|
201
210
|
export interface PluginGenericProps<UserType extends User = User> {
|
package/src/types/properties.ts
CHANGED
|
@@ -149,7 +149,7 @@ export interface BaseProperty<T extends CMSType, CustomProps = any> {
|
|
|
149
149
|
/**
|
|
150
150
|
* This value will be set by default for new entities.
|
|
151
151
|
*/
|
|
152
|
-
defaultValue?: T;
|
|
152
|
+
defaultValue?: T | null;
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
155
|
* Should this property be editable. If set to true, the user will be able to modify the property and
|
|
@@ -783,6 +783,11 @@ export type StorageConfig = {
|
|
|
783
783
|
*/
|
|
784
784
|
postProcess?: (pathOrUrl: string) => Promise<string>;
|
|
785
785
|
|
|
786
|
+
/**
|
|
787
|
+
* You can use this prop in order to provide a custom preview URL.
|
|
788
|
+
* Useful when the file's path is different from the original field value
|
|
789
|
+
*/
|
|
790
|
+
previewUrl?: (fileName: string) => string;
|
|
786
791
|
}
|
|
787
792
|
|
|
788
793
|
/**
|
|
@@ -812,7 +817,7 @@ export interface UploadedFileContext {
|
|
|
812
817
|
/**
|
|
813
818
|
* Entity path. E.g. `products/PID/locales`
|
|
814
819
|
*/
|
|
815
|
-
path
|
|
820
|
+
path?: string;
|
|
816
821
|
|
|
817
822
|
/**
|
|
818
823
|
* Values of the current entity
|
package/src/util/entities.ts
CHANGED
|
@@ -48,12 +48,12 @@ export function getDefaultValuesFor<M extends Record<string, any>>(properties: P
|
|
|
48
48
|
|
|
49
49
|
export function getDefaultValueFor(property: PropertyOrBuilder) {
|
|
50
50
|
if (isPropertyBuilder(property)) return undefined;
|
|
51
|
-
if (property.
|
|
51
|
+
if (property.defaultValue || property.defaultValue === null) {
|
|
52
|
+
return property.defaultValue;
|
|
53
|
+
} else if (property.dataType === "map" && property.properties) {
|
|
52
54
|
const defaultValuesFor = getDefaultValuesFor(property.properties as Properties);
|
|
53
55
|
if (Object.keys(defaultValuesFor).length === 0) return undefined;
|
|
54
56
|
return defaultValuesFor;
|
|
55
|
-
} else if (property.defaultValue) {
|
|
56
|
-
return property.defaultValue;
|
|
57
57
|
} else {
|
|
58
58
|
return getDefaultValueForDataType(property.dataType);
|
|
59
59
|
}
|
|
@@ -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/objects.ts
CHANGED
|
@@ -141,15 +141,25 @@ export function removePropsIfExisting(source: any, comparison: any) {
|
|
|
141
141
|
|
|
142
142
|
const res = isArray(source) ? [...source] : { ...source };
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (
|
|
147
|
-
res
|
|
148
|
-
} else if (res[
|
|
149
|
-
|
|
144
|
+
if (isArray(res)) {
|
|
145
|
+
for (let i = res.length - 1; i >= 0; i--) {
|
|
146
|
+
if (res[i] === comparison[i]) {
|
|
147
|
+
res.splice(i, 1);
|
|
148
|
+
} else if (isObject(res[i]) && isObject(comparison[i])) {
|
|
149
|
+
res[i] = removePropsIfExisting(res[i], comparison[i]);
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
}
|
|
152
|
+
} else {
|
|
153
|
+
Object.keys(comparison).forEach(key => {
|
|
154
|
+
if (key in res) {
|
|
155
|
+
if (isObject(res[key]) && isObject(comparison[key])) {
|
|
156
|
+
res[key] = removePropsIfExisting(res[key], comparison[key]);
|
|
157
|
+
} else if (res[key] === comparison[key]) {
|
|
158
|
+
delete res[key];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
153
163
|
|
|
154
164
|
return res;
|
|
155
165
|
}
|
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
|
|
package/src/util/storage.ts
CHANGED
|
@@ -7,15 +7,28 @@ import {
|
|
|
7
7
|
} from "../types";
|
|
8
8
|
import { randomString } from "./strings";
|
|
9
9
|
|
|
10
|
+
interface ResolveFilenameStringParams<M extends object> {
|
|
11
|
+
input: string | ((context: UploadedFileContext) => (Promise<string> | string));
|
|
12
|
+
storage: StorageConfig;
|
|
13
|
+
values: EntityValues<M>;
|
|
14
|
+
entityId: string;
|
|
15
|
+
path?: string;
|
|
16
|
+
property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
|
|
17
|
+
file: File;
|
|
18
|
+
propertyKey: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
10
21
|
export async function resolveFilenameString<M extends object>(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
{
|
|
23
|
+
input,
|
|
24
|
+
storage,
|
|
25
|
+
values,
|
|
26
|
+
entityId,
|
|
27
|
+
path,
|
|
28
|
+
property,
|
|
29
|
+
file,
|
|
30
|
+
propertyKey
|
|
31
|
+
}: ResolveFilenameStringParams<M>): Promise<string> {
|
|
19
32
|
let result;
|
|
20
33
|
if (typeof input === "function") {
|
|
21
34
|
result = await input({
|
|
@@ -30,7 +43,13 @@ export async function resolveFilenameString<M extends object>(
|
|
|
30
43
|
if (!result)
|
|
31
44
|
console.warn("Storage callback returned empty result. Using default name value")
|
|
32
45
|
} else {
|
|
33
|
-
result = replacePlaceholders(
|
|
46
|
+
result = replacePlaceholders({
|
|
47
|
+
file,
|
|
48
|
+
input,
|
|
49
|
+
entityId,
|
|
50
|
+
propertyKey,
|
|
51
|
+
path
|
|
52
|
+
});
|
|
34
53
|
}
|
|
35
54
|
|
|
36
55
|
if (!result)
|
|
@@ -39,15 +58,28 @@ export async function resolveFilenameString<M extends object>(
|
|
|
39
58
|
return result;
|
|
40
59
|
}
|
|
41
60
|
|
|
61
|
+
interface ResolveStoragePathStringParams<M extends object> {
|
|
62
|
+
input: string | ((context: UploadedFileContext) => string);
|
|
63
|
+
storage: StorageConfig;
|
|
64
|
+
values: EntityValues<M>;
|
|
65
|
+
entityId: string;
|
|
66
|
+
path?: string;
|
|
67
|
+
property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
|
|
68
|
+
file: File;
|
|
69
|
+
propertyKey: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
42
72
|
export function resolveStoragePathString<M extends object>(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
73
|
+
{
|
|
74
|
+
input,
|
|
75
|
+
storage,
|
|
76
|
+
values,
|
|
77
|
+
entityId,
|
|
78
|
+
path,
|
|
79
|
+
property,
|
|
80
|
+
file,
|
|
81
|
+
propertyKey
|
|
82
|
+
}: ResolveStoragePathStringParams<M>): string {
|
|
51
83
|
let result;
|
|
52
84
|
if (typeof input === "function") {
|
|
53
85
|
result = input({
|
|
@@ -62,7 +94,13 @@ export function resolveStoragePathString<M extends object>(
|
|
|
62
94
|
if (!result)
|
|
63
95
|
console.warn("Storage callback returned empty result. Using default name value")
|
|
64
96
|
} else {
|
|
65
|
-
result = replacePlaceholders(
|
|
97
|
+
result = replacePlaceholders({
|
|
98
|
+
file,
|
|
99
|
+
input,
|
|
100
|
+
entityId,
|
|
101
|
+
propertyKey,
|
|
102
|
+
path
|
|
103
|
+
});
|
|
66
104
|
}
|
|
67
105
|
|
|
68
106
|
if (!result)
|
|
@@ -71,14 +109,30 @@ export function resolveStoragePathString<M extends object>(
|
|
|
71
109
|
return result;
|
|
72
110
|
}
|
|
73
111
|
|
|
74
|
-
|
|
112
|
+
interface Placeholders {
|
|
113
|
+
file: File;
|
|
114
|
+
input: string;
|
|
115
|
+
entityId: string;
|
|
116
|
+
propertyKey: string;
|
|
117
|
+
path?: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function replacePlaceholders({
|
|
121
|
+
file,
|
|
122
|
+
input,
|
|
123
|
+
entityId,
|
|
124
|
+
propertyKey,
|
|
125
|
+
path
|
|
126
|
+
}: Placeholders) {
|
|
75
127
|
const ext = file.name.split(".").pop();
|
|
76
128
|
let result = input.replace("{entityId}", entityId)
|
|
77
129
|
.replace("{propertyKey}", propertyKey)
|
|
78
130
|
.replace("{rand}", randomString())
|
|
79
131
|
.replace("{file}", file.name)
|
|
80
|
-
.replace("{file.type}", file.type)
|
|
81
|
-
|
|
132
|
+
.replace("{file.type}", file.type);
|
|
133
|
+
if (path) {
|
|
134
|
+
result = result.replace("{path}", path);
|
|
135
|
+
}
|
|
82
136
|
if (ext) {
|
|
83
137
|
result = result.replace("{file.ext}", ext);
|
|
84
138
|
const name = file.name.replace(`.${ext}`, "");
|
|
@@ -46,7 +46,7 @@ export function useStorageUploadController<M extends object>({
|
|
|
46
46
|
entityId: string,
|
|
47
47
|
entityValues: EntityValues<M>,
|
|
48
48
|
value: string | string[] | null;
|
|
49
|
-
path
|
|
49
|
+
path?: string,
|
|
50
50
|
propertyKey: string,
|
|
51
51
|
property: ResolvedStringProperty | ResolvedArrayProperty<string[]>,
|
|
52
52
|
storageSource: StorageSource,
|
|
@@ -95,7 +95,16 @@ export function useStorageUploadController<M extends object>({
|
|
|
95
95
|
|
|
96
96
|
const fileNameBuilder = useCallback(async (file: File) => {
|
|
97
97
|
if (storage.fileName) {
|
|
98
|
-
const fileName = await resolveFilenameString(
|
|
98
|
+
const fileName = await resolveFilenameString({
|
|
99
|
+
input: storage.fileName,
|
|
100
|
+
storage,
|
|
101
|
+
values: entityValues,
|
|
102
|
+
entityId,
|
|
103
|
+
path,
|
|
104
|
+
property,
|
|
105
|
+
file,
|
|
106
|
+
propertyKey
|
|
107
|
+
});
|
|
99
108
|
if (!fileName || fileName.length === 0) {
|
|
100
109
|
throw Error("You need to return a valid filename");
|
|
101
110
|
}
|
|
@@ -105,7 +114,16 @@ export function useStorageUploadController<M extends object>({
|
|
|
105
114
|
}, [entityId, entityValues, path, property, propertyKey, storage]);
|
|
106
115
|
|
|
107
116
|
const storagePathBuilder = useCallback((file: File) => {
|
|
108
|
-
return resolveStoragePathString(
|
|
117
|
+
return resolveStoragePathString({
|
|
118
|
+
input: storage.storagePath,
|
|
119
|
+
storage,
|
|
120
|
+
values: entityValues,
|
|
121
|
+
entityId,
|
|
122
|
+
path,
|
|
123
|
+
property,
|
|
124
|
+
file,
|
|
125
|
+
propertyKey
|
|
126
|
+
}) ?? "/";
|
|
109
127
|
}, [entityId, entityValues, path, property, propertyKey, storage]);
|
|
110
128
|
|
|
111
129
|
const onFileUploadComplete = useCallback(async (uploadedPath: string,
|
package/dist/core/Drawer.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Props used in case you need to override the default drawer
|
|
3
|
-
* @group Core
|
|
4
|
-
*/
|
|
5
|
-
export type DrawerProps = {
|
|
6
|
-
hovered: boolean;
|
|
7
|
-
drawerOpen: boolean;
|
|
8
|
-
openDrawer: () => void;
|
|
9
|
-
closeDrawer: () => void;
|
|
10
|
-
autoOpenDrawer?: boolean;
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Default drawer used in the CMS
|
|
14
|
-
* @group Core
|
|
15
|
-
*/
|
|
16
|
-
export declare function Drawer(): import("react/jsx-runtime").JSX.Element;
|
package/dist/core/Scaffold.d.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { DrawerProps } from "./Drawer";
|
|
3
|
-
import { FireCMSAppBarProps } from "../components";
|
|
4
|
-
export declare const DRAWER_WIDTH = 280;
|
|
5
|
-
export declare function useDrawer(): DrawerProps;
|
|
6
|
-
/**
|
|
7
|
-
* @group Core
|
|
8
|
-
*/
|
|
9
|
-
export interface ScaffoldProps<ExtraAppbarProps = object> {
|
|
10
|
-
/**
|
|
11
|
-
* Name of the app, displayed as the main title and in the tab title
|
|
12
|
-
*/
|
|
13
|
-
name?: React.ReactNode;
|
|
14
|
-
/**
|
|
15
|
-
* Logo to be displayed in the drawer of the CMS
|
|
16
|
-
*/
|
|
17
|
-
logo?: string;
|
|
18
|
-
/**
|
|
19
|
-
* Whether to include the drawer in the scaffold
|
|
20
|
-
*/
|
|
21
|
-
includeDrawer?: boolean;
|
|
22
|
-
/**
|
|
23
|
-
* You can define a custom drawer to be displayed in the scaffold.
|
|
24
|
-
* Use the hook `useDrawer` to access the context values.
|
|
25
|
-
*/
|
|
26
|
-
drawer?: React.ReactNode;
|
|
27
|
-
/**
|
|
28
|
-
* Open the drawer on hover
|
|
29
|
-
*/
|
|
30
|
-
autoOpenDrawer?: boolean;
|
|
31
|
-
/**
|
|
32
|
-
* The AppBar component to be used in the scaffold.
|
|
33
|
-
*/
|
|
34
|
-
FireCMSAppBar?: React.ComponentType<FireCMSAppBarProps<ExtraAppbarProps>>;
|
|
35
|
-
/**
|
|
36
|
-
* Additional props passed to the custom AppBar
|
|
37
|
-
*/
|
|
38
|
-
fireCMSAppBarProps?: Partial<FireCMSAppBarProps> & ExtraAppbarProps;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* This view acts as a scaffold for FireCMS.
|
|
42
|
-
*
|
|
43
|
-
* It is in charge of displaying the navigation drawer, top bar and main
|
|
44
|
-
* collection views.
|
|
45
|
-
* This component needs a parent {@link FireCMS}
|
|
46
|
-
*
|
|
47
|
-
* @param props
|
|
48
|
-
* @constructor
|
|
49
|
-
* @group Core
|
|
50
|
-
*/
|
|
51
|
-
export declare const Scaffold: React.NamedExoticComponent<React.PropsWithChildren<ScaffoldProps<object>>>;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { Entity, EntityCollection, EntityStatus, EntityValues, FormContext, ResolvedEntityCollection } from "../types";
|
|
2
|
-
import { ValidationError } from "yup";
|
|
3
|
-
/**
|
|
4
|
-
* @group Components
|
|
5
|
-
*/
|
|
6
|
-
export interface EntityFormProps<M extends Record<string, any>> {
|
|
7
|
-
/**
|
|
8
|
-
* New or existing status
|
|
9
|
-
*/
|
|
10
|
-
status: EntityStatus;
|
|
11
|
-
/**
|
|
12
|
-
* Path of the collection this entity is located
|
|
13
|
-
*/
|
|
14
|
-
path: string;
|
|
15
|
-
/**
|
|
16
|
-
* The collection is used to build the fields of the form
|
|
17
|
-
*/
|
|
18
|
-
collection: EntityCollection<M>;
|
|
19
|
-
/**
|
|
20
|
-
* The updated entity is passed from the parent component when the underlying data
|
|
21
|
-
* has changed in the datasource
|
|
22
|
-
*/
|
|
23
|
-
entity?: Entity<M>;
|
|
24
|
-
/**
|
|
25
|
-
* The callback function called when Save is clicked and validation is correct
|
|
26
|
-
*/
|
|
27
|
-
onEntitySaveRequested: (props: EntityFormSaveParams<M>) => Promise<void>;
|
|
28
|
-
/**
|
|
29
|
-
* The callback function called when discard is clicked
|
|
30
|
-
*/
|
|
31
|
-
onDiscard?: () => void;
|
|
32
|
-
/**
|
|
33
|
-
* The callback function when the form is dirty, so the values are different
|
|
34
|
-
* from the original ones
|
|
35
|
-
*/
|
|
36
|
-
onModified?: (dirty: boolean) => void;
|
|
37
|
-
/**
|
|
38
|
-
* The callback function when the form original values have been modified
|
|
39
|
-
*/
|
|
40
|
-
onValuesChanged?: (values?: EntityValues<M>) => void;
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
* @param id
|
|
44
|
-
*/
|
|
45
|
-
onIdChange?: (id: string) => void;
|
|
46
|
-
currentEntityId?: string;
|
|
47
|
-
onFormContextChange?: (formContext: FormContext<M>) => void;
|
|
48
|
-
hideId?: boolean;
|
|
49
|
-
autoSave?: boolean;
|
|
50
|
-
onIdUpdateError?: (error: any) => void;
|
|
51
|
-
}
|
|
52
|
-
export type EntityFormSaveParams<M extends Record<string, any>> = {
|
|
53
|
-
collection: ResolvedEntityCollection<M>;
|
|
54
|
-
path: string;
|
|
55
|
-
entityId: string | undefined;
|
|
56
|
-
values: EntityValues<M>;
|
|
57
|
-
previousValues?: EntityValues<M>;
|
|
58
|
-
closeAfterSave: boolean;
|
|
59
|
-
autoSave: boolean;
|
|
60
|
-
};
|
|
61
|
-
/**
|
|
62
|
-
* This is the form used internally by the CMS
|
|
63
|
-
* @param status
|
|
64
|
-
* @param path
|
|
65
|
-
* @param collection
|
|
66
|
-
* @param entity
|
|
67
|
-
* @param onEntitySave
|
|
68
|
-
* @param onDiscard
|
|
69
|
-
* @param onModified
|
|
70
|
-
* @param onValuesChanged
|
|
71
|
-
* @constructor
|
|
72
|
-
* @group Components
|
|
73
|
-
*/
|
|
74
|
-
export declare const EntityForm: typeof EntityFormInternal;
|
|
75
|
-
declare function EntityFormInternal<M extends Record<string, any>>({ status, path, collection: inputCollection, entity, onEntitySaveRequested, onDiscard, onModified, onValuesChanged, onIdChange, onFormContextChange, hideId, autoSave, onIdUpdateError, }: EntityFormProps<M>): import("react/jsx-runtime").JSX.Element;
|
|
76
|
-
export declare function yupToFormErrors(yupError: ValidationError): Record<string, any>;
|
|
77
|
-
export {};
|