@rebasepro/admin 0.1.2 → 0.2.3

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 (243) hide show
  1. package/LICENSE +21 -6
  2. package/dist/{CollectionEditorDialog-ywdxhs1L.js → CollectionEditorDialog-CmGXXSY9.js} +42 -209
  3. package/dist/CollectionEditorDialog-CmGXXSY9.js.map +1 -0
  4. package/dist/{CollectionsStudioView-BDzMFzqH.js → CollectionsStudioView-DcLHT5bU.js} +6 -8
  5. package/dist/CollectionsStudioView-DcLHT5bU.js.map +1 -0
  6. package/dist/{ContentHomePage-0tHuEIm_.js → ContentHomePage-C7vFqKSe.js} +5 -7
  7. package/dist/ContentHomePage-C7vFqKSe.js.map +1 -0
  8. package/dist/{ExportCollectionAction-BIrq92To.js → ExportCollectionAction-BfN34eWX.js} +36 -38
  9. package/dist/ExportCollectionAction-BfN34eWX.js.map +1 -0
  10. package/dist/{ImportCollectionAction-h8yg_To8.js → ImportCollectionAction-SZrInjhx.js} +5 -7
  11. package/dist/ImportCollectionAction-SZrInjhx.js.map +1 -0
  12. package/dist/{PropertyEditView-BuZrNnBN.js → PropertyEditView-Cvryrb3B.js} +563 -489
  13. package/dist/PropertyEditView-Cvryrb3B.js.map +1 -0
  14. package/dist/{RolesView-CMPsaIXo.js → RolesView-BCb7qwWs.js} +22 -11
  15. package/dist/RolesView-BCb7qwWs.js.map +1 -0
  16. package/dist/{UsersView-BkeblMVT.js → UsersView-Cex24r8H.js} +7 -71
  17. package/dist/UsersView-Cex24r8H.js.map +1 -0
  18. package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +2 -2
  19. package/dist/collection_editor/ui/collection_editor/properties/RelationPropertyField.d.ts +1 -7
  20. package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +3 -0
  21. package/dist/collection_editor_ui.js +5 -5
  22. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
  23. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
  24. package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
  25. package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
  26. package/dist/components/EntityDetailView.d.ts +31 -0
  27. package/dist/components/EntityEditView.d.ts +3 -2
  28. package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
  29. package/dist/components/admin/CreationResultDialog.d.ts +5 -0
  30. package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
  31. package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
  32. package/dist/components/common/default_entity_actions.d.ts +7 -1
  33. package/dist/components/field_configs.d.ts +1 -1
  34. package/dist/components/index.d.ts +1 -0
  35. package/dist/data_import/utils/data.d.ts +1 -1
  36. package/dist/data_import/utils/file_headers.d.ts +6 -1
  37. package/dist/data_import/utils/file_to_json.d.ts +1 -11
  38. package/dist/data_import/utils/transforms.d.ts +11 -0
  39. package/dist/editor.js +2 -4
  40. package/dist/editor.js.map +1 -1
  41. package/dist/form/EntityForm.d.ts +1 -1
  42. package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
  43. package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
  44. package/dist/form/index.d.ts +1 -0
  45. package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
  46. package/dist/{index-eRJbMvHi.js → index-DjduZG1T.js} +3 -3
  47. package/dist/index-DjduZG1T.js.map +1 -0
  48. package/dist/{index-BuZaHcyc.js → index-MKPc70-v.js} +3 -3
  49. package/dist/index-MKPc70-v.js.map +1 -0
  50. package/dist/{index-CS6uJ7oW.js → index-PLIQXpTt.js} +4 -6
  51. package/dist/index-PLIQXpTt.js.map +1 -0
  52. package/dist/index.d.ts +4 -1
  53. package/dist/index.js +352 -148
  54. package/dist/index.js.map +1 -1
  55. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  56. package/dist/types/components/EntityFormProps.d.ts +2 -1
  57. package/dist/types/fields.d.ts +3 -3
  58. package/dist/util/navigation_utils.d.ts +1 -1
  59. package/dist/{util-zfU1zOCX.js → util-DbWax_sV.js} +5453 -2641
  60. package/dist/util-DbWax_sV.js.map +1 -0
  61. package/package.json +46 -39
  62. package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
  63. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
  64. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
  65. package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
  66. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
  67. package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
  68. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
  69. package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
  70. package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
  71. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
  72. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
  73. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
  74. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +23 -17
  75. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
  76. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
  77. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
  78. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
  79. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
  80. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
  81. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
  82. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
  83. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
  84. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
  85. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
  86. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
  87. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
  88. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
  89. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
  90. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
  91. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
  92. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
  93. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
  94. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
  95. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
  96. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
  97. package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +37 -57
  98. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
  99. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
  100. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
  101. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
  102. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
  103. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
  104. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
  105. package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
  106. package/src/collection_editor/validateCollectionJson.ts +97 -10
  107. package/src/components/AdminModeSyncer.tsx +1 -1
  108. package/src/components/ArrayContainer.tsx +19 -15
  109. package/src/components/ClearFilterSortButton.tsx +1 -2
  110. package/src/components/CollectionEditorDialogs.tsx +1 -1
  111. package/src/components/DefaultAppBar.tsx +15 -3
  112. package/src/components/DefaultDrawer.tsx +3 -3
  113. package/src/components/DrawerNavigationGroup.tsx +1 -2
  114. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +14 -6
  115. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +1 -1
  116. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  117. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
  118. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
  119. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
  120. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
  121. package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
  122. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
  123. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +1 -2
  124. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
  125. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
  126. package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
  127. package/src/components/EntityCollectionView/Board.tsx +1 -2
  128. package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
  129. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
  130. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
  131. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
  132. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +87 -18
  133. package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
  134. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
  135. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
  136. package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
  137. package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
  138. package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
  139. package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
  140. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
  141. package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
  142. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
  143. package/src/components/EntityDetailView.tsx +619 -0
  144. package/src/components/EntityEditView.tsx +29 -10
  145. package/src/components/EntityEditViewFormActions.tsx +20 -7
  146. package/src/components/EntityPreview.tsx +14 -5
  147. package/src/components/EntitySidePanel.tsx +116 -62
  148. package/src/components/EntityView.tsx +1 -2
  149. package/src/components/HomePage/ContentHomePage.tsx +1 -1
  150. package/src/components/HomePage/FavouritesView.tsx +1 -2
  151. package/src/components/HomePage/NavigationCard.tsx +1 -2
  152. package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
  153. package/src/components/HomePage/NavigationGroup.tsx +1 -2
  154. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  155. package/src/components/PropertyIdCopyTooltip.tsx +1 -2
  156. package/src/components/RebaseAuthGate.tsx +2 -2
  157. package/src/components/RebaseNavigation.tsx +9 -7
  158. package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
  159. package/src/components/RelationSelector.tsx +34 -6
  160. package/src/components/SearchIconsView.tsx +10 -2
  161. package/src/components/SelectableTable/SelectableTable.tsx +2 -2
  162. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
  163. package/src/components/SideDialogs.tsx +63 -38
  164. package/src/components/UserSelector.tsx +30 -6
  165. package/src/components/admin/CreationResultDialog.tsx +135 -0
  166. package/src/components/admin/RolesFilterSelect.tsx +45 -0
  167. package/src/components/admin/RolesView.tsx +53 -14
  168. package/src/components/admin/UserRolesSelectField.tsx +50 -0
  169. package/src/components/admin/UsersView.tsx +41 -124
  170. package/src/components/app/Scaffold.tsx +1 -2
  171. package/src/components/common/default_entity_actions.tsx +119 -12
  172. package/src/components/field_configs.tsx +39 -3
  173. package/src/components/history/EntityHistoryEntry.tsx +1 -2
  174. package/src/components/history/EntityHistoryView.tsx +1 -2
  175. package/src/components/index.ts +2 -0
  176. package/src/data_export/export/BasicExportAction.tsx +35 -38
  177. package/src/data_export/export/ExportCollectionAction.tsx +39 -40
  178. package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
  179. package/src/data_import/components/ImportFileUpload.tsx +1 -2
  180. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
  181. package/src/data_import/import/ImportCollectionAction.tsx +21 -8
  182. package/src/data_import/utils/data.ts +23 -5
  183. package/src/data_import/utils/file_headers.ts +13 -89
  184. package/src/data_import/utils/file_to_json.ts +43 -68
  185. package/src/data_import/utils/transforms.ts +47 -0
  186. package/src/editor/components/SlashCommandMenu.tsx +17 -2
  187. package/src/editor/components/editor-bubble-item.tsx +1 -1
  188. package/src/editor/extensions/Image/index.ts +1 -1
  189. package/src/editor/extensions/Image.ts +1 -1
  190. package/src/editor/selectors/color-selector.tsx +1 -2
  191. package/src/editor/selectors/link-selector.tsx +1 -2
  192. package/src/editor/selectors/node-selector.tsx +16 -2
  193. package/src/editor/selectors/text-buttons.tsx +1 -2
  194. package/src/editor/utils/prosemirror-utils.ts +1 -1
  195. package/src/form/EntityForm.tsx +16 -6
  196. package/src/form/EntityFormActions.tsx +11 -3
  197. package/src/form/PropertyFieldBinding.tsx +5 -12
  198. package/src/form/components/FieldHelperText.tsx +1 -2
  199. package/src/form/components/LocalChangesMenu.tsx +17 -2
  200. package/src/form/components/StorageItemPreview.tsx +1 -2
  201. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
  202. package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
  203. package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
  204. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
  205. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
  206. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
  207. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
  208. package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
  209. package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
  210. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
  211. package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
  212. package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
  213. package/src/form/index.tsx +1 -0
  214. package/src/form/validation.ts +54 -2
  215. package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
  216. package/src/hooks/navigation/useResolvedViews.tsx +30 -15
  217. package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
  218. package/src/index.ts +6 -0
  219. package/src/preview/PropertyPreview.tsx +1 -1
  220. package/src/preview/components/ImagePreview.tsx +1 -1
  221. package/src/preview/components/UrlComponentPreview.tsx +1 -2
  222. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
  223. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
  224. package/src/routes/RebaseRoute.tsx +64 -35
  225. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  226. package/src/types/components/EntityFormProps.tsx +3 -1
  227. package/src/types/fields.tsx +4 -3
  228. package/src/util/navigation_utils.ts +4 -3
  229. package/src/util/previews.ts +1 -1
  230. package/src/util/property_utils.tsx +22 -6
  231. package/src/util/resolutions.ts +2 -2
  232. package/dist/CollectionEditorDialog-ywdxhs1L.js.map +0 -1
  233. package/dist/CollectionsStudioView-BDzMFzqH.js.map +0 -1
  234. package/dist/ContentHomePage-0tHuEIm_.js.map +0 -1
  235. package/dist/ExportCollectionAction-BIrq92To.js.map +0 -1
  236. package/dist/ImportCollectionAction-h8yg_To8.js.map +0 -1
  237. package/dist/PropertyEditView-BuZrNnBN.js.map +0 -1
  238. package/dist/RolesView-CMPsaIXo.js.map +0 -1
  239. package/dist/UsersView-BkeblMVT.js.map +0 -1
  240. package/dist/index-BuZaHcyc.js.map +0 -1
  241. package/dist/index-CS6uJ7oW.js.map +0 -1
  242. package/dist/index-eRJbMvHi.js.map +0 -1
  243. package/dist/util-zfU1zOCX.js.map +0 -1
