@firecms/core 3.0.0-canary.7 → 3.0.0-canary.71
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/README.md +2 -2
- 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/ClearFilterSortButton.d.ts +5 -0
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +11 -11
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
- package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
- package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +2 -0
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -3
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
- package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
- package/dist/components/EntityPreview.d.ts +26 -7
- package/dist/components/EntityView.d.ts +11 -0
- package/dist/components/FieldCaption.d.ts +5 -0
- package/dist/components/HomePage/NavigationCard.d.ts +8 -0
- package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
- package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
- package/dist/components/HomePage/index.d.ts +3 -1
- package/dist/components/ReferenceWidget.d.ts +3 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +6 -7
- package/dist/components/VirtualTable/types.d.ts +3 -3
- package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
- package/dist/components/common/index.d.ts +1 -0
- package/dist/components/common/table_height.d.ts +5 -0
- package/dist/components/common/types.d.ts +4 -6
- package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
- package/dist/components/index.d.ts +6 -3
- package/dist/contexts/AuthControllerContext.d.ts +1 -1
- package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +5 -8
- package/dist/core/DefaultDrawer.d.ts +19 -0
- package/dist/core/DrawerNavigationItem.d.ts +9 -0
- package/dist/core/EntityEditView.d.ts +36 -0
- package/dist/core/NavigationRoutes.d.ts +2 -2
- package/dist/core/index.d.ts +3 -4
- package/dist/form/PropertiesForm.d.ts +8 -0
- package/dist/form/components/ErrorFocus.d.ts +1 -1
- package/dist/form/components/FieldHelperText.d.ts +3 -3
- package/dist/form/components/StorageItemPreview.d.ts +2 -3
- package/dist/form/components/StorageUploadProgress.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/StorageUploadFieldBinding.d.ts +3 -4
- package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
- package/dist/form/index.d.ts +0 -2
- package/dist/form/validation.d.ts +1 -1
- package/dist/hooks/data/delete.d.ts +2 -2
- package/dist/hooks/data/save.d.ts +2 -3
- package/dist/hooks/data/useDataSource.d.ts +2 -2
- package/dist/hooks/data/useEntityFetch.d.ts +3 -3
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useBuildNavigationController.d.ts +6 -4
- package/dist/hooks/useProjectLog.d.ts +6 -2
- package/dist/hooks/useStorageSource.d.ts +2 -2
- package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +10507 -9993
- 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/internal/useBuildDataSource.d.ts +1 -16
- package/dist/preview/PropertyPreview.d.ts +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +1 -4
- package/dist/preview/components/BooleanPreview.d.ts +5 -1
- package/dist/preview/components/EnumValuesChip.d.ts +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +3 -8
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/auth.d.ts +37 -1
- package/dist/types/collections.d.ts +44 -6
- package/dist/types/datasource.d.ts +21 -14
- package/dist/types/entities.d.ts +5 -1
- package/dist/types/entity_actions.d.ts +14 -0
- package/dist/types/entity_callbacks.d.ts +2 -2
- package/dist/types/entity_overrides.d.ts +6 -0
- package/dist/types/fields.d.ts +31 -30
- package/dist/types/index.d.ts +2 -1
- package/dist/types/navigation.d.ts +15 -14
- package/dist/types/permissions.d.ts +5 -1
- package/dist/types/plugins.d.ts +22 -22
- package/dist/types/properties.d.ts +13 -5
- package/dist/types/property_config.d.ts +2 -2
- package/dist/types/roles.d.ts +31 -0
- package/dist/types/storage.d.ts +11 -3
- package/dist/types/user.d.ts +5 -0
- package/dist/util/collections.d.ts +9 -1
- package/dist/util/entities.d.ts +1 -1
- package/dist/util/icon_synonyms.d.ts +1 -97
- package/dist/util/icons.d.ts +8 -2
- package/dist/util/navigation_utils.d.ts +2 -2
- package/dist/util/objects.d.ts +1 -1
- package/dist/util/permissions.d.ts +4 -4
- package/dist/util/references.d.ts +4 -2
- package/dist/util/resolutions.d.ts +14 -14
- package/dist/util/storage.d.ts +23 -2
- package/dist/util/useStorageUploadController.d.ts +1 -1
- package/dist/util/useTraceUpdate.d.ts +1 -0
- package/package.json +139 -119
- package/src/app/AppBar.tsx +18 -0
- package/src/app/Drawer.tsx +25 -0
- package/src/app/Scaffold.tsx +249 -0
- package/src/app/index.ts +4 -0
- package/src/app/useApp.tsx +32 -0
- package/src/components/ClearFilterSortButton.tsx +41 -0
- package/src/components/DeleteEntityDialog.tsx +4 -4
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +4 -4
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +276 -279
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +48 -45
- package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +18 -17
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -5
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +29 -34
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +16 -12
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +4 -5
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +75 -74
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
- package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
- package/src/components/EntityPreview.tsx +209 -70
- package/src/components/EntityView.tsx +84 -0
- package/src/components/FieldCaption.tsx +14 -0
- package/src/components/HomePage/DefaultHomePage.tsx +15 -11
- package/src/components/HomePage/NavigationCard.tsx +69 -0
- package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
- package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
- package/src/components/HomePage/index.tsx +3 -1
- package/src/components/PropertyIdCopyTooltipContent.tsx +2 -3
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
- package/src/components/ReferenceWidget.tsx +22 -12
- package/src/components/SearchIconsView.tsx +5 -5
- package/src/components/SelectableTable/SelectableTable.tsx +5 -3
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -24
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
- package/src/components/VirtualTable/VirtualTable.tsx +38 -29
- package/src/components/VirtualTable/VirtualTableHeader.tsx +4 -4
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
- package/src/components/VirtualTable/VirtualTableProps.tsx +7 -7
- package/src/components/VirtualTable/VirtualTableRow.tsx +4 -5
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
- package/src/components/VirtualTable/types.tsx +2 -3
- package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +11 -7
- package/src/components/common/index.ts +1 -0
- package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
- package/src/components/common/types.tsx +4 -6
- package/src/components/common/useColumnsIds.tsx +10 -2
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
- package/src/components/common/useTableSearchHelper.ts +39 -9
- package/src/components/index.tsx +6 -3
- package/src/contexts/AuthControllerContext.tsx +1 -1
- package/src/{components/FireCMSAppBar.tsx → core/DefaultAppBar.tsx} +51 -34
- package/src/core/DefaultDrawer.tsx +177 -0
- package/src/core/DrawerNavigationItem.tsx +62 -0
- package/src/core/EntityEditView.tsx +1100 -0
- package/src/core/EntitySidePanel.tsx +3 -4
- package/src/core/FireCMS.tsx +54 -43
- package/src/core/NavigationRoutes.tsx +14 -7
- package/src/core/field_configs.tsx +2 -3
- package/src/core/index.tsx +3 -4
- package/src/form/PropertiesForm.tsx +81 -0
- package/src/form/PropertyFieldBinding.tsx +29 -7
- package/src/form/components/FieldHelperText.tsx +3 -3
- package/src/form/components/StorageItemPreview.tsx +5 -7
- package/src/form/components/StorageUploadProgress.tsx +9 -8
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +10 -12
- package/src/form/field_bindings/BlockFieldBinding.tsx +2 -2
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +19 -19
- package/src/form/field_bindings/MapFieldBinding.tsx +25 -17
- package/src/form/field_bindings/MarkdownFieldBinding.tsx +2 -2
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -9
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +16 -13
- package/src/form/field_bindings/SelectFieldBinding.tsx +3 -3
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -35
- package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
- package/src/form/index.tsx +4 -4
- package/src/form/validation.ts +4 -21
- package/src/hooks/data/delete.ts +3 -3
- package/src/hooks/data/save.ts +4 -2
- package/src/hooks/data/useCollectionFetch.tsx +1 -1
- package/src/hooks/data/useDataSource.tsx +8 -3
- package/src/hooks/data/useEntityFetch.tsx +4 -4
- package/src/hooks/index.tsx +3 -0
- package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
- package/src/hooks/useBuildModeController.tsx +11 -5
- package/src/hooks/useBuildNavigationController.tsx +200 -83
- package/src/hooks/useProjectLog.tsx +17 -7
- package/src/hooks/useReferenceDialog.tsx +2 -2
- package/src/hooks/useResolvedNavigationFrom.tsx +1 -1
- package/src/hooks/useStorageSource.tsx +7 -2
- package/src/hooks/useValidateAuthenticator.tsx +115 -0
- package/src/index.ts +1 -0
- package/src/internal/useBuildDataSource.ts +54 -47
- package/src/internal/useBuildSideEntityController.tsx +88 -21
- package/src/preview/PropertyPreview.tsx +5 -15
- package/src/preview/PropertyPreviewProps.tsx +1 -11
- package/src/preview/components/BooleanPreview.tsx +19 -4
- package/src/preview/components/EnumValuesChip.tsx +2 -2
- package/src/preview/components/ReferencePreview.tsx +72 -165
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +2 -1
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -3
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +2 -3
- package/src/preview/property_previews/MapPropertyPreview.tsx +5 -5
- package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
- package/src/types/analytics.ts +1 -0
- package/src/types/auth.tsx +50 -1
- package/src/types/collections.ts +51 -6
- package/src/types/customization_controller.tsx +0 -1
- package/src/types/datasource.ts +24 -17
- package/src/types/entities.ts +9 -1
- package/src/types/entity_actions.tsx +17 -0
- package/src/types/entity_callbacks.ts +2 -2
- package/src/types/entity_overrides.tsx +7 -0
- package/src/types/fields.tsx +33 -33
- package/src/types/firecms.tsx +0 -1
- package/src/types/index.ts +2 -1
- package/src/types/navigation.ts +17 -17
- package/src/types/permissions.ts +6 -1
- package/src/types/plugins.tsx +28 -30
- package/src/types/properties.ts +19 -7
- package/src/types/property_config.tsx +2 -2
- package/src/types/roles.ts +41 -0
- package/src/types/side_entity_controller.tsx +1 -0
- package/src/types/storage.ts +12 -3
- package/src/types/user.ts +7 -0
- package/src/util/collections.ts +22 -0
- package/src/util/entities.ts +2 -1
- package/src/util/enums.ts +1 -1
- package/src/util/icon_list.ts +2 -2
- package/src/util/icon_synonyms.ts +3 -99
- package/src/util/icons.tsx +11 -3
- package/src/util/navigation_utils.ts +6 -6
- package/src/util/objects.ts +8 -21
- package/src/util/permissions.ts +12 -8
- package/src/util/references.ts +36 -5
- package/src/util/resolutions.ts +32 -31
- package/src/util/storage.ts +75 -21
- package/src/util/strings.ts +2 -2
- package/src/util/useStorageUploadController.tsx +21 -3
- package/src/util/useTraceUpdate.tsx +2 -1
- package/dist/components/VirtualTable/common.d.ts +0 -2
- package/dist/core/Drawer.d.ts +0 -23
- package/dist/core/EntityView.d.ts +0 -22
- package/dist/core/Scaffold.d.ts +0 -55
- package/dist/core/SideEntityView.d.ts +0 -7
- package/dist/form/EntityForm.d.ts +0 -77
- package/dist/internal/useBuildCustomizationController.d.ts +0 -2
- package/dist/internal/useLocaleConfig.d.ts +0 -1
- package/dist/types/appcheck.d.ts +0 -26
- package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
- package/src/core/Drawer.tsx +0 -164
- package/src/core/EntityView.tsx +0 -578
- package/src/core/Scaffold.tsx +0 -281
- package/src/core/SideEntityView.tsx +0 -38
- package/src/form/EntityForm.tsx +0 -720
- package/src/internal/useBuildCustomizationController.tsx +0 -5
- package/src/internal/useLocaleConfig.tsx +0 -18
- package/src/types/appcheck.ts +0 -29
package/src/util/icons.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { CMSView, EntityCollection } from "../types";
|
|
3
2
|
import { hashString } from "./hash";
|
|
4
3
|
import { coolIconKeys, Icon, iconKeys } from "@firecms/ui";
|
|
5
4
|
import { slugify } from "./strings";
|
|
@@ -14,8 +13,17 @@ export function getIcon(iconKey?: string, className?: string): React.ReactElemen
|
|
|
14
13
|
return iconKey in iconKeysMap ? <Icon iconKey={iconKey} size={"medium"} className={className}/> : undefined;
|
|
15
14
|
}
|
|
16
15
|
|
|
16
|
+
export type IconViewProps = {
|
|
17
|
+
path: string;
|
|
18
|
+
name: string;
|
|
19
|
+
singularName?: string;
|
|
20
|
+
group?: string;
|
|
21
|
+
icon?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
export const IconForView = React.memo(
|
|
18
|
-
function IconForView({ collectionOrView, className }: { collectionOrView
|
|
25
|
+
function IconForView({ collectionOrView, className }: { collectionOrView?: IconViewProps, className?: string }): React.ReactElement {
|
|
26
|
+
if (!collectionOrView) return <></>;
|
|
19
27
|
const icon = getIcon(collectionOrView.icon, className);
|
|
20
28
|
if (collectionOrView?.icon && icon)
|
|
21
29
|
return icon;
|
|
@@ -39,7 +47,7 @@ export const IconForView = React.memo(
|
|
|
39
47
|
|
|
40
48
|
return <Icon iconKey={key} size={"medium"} className={className}/>;
|
|
41
49
|
}, (prevProps, nextProps) => {
|
|
42
|
-
return equal(prevProps.collectionOrView
|
|
50
|
+
return equal(prevProps.collectionOrView?.icon, nextProps.collectionOrView?.icon);
|
|
43
51
|
});
|
|
44
52
|
|
|
45
53
|
const iconKeysMap: Record<string, string> = iconKeys.reduce((acc: Record<string, string>, key) => {
|
|
@@ -60,14 +60,14 @@ export function resolveCollectionPathIds(path: string, allCollections: EntityCol
|
|
|
60
60
|
/**
|
|
61
61
|
* Find the corresponding view at any depth for a given path.
|
|
62
62
|
* Note that path or segments of the paths can be collection aliases.
|
|
63
|
-
* @param
|
|
63
|
+
* @param pathOrId
|
|
64
64
|
* @param collections
|
|
65
65
|
*/
|
|
66
|
-
export function getCollectionByPathOrId(
|
|
66
|
+
export function getCollectionByPathOrId(pathOrId: string, collections: EntityCollection[]): EntityCollection | undefined {
|
|
67
67
|
|
|
68
|
-
const subpaths = removeInitialAndTrailingSlashes(
|
|
68
|
+
const subpaths = removeInitialAndTrailingSlashes(pathOrId).split("/");
|
|
69
69
|
if (subpaths.length % 2 === 0) {
|
|
70
|
-
throw Error(`
|
|
70
|
+
throw Error(`getCollectionByPathOrId: Collection paths must have an odd number of segments: ${pathOrId}`);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
const subpathCombinations = getCollectionPathsCombinations(subpaths);
|
|
@@ -80,10 +80,10 @@ export function getCollectionByPathOrId(pathOrAlias: string, collections: Entity
|
|
|
80
80
|
|
|
81
81
|
if (navigationEntry) {
|
|
82
82
|
|
|
83
|
-
if (subpathCombination ===
|
|
83
|
+
if (subpathCombination === pathOrId) {
|
|
84
84
|
result = navigationEntry;
|
|
85
85
|
} else if (navigationEntry.subcollections) {
|
|
86
|
-
const newPath =
|
|
86
|
+
const newPath = pathOrId.replace(subpathCombination, "").split("/").slice(2).join("/");
|
|
87
87
|
if (newPath.length > 0)
|
|
88
88
|
result = getCollectionByPathOrId(newPath, navigationEntry.subcollections);
|
|
89
89
|
}
|
package/src/util/objects.ts
CHANGED
|
@@ -12,38 +12,25 @@ export function isObject(item: any) {
|
|
|
12
12
|
return item && typeof item === "object" && !Array.isArray(item);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function mergeDeep<T extends
|
|
15
|
+
export function mergeDeep<T extends Record<any, any>, U extends Record<any, any>>(target: T, source: U): T & U {
|
|
16
16
|
const targetIsObject = isObject(target);
|
|
17
|
-
const output
|
|
17
|
+
const output = targetIsObject ? { ...target } : target;
|
|
18
18
|
if (targetIsObject && isObject(source)) {
|
|
19
19
|
Object.keys(source).forEach(key => {
|
|
20
|
-
|
|
20
|
+
const sourceElement = source[key];
|
|
21
|
+
if (isObject(sourceElement)) {
|
|
21
22
|
if (!(key in target))
|
|
22
|
-
Object.assign(output, { [key]:
|
|
23
|
+
Object.assign(output, { [key]: sourceElement });
|
|
23
24
|
else
|
|
24
|
-
(output as any)[key] = mergeDeep((target as any)[key],
|
|
25
|
+
(output as any)[key] = mergeDeep((target as any)[key], sourceElement);
|
|
25
26
|
} else {
|
|
26
|
-
Object.assign(output, { [key]:
|
|
27
|
+
Object.assign(output, { [key]: sourceElement });
|
|
27
28
|
}
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
|
-
return output;
|
|
31
|
+
return output as T;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
// export function getValueInPath(o: object | undefined, path: string): any {
|
|
34
|
-
// if (!o) return undefined;
|
|
35
|
-
// if (typeof o === "object") {
|
|
36
|
-
// if (path in o) {
|
|
37
|
-
// return (o as any)[path];
|
|
38
|
-
// }
|
|
39
|
-
// if (path.includes(".")) {
|
|
40
|
-
// const pathSegments = path.split(".");
|
|
41
|
-
// return getValueInPath((o as any)[pathSegments[0]], pathSegments.slice(1).join("."))
|
|
42
|
-
// }
|
|
43
|
-
// }
|
|
44
|
-
// return undefined;
|
|
45
|
-
// }
|
|
46
|
-
|
|
47
34
|
export function getValueInPath(o: object | undefined, path: string): any {
|
|
48
35
|
if (!o) return undefined;
|
|
49
36
|
if (typeof o === "object") {
|
package/src/util/permissions.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AuthController, Entity, EntityCollection, Permissions, User } from "../types";
|
|
2
|
+
import { fullPathToCollectionSegments } from "./paths";
|
|
2
3
|
|
|
3
4
|
const DEFAULT_PERMISSIONS = {
|
|
4
5
|
read: true,
|
|
@@ -10,8 +11,8 @@ const DEFAULT_PERMISSIONS = {
|
|
|
10
11
|
export function resolvePermissions<M extends Record<string, any>, UserType extends User>
|
|
11
12
|
(collection: EntityCollection<M>,
|
|
12
13
|
authController: AuthController<UserType>,
|
|
13
|
-
|
|
14
|
-
entity: Entity<M> | null): Permissions {
|
|
14
|
+
path: string,
|
|
15
|
+
entity: Entity<M> | null): Permissions | undefined {
|
|
15
16
|
|
|
16
17
|
const permission = collection.permissions;
|
|
17
18
|
if (permission === undefined) {
|
|
@@ -19,8 +20,10 @@ export function resolvePermissions<M extends Record<string, any>, UserType exten
|
|
|
19
20
|
} else if (typeof permission === "object") {
|
|
20
21
|
return permission as Permissions;
|
|
21
22
|
} else if (typeof permission === "function") {
|
|
23
|
+
const pathSegments = fullPathToCollectionSegments(path);
|
|
22
24
|
return permission({
|
|
23
25
|
entity,
|
|
26
|
+
path,
|
|
24
27
|
user: authController.user,
|
|
25
28
|
authController,
|
|
26
29
|
collection,
|
|
@@ -35,27 +38,28 @@ export function canEditEntity<M extends Record<string, any>, UserType extends Us
|
|
|
35
38
|
(
|
|
36
39
|
collection: EntityCollection<M>,
|
|
37
40
|
authController: AuthController<UserType>,
|
|
38
|
-
|
|
41
|
+
path: string,
|
|
39
42
|
entity: Entity<M> | null): boolean {
|
|
40
|
-
return resolvePermissions(collection, authController,
|
|
43
|
+
return resolvePermissions(collection, authController, path, entity)?.edit ?? DEFAULT_PERMISSIONS.edit;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export function canCreateEntity<M extends Record<string, any>, UserType extends User>
|
|
44
47
|
(
|
|
45
48
|
collection: EntityCollection<M>,
|
|
46
49
|
authController: AuthController<UserType>,
|
|
47
|
-
|
|
50
|
+
path: string,
|
|
48
51
|
entity: Entity<M> | null): boolean {
|
|
49
|
-
|
|
52
|
+
if (collection.collectionGroup) return false;
|
|
53
|
+
return resolvePermissions(collection, authController, path, entity)?.create ?? DEFAULT_PERMISSIONS.create;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
export function canDeleteEntity<M extends Record<string, any>, UserType extends User>
|
|
53
57
|
(
|
|
54
58
|
collection: EntityCollection<M>,
|
|
55
59
|
authController: AuthController<UserType>,
|
|
56
|
-
|
|
60
|
+
path: string,
|
|
57
61
|
entity: Entity<M> | null): boolean {
|
|
58
|
-
return resolvePermissions(collection, authController,
|
|
62
|
+
return resolvePermissions(collection, authController, path, entity)?.delete ?? DEFAULT_PERMISSIONS.delete;
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
// export function resolveCollectionsPermissions(roles: Role[]): Record<string, Permissions> {
|
package/src/util/references.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { EntityCollection, PropertyConfig } from "../types";
|
|
1
|
+
import { EntityCollection, PropertyConfig, ResolvedEntityCollection } from "../types";
|
|
2
2
|
import { isReferenceProperty } from "./property_utils";
|
|
3
3
|
import { isPropertyBuilder } from "./entities";
|
|
4
|
+
import { getFieldConfig } from "../core";
|
|
4
5
|
|
|
5
|
-
export function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export function getEntityPreviewKeys(targetCollection: EntityCollection<any>,
|
|
7
|
+
fields: Record<string, PropertyConfig>,
|
|
8
|
+
previewProperties?: string[],
|
|
9
|
+
limit = 3) {
|
|
9
10
|
const allProperties = Object.keys(targetCollection.properties);
|
|
10
11
|
let listProperties = previewProperties?.filter(p => allProperties.includes(p as string));
|
|
11
12
|
if (listProperties && listProperties.length > 0) {
|
|
@@ -18,3 +19,33 @@ export function getReferencePreviewKeys(targetCollection: EntityCollection<any>,
|
|
|
18
19
|
}).slice(0, limit);
|
|
19
20
|
}
|
|
20
21
|
}
|
|
22
|
+
|
|
23
|
+
export function getEntityTitlePropertyKey<M extends Record<string, any>>(collection: EntityCollection<M>, propertyConfigs: Record<string, PropertyConfig<any>>): string | undefined {
|
|
24
|
+
if (collection.titleProperty) {
|
|
25
|
+
return collection.titleProperty as string;
|
|
26
|
+
}
|
|
27
|
+
// find first text field property
|
|
28
|
+
for (const key in collection.properties) {
|
|
29
|
+
const property = collection.properties[key];
|
|
30
|
+
if (!isPropertyBuilder(property)) {
|
|
31
|
+
const field = getFieldConfig(property, propertyConfigs);
|
|
32
|
+
if (field?.key === "text_field") {
|
|
33
|
+
return key;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getEntityImagePreviewPropertyKey<M extends object>(collection: ResolvedEntityCollection<M>): string | undefined {
|
|
41
|
+
|
|
42
|
+
// find first text field property
|
|
43
|
+
for (const key in collection.properties) {
|
|
44
|
+
const property = collection.properties[key];
|
|
45
|
+
if (property.dataType === "string" && property.storage?.acceptedFiles?.includes("image/*")) {
|
|
46
|
+
return key;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
package/src/util/resolutions.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { getDefaultValuesFor, isPropertyBuilder } from "./entities";
|
|
|
26
26
|
import { DEFAULT_ONE_OF_TYPE } from "./common";
|
|
27
27
|
import { getIn } from "@firecms/formex";
|
|
28
28
|
import { enumToObjectEntries } from "./enums";
|
|
29
|
-
import { isDefaultFieldConfigId } from "../core";
|
|
29
|
+
import { isDefaultFieldConfigId } from "../core/field_configs";
|
|
30
30
|
|
|
31
31
|
// import util from "util";
|
|
32
32
|
|
|
@@ -38,7 +38,8 @@ export const resolveCollection = <M extends Record<string, any>, >
|
|
|
38
38
|
values,
|
|
39
39
|
previousValues,
|
|
40
40
|
userConfigPersistence,
|
|
41
|
-
fields
|
|
41
|
+
fields,
|
|
42
|
+
ignoreMissingFields = false
|
|
42
43
|
}: {
|
|
43
44
|
collection: EntityCollection<M> | ResolvedEntityCollection<M>;
|
|
44
45
|
path: string,
|
|
@@ -47,6 +48,7 @@ export const resolveCollection = <M extends Record<string, any>, >
|
|
|
47
48
|
previousValues?: Partial<EntityValues<M>>,
|
|
48
49
|
userConfigPersistence?: UserConfigurationPersistence;
|
|
49
50
|
fields?: Record<string, PropertyConfig>;
|
|
51
|
+
ignoreMissingFields?: boolean;
|
|
50
52
|
}): ResolvedEntityCollection<M> => {
|
|
51
53
|
|
|
52
54
|
const collectionOverride = userConfigPersistence?.getCollectionConfig<M>(path);
|
|
@@ -58,16 +60,15 @@ export const resolveCollection = <M extends Record<string, any>, >
|
|
|
58
60
|
|
|
59
61
|
const resolvedProperties = Object.entries(collection.properties)
|
|
60
62
|
.map(([key, propertyOrBuilder]) => {
|
|
61
|
-
const propertyValue = usedValues ? getIn(usedValues, key) : undefined;
|
|
62
63
|
const childResolvedProperty = resolveProperty({
|
|
63
64
|
propertyKey: key,
|
|
64
65
|
propertyOrBuilder: propertyOrBuilder as PropertyOrBuilder | ResolvedProperty,
|
|
65
66
|
values: usedValues,
|
|
66
67
|
previousValues: usedPreviousValues,
|
|
67
68
|
path,
|
|
68
|
-
propertyValue,
|
|
69
69
|
entityId,
|
|
70
|
-
fields
|
|
70
|
+
fields,
|
|
71
|
+
ignoreMissingFields
|
|
71
72
|
});
|
|
72
73
|
if (!childResolvedProperty) return {};
|
|
73
74
|
return ({
|
|
@@ -95,17 +96,15 @@ export const resolveCollection = <M extends Record<string, any>, >
|
|
|
95
96
|
* Resolve property builders, enums and arrays.
|
|
96
97
|
* @param propertyOrBuilder
|
|
97
98
|
* @param propertyValue
|
|
98
|
-
* @param values
|
|
99
99
|
*/
|
|
100
100
|
export function resolveProperty<T extends CMSType = CMSType, M extends Record<string, any> = any>({
|
|
101
101
|
propertyOrBuilder,
|
|
102
|
-
propertyValue,
|
|
103
102
|
fromBuilder = false,
|
|
103
|
+
ignoreMissingFields = false,
|
|
104
104
|
...props
|
|
105
105
|
}: {
|
|
106
106
|
propertyKey?: string,
|
|
107
107
|
propertyOrBuilder: PropertyOrBuilder<T, M> | ResolvedProperty<T>,
|
|
108
|
-
propertyValue?: unknown,
|
|
109
108
|
values?: Partial<M>,
|
|
110
109
|
previousValues?: Partial<M>,
|
|
111
110
|
path?: string,
|
|
@@ -113,6 +112,7 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
113
112
|
index?: number,
|
|
114
113
|
fromBuilder?: boolean;
|
|
115
114
|
fields?: Record<string, PropertyConfig<any>>;
|
|
115
|
+
ignoreMissingFields?: boolean;
|
|
116
116
|
}): ResolvedProperty<T> | null {
|
|
117
117
|
|
|
118
118
|
if (typeof propertyOrBuilder === "object" && "resolved" in propertyOrBuilder) {
|
|
@@ -128,10 +128,11 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
128
128
|
if (!path)
|
|
129
129
|
throw Error("Trying to resolve a property builder without specifying the entity path");
|
|
130
130
|
|
|
131
|
+
const usedPropertyValue = props.propertyKey ? getIn(props.values, props.propertyKey) : undefined;
|
|
131
132
|
const result: Property<T> | null = propertyOrBuilder({
|
|
132
133
|
...props,
|
|
133
134
|
path,
|
|
134
|
-
propertyValue,
|
|
135
|
+
propertyValue: usedPropertyValue,
|
|
135
136
|
values: props.values ?? {},
|
|
136
137
|
previousValues: props.previousValues ?? props.values ?? {}
|
|
137
138
|
});
|
|
@@ -142,17 +143,17 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
142
143
|
|
|
143
144
|
resolvedProperty = resolveProperty({
|
|
144
145
|
...props,
|
|
145
|
-
propertyValue,
|
|
146
146
|
propertyOrBuilder: result,
|
|
147
|
-
fromBuilder: true
|
|
147
|
+
fromBuilder: true,
|
|
148
|
+
ignoreMissingFields
|
|
148
149
|
});
|
|
149
150
|
} else {
|
|
150
151
|
const property = propertyOrBuilder as Property<T>;
|
|
151
152
|
if (property.dataType === "map" && property.properties) {
|
|
152
153
|
const properties = resolveProperties({
|
|
154
|
+
ignoreMissingFields,
|
|
153
155
|
...props,
|
|
154
156
|
properties: property.properties,
|
|
155
|
-
propertyValue
|
|
156
157
|
});
|
|
157
158
|
resolvedProperty = {
|
|
158
159
|
...property,
|
|
@@ -163,8 +164,8 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
163
164
|
} else if (property.dataType === "array") {
|
|
164
165
|
resolvedProperty = resolveArrayProperty({
|
|
165
166
|
property,
|
|
166
|
-
propertyValue,
|
|
167
167
|
fromBuilder,
|
|
168
|
+
ignoreMissingFields,
|
|
168
169
|
...props
|
|
169
170
|
}) as ResolvedProperty<any>;
|
|
170
171
|
} else if ((property.dataType === "string" || property.dataType === "number") && property.enumValues) {
|
|
@@ -182,12 +183,12 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
182
183
|
|
|
183
184
|
if (resolvedProperty.propertyConfig && !isDefaultFieldConfigId(resolvedProperty.propertyConfig)) {
|
|
184
185
|
const cmsFields = props.fields;
|
|
185
|
-
if (!cmsFields) {
|
|
186
|
-
throw Error(`Trying to resolve a property with key ${resolvedProperty.propertyConfig} that inherits from a custom property config but no custom property configs were provided. Use the property
|
|
186
|
+
if (!cmsFields && !ignoreMissingFields) {
|
|
187
|
+
throw Error(`Trying to resolve a property with key '${resolvedProperty.propertyConfig}' that inherits from a custom property config but no custom property configs were provided. Use the property 'propertyConfigs' in your app config to provide them`);
|
|
187
188
|
}
|
|
188
|
-
const customField: PropertyConfig
|
|
189
|
+
const customField: PropertyConfig | undefined = cmsFields?.[resolvedProperty.propertyConfig];
|
|
189
190
|
if (!customField) {
|
|
190
|
-
console.warn(`Trying to resolve a property with key ${resolvedProperty.propertyConfig} that inherits from a custom property config but no custom property config with that key was found. Check the
|
|
191
|
+
console.warn(`Trying to resolve a property with key '${resolvedProperty.propertyConfig}' that inherits from a custom property config but no custom property config with that key was found. Check the 'propertyConfigs' in your app config`)
|
|
191
192
|
console.warn("Available property configs", cmsFields);
|
|
192
193
|
return null;
|
|
193
194
|
}
|
|
@@ -198,7 +199,7 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
198
199
|
}
|
|
199
200
|
const customFieldProperty = resolveProperty<any>({
|
|
200
201
|
propertyOrBuilder: configPropertyOrBuilder,
|
|
201
|
-
|
|
202
|
+
ignoreMissingFields,
|
|
202
203
|
...props
|
|
203
204
|
});
|
|
204
205
|
if (customFieldProperty) {
|
|
@@ -219,12 +220,11 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
219
220
|
export function resolveArrayProperty<T extends any[], M>({
|
|
220
221
|
propertyKey,
|
|
221
222
|
property,
|
|
222
|
-
|
|
223
|
+
ignoreMissingFields = false,
|
|
223
224
|
...props
|
|
224
225
|
}: {
|
|
225
226
|
propertyKey?: string,
|
|
226
227
|
property: ArrayProperty<T> | ResolvedArrayProperty<T>,
|
|
227
|
-
propertyValue: any,
|
|
228
228
|
values?: Partial<M>,
|
|
229
229
|
previousValues?: Partial<M>,
|
|
230
230
|
path?: string,
|
|
@@ -232,7 +232,9 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
232
232
|
index?: number,
|
|
233
233
|
fromBuilder?: boolean;
|
|
234
234
|
fields?: Record<string, PropertyConfig>;
|
|
235
|
+
ignoreMissingFields?: boolean;
|
|
235
236
|
}): ResolvedArrayProperty {
|
|
237
|
+
const propertyValue = propertyKey ? getIn(props.values, propertyKey) : undefined;
|
|
236
238
|
|
|
237
239
|
if (property.of) {
|
|
238
240
|
if (Array.isArray(property.of)) {
|
|
@@ -244,7 +246,7 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
244
246
|
return resolveProperty({
|
|
245
247
|
propertyKey: `${propertyKey}.${index}`,
|
|
246
248
|
propertyOrBuilder: p as Property<any>,
|
|
247
|
-
|
|
249
|
+
ignoreMissingFields,
|
|
248
250
|
...props,
|
|
249
251
|
index
|
|
250
252
|
});
|
|
@@ -256,7 +258,7 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
256
258
|
? propertyValue.map((v: any, index: number) => resolveProperty({
|
|
257
259
|
propertyKey: `${propertyKey}.${index}`,
|
|
258
260
|
propertyOrBuilder: of,
|
|
259
|
-
|
|
261
|
+
ignoreMissingFields,
|
|
260
262
|
...props,
|
|
261
263
|
index
|
|
262
264
|
})).filter(e => Boolean(e)) as ResolvedProperty[]
|
|
@@ -264,10 +266,10 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
264
266
|
const ofProperty = resolveProperty({
|
|
265
267
|
propertyKey: `${propertyKey}`,
|
|
266
268
|
propertyOrBuilder: of,
|
|
267
|
-
|
|
269
|
+
ignoreMissingFields,
|
|
268
270
|
...props
|
|
269
271
|
});
|
|
270
|
-
if (!ofProperty)
|
|
272
|
+
if (!ofProperty && !ignoreMissingFields)
|
|
271
273
|
throw Error("When using a property builder as the 'of' prop of an ArrayProperty, you must return a valid child property")
|
|
272
274
|
return {
|
|
273
275
|
...property,
|
|
@@ -287,14 +289,14 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
287
289
|
return resolveProperty({
|
|
288
290
|
propertyKey: `${propertyKey}.${index}`,
|
|
289
291
|
propertyOrBuilder: childProperty,
|
|
290
|
-
|
|
292
|
+
ignoreMissingFields,
|
|
291
293
|
...props
|
|
292
294
|
});
|
|
293
295
|
}).filter(e => Boolean(e)) as ResolvedProperty[]
|
|
294
296
|
: [];
|
|
295
297
|
const properties = resolveProperties<any>({
|
|
296
298
|
properties: property.oneOf.properties,
|
|
297
|
-
|
|
299
|
+
ignoreMissingFields,
|
|
298
300
|
...props
|
|
299
301
|
});
|
|
300
302
|
return {
|
|
@@ -326,11 +328,10 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
326
328
|
*/
|
|
327
329
|
export function resolveProperties<M extends Record<string, any>>({
|
|
328
330
|
properties,
|
|
329
|
-
|
|
331
|
+
ignoreMissingFields,
|
|
330
332
|
...props
|
|
331
333
|
}: {
|
|
332
334
|
properties: PropertiesOrBuilders<M>,
|
|
333
|
-
propertyValue: unknown,
|
|
334
335
|
values?: Partial<M>,
|
|
335
336
|
previousValues?: Partial<M>,
|
|
336
337
|
path?: string,
|
|
@@ -338,14 +339,14 @@ export function resolveProperties<M extends Record<string, any>>({
|
|
|
338
339
|
index?: number,
|
|
339
340
|
fromBuilder?: boolean;
|
|
340
341
|
fields?: Record<string, PropertyConfig>;
|
|
342
|
+
ignoreMissingFields?: boolean;
|
|
341
343
|
}): ResolvedProperties<M> {
|
|
342
344
|
return Object.entries<PropertyOrBuilder>(properties as Record<string, PropertyOrBuilder>)
|
|
343
345
|
.map(([key, property]) => {
|
|
344
|
-
const thisPropertyValue = propertyValue && typeof propertyValue === "object" ? getValueInPath(propertyValue, key) : undefined;
|
|
345
346
|
const childResolvedProperty = resolveProperty({
|
|
346
347
|
propertyKey: key,
|
|
347
348
|
propertyOrBuilder: property,
|
|
348
|
-
|
|
349
|
+
ignoreMissingFields,
|
|
349
350
|
...props
|
|
350
351
|
});
|
|
351
352
|
if (!childResolvedProperty) return {};
|
|
@@ -367,7 +368,7 @@ export function resolvePropertyEnum(property: StringProperty | NumberProperty, f
|
|
|
367
368
|
return {
|
|
368
369
|
...property,
|
|
369
370
|
resolved: true,
|
|
370
|
-
enumValues: enumToObjectEntries(property.enumValues)?.filter((value) => value && value.id && value.label) ?? [],
|
|
371
|
+
enumValues: enumToObjectEntries(property.enumValues)?.filter((value) => value && (value.id || value.id === 0) && value.label) ?? [],
|
|
371
372
|
fromBuilder: fromBuilder ?? false
|
|
372
373
|
}
|
|
373
374
|
}
|
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}`, "");
|
package/src/util/strings.ts
CHANGED
|
@@ -56,8 +56,8 @@ export function unslugify(slug?: string): string {
|
|
|
56
56
|
const result = slug.replace(/[-_]/g, " ");
|
|
57
57
|
return result.replace(/\w\S*/g, function (txt) {
|
|
58
58
|
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
|
59
|
-
});
|
|
59
|
+
}).trim();
|
|
60
60
|
} else {
|
|
61
|
-
return slug;
|
|
61
|
+
return slug.trim();
|
|
62
62
|
}
|
|
63
63
|
}
|