@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.
Files changed (85) hide show
  1. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
  2. package/dist/components/HomePage/DefaultHomePage.d.ts +2 -15
  3. package/dist/components/HomePage/HomePageDnD.d.ts +76 -0
  4. package/dist/components/HomePage/NavigationCard.d.ts +3 -1
  5. package/dist/components/HomePage/NavigationCardBinding.d.ts +3 -2
  6. package/dist/components/HomePage/NavigationGroup.d.ts +7 -1
  7. package/dist/components/HomePage/RenameGroupDialog.d.ts +9 -0
  8. package/dist/core/EntityEditView.d.ts +3 -0
  9. package/dist/core/EntityEditViewFormActions.d.ts +1 -1
  10. package/dist/core/field_configs.d.ts +1 -1
  11. package/dist/form/EntityForm.d.ts +2 -1
  12. package/dist/form/EntityFormActions.d.ts +6 -2
  13. package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +9 -0
  14. package/dist/form/index.d.ts +1 -0
  15. package/dist/hooks/useBuildNavigationController.d.ts +51 -2
  16. package/dist/index.es.js +2184 -1052
  17. package/dist/index.es.js.map +1 -1
  18. package/dist/index.umd.js +2181 -1049
  19. package/dist/index.umd.js.map +1 -1
  20. package/dist/types/analytics.d.ts +1 -1
  21. package/dist/types/collections.d.ts +8 -2
  22. package/dist/types/customization_controller.d.ts +8 -0
  23. package/dist/types/entity_actions.d.ts +46 -6
  24. package/dist/types/firecms.d.ts +8 -0
  25. package/dist/types/navigation.d.ts +21 -5
  26. package/dist/types/plugins.d.ts +20 -1
  27. package/dist/types/properties.d.ts +7 -0
  28. package/dist/types/property_config.d.ts +1 -1
  29. package/dist/types/side_entity_controller.d.ts +4 -0
  30. package/dist/util/icons.d.ts +2 -2
  31. package/dist/util/navigation_from_path.d.ts +4 -0
  32. package/dist/util/resolutions.d.ts +2 -1
  33. package/package.json +5 -5
  34. package/src/components/ConfirmationDialog.tsx +1 -0
  35. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +6 -0
  36. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +25 -3
  37. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +2 -2
  38. package/src/components/EntityCollectionView/EntityCollectionView.tsx +7 -4
  39. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +3 -2
  40. package/src/components/FireCMSLogo.tsx +7 -51
  41. package/src/components/HomePage/DefaultHomePage.tsx +491 -157
  42. package/src/components/HomePage/FavouritesView.tsx +3 -3
  43. package/src/components/HomePage/HomePageDnD.tsx +599 -0
  44. package/src/components/HomePage/NavigationCard.tsx +47 -38
  45. package/src/components/HomePage/NavigationCardBinding.tsx +10 -6
  46. package/src/components/HomePage/NavigationGroup.tsx +63 -29
  47. package/src/components/HomePage/RenameGroupDialog.tsx +117 -0
  48. package/src/components/UnsavedChangesDialog.tsx +6 -2
  49. package/src/components/common/default_entity_actions.tsx +25 -9
  50. package/src/components/common/useDataSourceTableController.tsx +2 -2
  51. package/src/core/DefaultDrawer.tsx +8 -8
  52. package/src/core/DrawerNavigationItem.tsx +1 -1
  53. package/src/core/EntityEditView.tsx +41 -6
  54. package/src/core/EntityEditViewFormActions.tsx +154 -29
  55. package/src/core/EntitySidePanel.tsx +5 -2
  56. package/src/core/FireCMS.tsx +2 -0
  57. package/src/core/field_configs.tsx +15 -1
  58. package/src/form/EntityForm.tsx +36 -4
  59. package/src/form/EntityFormActions.tsx +51 -9
  60. package/src/form/components/StorageItemPreview.tsx +1 -1
  61. package/src/form/components/StorageUploadProgress.tsx +3 -3
  62. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +4 -2
  63. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +135 -0
  64. package/src/form/field_bindings/RepeatFieldBinding.tsx +0 -1
  65. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +12 -17
  66. package/src/form/index.tsx +1 -0
  67. package/src/hooks/useBuildNavigationController.tsx +273 -84
  68. package/src/internal/useBuildSideEntityController.tsx +7 -4
  69. package/src/preview/PropertyPreview.tsx +14 -0
  70. package/src/routes/FireCMSRoute.tsx +3 -3
  71. package/src/types/analytics.ts +3 -0
  72. package/src/types/collections.ts +8 -2
  73. package/src/types/customization_controller.tsx +9 -0
  74. package/src/types/entity_actions.tsx +57 -6
  75. package/src/types/firecms.tsx +9 -0
  76. package/src/types/navigation.ts +28 -6
  77. package/src/types/plugins.tsx +24 -1
  78. package/src/types/properties.ts +8 -0
  79. package/src/types/property_config.tsx +1 -0
  80. package/src/types/side_entity_controller.tsx +5 -0
  81. package/src/util/icons.tsx +22 -7
  82. package/src/util/join_collections.ts +3 -1
  83. package/src/util/navigation_from_path.ts +15 -5
  84. package/src/util/navigation_utils.ts +2 -2
  85. 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: Entity<M>;
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
- * If this actions is being called from a side dialog
92
+ * Optional function to navigate back (e.g. when deleting an entity or navigating from a form)
56
93
  */
57
- sideEntityController?: SideEntityController;
58
- openEntityMode: "side_panel" | "full_screen";
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
  };
@@ -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?: TopNavigationResult;
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
- export interface TopNavigationEntry {
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 TopNavigationResult = {
204
- navigationEntries: TopNavigationEntry[];
217
+ export type NavigationResult = {
218
+ allowDragAndDrop: boolean;
219
+ navigationEntries: NavigationEntry[];
205
220
  groups: string[];
221
+ onNavigationEntriesUpdate: (entries: NavigationGroupMapping[]) => void;
206
222
  };
@@ -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
  */
@@ -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.14",
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.14",
57
- "@firecms/formex": "^3.0.0-beta.14",
58
- "@firecms/ui": "^3.0.0-beta.14",
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": "22973ce94cd4ee8ccb4d586ba7f15383dc2cf30b",
110
+ "gitHead": "0abe2ca034f396e389db595f07ef4b24b439c648",
111
111
  "publishConfig": {
112
112
  "access": "public"
113
113
  },
@@ -29,6 +29,7 @@ export function ConfirmationDialog({
29
29
 
30
30
  <DialogActions>
31
31
  <Button
32
+ color={"primary"}
32
33
  variant={"text"}
33
34
  onClick={onCancel}
34
35
  autoFocus>Cancel</Button>
@@ -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 (isAStorageProperty) {
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-2 md:mr-4 mr-2">
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-2">
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: collection.entityActions
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={fullIdPath ?? 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