@@ -1,14 +1,15 @@
1
1
 
2
2
  import type { EntityCollection, Property } from "@rebasepro/types";
3
3
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
- import { CollectionSize, Entity, EntityTableController, SelectionController } from "@rebasepro/types";
5
- import { getEntityImagePreviewPropertyKey } from "@rebasepro/common";
4
+ import { CollectionSize, Entity, EntityAction, EntityTableController, SelectionController } from "@rebasepro/types";
6
5
  import {
7
6
  Checkbox,
8
7
  Chip,
9
8
  CircularProgress,
10
9
  cls,
11
10
  defaultBorderMixin,
11
+ IconButton,
12
+ Tooltip,
12
13
  Typography
13
14
  } from "@rebasepro/ui";
14
15
  import { PropertyPreview } from "../../preview";
@@ -17,10 +18,12 @@ import {
17
18
  useCustomizationController
18
19
  } from "@rebasepro/core";
19
20
  import { useAnalyticsController } from "@rebasepro/core";
20
- import { getEntityTitlePropertyKey, getEntityPreviewKeys } from "../../util/previews";
21
+ import { getEntityPreviewKeys } from "../../util/previews";
21
22
  import { IconForView } from "@rebasepro/core";
22
23
  import { getValueInPath } from "@rebasepro/utils";
