@firecms/core 3.0.0-beta.7 → 3.0.0-beta.9
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/ArrayContainer.d.ts +2 -1
- package/dist/components/CircularProgressCenter.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +0 -1
- package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +1 -1
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +1 -1
- package/dist/components/EntityPreview.d.ts +1 -1
- package/dist/components/ErrorView.d.ts +1 -1
- package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
- package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
- package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +14 -6
- package/dist/components/common/useColumnsIds.d.ts +2 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +3 -8
- package/dist/core/DefaultDrawer.d.ts +19 -0
- package/dist/core/DrawerNavigationItem.d.ts +2 -1
- package/dist/core/EntityEditView.d.ts +18 -4
- package/dist/core/FireCMS.d.ts +1 -1
- package/dist/core/NavigationRoutes.d.ts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/FieldHelperText.d.ts +3 -3
- package/dist/form/components/FormikArrayContainer.d.ts +2 -1
- package/dist/form/components/LabelWithIcon.d.ts +1 -1
- package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
- package/dist/form/components/StorageItemPreview.d.ts +4 -4
- package/dist/form/components/index.d.ts +1 -0
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
- package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
- package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -5
- package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
- package/dist/form/index.d.ts +3 -5
- package/dist/form/useClearRestoreValue.d.ts +2 -2
- package/dist/hooks/useProjectLog.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +14434 -11300
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +19987 -587
- package/dist/index.umd.js.map +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +6 -1
- package/dist/preview/components/EnumValuesChip.d.ts +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +1 -1
- package/dist/preview/components/StorageThumbnail.d.ts +2 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
- package/dist/types/auth.d.ts +2 -2
- package/dist/types/collections.d.ts +26 -3
- package/dist/types/datasource.d.ts +53 -30
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/entity_overrides.d.ts +2 -2
- package/dist/types/fields.d.ts +47 -41
- package/dist/types/navigation.d.ts +1 -0
- package/dist/types/plugins.d.ts +11 -3
- package/dist/types/properties.d.ts +25 -20
- package/dist/types/side_dialogs_controller.d.ts +10 -0
- package/dist/types/storage.d.ts +75 -0
- package/dist/util/entities.d.ts +1 -1
- package/dist/util/icon_list.d.ts +5 -1
- package/dist/util/icons.d.ts +3 -2
- package/dist/util/index.d.ts +1 -0
- package/dist/util/plurals.d.ts +0 -2
- package/dist/util/property_utils.d.ts +1 -1
- package/dist/util/resolutions.d.ts +15 -1
- package/dist/util/storage.d.ts +23 -2
- package/dist/util/useStorageUploadController.d.ts +3 -3
- package/package.json +18 -29
- package/src/app/AppBar.tsx +18 -0
- package/src/app/Drawer.tsx +25 -0
- package/src/{core → app}/Scaffold.tsx +71 -122
- package/src/app/index.ts +4 -0
- package/src/app/useApp.tsx +32 -0
- package/src/components/ArrayContainer.tsx +15 -10
- package/src/components/CircularProgressCenter.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +11 -18
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +2 -2
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +4 -2
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +21 -14
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +12 -4
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +17 -19
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +19 -7
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +5 -6
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +33 -29
- package/src/components/EntityCollectionView/useSelectionController.tsx +19 -7
- package/src/components/EntityPreview.tsx +30 -31
- package/src/components/ErrorView.tsx +1 -1
- package/src/components/HomePage/DefaultHomePage.tsx +24 -18
- package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
- package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
- package/src/components/PropertyIdCopyTooltip.tsx +48 -0
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +7 -6
- package/src/components/SearchIconsView.tsx +5 -2
- package/src/components/SelectableTable/SelectableTable.tsx +2 -4
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +1 -1
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +54 -7
- package/src/components/VirtualTable/VirtualTable.tsx +36 -10
- package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
- package/src/components/VirtualTable/VirtualTableProps.tsx +17 -8
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -3
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -1
- package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +14 -28
- package/src/components/common/useColumnsIds.tsx +13 -0
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -12
- package/src/components/common/useTableSearchHelper.ts +53 -12
- package/src/components/index.tsx +2 -1
- package/src/contexts/DialogsProvider.tsx +2 -2
- package/src/{components/FireCMSAppBar.tsx → core/DefaultAppBar.tsx} +28 -30
- package/src/core/DefaultDrawer.tsx +183 -0
- package/src/core/DrawerNavigationItem.tsx +31 -27
- package/src/core/EntityEditView.tsx +712 -145
- package/src/core/EntitySidePanel.tsx +0 -1
- package/src/core/FireCMS.tsx +2 -2
- package/src/core/NavigationRoutes.tsx +4 -4
- package/src/core/SideDialogs.tsx +1 -0
- package/src/core/field_configs.tsx +5 -5
- package/src/core/index.tsx +2 -2
- package/src/form/PropertyFieldBinding.tsx +53 -19
- package/src/form/components/CustomIdField.tsx +4 -2
- package/src/form/components/FieldHelperText.tsx +4 -4
- package/src/form/components/FormikArrayContainer.tsx +4 -1
- package/src/form/components/LabelWithIcon.tsx +27 -19
- package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
- package/src/form/components/StorageItemPreview.tsx +20 -10
- package/src/form/components/StorageUploadProgress.tsx +0 -1
- package/src/form/components/index.tsx +1 -0
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +26 -15
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +28 -25
- package/src/form/field_bindings/BlockFieldBinding.tsx +13 -11
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -14
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +48 -42
- package/src/form/field_bindings/MapFieldBinding.tsx +17 -17
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +150 -0
- package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +25 -20
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +9 -14
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +27 -18
- package/src/form/field_bindings/RepeatFieldBinding.tsx +32 -19
- package/src/form/field_bindings/SelectFieldBinding.tsx +17 -10
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +33 -43
- package/src/form/field_bindings/SwitchFieldBinding.tsx +9 -5
- package/src/form/field_bindings/TextFieldBinding.tsx +26 -23
- package/src/form/index.tsx +4 -9
- package/src/form/useClearRestoreValue.tsx +2 -2
- package/src/form/validation.ts +1 -17
- package/src/hooks/data/delete.ts +2 -1
- package/src/hooks/data/save.ts +5 -2
- package/src/hooks/data/useDataSource.tsx +11 -3
- package/src/hooks/useBuildNavigationController.tsx +10 -3
- package/src/hooks/useProjectLog.tsx +18 -7
- package/src/index.ts +1 -0
- package/src/internal/useBuildDataSource.ts +69 -74
- package/src/internal/useBuildSideDialogsController.tsx +1 -0
- package/src/internal/useBuildSideEntityController.tsx +17 -4
- package/src/internal/useUnsavedChangesDialog.tsx +3 -1
- package/src/preview/PropertyPreview.tsx +7 -4
- package/src/preview/PropertyPreviewProps.tsx +7 -1
- package/src/preview/components/BooleanPreview.tsx +1 -1
- package/src/preview/components/EnumValuesChip.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +24 -34
- package/src/preview/components/ReferencePreview.tsx +2 -12
- package/src/preview/components/StorageThumbnail.tsx +5 -1
- package/src/preview/components/UrlComponentPreview.tsx +44 -11
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -2
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +1 -1
- package/src/preview/property_previews/MapPropertyPreview.tsx +1 -1
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +2 -2
- package/src/preview/property_previews/StringPropertyPreview.tsx +2 -2
- package/src/preview/util.ts +2 -2
- package/src/types/auth.tsx +2 -2
- package/src/types/collections.ts +29 -4
- package/src/types/customization_controller.tsx +0 -1
- package/src/types/datasource.ts +62 -43
- package/src/types/entities.ts +2 -0
- package/src/types/entity_overrides.tsx +2 -2
- package/src/types/fields.tsx +51 -45
- package/src/types/navigation.ts +1 -0
- package/src/types/plugins.tsx +12 -3
- package/src/types/properties.ts +25 -19
- package/src/types/side_dialogs_controller.tsx +13 -0
- package/src/types/storage.ts +82 -0
- package/src/util/entities.ts +5 -4
- package/src/util/icon_list.ts +14 -9
- package/src/util/icons.tsx +8 -2
- package/src/util/index.ts +1 -0
- package/src/util/objects.ts +17 -7
- package/src/util/permissions.ts +1 -0
- package/src/util/plurals.ts +0 -2
- package/src/util/property_utils.tsx +1 -1
- package/src/util/references.ts +3 -0
- package/src/util/resolutions.ts +43 -11
- package/src/util/storage.ts +79 -21
- package/src/util/useStorageUploadController.tsx +33 -7
- package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -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/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
- package/src/components/PropertyIdCopyTooltipContent.tsx +0 -27
- package/src/core/Drawer.tsx +0 -139
- package/src/form/EntityForm.tsx +0 -736
- package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
package/src/util/resolutions.ts
CHANGED
|
@@ -217,6 +217,38 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
217
217
|
: null;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
export function getArrayResolvedProperties<M>({
|
|
221
|
+
propertyKey,
|
|
222
|
+
propertyValue,
|
|
223
|
+
property,
|
|
224
|
+
...props
|
|
225
|
+
}: {
|
|
226
|
+
propertyValue: any,
|
|
227
|
+
propertyKey?: string,
|
|
228
|
+
property: ArrayProperty<any> | ResolvedArrayProperty<any>,
|
|
229
|
+
ignoreMissingFields: boolean,
|
|
230
|
+
values?: Partial<M>;
|
|
231
|
+
previousValues?: Partial<M>;
|
|
232
|
+
path?: string;
|
|
233
|
+
entityId?: string;
|
|
234
|
+
index?: number;
|
|
235
|
+
fromBuilder?: boolean;
|
|
236
|
+
fields?: Record<string, PropertyConfig>
|
|
237
|
+
}) {
|
|
238
|
+
|
|
239
|
+
const of = property.of;
|
|
240
|
+
return Array.isArray(propertyValue)
|
|
241
|
+
? propertyValue.map((v: any, index: number) => {
|
|
242
|
+
return resolveProperty({
|
|
243
|
+
propertyKey: `${propertyKey}.${index}`,
|
|
244
|
+
propertyOrBuilder: of,
|
|
245
|
+
...props,
|
|
246
|
+
index
|
|
247
|
+
});
|
|
248
|
+
}).filter(e => Boolean(e)) as ResolvedProperty[]
|
|
249
|
+
: [];
|
|
250
|
+
}
|
|
251
|
+
|
|
220
252
|
export function resolveArrayProperty<T extends any[], M>({
|
|
221
253
|
propertyKey,
|
|
222
254
|
property,
|
|
@@ -254,17 +286,14 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
254
286
|
} as ResolvedArrayProperty;
|
|
255
287
|
} else {
|
|
256
288
|
const of = property.of;
|
|
257
|
-
const resolvedProperties
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
})).filter(e => Boolean(e)) as ResolvedProperty[]
|
|
265
|
-
: [];
|
|
289
|
+
const resolvedProperties = getArrayResolvedProperties({
|
|
290
|
+
propertyValue,
|
|
291
|
+
propertyKey,
|
|
292
|
+
property,
|
|
293
|
+
ignoreMissingFields,
|
|
294
|
+
...props
|
|
295
|
+
});
|
|
266
296
|
const ofProperty = resolveProperty({
|
|
267
|
-
propertyKey: `${propertyKey}`,
|
|
268
297
|
propertyOrBuilder: of,
|
|
269
298
|
ignoreMissingFields,
|
|
270
299
|
...props
|
|
@@ -295,6 +324,7 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
295
324
|
}).filter(e => Boolean(e)) as ResolvedProperty[]
|
|
296
325
|
: [];
|
|
297
326
|
const properties = resolveProperties<any>({
|
|
327
|
+
propertyKey,
|
|
298
328
|
properties: property.oneOf.properties,
|
|
299
329
|
ignoreMissingFields,
|
|
300
330
|
...props
|
|
@@ -327,10 +357,12 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
327
357
|
* @param value
|
|
328
358
|
*/
|
|
329
359
|
export function resolveProperties<M extends Record<string, any>>({
|
|
360
|
+
propertyKey,
|
|
330
361
|
properties,
|
|
331
362
|
ignoreMissingFields,
|
|
332
363
|
...props
|
|
333
364
|
}: {
|
|
365
|
+
propertyKey?: string,
|
|
334
366
|
properties: PropertiesOrBuilders<M>,
|
|
335
367
|
values?: Partial<M>,
|
|
336
368
|
previousValues?: Partial<M>,
|
|
@@ -344,7 +376,7 @@ export function resolveProperties<M extends Record<string, any>>({
|
|
|
344
376
|
return Object.entries<PropertyOrBuilder>(properties as Record<string, PropertyOrBuilder>)
|
|
345
377
|
.map(([key, property]) => {
|
|
346
378
|
const childResolvedProperty = resolveProperty({
|
|
347
|
-
propertyKey: key,
|
|
379
|
+
propertyKey: propertyKey ? `${propertyKey}.${key}` : undefined,
|
|
348
380
|
propertyOrBuilder: property,
|
|
349
381
|
ignoreMissingFields,
|
|
350
382
|
...props
|
package/src/util/storage.ts
CHANGED
|
@@ -1,22 +1,39 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ArrayProperty,
|
|
2
3
|
EntityValues,
|
|
4
|
+
PropertyOrBuilder,
|
|
3
5
|
ResolvedArrayProperty,
|
|
4
6
|
ResolvedStringProperty,
|
|
5
7
|
StorageConfig,
|
|
8
|
+
StringProperty,
|
|
6
9
|
UploadedFileContext
|
|
7
10
|
} from "../types";
|
|
8
11
|
import { randomString } from "./strings";
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
input: string | ((context: UploadedFileContext) => Promise<string> | string)
|
|
12
|
-
storage: StorageConfig
|
|
13
|
-
values: EntityValues<M
|
|
14
|
-
entityId: string
|
|
15
|
-
path
|
|
13
|
+
interface ResolveFilenameStringParams<M extends object> {
|
|
14
|
+
input: string | ((context: UploadedFileContext) => (Promise<string> | string));
|
|
15
|
+
storage: StorageConfig;
|
|
16
|
+
values: EntityValues<M>;
|
|
17
|
+
entityId: string;
|
|
18
|
+
path?: string;
|
|
16
19
|
property: ResolvedStringProperty | ResolvedArrayProperty<string[]>,
|
|
17
|
-
file: File
|
|
18
|
-
propertyKey: string
|
|
20
|
+
file: File;
|
|
21
|
+
propertyKey: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function resolveStorageFilenameString<M extends object>(
|
|
25
|
+
{
|
|
26
|
+
input,
|
|
27
|
+
storage,
|
|
28
|
+
values,
|
|
29
|
+
entityId,
|
|
30
|
+
path,
|
|
31
|
+
property,
|
|
32
|
+
file,
|
|
33
|
+
propertyKey
|
|
34
|
+
}: ResolveFilenameStringParams<M>): Promise<string> {
|
|
19
35
|
let result;
|
|
36
|
+
|
|
20
37
|
if (typeof input === "function") {
|
|
21
38
|
result = await input({
|
|
22
39
|
path,
|
|
@@ -30,7 +47,13 @@ export async function resolveFilenameString<M extends object>(
|
|
|
30
47
|
if (!result)
|
|
31
48
|
console.warn("Storage callback returned empty result. Using default name value")
|
|
32
49
|
} else {
|
|
33
|
-
result = replacePlaceholders(
|
|
50
|
+
result = replacePlaceholders({
|
|
51
|
+
file,
|
|
52
|
+
input,
|
|
53
|
+
entityId,
|
|
54
|
+
propertyKey,
|
|
55
|
+
path
|
|
56
|
+
});
|
|
34
57
|
}
|
|
35
58
|
|
|
36
59
|
if (!result)
|
|
@@ -39,15 +62,28 @@ export async function resolveFilenameString<M extends object>(
|
|
|
39
62
|
return result;
|
|
40
63
|
}
|
|
41
64
|
|
|
65
|
+
interface ResolveStoragePathStringParams<M extends object> {
|
|
66
|
+
input: string | ((context: UploadedFileContext) => string);
|
|
67
|
+
storage: StorageConfig;
|
|
68
|
+
values: EntityValues<M>;
|
|
69
|
+
entityId: string;
|
|
70
|
+
path?: string;
|
|
71
|
+
property: ResolvedStringProperty | ResolvedArrayProperty<string[]>;
|
|
72
|
+
file: File;
|
|
73
|
+
propertyKey: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
42
76
|
export function resolveStoragePathString<M extends object>(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
{
|
|
78
|
+
input,
|
|
79
|
+
storage,
|
|
80
|
+
values,
|
|
81
|
+
entityId,
|
|
82
|
+
path,
|
|
83
|
+
property,
|
|
84
|
+
file,
|
|
85
|
+
propertyKey
|
|
86
|
+
}: ResolveStoragePathStringParams<M>): string {
|
|
51
87
|
let result;
|
|
52
88
|
if (typeof input === "function") {
|
|
53
89
|
result = input({
|
|
@@ -62,7 +98,13 @@ export function resolveStoragePathString<M extends object>(
|
|
|
62
98
|
if (!result)
|
|
63
99
|
console.warn("Storage callback returned empty result. Using default name value")
|
|
64
100
|
} else {
|
|
65
|
-
result = replacePlaceholders(
|
|
101
|
+
result = replacePlaceholders({
|
|
102
|
+
file,
|
|
103
|
+
input,
|
|
104
|
+
entityId,
|
|
105
|
+
propertyKey,
|
|
106
|
+
path
|
|
107
|
+
});
|
|
66
108
|
}
|
|
67
109
|
|
|
68
110
|
if (!result)
|
|
@@ -71,14 +113,30 @@ export function resolveStoragePathString<M extends object>(
|
|
|
71
113
|
return result;
|
|
72
114
|
}
|
|
73
115
|
|
|
74
|
-
|
|
116
|
+
interface Placeholders {
|
|
117
|
+
file: File;
|
|
118
|
+
input: string;
|
|
119
|
+
entityId: string;
|
|
120
|
+
propertyKey: string;
|
|
121
|
+
path?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function replacePlaceholders({
|
|
125
|
+
file,
|
|
126
|
+
input,
|
|
127
|
+
entityId,
|
|
128
|
+
propertyKey,
|
|
129
|
+
path
|
|
130
|
+
}: Placeholders) {
|
|
75
131
|
const ext = file.name.split(".").pop();
|
|
76
132
|
let result = input.replace("{entityId}", entityId)
|
|
77
133
|
.replace("{propertyKey}", propertyKey)
|
|
78
134
|
.replace("{rand}", randomString())
|
|
79
135
|
.replace("{file}", file.name)
|
|
80
|
-
.replace("{file.type}", file.type)
|
|
81
|
-
|
|
136
|
+
.replace("{file.type}", file.type);
|
|
137
|
+
if (path) {
|
|
138
|
+
result = result.replace("{path}", path);
|
|
139
|
+
}
|
|
82
140
|
if (ext) {
|
|
83
141
|
result = result.replace("{file.ext}", ext);
|
|
84
142
|
const name = file.name.replace(`.${ext}`, "");
|
|
@@ -2,9 +2,11 @@ import Resizer from "react-image-file-resizer";
|
|
|
2
2
|
import equal from "react-fast-compare";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
+
ArrayProperty,
|
|
5
6
|
EntityValues,
|
|
6
7
|
ImageCompression,
|
|
7
8
|
Property,
|
|
9
|
+
PropertyOrBuilder,
|
|
8
10
|
ResolvedArrayProperty,
|
|
9
11
|
ResolvedStringProperty,
|
|
10
12
|
StorageConfig,
|
|
@@ -14,7 +16,8 @@ import {
|
|
|
14
16
|
import { useCallback, useEffect, useState } from "react";
|
|
15
17
|
import { PreviewSize } from "../preview";
|
|
16
18
|
import { randomString } from "./strings";
|
|
17
|
-
import {
|
|
19
|
+
import { resolveStorageFilenameString, resolveStoragePathString } from "./storage";
|
|
20
|
+
import { resolveProperty } from "./resolutions";
|
|
18
21
|
|
|
19
22
|
/**
|
|
20
23
|
* Internal representation of an item in the storage
|
|
@@ -46,9 +49,9 @@ export function useStorageUploadController<M extends object>({
|
|
|
46
49
|
entityId: string,
|
|
47
50
|
entityValues: EntityValues<M>,
|
|
48
51
|
value: string | string[] | null;
|
|
49
|
-
path
|
|
52
|
+
path?: string,
|
|
50
53
|
propertyKey: string,
|
|
51
|
-
property: ResolvedStringProperty | ResolvedArrayProperty<string[]>,
|
|
54
|
+
property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>,
|
|
52
55
|
storageSource: StorageSource,
|
|
53
56
|
disabled: boolean,
|
|
54
57
|
onChange: (value: string | string[] | null) => void
|
|
@@ -93,20 +96,43 @@ export function useStorageUploadController<M extends object>({
|
|
|
93
96
|
}
|
|
94
97
|
}, [internalInitialValue, value, initialValue]);
|
|
95
98
|
|
|
99
|
+
const resolvedProperty = resolveProperty({
|
|
100
|
+
propertyOrBuilder: property as PropertyOrBuilder,
|
|
101
|
+
values: entityValues
|
|
102
|
+
}) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
|
|
103
|
+
|
|
96
104
|
const fileNameBuilder = useCallback(async (file: File) => {
|
|
97
105
|
if (storage.fileName) {
|
|
98
|
-
const fileName = await
|
|
106
|
+
const fileName = await resolveStorageFilenameString({
|
|
107
|
+
input: storage.fileName,
|
|
108
|
+
storage,
|
|
109
|
+
values: entityValues,
|
|
110
|
+
entityId,
|
|
111
|
+
path,
|
|
112
|
+
property: resolvedProperty,
|
|
113
|
+
file,
|
|
114
|
+
propertyKey
|
|
115
|
+
});
|
|
99
116
|
if (!fileName || fileName.length === 0) {
|
|
100
117
|
throw Error("You need to return a valid filename");
|
|
101
118
|
}
|
|
102
119
|
return fileName;
|
|
103
120
|
}
|
|
104
121
|
return randomString() + "_" + file.name;
|
|
105
|
-
}, [entityId, entityValues, path,
|
|
122
|
+
}, [entityId, entityValues, path, resolvedProperty, propertyKey, storage]);
|
|
106
123
|
|
|
107
124
|
const storagePathBuilder = useCallback((file: File) => {
|
|
108
|
-
return resolveStoragePathString(
|
|
109
|
-
|
|
125
|
+
return resolveStoragePathString({
|
|
126
|
+
input: storage.storagePath,
|
|
127
|
+
storage,
|
|
128
|
+
values: entityValues,
|
|
129
|
+
entityId,
|
|
130
|
+
path,
|
|
131
|
+
property: resolvedProperty,
|
|
132
|
+
file,
|
|
133
|
+
propertyKey
|
|
134
|
+
}) ?? "/";
|
|
135
|
+
}, [entityId, entityValues, path, resolvedProperty, propertyKey, storage]);
|
|
110
136
|
|
|
111
137
|
const onFileUploadComplete = useCallback(async (uploadedPath: string,
|
|
112
138
|
entry: StorageFieldItem,
|
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 {};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { FieldProps } from "../../types";
|
|
2
|
-
/**
|
|
3
|
-
* Render a markdown field that allows edition and seeing the preview.
|
|
4
|
-
*
|
|
5
|
-
* This is one of the internal components that get mapped natively inside forms
|
|
6
|
-
* and tables to the specified properties.
|
|
7
|
-
* @group Form fields
|
|
8
|
-
*/
|
|
9
|
-
export declare function MarkdownFieldBinding({ propertyKey, value, setValue, error, showError, disabled, autoFocus, touched, property, tableMode, includeDescription, context }: FieldProps<string>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { ContentCopyIcon, IconButton, Typography } from "@firecms/ui";
|
|
2
|
-
import { useCallback, useState } from "react";
|
|
3
|
-
|
|
4
|
-
export function PropertyIdCopyTooltipContent({ propertyId }: { propertyId: string }) {
|
|
5
|
-
|
|
6
|
-
const [copied, setCopied] = useState(false);
|
|
7
|
-
|
|
8
|
-
return (
|
|
9
|
-
<div className={"flex flex-row gap-2 items-center justify-center text-white"}>
|
|
10
|
-
<div>
|
|
11
|
-
<Typography variant={"caption"} className={"min-w-20 text-slate-400"}
|
|
12
|
-
color={"disabled"}>{copied ? "Copied" : "Property ID"}</Typography>
|
|
13
|
-
<Typography variant={"caption"} className={"text-white"}><code>{propertyId}</code></Typography>
|
|
14
|
-
</div>
|
|
15
|
-
<IconButton size={"small"}>
|
|
16
|
-
<ContentCopyIcon size={"smallest"}
|
|
17
|
-
className={"text-white"}
|
|
18
|
-
onClick={useCallback(() => {
|
|
19
|
-
navigator.clipboard.writeText(propertyId);
|
|
20
|
-
setCopied(true);
|
|
21
|
-
setTimeout(() => setCopied(false), 2000);
|
|
22
|
-
}, [propertyId])}
|
|
23
|
-
/>
|
|
24
|
-
</IconButton>
|
|
25
|
-
</div>
|
|
26
|
-
);
|
|
27
|
-
}
|
package/src/core/Drawer.tsx
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import React, { useCallback } from "react";
|
|
2
|
-
|
|
3
|
-
import { useLargeLayout, useNavigationController } from "../hooks";
|
|
4
|
-
|
|
5
|
-
import { useNavigate } from "react-router-dom";
|
|
6
|
-
import { CMSAnalyticsEvent, TopNavigationEntry, TopNavigationResult } from "../types";
|
|
7
|
-
import { IconForView } from "../util";
|
|
8
|
-
import { cls, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip, Typography } from "@firecms/ui";
|
|
9
|
-
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
10
|
-
import { useDrawer } from "./Scaffold";
|
|
11
|
-
import { DrawerNavigationItem } from "./DrawerNavigationItem";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Props used in case you need to override the default drawer
|
|
15
|
-
* @group Core
|
|
16
|
-
*/
|
|
17
|
-
export type DrawerProps = {
|
|
18
|
-
hovered: boolean,
|
|
19
|
-
drawerOpen: boolean,
|
|
20
|
-
openDrawer: () => void,
|
|
21
|
-
closeDrawer: () => void,
|
|
22
|
-
autoOpenDrawer?: boolean
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Default drawer used in the CMS
|
|
27
|
-
* @group Core
|
|
28
|
-
*/
|
|
29
|
-
export function Drawer() {
|
|
30
|
-
|
|
31
|
-
const {
|
|
32
|
-
hovered,
|
|
33
|
-
drawerOpen,
|
|
34
|
-
closeDrawer,
|
|
35
|
-
} = useDrawer();
|
|
36
|
-
|
|
37
|
-
const analyticsController = useAnalyticsController();
|
|
38
|
-
const navigation = useNavigationController();
|
|
39
|
-
|
|
40
|
-
const tooltipsOpen = hovered && !drawerOpen;
|
|
41
|
-
const largeLayout = useLargeLayout();
|
|
42
|
-
const navigate = useNavigate();
|
|
43
|
-
|
|
44
|
-
const [adminMenuOpen, setAdminMenuOpen] = React.useState(false);
|
|
45
|
-
|
|
46
|
-
if (!navigation.topLevelNavigation)
|
|
47
|
-
throw Error("Navigation not ready in Drawer");
|
|
48
|
-
|
|
49
|
-
const {
|
|
50
|
-
navigationEntries,
|
|
51
|
-
groups
|
|
52
|
-
}: TopNavigationResult = navigation.topLevelNavigation;
|
|
53
|
-
|
|
54
|
-
const adminViews = navigationEntries.filter(e => e.type === "admin") ?? [];
|
|
55
|
-
const groupsWithoutAdmin = groups.filter(g => g !== "Admin");
|
|
56
|
-
|
|
57
|
-
const buildGroupHeader = useCallback((group?: string) => {
|
|
58
|
-
if (!drawerOpen) return <div className="h-12 w-full"/>;
|
|
59
|
-
return <div
|
|
60
|
-
className="pt-8 pl-6 pr-8 pb-2 flex flex-row items-center">
|
|
61
|
-
<Typography variant={"caption"}
|
|
62
|
-
color={"secondary"}
|
|
63
|
-
className="font-medium flex-grow line-clamp-1">
|
|
64
|
-
{group ? group.toUpperCase() : "Views".toUpperCase()}
|
|
65
|
-
</Typography>
|
|
66
|
-
|
|
67
|
-
</div>;
|
|
68
|
-
}, [drawerOpen]);
|
|
69
|
-
|
|
70
|
-
const onClick = (view: TopNavigationEntry) => {
|
|
71
|
-
const eventName: CMSAnalyticsEvent = view.type === "collection"
|
|
72
|
-
? "drawer_navigate_to_collection"
|
|
73
|
-
: (view.type === "view" ? "drawer_navigate_to_view" : "unmapped_event");
|
|
74
|
-
analyticsController.onAnalyticsEvent?.(eventName, { url: view.url });
|
|
75
|
-
if (!largeLayout)
|
|
76
|
-
closeDrawer();
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
return (
|
|
80
|
-
<>
|
|
81
|
-
|
|
82
|
-
<div className={"flex-grow overflow-scroll no-scrollbar"}>
|
|
83
|
-
|
|
84
|
-
{groupsWithoutAdmin.map((group) => (
|
|
85
|
-
<React.Fragment
|
|
86
|
-
key={`drawer_group_${group}`}>
|
|
87
|
-
{buildGroupHeader(group)}
|
|
88
|
-
{Object.values(navigationEntries)
|
|
89
|
-
.filter(e => e.group === group)
|
|
90
|
-
.map((view, index) =>
|
|
91
|
-
<DrawerNavigationItem
|
|
92
|
-
key={`navigation_${index}`}
|
|
93
|
-
icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
|
|
94
|
-
tooltipsOpen={tooltipsOpen}
|
|
95
|
-
drawerOpen={drawerOpen}
|
|
96
|
-
onClick={() => onClick(view)}
|
|
97
|
-
url={view.url}
|
|
98
|
-
name={view.name}/>)}
|
|
99
|
-
</React.Fragment>
|
|
100
|
-
))}
|
|
101
|
-
|
|
102
|
-
</div>
|
|
103
|
-
|
|
104
|
-
{adminViews.length > 0 && <Menu
|
|
105
|
-
open={adminMenuOpen}
|
|
106
|
-
onOpenChange={setAdminMenuOpen}
|
|
107
|
-
trigger={
|
|
108
|
-
<IconButton
|
|
109
|
-
shape={"square"}
|
|
110
|
-
className={"m-4 text-gray-900 dark:text-white w-fit"}>
|
|
111
|
-
<Tooltip title={"Admin"}
|
|
112
|
-
open={tooltipsOpen}
|
|
113
|
-
side={"right"} sideOffset={28}>
|
|
114
|
-
<MoreVertIcon/>
|
|
115
|
-
</Tooltip>
|
|
116
|
-
{drawerOpen && <div
|
|
117
|
-
className={cls(
|
|
118
|
-
drawerOpen ? "opacity-100" : "opacity-0 hidden",
|
|
119
|
-
"mx-4 font-inherit text-inherit"
|
|
120
|
-
)}>
|
|
121
|
-
ADMIN
|
|
122
|
-
</div>}
|
|
123
|
-
</IconButton>}
|
|
124
|
-
>
|
|
125
|
-
{adminViews.map((entry, index) =>
|
|
126
|
-
<MenuItem
|
|
127
|
-
onClick={(event) => {
|
|
128
|
-
event.preventDefault();
|
|
129
|
-
navigate(entry.path);
|
|
130
|
-
}}
|
|
131
|
-
key={`navigation_${index}`}>
|
|
132
|
-
{<IconForView collectionOrView={entry.view}/>}
|
|
133
|
-
{entry.name}
|
|
134
|
-
</MenuItem>)}
|
|
135
|
-
|
|
136
|
-
</Menu>}
|
|
137
|
-
</>
|
|
138
|
-
);
|
|
139
|
-
}
|