@firecms/core 3.0.0-beta.14 → 3.0.0-beta.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
- package/dist/components/HomePage/DefaultHomePage.d.ts +2 -15
- package/dist/components/HomePage/HomePageDnD.d.ts +76 -0
- package/dist/components/HomePage/NavigationCard.d.ts +3 -1
- package/dist/components/HomePage/NavigationCardBinding.d.ts +3 -2
- package/dist/components/HomePage/NavigationGroup.d.ts +7 -1
- package/dist/components/HomePage/RenameGroupDialog.d.ts +9 -0
- package/dist/core/EntityEditView.d.ts +3 -0
- package/dist/core/EntityEditViewFormActions.d.ts +1 -1
- package/dist/core/field_configs.d.ts +1 -1
- package/dist/form/EntityForm.d.ts +2 -1
- package/dist/form/EntityFormActions.d.ts +6 -2
- package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +9 -0
- package/dist/form/index.d.ts +1 -0
- package/dist/hooks/useBuildNavigationController.d.ts +51 -2
- package/dist/index.es.js +2184 -1052
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +2181 -1049
- package/dist/index.umd.js.map +1 -1
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/collections.d.ts +8 -2
- package/dist/types/customization_controller.d.ts +8 -0
- package/dist/types/entity_actions.d.ts +46 -6
- package/dist/types/firecms.d.ts +8 -0
- package/dist/types/navigation.d.ts +21 -5
- package/dist/types/plugins.d.ts +20 -1
- package/dist/types/properties.d.ts +7 -0
- package/dist/types/property_config.d.ts +1 -1
- package/dist/types/side_entity_controller.d.ts +4 -0
- package/dist/util/icons.d.ts +2 -2
- package/dist/util/navigation_from_path.d.ts +4 -0
- package/dist/util/resolutions.d.ts +2 -1
- package/package.json +5 -5
- package/src/components/ConfirmationDialog.tsx +1 -0
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +6 -0
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +25 -3
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +2 -2
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +7 -4
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +3 -2
- package/src/components/FireCMSLogo.tsx +7 -51
- package/src/components/HomePage/DefaultHomePage.tsx +491 -157
- package/src/components/HomePage/FavouritesView.tsx +3 -3
- package/src/components/HomePage/HomePageDnD.tsx +599 -0
- package/src/components/HomePage/NavigationCard.tsx +47 -38
- package/src/components/HomePage/NavigationCardBinding.tsx +10 -6
- package/src/components/HomePage/NavigationGroup.tsx +63 -29
- package/src/components/HomePage/RenameGroupDialog.tsx +117 -0
- package/src/components/UnsavedChangesDialog.tsx +6 -2
- package/src/components/common/default_entity_actions.tsx +25 -9
- package/src/components/common/useDataSourceTableController.tsx +2 -2
- package/src/core/DefaultDrawer.tsx +8 -8
- package/src/core/DrawerNavigationItem.tsx +1 -1
- package/src/core/EntityEditView.tsx +41 -6
- package/src/core/EntityEditViewFormActions.tsx +154 -29
- package/src/core/EntitySidePanel.tsx +5 -2
- package/src/core/FireCMS.tsx +2 -0
- package/src/core/field_configs.tsx +15 -1
- package/src/form/EntityForm.tsx +36 -4
- package/src/form/EntityFormActions.tsx +51 -9
- package/src/form/components/StorageItemPreview.tsx +1 -1
- package/src/form/components/StorageUploadProgress.tsx +3 -3
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +4 -2
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +135 -0
- package/src/form/field_bindings/RepeatFieldBinding.tsx +0 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +12 -17
- package/src/form/index.tsx +1 -0
- package/src/hooks/useBuildNavigationController.tsx +273 -84
- package/src/internal/useBuildSideEntityController.tsx +7 -4
- package/src/preview/PropertyPreview.tsx +14 -0
- package/src/routes/FireCMSRoute.tsx +3 -3
- package/src/types/analytics.ts +3 -0
- package/src/types/collections.ts +8 -2
- package/src/types/customization_controller.tsx +9 -0
- package/src/types/entity_actions.tsx +57 -6
- package/src/types/firecms.tsx +9 -0
- package/src/types/navigation.ts +28 -6
- package/src/types/plugins.tsx +24 -1
- package/src/types/properties.ts +8 -0
- package/src/types/property_config.tsx +1 -0
- package/src/types/side_entity_controller.tsx +5 -0
- package/src/util/icons.tsx +22 -7
- package/src/util/join_collections.ts +3 -1
- package/src/util/navigation_from_path.ts +15 -5
- package/src/util/navigation_utils.ts +2 -2
- package/src/util/resolutions.ts +13 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export type CMSAnalyticsEvent = "entity_click" | "entity_click_from_reference" | "reference_selection_clear" | "reference_selection_toggle" | "reference_selected_single" | "reference_selection_new_entity" | "edit_entity_clicked" | "entity_edited" | "new_entity_click" | "new_entity_saved" | "copy_entity_click" | "entity_copied" | "single_delete_dialog_open" | "multiple_delete_dialog_open" | "single_entity_deleted" | "multiple_entities_deleted" | "drawer_navigate_to_home" | "drawer_navigate_to_collection" | "drawer_navigate_to_view" | "home_navigate_to_collection" | "home_favorite_navigate_to_collection" | "home_navigate_to_view" | "home_navigate_to_admin_view" | "home_favorite_navigate_to_view" | "collection_inline_editing" | "unmapped_event";
|
|
1
|
+
export type CMSAnalyticsEvent = "entity_click" | "entity_click_from_reference" | "reference_selection_clear" | "reference_selection_toggle" | "reference_selected_single" | "reference_selection_new_entity" | "edit_entity_clicked" | "entity_edited" | "new_entity_click" | "new_entity_saved" | "copy_entity_click" | "entity_copied" | "single_delete_dialog_open" | "multiple_delete_dialog_open" | "single_entity_deleted" | "multiple_entities_deleted" | "drawer_navigate_to_home" | "drawer_navigate_to_collection" | "drawer_navigate_to_view" | "home_navigate_to_collection" | "home_favorite_navigate_to_collection" | "home_navigate_to_view" | "home_navigate_to_admin_view" | "home_favorite_navigate_to_view" | "home_move_card" | "home_move_group" | "home_drop_new_group" | "collection_inline_editing" | "unmapped_event";
|
|
@@ -61,11 +61,14 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
|
|
|
61
61
|
* e.g. 'account_tree' or 'person'.
|
|
62
62
|
* Find all the icons in https://firecms.co/docs/icons
|
|
63
63
|
*/
|
|
64
|
-
icon?: string;
|
|
64
|
+
icon?: string | React.ReactNode;
|
|
65
65
|
/**
|
|
66
66
|
* Optional field used to group top level navigation entries under a~
|
|
67
67
|
* navigation view. If you set this value in a subcollection it has no
|
|
68
68
|
* effect.
|
|
69
|
+
* @deprecated This prop is deprecated and will be removed in the future.
|
|
70
|
+
* You can apply grouping by using the `navigationGroupMappings` prop in the
|
|
71
|
+
* {@link useBuildNavigationController} hook instead.
|
|
69
72
|
*/
|
|
70
73
|
group?: string;
|
|
71
74
|
/**
|
|
@@ -170,8 +173,11 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
|
|
|
170
173
|
* }
|
|
171
174
|
* }
|
|
172
175
|
* ```
|
|
176
|
+
*
|
|
177
|
+
* You can also pass the action as a string that represents the `key`, in which case it will
|
|
178
|
+
* use the action defined in the main configuration under `entityActions`.
|
|
173
179
|
*/
|
|
174
|
-
entityActions?: EntityAction<M, USER>[];
|
|
180
|
+
entityActions?: (EntityAction<M, USER> | string)[];
|
|
175
181
|
/**
|
|
176
182
|
* Pass your own selection controller if you want to control selected
|
|
177
183
|
* entities externally.
|
|
@@ -4,6 +4,7 @@ import { FireCMSPlugin } from "./plugins";
|
|
|
4
4
|
import { EntityCustomView } from "./collections";
|
|
5
5
|
import { Locale } from "./locales";
|
|
6
6
|
import { PropertyConfig } from "./property_config";
|
|
7
|
+
import { EntityAction } from "./entity_actions";
|
|
7
8
|
export type CustomizationController = {
|
|
8
9
|
/**
|
|
9
10
|
* Builder for generating utility links for entities
|
|
@@ -21,6 +22,13 @@ export type CustomizationController = {
|
|
|
21
22
|
* You can also define an entity view from the UI.
|
|
22
23
|
*/
|
|
23
24
|
entityViews?: EntityCustomView[];
|
|
25
|
+
/**
|
|
26
|
+
* List of actions that can be performed on entities.
|
|
27
|
+
* These actions are displayed in the entity view and in the collection view.
|
|
28
|
+
* You can later reuse these actions in the `entityActions` prop of a collection,
|
|
29
|
+
* by specifying the `key` of the action.
|
|
30
|
+
*/
|
|
31
|
+
entityActions?: EntityAction<any, any>[];
|
|
24
32
|
/**
|
|
25
33
|
* Format of the dates in the CMS.
|
|
26
34
|
* Defaults to 'MMMM dd, yyyy, HH:mm:ss'
|
|
@@ -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 { FormContext } from "./fields";
|
|
7
8
|
/**
|
|
8
9
|
* An entity action is a custom action that can be performed on an entity.
|
|
9
10
|
* They are displayed in the entity view and in the collection view.
|
|
@@ -15,7 +16,10 @@ export type EntityAction<M extends object = any, USER extends User = User> = {
|
|
|
15
16
|
name: string;
|
|
16
17
|
/**
|
|
17
18
|
* Key of the action. You only need to provide this if you want to
|
|
18
|
-
* override the default actions
|
|
19
|
+
* override the default actions, or if you are not passing the action
|
|
20
|
+
* directly to the `entityActions` prop of a collection.
|
|
21
|
+
* You can define your actions at the app level, in which case you
|
|
22
|
+
* must provide a key.
|
|
19
23
|
* The default actions are:
|
|
20
24
|
* - edit
|
|
21
25
|
* - delete
|
|
@@ -31,6 +35,11 @@ export type EntityAction<M extends object = any, USER extends User = User> = {
|
|
|
31
35
|
* @param props
|
|
32
36
|
*/
|
|
33
37
|
onClick: (props: EntityActionClickProps<M, USER>) => Promise<void> | void;
|
|
38
|
+
/**
|
|
39
|
+
* Optional callback in case you want to disable the action
|
|
40
|
+
* @param props
|
|
41
|
+
*/
|
|
42
|
+
isEnabled?: (props: EntityActionClickProps<M, USER>) => boolean;
|
|
34
43
|
/**
|
|
35
44
|
* Show this action collapsed in the menu of the collection view.
|
|
36
45
|
* Defaults to true
|
|
@@ -43,17 +52,48 @@ export type EntityAction<M extends object = any, USER extends User = User> = {
|
|
|
43
52
|
includeInForm?: boolean;
|
|
44
53
|
};
|
|
45
54
|
export type EntityActionClickProps<M extends object, USER extends User = User> = {
|
|
46
|
-
entity
|
|
55
|
+
entity?: Entity<M>;
|
|
47
56
|
context: FireCMSContext<USER>;
|
|
48
57
|
fullPath?: string;
|
|
58
|
+
fullIdPath?: string;
|
|
49
59
|
collection?: EntityCollection<M>;
|
|
60
|
+
/**
|
|
61
|
+
* Optional form context, present if the action is being called from a form.
|
|
62
|
+
* This allows you to access the form state and methods, including modifying the form values.
|
|
63
|
+
*/
|
|
64
|
+
formContext?: FormContext;
|
|
65
|
+
/**
|
|
66
|
+
* Present if this actions is being called from a side dialog only
|
|
67
|
+
*/
|
|
68
|
+
sideEntityController?: SideEntityController;
|
|
69
|
+
/**
|
|
70
|
+
* Is the action being called from the collection view or from the entity form view?
|
|
71
|
+
*/
|
|
72
|
+
view: "collection" | "form";
|
|
73
|
+
/**
|
|
74
|
+
* If the action is rendered in the form, is it open in a side panel or full screen?
|
|
75
|
+
*/
|
|
76
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
77
|
+
/**
|
|
78
|
+
* Optional selection controller, present if the action is being called from a collection view
|
|
79
|
+
*/
|
|
50
80
|
selectionController?: SelectionController;
|
|
81
|
+
/**
|
|
82
|
+
* Optional highlight function to highlight the entity in the collection view
|
|
83
|
+
* @param entity
|
|
84
|
+
*/
|
|
51
85
|
highlightEntity?: (entity: Entity<any>) => void;
|
|
86
|
+
/**
|
|
87
|
+
* Optional unhighlight function to remove the highlight from the entity in the collection view
|
|
88
|
+
* @param entity
|
|
89
|
+
*/
|
|
52
90
|
unhighlightEntity?: (entity: Entity<any>) => void;
|
|
53
|
-
onCollectionChange?: () => void;
|
|
54
91
|
/**
|
|
55
|
-
*
|
|
92
|
+
* Optional function to navigate back (e.g. when deleting an entity or navigating from a form)
|
|
56
93
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
94
|
+
navigateBack?: () => void;
|
|
95
|
+
/**
|
|
96
|
+
* Callback to be called when the collection changes, e.g. after an entity is deleted or created.
|
|
97
|
+
*/
|
|
98
|
+
onCollectionChange?: () => void;
|
|
59
99
|
};
|
package/dist/types/firecms.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { EntityLinkBuilder } from "./entity_link_builder";
|
|
|
12
12
|
import { UserConfigurationPersistence } from "./local_config_persistence";
|
|
13
13
|
import { FireCMSPlugin } from "./plugins";
|
|
14
14
|
import { CMSAnalyticsEvent } from "./analytics";
|
|
15
|
+
import { EntityAction } from "./entity_actions";
|
|
15
16
|
/**
|
|
16
17
|
* Use this callback to build entity collections dynamically.
|
|
17
18
|
* You can use the user to decide which collections to show.
|
|
@@ -85,6 +86,13 @@ export type FireCMSProps<USER extends User> = {
|
|
|
85
86
|
* You can also define an entity view from the UI.
|
|
86
87
|
*/
|
|
87
88
|
entityViews?: EntityCustomView[];
|
|
89
|
+
/**
|
|
90
|
+
* List of actions that can be performed on entities.
|
|
91
|
+
* These actions are displayed in the entity view and in the collection view.
|
|
92
|
+
* You can later reuse these actions in the `entityActions` prop of a collection,
|
|
93
|
+
* by specifying the `key` of the action.
|
|
94
|
+
*/
|
|
95
|
+
entityActions?: EntityAction[];
|
|
88
96
|
/**
|
|
89
97
|
* Format of the dates in the CMS.
|
|
90
98
|
* Defaults to 'MMMM dd, yyyy, HH:mm:ss'
|
|
@@ -31,7 +31,7 @@ export type NavigationController<EC extends EntityCollection = EntityCollection<
|
|
|
31
31
|
* level of the navigation (e.g. in the home page or the navigation
|
|
32
32
|
* drawer)
|
|
33
33
|
*/
|
|
34
|
-
topLevelNavigation?:
|
|
34
|
+
topLevelNavigation?: NavigationResult;
|
|
35
35
|
/**
|
|
36
36
|
* Is the navigation loading (the configuration persistence has not
|
|
37
37
|
* loaded yet, or a specified navigation builder has not completed)
|
|
@@ -172,7 +172,7 @@ export interface CMSView {
|
|
|
172
172
|
* e.g. 'account_tree' or 'person'
|
|
173
173
|
* Find all the icons in https://firecms.co/docs/icons
|
|
174
174
|
*/
|
|
175
|
-
icon?: string;
|
|
175
|
+
icon?: string | React.ReactNode;
|
|
176
176
|
/**
|
|
177
177
|
* Should this view be hidden from the main navigation panel.
|
|
178
178
|
* It will still be accessible if you reach the specified path
|
|
@@ -190,7 +190,21 @@ export interface CMSView {
|
|
|
190
190
|
*/
|
|
191
191
|
group?: string;
|
|
192
192
|
}
|
|
193
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Used to group navigation entries in the main navigation.
|
|
195
|
+
*/
|
|
196
|
+
export interface NavigationGroupMapping {
|
|
197
|
+
/**
|
|
198
|
+
* Name of the group, used to display the group header in the UI
|
|
199
|
+
*/
|
|
200
|
+
name: string;
|
|
201
|
+
/**
|
|
202
|
+
* List of collection ids or view paths that belong to this group.
|
|
203
|
+
*/
|
|
204
|
+
entries: string[];
|
|
205
|
+
}
|
|
206
|
+
export interface NavigationEntry {
|
|
207
|
+
id: string;
|
|
194
208
|
url: string;
|
|
195
209
|
name: string;
|
|
196
210
|
path: string;
|
|
@@ -200,7 +214,9 @@ export interface TopNavigationEntry {
|
|
|
200
214
|
description?: string;
|
|
201
215
|
group: string;
|
|
202
216
|
}
|
|
203
|
-
export type
|
|
204
|
-
|
|
217
|
+
export type NavigationResult = {
|
|
218
|
+
allowDragAndDrop: boolean;
|
|
219
|
+
navigationEntries: NavigationEntry[];
|
|
205
220
|
groups: string[];
|
|
221
|
+
onNavigationEntriesUpdate: (entries: NavigationGroupMapping[]) => void;
|
|
206
222
|
};
|
package/dist/types/plugins.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { FieldProps, FormContext } from "./fields";
|
|
|
6
6
|
import { CMSType, Property } from "./properties";
|
|
7
7
|
import { EntityStatus } from "./entities";
|
|
8
8
|
import { ResolvedProperty } from "./resolved_entities";
|
|
9
|
+
import { NavigationGroupMapping } from "./navigation";
|
|
9
10
|
/**
|
|
10
11
|
* Interface used to define plugins for FireCMS.
|
|
11
12
|
* NOTE: This is a work in progress and the API is not stable yet.
|
|
@@ -70,6 +71,17 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
70
71
|
title: string;
|
|
71
72
|
children: React.ReactNode;
|
|
72
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* Allow reordering with drag and drop of the collections in the home page.
|
|
76
|
+
*/
|
|
77
|
+
allowDragAndDrop?: boolean;
|
|
78
|
+
navigationEntries?: NavigationGroupMapping[];
|
|
79
|
+
/**
|
|
80
|
+
* This method will be called when the entries are updated in the home page.
|
|
81
|
+
* group => navigationEntriesOrder (path)
|
|
82
|
+
* @param entries
|
|
83
|
+
*/
|
|
84
|
+
onNavigationEntriesUpdate?: (entries: NavigationGroupMapping[]) => void;
|
|
73
85
|
};
|
|
74
86
|
collectionView?: {
|
|
75
87
|
/**
|
|
@@ -127,7 +139,14 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
127
139
|
Component: React.ComponentType<PropsWithChildren<FORM_PROPS & PluginFormActionProps<any, EC>>>;
|
|
128
140
|
props?: FORM_PROPS;
|
|
129
141
|
};
|
|
142
|
+
/**
|
|
143
|
+
* Add custom actions to the default ones ("Save", "Discard"...)
|
|
144
|
+
*/
|
|
130
145
|
Actions?: React.ComponentType<PluginFormActionProps<any, EC>>;
|
|
146
|
+
/**
|
|
147
|
+
* Add custom actions to the top of the form
|
|
148
|
+
*/
|
|
149
|
+
ActionsTop?: React.ComponentType<PluginFormActionProps<any, EC>>;
|
|
131
150
|
fieldBuilder?: <T extends CMSType = CMSType>(props: PluginFieldBuilderParams<T, any, EC>) => React.ComponentType<FieldProps<T>> | null;
|
|
132
151
|
fieldBuilderEnabled?: <T extends CMSType = CMSType>(props: PluginFieldBuilderParams<T>) => boolean;
|
|
133
152
|
};
|
|
@@ -169,12 +188,12 @@ export interface PluginHomePageActionsProps<EP extends object = object, M extend
|
|
|
169
188
|
export interface PluginFormActionProps<USER extends User = User, EC extends EntityCollection = EntityCollection> {
|
|
170
189
|
entityId?: string;
|
|
171
190
|
path: string;
|
|
191
|
+
parentCollectionIds: string[];
|
|
172
192
|
status: EntityStatus;
|
|
173
193
|
collection: EC;
|
|
174
194
|
disabled: boolean;
|
|
175
195
|
formContext?: FormContext<any>;
|
|
176
196
|
context: FireCMSContext<USER>;
|
|
177
|
-
currentEntityId?: string;
|
|
178
197
|
openEntityMode: "side_panel" | "full_screen";
|
|
179
198
|
}
|
|
180
199
|
export type PluginFieldBuilderParams<T extends CMSType = CMSType, M extends Record<string, any> = any, EC extends EntityCollection<M> = EntityCollection<M>> = {
|
|
@@ -312,6 +312,13 @@ export interface StringProperty extends BaseProperty<string> {
|
|
|
312
312
|
* Add an icon to clear the value and set it to `null`. Defaults to `false`
|
|
313
313
|
*/
|
|
314
314
|
clearable?: boolean;
|
|
315
|
+
/**
|
|
316
|
+
* You can use this property (a string) to behave as a reference to another
|
|
317
|
+
* collection. The stored value is the ID of the entity in the
|
|
318
|
+
* collection, and the `path` prop is used to
|
|
319
|
+
* define the collection this reference points to.
|
|
320
|
+
*/
|
|
321
|
+
reference?: ReferenceProperty;
|
|
315
322
|
}
|
|
316
323
|
/**
|
|
317
324
|
* @group Entity properties
|
|
@@ -37,4 +37,4 @@ export type PropertyConfig<T extends CMSType = any> = {
|
|
|
37
37
|
*/
|
|
38
38
|
description?: string;
|
|
39
39
|
};
|
|
40
|
-
export type PropertyConfigId = "text_field" | "multiline" | "markdown" | "url" | "email" | "select" | "multi_select" | "number_input" | "number_select" | "multi_number_select" | "file_upload" | "multi_file_upload" | "group" | "key_value" | "reference" | "multi_references" | "switch" | "date_time" | "repeat" | "custom_array" | "block";
|
|
40
|
+
export type PropertyConfigId = "text_field" | "multiline" | "markdown" | "url" | "email" | "select" | "multi_select" | "number_input" | "number_select" | "multi_number_select" | "file_upload" | "multi_file_upload" | "group" | "key_value" | "reference" | "reference_as_string" | "multi_references" | "switch" | "date_time" | "repeat" | "custom_array" | "block";
|
|
@@ -11,6 +11,10 @@ export interface EntitySidePanelProps<M extends Record<string, any> = any> {
|
|
|
11
11
|
* Absolute path of the entity
|
|
12
12
|
*/
|
|
13
13
|
path: string;
|
|
14
|
+
/**
|
|
15
|
+
* Full CMS path of the entity, including the collection and sub-collections.
|
|
16
|
+
*/
|
|
17
|
+
fullIdPath?: string;
|
|
14
18
|
/**
|
|
15
19
|
* ID of the entity, if not set, it means we are creating a new entity
|
|
16
20
|
*/
|
package/dist/util/icons.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { IconColor } from "@firecms/ui";
|
|
3
|
-
export declare function getIcon(iconKey?: string, className?: string, color?: IconColor): React.ReactElement | undefined;
|
|
3
|
+
export declare function getIcon(iconKey?: string | React.ReactNode, className?: string, color?: IconColor, size?: "smallest" | "small" | "medium" | "large" | number): React.ReactElement | undefined;
|
|
4
4
|
export type IconViewProps = {
|
|
5
5
|
path: string;
|
|
6
6
|
name: string;
|
|
7
7
|
singularName?: string;
|
|
8
8
|
group?: string;
|
|
9
|
-
icon?: string;
|
|
9
|
+
icon?: string | React.ReactNode;
|
|
10
10
|
};
|
|
11
11
|
export declare const IconForView: React.NamedExoticComponent<{
|
|
12
12
|
collectionOrView?: IconViewProps;
|
|
@@ -4,6 +4,7 @@ export interface NavigationViewEntityInternal<M extends Record<string, any>> {
|
|
|
4
4
|
type: "entity";
|
|
5
5
|
entityId: string;
|
|
6
6
|
path: string;
|
|
7
|
+
fullIdPath: string;
|
|
7
8
|
fullPath: string;
|
|
8
9
|
parentCollection: EntityCollection<M>;
|
|
9
10
|
}
|
|
@@ -11,12 +12,14 @@ export interface NavigationViewCollectionInternal<M extends Record<string, any>>
|
|
|
11
12
|
type: "collection";
|
|
12
13
|
id: string;
|
|
13
14
|
path: string;
|
|
15
|
+
fullIdPath: string;
|
|
14
16
|
fullPath: string;
|
|
15
17
|
collection: EntityCollection<M>;
|
|
16
18
|
}
|
|
17
19
|
export interface NavigationViewEntityCustomInternal<M extends Record<string, any>> {
|
|
18
20
|
type: "custom_view";
|
|
19
21
|
path: string;
|
|
22
|
+
fullIdPath: string;
|
|
20
23
|
fullPath: string;
|
|
21
24
|
entityId: string;
|
|
22
25
|
view: EntityCustomView<M>;
|
|
@@ -25,5 +28,6 @@ export declare function getNavigationEntriesFromPath(props: {
|
|
|
25
28
|
path: string;
|
|
26
29
|
collections: EntityCollection[] | undefined;
|
|
27
30
|
currentFullPath?: string;
|
|
31
|
+
currentFullIdPath?: string;
|
|
28
32
|
contextEntityViews?: EntityCustomView<any>[];
|
|
29
33
|
}): NavigationViewInternal[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrayProperty, AuthController, CMSType, CustomizationController, EntityCollection, EntityCustomView, EntityValues, EnumValueConfig, EnumValues, NumberProperty, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedArrayProperty, ResolvedEntityCollection, ResolvedNumberProperty, ResolvedProperties, ResolvedProperty, ResolvedStringProperty, StringProperty, UserConfigurationPersistence } from "../types";
|
|
1
|
+
import { ArrayProperty, AuthController, CMSType, CustomizationController, EntityAction, EntityCollection, EntityCustomView, EntityValues, EnumValueConfig, EnumValues, NumberProperty, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedArrayProperty, ResolvedEntityCollection, ResolvedNumberProperty, ResolvedProperties, ResolvedProperty, ResolvedStringProperty, StringProperty, UserConfigurationPersistence } from "../types";
|
|
2
2
|
export declare const resolveCollection: <M extends Record<string, any>>({ collection, path, entityId, values, previousValues, userConfigPersistence, propertyConfigs, ignoreMissingFields, authController }: {
|
|
3
3
|
collection: EntityCollection<M> | ResolvedEntityCollection<M>;
|
|
4
4
|
path: string;
|
|
@@ -81,6 +81,7 @@ export declare function resolveProperties<M extends Record<string, any>>({ prope
|
|
|
81
81
|
export declare function resolvePropertyEnum(property: StringProperty | NumberProperty, fromBuilder?: boolean): ResolvedStringProperty | ResolvedNumberProperty;
|
|
82
82
|
export declare function resolveEnumValues(input: EnumValues): EnumValueConfig[] | undefined;
|
|
83
83
|
export declare function resolveEntityView(entityView: string | EntityCustomView<any>, contextEntityViews?: EntityCustomView<any>[]): EntityCustomView<any> | undefined;
|
|
84
|
+
export declare function resolveEntityAction<M extends Record<string, any>>(entityAction: string | EntityAction<M>, contextEntityActions?: EntityAction<M>[]): EntityAction<M> | undefined;
|
|
84
85
|
export declare function resolvedSelectedEntityView<M extends Record<string, any>>(customViews: (string | EntityCustomView<M>)[] | undefined, customizationController: CustomizationController, selectedTab?: string, canEdit?: boolean): {
|
|
85
86
|
resolvedEntityViews: EntityCustomView<M>[];
|
|
86
87
|
selectedEntityView: EntityCustomView<M> | undefined;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-beta.
|
|
4
|
+
"version": "3.0.0-beta.15",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"@dnd-kit/core": "^6.3.1",
|
|
54
54
|
"@dnd-kit/modifiers": "^9.0.0",
|
|
55
55
|
"@dnd-kit/sortable": "^10.0.0",
|
|
56
|
-
"@firecms/editor": "^3.0.0-beta.
|
|
57
|
-
"@firecms/formex": "^3.0.0-beta.
|
|
58
|
-
"@firecms/ui": "^3.0.0-beta.
|
|
56
|
+
"@firecms/editor": "^3.0.0-beta.15",
|
|
57
|
+
"@firecms/formex": "^3.0.0-beta.15",
|
|
58
|
+
"@firecms/ui": "^3.0.0-beta.15",
|
|
59
59
|
"@radix-ui/react-portal": "^1.1.3",
|
|
60
60
|
"clsx": "^2.1.1",
|
|
61
61
|
"date-fns": "^3.6.0",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"dist",
|
|
108
108
|
"src"
|
|
109
109
|
],
|
|
110
|
-
"gitHead": "
|
|
110
|
+
"gitHead": "0abe2ca034f396e389db595f07ef4b24b439c648",
|
|
111
111
|
"publishConfig": {
|
|
112
112
|
"access": "public"
|
|
113
113
|
},
|
|
@@ -33,6 +33,7 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
33
33
|
entity,
|
|
34
34
|
collection,
|
|
35
35
|
fullPath,
|
|
36
|
+
fullIdPath,
|
|
36
37
|
width,
|
|
37
38
|
frozen,
|
|
38
39
|
isSelected,
|
|
@@ -50,6 +51,7 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
50
51
|
entity: Entity<any>,
|
|
51
52
|
collection?: EntityCollection<any>,
|
|
52
53
|
fullPath?: string,
|
|
54
|
+
fullIdPath?: string,
|
|
53
55
|
width: number,
|
|
54
56
|
frozen?: boolean,
|
|
55
57
|
size: CollectionSize,
|
|
@@ -105,8 +107,10 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
105
107
|
onClick={(event: MouseEvent) => {
|
|
106
108
|
event.stopPropagation();
|
|
107
109
|
action.onClick({
|
|
110
|
+
view: "collection",
|
|
108
111
|
entity,
|
|
109
112
|
fullPath,
|
|
113
|
+
fullIdPath,
|
|
110
114
|
collection,
|
|
111
115
|
context,
|
|
112
116
|
selectionController,
|
|
@@ -134,8 +138,10 @@ export const EntityCollectionRowActions = function EntityCollectionRowActions({
|
|
|
134
138
|
onClick={(e) => {
|
|
135
139
|
e.stopPropagation();
|
|
136
140
|
action.onClick({
|
|
141
|
+
view: "collection",
|
|
137
142
|
entity,
|
|
138
143
|
fullPath,
|
|
144
|
+
fullIdPath,
|
|
139
145
|
collection,
|
|
140
146
|
context,
|
|
141
147
|
selectionController,
|
|
@@ -4,10 +4,12 @@ import {
|
|
|
4
4
|
CMSType,
|
|
5
5
|
Entity,
|
|
6
6
|
EntityReference,
|
|
7
|
+
ReferenceProperty,
|
|
7
8
|
ResolvedArrayProperty,
|
|
8
9
|
ResolvedNumberProperty,
|
|
9
10
|
ResolvedProperty,
|
|
10
|
-
ResolvedStringProperty
|
|
11
|
+
ResolvedStringProperty,
|
|
12
|
+
StringProperty
|
|
11
13
|
} from "../../types";
|
|
12
14
|
|
|
13
15
|
import { VirtualTableInput } from "../VirtualTable/fields/VirtualTableInput";
|
|
@@ -251,7 +253,27 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
251
253
|
|
|
252
254
|
if (!customField && (!customPreview || selected)) {
|
|
253
255
|
const isAStorageProperty = isStorageProperty(property);
|
|
254
|
-
if (
|
|
256
|
+
if (property.dataType === "string" && (property as StringProperty).reference?.path) {
|
|
257
|
+
const stringProperty = property as StringProperty;
|
|
258
|
+
const path = stringProperty.reference?.path as string;
|
|
259
|
+
const referenceProperty = stringProperty.reference as ReferenceProperty;
|
|
260
|
+
const referenceValue = internalValue ? new EntityReference(internalValue, path) : undefined;
|
|
261
|
+
innerComponent =
|
|
262
|
+
<TableReferenceField name={propertyKey as string}
|
|
263
|
+
internalValue={referenceValue}
|
|
264
|
+
updateValue={(v) => updateValue(v ? (v as EntityReference).id : null)}
|
|
265
|
+
disabled={disabled}
|
|
266
|
+
size={size}
|
|
267
|
+
path={path}
|
|
268
|
+
multiselect={false}
|
|
269
|
+
previewProperties={referenceProperty.previewProperties}
|
|
270
|
+
includeId={referenceProperty.includeId}
|
|
271
|
+
includeEntityLink={referenceProperty.includeEntityLink}
|
|
272
|
+
title={stringProperty.name}
|
|
273
|
+
forceFilter={referenceProperty.forceFilter}
|
|
274
|
+
/>;
|
|
275
|
+
allowScroll = false;
|
|
276
|
+
} else if (isAStorageProperty) {
|
|
255
277
|
innerComponent = <TableStorageUpload error={validationError ?? error}
|
|
256
278
|
disabled={disabled}
|
|
257
279
|
focused={selected}
|
|
@@ -310,7 +332,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
310
332
|
updateValue={updateValue}
|
|
311
333
|
/>;
|
|
312
334
|
fullHeight = true;
|
|
313
|
-
} else if (stringProperty.markdown || !stringProperty.storage) {
|
|
335
|
+
} else if (stringProperty.markdown || !stringProperty.storage || !stringProperty.reference) {
|
|
314
336
|
const multiline = Boolean(stringProperty.multiline) || Boolean(stringProperty.markdown);
|
|
315
337
|
innerComponent = <VirtualTableInput error={validationError ?? error}
|
|
316
338
|
disabled={disabled}
|
|
@@ -73,7 +73,7 @@ export function CollectionTableToolbar({
|
|
|
73
73
|
<div
|
|
74
74
|
className={cls(defaultBorderMixin, "no-scrollbar min-h-[56px] overflow-x-auto px-2 md:px-4 bg-surface-50 dark:bg-surface-900 border-b flex flex-row justify-between items-center w-full")}>
|
|
75
75
|
|
|
76
|
-
<div className="flex items-center gap-
|
|
76
|
+
<div className="flex items-center gap-1 md:mr-4 mr-2">
|
|
77
77
|
|
|
78
78
|
{title && <div className={"hidden lg:block"}>
|
|
79
79
|
{title}
|
|
@@ -85,7 +85,7 @@ export function CollectionTableToolbar({
|
|
|
85
85
|
|
|
86
86
|
</div>
|
|
87
87
|
|
|
88
|
-
<div className="flex items-center gap-
|
|
88
|
+
<div className="flex items-center gap-1">
|
|
89
89
|
|
|
90
90
|
{largeLayout && <div className="w-[22px] mr-4">
|
|
91
91
|
{loading &&
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
mergeEntityActions,
|
|
32
32
|
navigateToEntity,
|
|
33
33
|
resolveCollection,
|
|
34
|
+
resolveEntityAction,
|
|
34
35
|
resolveProperty
|
|
35
36
|
} from "../../util";
|
|
36
37
|
import { ReferencePreview } from "../../preview";
|
|
@@ -151,7 +152,6 @@ export const EntityCollectionView = React.memo(
|
|
|
151
152
|
}: EntityCollectionViewProps<M>
|
|
152
153
|
) {
|
|
153
154
|
|
|
154
|
-
|
|
155
155
|
const context = useFireCMSContext();
|
|
156
156
|
const navigation = useNavigationController();
|
|
157
157
|
const fullPath = fullPathProp ?? collectionProp.path;
|
|
@@ -256,7 +256,6 @@ export const EntityCollectionView = React.memo(
|
|
|
256
256
|
}, [unselectNavigatedEntity, sideEntityController]);
|
|
257
257
|
|
|
258
258
|
const onNewClick = useCallback(() => {
|
|
259
|
-
|
|
260
259
|
const collection = collectionRef.current;
|
|
261
260
|
analyticsController.onAnalyticsEvent?.("new_entity_click", {
|
|
262
261
|
path: fullPath
|
|
@@ -522,10 +521,13 @@ export const EntityCollectionView = React.memo(
|
|
|
522
521
|
}) => {
|
|
523
522
|
|
|
524
523
|
const isSelected = Boolean(usedSelectionController.selectedEntities.find(e => e.id == entity.id && e.path == entity.path));
|
|
524
|
+
const customEntityActions = (collection.entityActions ?? [])
|
|
525
|
+
.map(action => resolveEntityAction(action, customizationController.entityActions))
|
|
526
|
+
.filter(Boolean) as EntityAction[];
|
|
525
527
|
|
|
526
528
|
const actions = getActionsForEntity({
|
|
527
529
|
entity,
|
|
528
|
-
customEntityActions
|
|
530
|
+
customEntityActions
|
|
529
531
|
});
|
|
530
532
|
|
|
531
533
|
return (
|
|
@@ -539,7 +541,8 @@ export const EntityCollectionView = React.memo(
|
|
|
539
541
|
highlightEntity={setHighlightedEntity}
|
|
540
542
|
unhighlightEntity={unselectNavigatedEntity}
|
|
541
543
|
collection={collection}
|
|
542
|
-
fullPath={
|
|
544
|
+
fullPath={fullPath}
|
|
545
|
+
fullIdPath={fullIdPath}
|
|
543
546
|
actions={actions}
|
|
544
547
|
hideId={collection?.hideIdFromCollection}
|
|
545
548
|
onCollectionChange={updateLastDeleteTimestamp}
|
|
@@ -71,7 +71,7 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
71
71
|
? <Button
|
|
72
72
|
variant={"text"}
|
|
73
73
|
disabled={!(selectedEntities?.length) || !multipleDeleteEnabled}
|
|
74
|
-
startIcon={<DeleteIcon/>}
|
|
74
|
+
startIcon={<DeleteIcon size={"small"}/>}
|
|
75
75
|
onClick={onMultipleDeleteClick}
|
|
76
76
|
color={"primary"}
|
|
77
77
|
className="lg:w-20"
|
|
@@ -79,10 +79,11 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
79
79
|
({selectedEntities?.length})
|
|
80
80
|
</Button>
|
|
81
81
|
: <IconButton
|
|
82
|
+
size={"small"}
|
|
82
83
|
color={"primary"}
|
|
83
84
|
disabled={!(selectedEntities?.length) || !multipleDeleteEnabled}
|
|
84
85
|
onClick={onMultipleDeleteClick}>
|
|
85
|
-
<DeleteIcon/>
|
|
86
|
+
<DeleteIcon size={"small"}/>
|
|
86
87
|
</IconButton>;
|
|
87
88
|
multipleDeleteButton =
|
|
88
89
|
<Tooltip
|