23
24
  import { useCollectionSlotKeys, resolveEntitySlots, type CollectionSlotKeys } from "./useEntityPreviewSlots";
25
+ import { useCMSContext } from "../../hooks/useCMSContext";
26
+ import { resolveEntityAction } from "../../util/resolutions";
24
27
 
25
28
  export type EntityCollectionListViewProps<M extends Record<string, unknown> = Record<string, unknown>> = {
26
29
  collection: EntityCollection<M>;
@@ -45,6 +48,22 @@ export type EntityCollectionListViewProps<M extends Record<string, unknown> = Re
45
48
  * row is visually highlighted with a primary accent.
46
49
  */
47
50
  selectedEntityId?: string | number;
51
+
52
+ /**
53
+ * Callback to get entity actions for a given entity.
54
+ * Only actions with `showActionsInListView: true` will be rendered.
55
+ */
56
+ getActionsForEntity?: (params: { entity?: Entity<M>, customEntityActions?: EntityAction[] }) => EntityAction[];
57
+
58
+ /**
59
+ * Full path of the collection, used as context for action handlers.
60
+ */
61
+ path?: string;
62
+
63
+ /**
64
+ * How entities open when an action triggers navigation.
65
+ */
66
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
48
67
  };
49
68
 
50
69
  type ListColumnDef = {
@@ -58,19 +77,6 @@ type ListColumnDef = {
58
77
  width: string;
59
78
  };
60
79
 
61
- /**
62
- * Get the number of preview property lines to show based on size
63
- */
64
- function getPreviewCount(size: CollectionSize): number {
65
- switch (size) {
66
- case "xs": return 0;
67
- case "s": return 1;
68
- case "m": return 2;
69
- case "l": return 3;
70
- case "xl": return 4;
71
- default: return 2;
72
- }
73
- }
74
80
 
75
81
 
76
82
  /**
@@ -107,6 +113,9 @@ const OVERSCAN_COUNT = 8;
107
113
  /** Threshold in pixels from the bottom of the scroll area to trigger loading more. */
108
114
  const LOAD_MORE_THRESHOLD = 400;
109
115
 
116
+ /** Stable empty array for when no list-view actions are available. */
117
+ const EMPTY_LIST_VIEW_ACTIONS: EntityAction[] = [];
118
+
110
119
  /**
111
120
  * Walk up the DOM from `element` to find the nearest scrollable ancestor.
112
121
  */
@@ -262,11 +271,15 @@ export function EntityCollectionListView<M extends Record<string, unknown> = Rec
262
271
  emptyComponent,
263
272
 
264
273
  size = "m",
265
- selectedEntityId
274
+ selectedEntityId,
275
+ getActionsForEntity,
276
+ path,
277
+ openEntityMode
266
278
  }: EntityCollectionListViewProps<M>) {
267
279
  const authController = useAuthController();
268
280
  const customizationController = useCustomizationController();
269
281
  const analyticsController = useAnalyticsController();
282
+ const context = useCMSContext();
270
283
 
271
284
  const containerRef = useRef<HTMLDivElement>(null);
272
285
  const [containerWidth, setContainerWidth] = useState(1200);
@@ -475,6 +488,15 @@ export function EntityCollectionListView<M extends Record<string, unknown> = Rec
475
488
  return highlightedEntities?.some(e => e.id === entity.id && e.path === entity.path) ?? false;
476
489
  }, [highlightedEntities]);
