@firecms/core 3.0.0-canary.3 → 3.0.0-canary.30
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 +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +2 -2
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +1 -2
- package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
- package/dist/components/EntityPreview.d.ts +25 -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 -3
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
- package/dist/components/index.d.ts +4 -3
- package/dist/contexts/AuthControllerContext.d.ts +1 -1
- package/dist/{internal/EntityView.d.ts → core/EntityEditView.d.ts} +2 -2
- package/dist/core/SideEntityView.d.ts +7 -0
- package/dist/core/index.d.ts +0 -2
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/components/StorageItemPreview.d.ts +3 -2
- package/dist/form/components/StorageUploadProgress.d.ts +1 -1
- package/dist/form/components/index.d.ts +1 -0
- 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 +4 -3
- package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
- package/dist/form/index.d.ts +1 -0
- package/dist/form/validation.d.ts +1 -1
- package/dist/hooks/data/delete.d.ts +2 -2
- package/dist/hooks/data/save.d.ts +1 -1
- package/dist/hooks/data/useDataSource.d.ts +2 -2
- package/dist/hooks/data/useEntityFetch.d.ts +3 -3
- package/dist/hooks/index.d.ts +3 -1
- package/dist/{core → hooks}/useBuildModeController.d.ts +1 -1
- package/dist/hooks/useBuildNavigationController.d.ts +5 -2
- package/dist/hooks/useProjectLog.d.ts +6 -2
- package/dist/hooks/useStorageSource.d.ts +2 -2
- package/dist/hooks/useValidateAuthenticator.d.ts +25 -0
- package/dist/index.es.js +8055 -7703
- 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 +4 -0
- 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 +1 -7
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/auth.d.ts +37 -1
- package/dist/types/collections.d.ts +17 -4
- package/dist/types/datasource.d.ts +1 -1
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/entity_callbacks.d.ts +2 -2
- package/dist/types/entity_overrides.d.ts +6 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/navigation.d.ts +14 -13
- package/dist/types/permissions.d.ts +5 -1
- package/dist/types/plugins.d.ts +17 -19
- package/dist/types/properties.d.ts +2 -2
- 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/icons.d.ts +8 -2
- package/dist/util/permissions.d.ts +4 -4
- package/dist/util/references.d.ts +4 -2
- package/dist/util/resolutions.d.ts +1 -1
- package/dist/util/useTraceUpdate.d.ts +1 -0
- package/package.json +24 -24
- package/src/components/DeleteEntityDialog.tsx +4 -4
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +2 -2
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +273 -277
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +13 -13
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +10 -17
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +9 -5
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +28 -49
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
- package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
- package/src/components/EntityPreview.tsx +207 -70
- package/src/components/EntityView.tsx +84 -0
- package/src/components/FieldCaption.tsx +14 -0
- package/src/components/FireCMSAppBar.tsx +8 -0
- package/src/components/HomePage/DefaultHomePage.tsx +14 -10
- 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/ReferenceTable/ReferenceSelectionTable.tsx +3 -4
- package/src/components/ReferenceWidget.tsx +8 -8
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +11 -19
- package/src/components/VirtualTable/VirtualTableProps.tsx +1 -1
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +1 -1
- package/src/components/index.tsx +4 -3
- package/src/contexts/AuthControllerContext.tsx +1 -1
- package/src/core/Drawer.tsx +66 -39
- package/src/{internal/EntityView.tsx → core/EntityEditView.tsx} +22 -39
- package/src/core/EntitySidePanel.tsx +2 -2
- package/src/core/FireCMS.tsx +18 -2
- package/src/core/NavigationRoutes.tsx +8 -0
- package/src/core/SideEntityView.tsx +38 -0
- package/src/core/index.tsx +0 -2
- package/src/form/EntityForm.tsx +20 -12
- package/src/form/components/StorageItemPreview.tsx +5 -3
- package/src/form/components/StorageUploadProgress.tsx +6 -5
- package/src/form/components/index.tsx +1 -0
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +2 -3
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +12 -15
- package/src/form/field_bindings/BlockFieldBinding.tsx +2 -3
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +3 -3
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +18 -18
- package/src/form/field_bindings/MapFieldBinding.tsx +17 -17
- package/src/form/field_bindings/MarkdownFieldBinding.tsx +1 -2
- package/src/form/field_bindings/MultiSelectBinding.tsx +2 -3
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +3 -3
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +6 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +3 -3
- package/src/form/field_bindings/SelectFieldBinding.tsx +2 -3
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +15 -6
- package/src/form/field_bindings/SwitchFieldBinding.tsx +2 -3
- package/src/form/field_bindings/TextFieldBinding.tsx +10 -9
- package/src/form/index.tsx +1 -0
- package/src/form/validation.ts +3 -4
- package/src/hooks/data/delete.ts +3 -3
- package/src/hooks/data/save.ts +1 -1
- 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 +5 -1
- package/src/{core → hooks}/useBuildModeController.tsx +1 -1
- package/src/hooks/useBuildNavigationController.tsx +132 -70
- package/src/hooks/useProjectLog.tsx +16 -6
- package/src/hooks/useReferenceDialog.tsx +2 -2
- package/src/hooks/useStorageSource.tsx +7 -2
- package/src/hooks/useValidateAuthenticator.tsx +135 -0
- package/src/internal/useBuildDataSource.ts +7 -2
- package/src/internal/useBuildSideEntityController.tsx +3 -0
- package/src/preview/PropertyPreview.tsx +2 -2
- package/src/preview/PropertyPreviewProps.tsx +1 -11
- package/src/preview/components/BooleanPreview.tsx +19 -4
- package/src/preview/components/EnumValuesChip.tsx +1 -1
- package/src/preview/components/ReferencePreview.tsx +56 -148
- 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 +19 -4
- package/src/types/datasource.ts +1 -1
- package/src/types/entities.ts +4 -0
- package/src/types/entity_actions.tsx +4 -0
- package/src/types/entity_callbacks.ts +2 -2
- package/src/types/entity_overrides.tsx +7 -0
- package/src/types/firecms.tsx +0 -1
- package/src/types/index.ts +2 -0
- package/src/types/navigation.ts +17 -16
- package/src/types/permissions.ts +6 -1
- package/src/types/plugins.tsx +24 -27
- package/src/types/properties.ts +3 -2
- 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/icons.tsx +11 -3
- package/src/util/permissions.ts +11 -8
- package/src/util/references.ts +36 -5
- package/src/util/useTraceUpdate.tsx +2 -1
- package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
- /package/dist/{components → form/components}/LabelWithIcon.d.ts +0 -0
- /package/dist/{core → hooks}/useBuildLocalConfigurationPersistence.d.ts +0 -0
- /package/src/{components → form/components}/LabelWithIcon.tsx +0 -0
- /package/src/{core → hooks}/useBuildLocalConfigurationPersistence.tsx +0 -0
package/src/types/navigation.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import { EntityCollection } from "./collections";
|
|
2
3
|
import { EntityReference } from "./entities";
|
|
3
4
|
|
|
@@ -6,7 +7,7 @@ import { EntityReference } from "./entities";
|
|
|
6
7
|
* attributes.
|
|
7
8
|
* @group Models
|
|
8
9
|
*/
|
|
9
|
-
export type NavigationController = {
|
|
10
|
+
export type NavigationController<EC extends EntityCollection = EntityCollection<any>> = {
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* List of the mapped collections in the CMS.
|
|
@@ -22,6 +23,12 @@ export type NavigationController = {
|
|
|
22
23
|
*/
|
|
23
24
|
views?: CMSView[];
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Custom additional views created by the developer, added to the admin
|
|
28
|
+
* navigation
|
|
29
|
+
*/
|
|
30
|
+
adminViews?: CMSView[];
|
|
31
|
+
|
|
25
32
|
/**
|
|
26
33
|
* Configuration for the views that should be displayed at the top
|
|
27
34
|
* level of the navigation (e.g. in the home page or the navigation
|
|
@@ -49,18 +56,18 @@ export type NavigationController = {
|
|
|
49
56
|
* Get the collection configuration for a given path.
|
|
50
57
|
* The collection is resolved from the given path or alias.
|
|
51
58
|
*/
|
|
52
|
-
getCollection:
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
getCollection: (pathOrAlias: string,
|
|
60
|
+
entityId?: string,
|
|
61
|
+
includeUserOverride?: boolean) => EC | undefined;
|
|
55
62
|
/**
|
|
56
63
|
* Get the collection configuration from its parent path segments.
|
|
57
64
|
*/
|
|
58
|
-
getCollectionFromIds:
|
|
65
|
+
getCollectionFromIds: (ids: string[]) => EC | undefined;
|
|
59
66
|
|
|
60
67
|
/**
|
|
61
68
|
* Get the collection configuration from its parent path segments.
|
|
62
69
|
*/
|
|
63
|
-
getCollectionFromPaths:
|
|
70
|
+
getCollectionFromPaths: (pathSegments: string[]) => EC | undefined;
|
|
64
71
|
|
|
65
72
|
/**
|
|
66
73
|
* Default path under the navigation routes of the CMS will be created
|
|
@@ -116,13 +123,6 @@ export type NavigationController = {
|
|
|
116
123
|
*/
|
|
117
124
|
resolveAliasesFrom: (pathWithAliases: string) => string;
|
|
118
125
|
|
|
119
|
-
/**
|
|
120
|
-
* Location used as the base for routes.
|
|
121
|
-
* This is the location that will be used underneath, when the url changes while
|
|
122
|
-
* opening a side dialog
|
|
123
|
-
*/
|
|
124
|
-
baseLocation: string;
|
|
125
|
-
|
|
126
126
|
/**
|
|
127
127
|
* Call this method to recalculate the navigation
|
|
128
128
|
*/
|
|
@@ -192,6 +192,7 @@ export interface CMSView {
|
|
|
192
192
|
/**
|
|
193
193
|
* Optional field used to group top level navigation entries under a
|
|
194
194
|
* navigation view.
|
|
195
|
+
* This prop is ignored for admin views.
|
|
195
196
|
*/
|
|
196
197
|
group?: string;
|
|
197
198
|
|
|
@@ -201,11 +202,11 @@ export interface TopNavigationEntry {
|
|
|
201
202
|
url: string;
|
|
202
203
|
name: string;
|
|
203
204
|
path: string;
|
|
204
|
-
type: "collection" | "view";
|
|
205
|
+
type: "collection" | "view" | "admin";
|
|
205
206
|
collection?: EntityCollection;
|
|
206
|
-
view
|
|
207
|
+
view?: CMSView;
|
|
207
208
|
description?: string;
|
|
208
|
-
group
|
|
209
|
+
group: string;
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
export type TopNavigationResult = {
|
package/src/types/permissions.ts
CHANGED
|
@@ -41,6 +41,11 @@ export interface PermissionsBuilderProps<EC extends EntityCollection = EntityCol
|
|
|
41
41
|
*/
|
|
42
42
|
entity: Entity<M> | null;
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Path of the collection e.g. 'products/12345/locales'
|
|
46
|
+
*/
|
|
47
|
+
path: string;
|
|
48
|
+
|
|
44
49
|
/**
|
|
45
50
|
* Path segments of the collection e.g. ['products', 'locales']
|
|
46
51
|
*/
|
|
@@ -73,4 +78,4 @@ export type PermissionsBuilder<EC extends EntityCollection = EntityCollection, U
|
|
|
73
78
|
user,
|
|
74
79
|
collection,
|
|
75
80
|
authController
|
|
76
|
-
}: PermissionsBuilderProps<EC, UserType, M>) => Permissions);
|
|
81
|
+
}: PermissionsBuilderProps<EC, UserType, M>) => Permissions | undefined);
|
package/src/types/plugins.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import { FieldProps, FormContext } from "./fields";
|
|
|
7
7
|
import { CMSType, Property } from "./properties";
|
|
8
8
|
import { EntityStatus } from "./entities";
|
|
9
9
|
import { ResolvedProperty } from "./resolved_entities";
|
|
10
|
+
import { CMSView } from "./navigation";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Interface used to define plugins for FireCMS.
|
|
@@ -16,9 +17,9 @@ import { ResolvedProperty } from "./resolved_entities";
|
|
|
16
17
|
export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollection = EntityCollection, COL_ACTIONS_PROPS = any> = {
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
+
* Key of the plugin. This is used to identify the plugin in the CMS.
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
+
key: string;
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* If this flag is set to true, no content will be shown in the CMS
|
|
@@ -26,31 +27,6 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
26
27
|
*/
|
|
27
28
|
loading?: boolean;
|
|
28
29
|
|
|
29
|
-
collections?: {
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Use this component to add custom actions to the entity collections
|
|
33
|
-
* toolbar.
|
|
34
|
-
*/
|
|
35
|
-
CollectionActions?: React.ComponentType<CollectionActionsProps<any, any, EC> & COL_ACTIONS_PROPS> | React.ComponentType<CollectionActionsProps<any, any, EC> & COL_ACTIONS_PROPS>[];
|
|
36
|
-
|
|
37
|
-
collectionActionsProps?: COL_ACTIONS_PROPS;
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
form?: {
|
|
42
|
-
provider?: {
|
|
43
|
-
Component: React.ComponentType<PropsWithChildren<FORM_PROPS & PluginFormActionProps<any, EC>>>;
|
|
44
|
-
props?: FORM_PROPS;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
Actions?: React.ComponentType<PluginFormActionProps<any, EC>>;
|
|
48
|
-
|
|
49
|
-
fieldBuilder?: <T extends CMSType = CMSType>(props: PluginFieldBuilderParams<T, any, EC>) => React.ComponentType<FieldProps<T>> | null;
|
|
50
|
-
|
|
51
|
-
fieldBuilderEnabled?: <T extends CMSType = CMSType>(props: PluginFieldBuilderParams<T>) => boolean;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
30
|
/**
|
|
55
31
|
* You can use this prop to add higher order components to the CMS.
|
|
56
32
|
* The components will be added to the root of the CMS, so any component
|
|
@@ -113,6 +89,14 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
113
89
|
|
|
114
90
|
collectionView?: {
|
|
115
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Use this component to add custom actions to the entity collections
|
|
94
|
+
* toolbar.
|
|
95
|
+
*/
|
|
96
|
+
CollectionActions?: React.ComponentType<CollectionActionsProps<any, any, EC> & COL_ACTIONS_PROPS> | React.ComponentType<CollectionActionsProps<any, any, EC> & COL_ACTIONS_PROPS>[];
|
|
97
|
+
|
|
98
|
+
collectionActionsProps?: COL_ACTIONS_PROPS;
|
|
99
|
+
|
|
116
100
|
showTextSearchBar?: (props: {
|
|
117
101
|
context: FireCMSContext,
|
|
118
102
|
path: string,
|
|
@@ -151,6 +135,19 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
151
135
|
}>;
|
|
152
136
|
}
|
|
153
137
|
|
|
138
|
+
form?: {
|
|
139
|
+
provider?: {
|
|
140
|
+
Component: React.ComponentType<PropsWithChildren<FORM_PROPS & PluginFormActionProps<any, EC>>>;
|
|
141
|
+
props?: FORM_PROPS;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
Actions?: React.ComponentType<PluginFormActionProps<any, EC>>;
|
|
145
|
+
|
|
146
|
+
fieldBuilder?: <T extends CMSType = CMSType>(props: PluginFieldBuilderParams<T, any, EC>) => React.ComponentType<FieldProps<T>> | null;
|
|
147
|
+
|
|
148
|
+
fieldBuilderEnabled?: <T extends CMSType = CMSType>(props: PluginFieldBuilderParams<T>) => boolean;
|
|
149
|
+
}
|
|
150
|
+
|
|
154
151
|
}
|
|
155
152
|
|
|
156
153
|
/**
|
package/src/types/properties.ts
CHANGED
|
@@ -695,7 +695,7 @@ export interface ArrayPropertyValidationSchema extends PropertyValidationSchema
|
|
|
695
695
|
* Additional configuration related to Storage related fields
|
|
696
696
|
* @group Entity properties
|
|
697
697
|
*/
|
|
698
|
-
export
|
|
698
|
+
export type StorageConfig = {
|
|
699
699
|
|
|
700
700
|
/**
|
|
701
701
|
* File MIME types that can be uploaded to this reference. Don't specify for
|
|
@@ -770,7 +770,8 @@ export interface StorageConfig {
|
|
|
770
770
|
* Postprocess the saved value (storage path or URL)
|
|
771
771
|
* after it has been resolved.
|
|
772
772
|
*/
|
|
773
|
-
postProcess?: (pathOrUrl: string) => Promise<string
|
|
773
|
+
postProcess?: (pathOrUrl: string) => Promise<string>;
|
|
774
|
+
|
|
774
775
|
}
|
|
775
776
|
|
|
776
777
|
/**
|
|
@@ -11,7 +11,7 @@ export type PropertyConfig<T extends CMSType = any> = {
|
|
|
11
11
|
/**
|
|
12
12
|
* Key used to identify this property config.
|
|
13
13
|
*/
|
|
14
|
-
key: string
|
|
14
|
+
key: PropertyConfigId | string;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Name of this field type.
|
|
@@ -48,7 +48,7 @@ export type PropertyConfig<T extends CMSType = any> = {
|
|
|
48
48
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export type
|
|
51
|
+
export type PropertyConfigId =
|
|
52
52
|
"text_field" |
|
|
53
53
|
"multiline" |
|
|
54
54
|
"markdown" |
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Permissions } from "../index";
|
|
2
|
+
|
|
3
|
+
export type Role = {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ID of the role
|
|
7
|
+
*/
|
|
8
|
+
id: string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Name of the role
|
|
12
|
+
*/
|
|
13
|
+
name: string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* If this flag is true, the user can perform any action
|
|
17
|
+
*/
|
|
18
|
+
isAdmin?: boolean;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Default permissions for all collections for this role.
|
|
22
|
+
* You can override this values at the collection level using
|
|
23
|
+
* {@link collectionPermissions}
|
|
24
|
+
*/
|
|
25
|
+
defaultPermissions?: Permissions;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Record of stripped collection ids to their permissions.
|
|
29
|
+
* @see stripCollectionPath
|
|
30
|
+
*/
|
|
31
|
+
collectionPermissions?: Record<string, Permissions>;
|
|
32
|
+
|
|
33
|
+
config?: {
|
|
34
|
+
|
|
35
|
+
createCollections?: boolean;
|
|
36
|
+
|
|
37
|
+
editCollections?: boolean | "own";
|
|
38
|
+
|
|
39
|
+
deleteCollections?: boolean | "own";
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/types/storage.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface UploadFileProps {
|
|
|
6
6
|
fileName?: string,
|
|
7
7
|
path?: string,
|
|
8
8
|
metadata?: any,
|
|
9
|
+
bucket?: string
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -16,6 +17,10 @@ export interface UploadFileResult {
|
|
|
16
17
|
* Storage path including the file name where the file was uploaded.
|
|
17
18
|
*/
|
|
18
19
|
path: string;
|
|
20
|
+
/**
|
|
21
|
+
* Bucket where the file was uploaded
|
|
22
|
+
*/
|
|
23
|
+
bucket: string;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
/**
|
|
@@ -73,24 +78,28 @@ export interface StorageSource {
|
|
|
73
78
|
* @param fileName
|
|
74
79
|
* @param path
|
|
75
80
|
* @param metadata
|
|
81
|
+
* @param bucket
|
|
76
82
|
*/
|
|
77
83
|
uploadFile: ({
|
|
78
84
|
file,
|
|
79
85
|
fileName,
|
|
80
86
|
path,
|
|
81
|
-
metadata
|
|
87
|
+
metadata,
|
|
88
|
+
bucket
|
|
82
89
|
}: UploadFileProps) => Promise<UploadFileResult>;
|
|
83
90
|
|
|
84
91
|
/**
|
|
85
92
|
* Convert a storage path or URL into a download configuration
|
|
86
93
|
* @param path
|
|
94
|
+
* @param bucket
|
|
87
95
|
*/
|
|
88
|
-
getDownloadURL: (pathOrUrl: string) => Promise<DownloadConfig>;
|
|
96
|
+
getDownloadURL: (pathOrUrl: string, bucket?: string) => Promise<DownloadConfig>;
|
|
89
97
|
|
|
90
98
|
/**
|
|
91
99
|
* Get a file from a storage path.
|
|
92
100
|
* It returns null if the file does not exist.
|
|
93
101
|
* @param props
|
|
102
|
+
* @param bucket
|
|
94
103
|
*/
|
|
95
|
-
getFile: (path:string) => Promise<File | null>;
|
|
104
|
+
getFile: (path:string, bucket?: string) => Promise<File | null>;
|
|
96
105
|
}
|
package/src/types/user.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Role } from "./roles";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* This interface represents a user.
|
|
3
5
|
* It has some of the same fields as a Firebase User.
|
|
@@ -34,4 +36,9 @@ export type User = {
|
|
|
34
36
|
*/
|
|
35
37
|
readonly isAnonymous: boolean;
|
|
36
38
|
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
*/
|
|
42
|
+
roles?: Role[];
|
|
43
|
+
|
|
37
44
|
};
|
package/src/util/collections.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DefaultSelectedViewBuilder,
|
|
3
3
|
DefaultSelectedViewParams,
|
|
4
|
+
EntityCollection,
|
|
5
|
+
PermissionsBuilder,
|
|
4
6
|
PropertiesOrBuilders,
|
|
5
7
|
PropertyOrBuilder
|
|
6
8
|
} from "../types";
|
|
@@ -48,3 +50,23 @@ export function resolveDefaultSelectedView(
|
|
|
48
50
|
return defaultSelectedView(params);
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* If a collection is not applying permissions, we apply the given permissionsBuilder.
|
|
56
|
+
* This is used to apply the role permissions to the collections, unless they are already
|
|
57
|
+
* applying permissions.
|
|
58
|
+
* @param collections
|
|
59
|
+
* @param permissionsBuilder
|
|
60
|
+
*/
|
|
61
|
+
export const applyPermissionsFunctionIfEmpty = (collections: EntityCollection[], permissionsBuilder?: PermissionsBuilder<any, any>): EntityCollection[] => {
|
|
62
|
+
|
|
63
|
+
return collections.map(collection => {
|
|
64
|
+
if (collection.permissions) {
|
|
65
|
+
return collection;
|
|
66
|
+
}
|
|
67
|
+
return ({
|
|
68
|
+
...collection,
|
|
69
|
+
permissions: permissionsBuilder
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
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) => {
|
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,27 @@ 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
|
-
return resolvePermissions(collection, authController,
|
|
52
|
+
return resolvePermissions(collection, authController, path, entity)?.create ?? DEFAULT_PERMISSIONS.create;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
export function canDeleteEntity<M extends Record<string, any>, UserType extends User>
|
|
53
56
|
(
|
|
54
57
|
collection: EntityCollection<M>,
|
|
55
58
|
authController: AuthController<UserType>,
|
|
56
|
-
|
|
59
|
+
path: string,
|
|
57
60
|
entity: Entity<M> | null): boolean {
|
|
58
|
-
return resolvePermissions(collection, authController,
|
|
61
|
+
return resolvePermissions(collection, authController, path, entity)?.delete ?? DEFAULT_PERMISSIONS.delete;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
// 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
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useRef } from "react";
|
|
2
2
|
|
|
3
|
-
function printChanged(props: any, prev: any, path = "", depth = 0, maxDepth: number) {
|
|
3
|
+
export function printChanged(props: any, prev: any, path: string | undefined = "", depth: number | undefined = 0, maxDepth: number | undefined = 10) {
|
|
4
4
|
if (depth > maxDepth) {
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
@@ -17,6 +17,7 @@ function printChanged(props: any, prev: any, path = "", depth = 0, maxDepth: num
|
|
|
17
17
|
export function useTraceUpdate(props: any, maxDepth = 3) {
|
|
18
18
|
const prev = useRef(props);
|
|
19
19
|
useEffect(() => {
|
|
20
|
+
console.log("Changed props:");
|
|
20
21
|
printChanged(props, prev.current, "", 0, maxDepth);
|
|
21
22
|
prev.current = props;
|
|
22
23
|
});
|