@firecms/core 3.0.0-canary.7 → 3.0.0-canary.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/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/VirtualTable/VirtualTableProps.d.ts +1 -1
- package/dist/components/index.d.ts +4 -2
- package/dist/core/{EntityView.d.ts → EntityEditView.d.ts} +2 -2
- package/dist/core/SideEntityView.d.ts +2 -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/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/validation.d.ts +1 -1
- package/dist/hooks/data/useDataSource.d.ts +2 -2
- package/dist/hooks/useBuildNavigationController.d.ts +5 -2
- package/dist/hooks/useProjectLog.d.ts +5 -1
- package/dist/hooks/useStorageSource.d.ts +2 -2
- package/dist/index.es.js +8333 -8060
- 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/useRestoreScroll.d.ts +1 -1
- package/dist/preview/PropertyPreview.d.ts +1 -1
- 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 +13 -1
- package/dist/types/collections.d.ts +14 -1
- package/dist/types/entity_overrides.d.ts +6 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/navigation.d.ts +10 -9
- package/dist/types/permissions.d.ts +5 -1
- package/dist/types/plugins.d.ts +15 -17
- 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/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/package.json +23 -23
- 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 +12 -13
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +8 -15
- 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 +204 -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 +13 -9
- 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 +3 -3
- 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 -2
- package/src/core/Drawer.tsx +66 -39
- package/src/core/{EntityView.tsx → EntityEditView.tsx} +20 -37
- 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 +2 -2
- package/src/form/EntityForm.tsx +19 -11
- package/src/form/components/StorageItemPreview.tsx +5 -3
- package/src/form/components/StorageUploadProgress.tsx +6 -5
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +8 -12
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +15 -15
- package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -0
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -5
- package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
- package/src/form/validation.ts +3 -4
- package/src/hooks/data/useCollectionFetch.tsx +1 -1
- package/src/hooks/data/useDataSource.tsx +8 -3
- package/src/hooks/data/useEntityFetch.tsx +1 -1
- package/src/hooks/useBuildNavigationController.tsx +79 -38
- package/src/hooks/useProjectLog.tsx +11 -3
- package/src/hooks/useReferenceDialog.tsx +2 -2
- package/src/hooks/useStorageSource.tsx +7 -2
- package/src/preview/PropertyPreview.tsx +1 -1
- package/src/preview/components/BooleanPreview.tsx +16 -3
- package/src/preview/components/EnumValuesChip.tsx +1 -1
- package/src/preview/components/ReferencePreview.tsx +54 -146
- package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
- package/src/types/analytics.ts +1 -0
- package/src/types/auth.tsx +17 -1
- package/src/types/collections.ts +16 -1
- package/src/types/entity_actions.tsx +4 -0
- 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 +11 -10
- package/src/types/permissions.ts +6 -1
- package/src/types/plugins.tsx +22 -25
- 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/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/components/HomePage/NavigationCollectionCard.tsx +0 -146
|
@@ -6,7 +6,7 @@ import { PreviewType } from "../../types";
|
|
|
6
6
|
import { UrlComponentPreview } from "../components/UrlComponentPreview";
|
|
7
7
|
import { PropertyPreviewProps } from "../PropertyPreviewProps";
|
|
8
8
|
import { ErrorBoundary } from "../../components";
|
|
9
|
-
import { Chip, getColorSchemeForSeed } from "@firecms/ui";
|
|
9
|
+
import { Chip, cn, getColorSchemeForSeed } from "@firecms/ui";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @group Preview components
|
|
@@ -24,14 +24,14 @@ export function StringPropertyPreview({
|
|
|
24
24
|
return <EnumValuesChip
|
|
25
25
|
enumKey={enumKey}
|
|
26
26
|
enumValues={resolvedProperty.enumValues}
|
|
27
|
-
size={size
|
|
27
|
+
size={size}/>;
|
|
28
28
|
} else if (property.previewAsTag) {
|
|
29
29
|
const colorScheme = getColorSchemeForSeed(propertyKey ?? "");
|
|
30
30
|
return (
|
|
31
31
|
<ErrorBoundary>
|
|
32
32
|
<Chip
|
|
33
33
|
colorScheme={colorScheme}
|
|
34
|
-
size={size
|
|
34
|
+
size={size}>
|
|
35
35
|
{value}
|
|
36
36
|
</Chip>
|
|
37
37
|
</ErrorBoundary>);
|
|
@@ -45,15 +45,16 @@ export function StringPropertyPreview({
|
|
|
45
45
|
if (!value) return <></>;
|
|
46
46
|
const lines = value.split("\n");
|
|
47
47
|
return value && value.includes("\n")
|
|
48
|
-
? <div className={"overflow-x-scroll"}>
|
|
48
|
+
? <div className={cn("overflow-x-scroll", size === "tiny" ? "text-sm" : "")}>
|
|
49
49
|
{lines.map((str, index) =>
|
|
50
50
|
<React.Fragment key={`string_preview_${index}`}>
|
|
51
51
|
<span>{str}</span>
|
|
52
52
|
{index !== lines.length - 1 && <br/>}
|
|
53
53
|
</React.Fragment>)}
|
|
54
54
|
</div>
|
|
55
|
-
:
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
: (size === "tiny"
|
|
56
|
+
? <span className={"text-sm"}>{value}</span>
|
|
57
|
+
: <>{value}</>
|
|
58
|
+
);
|
|
58
59
|
}
|
|
59
60
|
}
|
package/src/types/analytics.ts
CHANGED
package/src/types/auth.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { User } from "./user";
|
|
2
|
+
import { Role } from "./roles";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Controller for retrieving the logged user or performing auth related operations.
|
|
@@ -6,7 +7,7 @@ import { User } from "./user";
|
|
|
6
7
|
* to do it as the result of a hook.
|
|
7
8
|
* @group Hooks and utilities
|
|
8
9
|
*/
|
|
9
|
-
export type AuthController<UserType extends User = User> = {
|
|
10
|
+
export type AuthController<UserType extends User = User, ExtraData extends any = any> = {
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* The user currently logged in
|
|
@@ -14,6 +15,11 @@ export type AuthController<UserType extends User = User> = {
|
|
|
14
15
|
*/
|
|
15
16
|
user: UserType | null;
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Roles related to the logged user
|
|
20
|
+
*/
|
|
21
|
+
roles?: Role[];
|
|
22
|
+
|
|
17
23
|
/**
|
|
18
24
|
* Initial loading flag. It is used not to display the login screen
|
|
19
25
|
* when the app first loads, and it has not been checked whether the user
|
|
@@ -21,6 +27,12 @@ export type AuthController<UserType extends User = User> = {
|
|
|
21
27
|
*/
|
|
22
28
|
initialLoading?: boolean;
|
|
23
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Loading flag. It is used to display a loading screen when the user is
|
|
32
|
+
* logging in or out.
|
|
33
|
+
*/
|
|
34
|
+
authLoading: boolean;
|
|
35
|
+
|
|
24
36
|
/**
|
|
25
37
|
* Sign out
|
|
26
38
|
*/
|
|
@@ -46,4 +58,8 @@ export type AuthController<UserType extends User = User> = {
|
|
|
46
58
|
*/
|
|
47
59
|
loginSkipped: boolean;
|
|
48
60
|
|
|
61
|
+
extra: ExtraData;
|
|
62
|
+
|
|
63
|
+
setExtra: (extra: ExtraData) => void;
|
|
64
|
+
|
|
49
65
|
};
|
package/src/types/collections.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { EnumValues, PropertiesOrBuilders } from "./properties";
|
|
|
8
8
|
import { FormContext } from "./fields";
|
|
9
9
|
import { EntityAction } from "./entity_actions";
|
|
10
10
|
import { ExportConfig } from "./export_import";
|
|
11
|
+
import { EntityOverrides } from "./entity_overrides";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* This interface represents a view that includes a collection of entities.
|
|
@@ -76,6 +77,13 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
|
|
|
76
77
|
*/
|
|
77
78
|
properties: PropertiesOrBuilders<M>;
|
|
78
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Title property of the entity. This is the property that will be used
|
|
82
|
+
* as the title in entity related views and references.
|
|
83
|
+
* If not specified, the first property simple text property will be used.
|
|
84
|
+
*/
|
|
85
|
+
titleProperty?: keyof M,
|
|
86
|
+
|
|
79
87
|
/**
|
|
80
88
|
* Can this collection be edited by the end user.
|
|
81
89
|
* Defaults to `true`.
|
|
@@ -276,6 +284,13 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
|
|
|
276
284
|
*
|
|
277
285
|
*/
|
|
278
286
|
exportable?: boolean | ExportConfig<UserType>;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* User id of the owner of this collection. This is used only by plugins, or if you
|
|
290
|
+
* are writing custom code
|
|
291
|
+
*/
|
|
292
|
+
ownerId?: string;
|
|
293
|
+
overrides?: EntityOverrides;
|
|
279
294
|
}
|
|
280
295
|
|
|
281
296
|
/**
|
|
@@ -346,7 +361,7 @@ export type SelectionController<M extends Record<string, any> = any> = {
|
|
|
346
361
|
|
|
347
362
|
/**
|
|
348
363
|
* Filter conditions in a `Query.where()` clause are specified using the
|
|
349
|
-
* strings
|
|
364
|
+
* strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.
|
|
350
365
|
* @group Models
|
|
351
366
|
*/
|
|
352
367
|
export type WhereFilterOp =
|
|
@@ -4,6 +4,7 @@ import { Entity } from "./entities";
|
|
|
4
4
|
import { EntityCollection, SelectionController } from "./collections";
|
|
5
5
|
import { User } from "./user";
|
|
6
6
|
import { SideEntityController } from "./side_entity_controller";
|
|
7
|
+
import { EntityOverrides } from "./entity_overrides";
|
|
7
8
|
|
|
8
9
|
export type EntityAction<M extends object = any, UserType extends User = User> = {
|
|
9
10
|
name: string;
|
|
@@ -21,8 +22,11 @@ export type EntityAction<M extends object = any, UserType extends User = User> =
|
|
|
21
22
|
* Show this action in the form, defaults to true
|
|
22
23
|
*/
|
|
23
24
|
includeInForm?: boolean;
|
|
25
|
+
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
|
|
29
|
+
|
|
26
30
|
export type EntityActionClickProps<M extends object, UserType extends User = User> = {
|
|
27
31
|
entity: Entity<M>;
|
|
28
32
|
context: FireCMSContext<UserType>;
|
package/src/types/firecms.tsx
CHANGED
package/src/types/index.ts
CHANGED
|
@@ -17,10 +17,12 @@ export * from "./side_entity_controller";
|
|
|
17
17
|
export * from "./side_dialogs_controller";
|
|
18
18
|
export * from "./firecms_context";
|
|
19
19
|
export * from "./entity_callbacks";
|
|
20
|
+
export * from "./entity_overrides";
|
|
20
21
|
export * from "./local_config_persistence";
|
|
21
22
|
export * from "./plugins";
|
|
22
23
|
export * from "./analytics";
|
|
23
24
|
export * from "./firecms";
|
|
25
|
+
export * from "./roles";
|
|
24
26
|
export * from "./appcheck";
|
|
25
27
|
export * from "./export_import";
|
|
26
28
|
export * from "./modify_collections";
|
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
|
|
|
@@ -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
|
|
@@ -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.
|
|
@@ -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/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): 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
|
+
}
|