477
490
 
491
+ // ── Compute list-view-visible actions per entity ──
492
+ const getListViewActions = useCallback((entity: Entity<M>): EntityAction[] => {
493
+ if (!getActionsForEntity) return EMPTY_LIST_VIEW_ACTIONS;
494
+ const customEntityActions = (collection.entityActions ?? [])
495
+ .map(action => resolveEntityAction(action, customizationController.entityActions))
496
+ .filter(Boolean) as EntityAction<M>[];
497
+ const allActions = getActionsForEntity({ entity, customEntityActions });
498
+ return allActions.filter(a => a.showActionsInListView);
499
+ }, [getActionsForEntity, collection.entityActions, customizationController.entityActions]);
478
500
 
479
501
  const rowClasses = getRowClasses(size);
480
502
 
@@ -615,6 +637,11 @@ export function EntityCollectionListView<M extends Record<string, unknown> = Rec
615
637
  size={size}
616
638
  isLast={isLast}
617
639
  isActive={selectedEntityId !== undefined && entity.id === selectedEntityId}
640
+ listViewActions={getListViewActions(entity)}
641
+ context={context}
642
+ path={path}
643
+ selectionController={selectionController}
644
+ openEntityMode={openEntityMode}
618
645
  />
619
646
  </div>
620
647
  );
@@ -668,7 +695,12 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
668
695
  showImage,
669
696
  size,
670
697
  isLast,
671
- isActive = false
698
+ isActive = false,
699
+ listViewActions = [],
700
+ context,
701
+ path,
702
+ selectionController,
703
+ openEntityMode
672
704
  }: {
673
705
  entity: Entity<M>;
674
706
  collection: EntityCollection<M>;
@@ -684,6 +716,11 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
684
716
  size: CollectionSize;
685
717
  isLast: boolean;
686
718
  isActive?: boolean;
719
+ listViewActions?: EntityAction[];
720
+ context?: ReturnType<typeof useCMSContext>;
721
+ path?: string;
722
+ selectionController?: SelectionController<M>;
723
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
687
724
  }) {
688
725
  // ── Resolve slots (pure function, no hooks) ──
689
726
  const slots = resolveEntitySlots(
@@ -898,6 +935,33 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
898
935
  )}
899
936
  </div>
900
937
  )}
938
+
939
+ {/* LIST VIEW ACTIONS — always visible on each row */}
940
+ {listViewActions.length > 0 && (
941
+ <div className="flex items-center gap-0.5 flex-shrink-0 ml-auto" onClick={(e) => e.stopPropagation()}>
942
+ {listViewActions.map((action, index) => (
943
+ <Tooltip key={action.key ?? index} title={action.name} asChild>
944
+ <IconButton
945
+ size="small"
946
+ onClick={(e: React.MouseEvent) => {
947
+ e.stopPropagation();
948
+ action.onClick({
949
+ view: "collection",
950
+ entity,
951
+ path,
952
+ collection,
953
+ context: context!,
954
+ sideEntityController: context?.sideEntityController,
955
+ selectionController,
956
+ openEntityMode: openEntityMode ?? collection?.openEntityMode ?? "full_screen"
957
+ });
958
+ }}>
959
+ {action.icon}
960
+ </IconButton>
961
+ </Tooltip>
962
+ ))}
963
+ </div>
964
+ )}
901
965
  </div>
902
966
  );
903
967
  }) as <M extends Record<string, unknown>>(props: {
@@ -915,5 +979,10 @@ const ListRow = React.memo(function ListRow<M extends Record<string, unknown>>({
915
979
  size: CollectionSize;
916
980
  isLast: boolean;
917
981
  isActive?: boolean;
982
+ listViewActions?: EntityAction[];
983
+ context?: ReturnType<typeof useCMSContext>;
984
+ path?: string;
985
+ selectionController?: SelectionController<M>;
986
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
918
987
  }) => React.ReactElement;
919
988
 
@@ -5,10 +5,11 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
5
5
 
6
6
  import { deepEqual as equal } from "fast-equals"
7
7
 
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- used as fallback for many array types
8
9
  const EMPTY_ARRAY: any[] = [];
9
10
  const DEFAULT_ENTITY_OPEN_MODE = "split";
10
11
 
11
- import { CollectionSize, Entity, EntityReference, EntityTableController, FilterValues, PartialEntityCollection, SaveEntityProps, ViewMode } from "@rebasepro/types";
12
+ import { CollectionSize, Entity, EntityReference, EntityTableController, FilterValues, PartialEntityCollection, ViewMode } from "@rebasepro/types";
12
13
  import {
13
14
  EntityCollectionRowActions,
14
15
  EntityCollectionTable
@@ -22,7 +23,6 @@ import { resolveEntityAction } from "../../util/resolutions";
22
23
  import { getPropertyInPath } from "../../util/property_utils";
23
24
  import { ReferencePreview } from "../../preview";
24
25
  import {
25
- saveEntityWithCallbacks,
26
26
  useAuthController,
27
27
  useCustomizationController,
28
28
  useData,
@@ -41,7 +41,7 @@ import { SplitListView } from "./SplitListView";
41
41
  import { EntityCollectionBoardView } from "./EntityCollectionBoardView";
42
42
  import { ViewModeToggle, KanbanPropertyOption } from "./ViewModeToggle";
43
43
  import { Button, cls, focusedDisabled, IconButton, Markdown, Popover, Skeleton, Tooltip, Typography, VirtualTableColumn , iconSize } from "@rebasepro/ui";
44
- import { PlusIcon, ArrowRightToLineIcon, SearchIcon } from "lucide-react";
44
+ import { ArrowRightToLineIcon, ErrorBoundary, PlusIcon, SearchIcon } from "@rebasepro/ui";
45
45
  import { setIn } from "@rebasepro/formex";
46
46
  import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
47
47
  import {
@@ -59,15 +59,14 @@ import { useSelectionController } from "./useSelectionController";
59
59
  import { EntityCollectionViewStartActions } from "./EntityCollectionViewStartActions";
60
60
  import { addRecentId, getRecentIds } from "./utils";
61
61
  import { useScrollRestoration } from "@rebasepro/core";
62
- import { ErrorBoundary } from "@rebasepro/ui";
63
62
  import { mergeDeep } from "@rebasepro/utils";
64
63
  import { useCollectionRegistryController, useUrlController, useSideEntityController, useCMSContext } from "../../index";
65
64
  import { useBreadcrumbsController } from "../../index";
66
65
 
67
66
  function getOpenEntityMode(
68
67
  viewMode: ViewMode,
69
- configuredMode?: "side_panel" | "full_screen" | "split"
70
- ): "side_panel" | "full_screen" | "split" {
68
+ configuredMode?: "side_panel" | "full_screen" | "split" | "dialog"
69
+ ): "side_panel" | "full_screen" | "split" | "dialog" {
71
70
  if (configuredMode) return configuredMode;
72
71
  if (viewMode === "kanban") return "side_panel";
73
72
  if (viewMode === "table" || viewMode === "cards") return "full_screen";
@@ -671,10 +670,14 @@ export const EntityCollectionView = React.memo(
671
670
  customEntityActions?: EntityAction[]
672
671
  }): EntityAction[] => {
673
672
  const deleteEnabled = entity ? canDelete(collection, path, entity) : true;
674
- const actions: EntityAction[] = [editEntityAction];
675
- if (createEnabled)
673
+ const disableActions = collection.disableDefaultActions ?? [];
674
+ const actions: EntityAction[] = [];
675
+ if (!disableActions.includes("edit")) {
676
+ actions.push(editEntityAction);
677
+ }
678
+ if (createEnabled && !disableActions.includes("copy"))
676
679
  actions.push(copyEntityAction);
677
- if (deleteEnabled)
680
+ if (deleteEnabled && !disableActions.includes("delete"))
678
681
  actions.push(deleteEntityAction);
679
682
  if (customEntityActions)
680
683
  return mergeEntityActions(actions, customEntityActions);
@@ -771,8 +774,8 @@ export const EntityCollectionView = React.memo(
771
774
  propertyKey,
772
775
  onHover,
773
776
  path,
774
- collection: collection as unknown as EntityCollection,
775
- tableController: tableController as unknown as EntityTableController,
777
+ collection: collection as EntityCollection,
778
+ tableController: tableController as EntityTableController,
776
779
  parentCollectionSlugs: parentCollectionSlugs ?? EMPTY_ARRAY, parentEntityIds: parentEntityIds ?? EMPTY_ARRAY
777
780
  };
778
781
  return <>{headerActionContributions.map((s, i) => (
@@ -953,6 +956,9 @@ export const EntityCollectionView = React.memo(
953
956
  highlightedEntities={highlightedEntity ? [highlightedEntity] : []}
954
957
  size={listSize}
955
958
  emptyComponent={emptyComponent}
959
+ getActionsForEntity={getActionsForEntity}
960
+ path={path}
961
+ openEntityMode={openEntityMode}
956
962
  />
957
963
  ) : (
958
964
  <EntityCollectionTable
@@ -1074,6 +1080,9 @@ export const EntityCollectionView = React.memo(
1074
1080
  size={listSize}
1075
1081
  emptyComponent={emptyComponent}
1076
1082
  selectedEntityId={selectedEntityIdProp}
1083
+ getActionsForEntity={getActionsForEntity}
1084
+ path={path}
1085
+ openEntityMode={openEntityMode}
1077
1086
  />
1078
1087
  </div>
1079
1088
  ) : (
@@ -5,11 +5,10 @@ import React, { lazy, Suspense } from "react";
5
5
  import { useLargeLayout, useTranslation, useSlot, resolveComponentRef } from "@rebasepro/core";
6
6
  import { CollectionActionsProps, EntityTableController, SelectionController } from "@rebasepro/types";
7
7
  import { Button, IconButton, Tooltip, Popover, iconSize } from "@rebasepro/ui";
8
- import { PlusIcon, Trash2Icon, MoreVerticalIcon } from "lucide-react";
9
- import { ErrorBoundary } from "@rebasepro/ui";
8
+ import { ErrorBoundary, MoreVerticalIcon, PlusIcon, Trash2Icon } from "@rebasepro/ui";
10
9
  import { usePermissions } from "@rebasepro/core";
11
10
  import { toArray } from "@rebasepro/utils";
12
- // Lazy-load import/export — pulls in xlsx (~800KB) only on demand
11
+ // Lazy-load import/export — pulls in exceljs only on demand
13
12
  const ImportCollectionAction = lazy(() => import("../../data_import/import").then(m => ({ default: m.ImportCollectionAction })));
14
13
  const ExportCollectionAction = lazy(() => import("../../data_export/export").then(m => ({ default: m.ExportCollectionAction })));
15
14
  import { EditorCollectionAction } from "../../collection_editor/ui/EditorCollectionAction";
@@ -135,7 +134,7 @@ export function EntityCollectionViewActions<M extends Record<string, unknown>>({
135
134
  );
136
135
  });
137
136
 
138
- const pluginActions = useSlot("collection.actions", actionProps as any);
137
+ const pluginActions = useSlot("collection.actions", actionProps as CollectionActionsProps);
139
138
 
140
139
  const secondaryActions = (
141
140
  <>
@@ -146,17 +145,17 @@ export function EntityCollectionViewActions<M extends Record<string, unknown>>({
146
145
  </ErrorBoundary>
147
146
  <ErrorBoundary>
148
147
  <Suspense fallback={null}>
149
- <ImportCollectionAction {...(actionProps as any)}/>
148
+ <ImportCollectionAction {...(actionProps as CollectionActionsProps)}/>
150
149
  </Suspense>
151
150
  </ErrorBoundary>
152
151
  <ErrorBoundary>
153
152
  <Suspense fallback={null}>
154
- <ExportCollectionAction {...(actionProps as any)}/>
153
+ <ExportCollectionAction {...(actionProps as CollectionActionsProps)}/>
155
154
  </Suspense>
156
155
  </ErrorBoundary>
157
156
  {hasCollectionEditor && (
158
157
  <ErrorBoundary>
159
- <EditorCollectionAction {...(actionProps as any)}/>
158
+ <EditorCollectionAction {...(actionProps as CollectionActionsProps)}/>
160
159
  </ErrorBoundary>
161
160
  )}
162
161
  </>
@@ -4,10 +4,10 @@ import React, { useState, useCallback } from "react";
4
4
  import { useAuthController, useLargeLayout, useTranslation, useSlot } from "@rebasepro/core";
5
5
  import { CollectionActionsProps, EntityTableController, SelectionController } from "@rebasepro/types";
6
6
  import { ErrorBoundary , iconSize } from "@rebasepro/ui";
7
- import { ArrowLeftIcon, FilterIcon } from "lucide-react";
7
+ import { ArrowLeftIcon, Badge, Button, cls, FilterIcon, IconButton, Tooltip } from "@rebasepro/ui";
8
8
  import { ClearFilterSortButton } from "../ClearFilterSortButton";
9
9
  import { FiltersDialog } from "./FiltersDialog";
10
- import { Badge, Button, cls, IconButton, Tooltip } from "@rebasepro/ui";
10
+ import { FilterPresetsButton } from "./FilterPresetsButton";
11
11
  import { toArray } from "@rebasepro/utils";
12
12
  import { useNavigate } from "react-router-dom";
13
13
  import { useUrlController, useCMSContext } from "../../index";
@@ -92,7 +92,6 @@ export function EntityCollectionViewStartActions<M extends Record<string, unknow
92
92
  </Tooltip>
93
93
  );
94
94
 
95
- // Filters button
96
95
  const filtersButton = resolvedProperties && tableController.setFilterValues && (
97
96
  <Tooltip title={t("filters")}
98
97
  key={"filters_tooltip"}>
@@ -108,7 +107,7 @@ export function EntityCollectionViewStartActions<M extends Record<string, unknow
108
107
  startIcon={<FilterIcon size={iconSize.small}/>}
109
108
  className={cls(activeFilterCount > 0 && "text-primary")}
110
109
  >
111
- {t("filters")}{activeFilterCount > 0 ? ` (${activeFilterCount})` : ""}
110
+ {activeFilterCount > 0 ? `(${activeFilterCount})` : t("filters")}
112
111
  </Button>
113
112
  ) : (
114
113
  <Button
@@ -124,13 +123,23 @@ export function EntityCollectionViewStartActions<M extends Record<string, unknow
124
123
  </Tooltip>
125
124
  );
126
125
 
126
+ const filterPresetsButton = collection.filterPresets?.length ? (
127
+ <FilterPresetsButton
128
+ key={"filter_presets"}
129
+ filterPresets={collection.filterPresets}
130
+ tableController={tableController}
131
+ compact={compact}
132
+ />
133
+ ) : null;
134
+
127
135
  const actions: React.ReactNode[] = [
128
136
  backButton,
129
137
  filtersButton,
130
138
  <ClearFilterSortButton
131
139
  key={"clear_filter"}
132
140
  tableController={tableController}
133
- enabled={!collection.fixedFilter}/>
141
+ enabled={!collection.fixedFilter}/>,
142
+ filterPresetsButton
134
143
  ];
135
144
 
136
145
  const pluginActionsStart = useSlot("collection.actions.start", actionProps);