@rebasepro/admin 0.1.0 → 0.2.1

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 (242) hide show
  1. package/LICENSE +21 -6
  2. package/dist/{CollectionEditorDialog-MbvXGzEq.js → CollectionEditorDialog-BXIh2AXg.js} +40 -31
  3. package/dist/CollectionEditorDialog-BXIh2AXg.js.map +1 -0
  4. package/dist/{CollectionsStudioView-D9X6aiAr.js → CollectionsStudioView-jR8iz_ja.js} +6 -8
  5. package/dist/CollectionsStudioView-jR8iz_ja.js.map +1 -0
  6. package/dist/{ContentHomePage-CfVB1eUo.js → ContentHomePage-BQZWuOFb.js} +5 -7
  7. package/dist/ContentHomePage-BQZWuOFb.js.map +1 -0
  8. package/dist/{ExportCollectionAction-CUwJg4F9.js → ExportCollectionAction-CMdiiv1L.js} +36 -38
  9. package/dist/ExportCollectionAction-CMdiiv1L.js.map +1 -0
  10. package/dist/{ImportCollectionAction-DGa_SF_8.js → ImportCollectionAction-C05lE0IW.js} +5 -7
  11. package/dist/ImportCollectionAction-C05lE0IW.js.map +1 -0
  12. package/dist/{PropertyEditView-C4nlYmAc.js → PropertyEditView-BB5xjnhZ.js} +261 -165
  13. package/dist/PropertyEditView-BB5xjnhZ.js.map +1 -0
  14. package/dist/{RolesView-CNWxnR8e.js → RolesView-CULIHWZ9.js} +22 -11
  15. package/dist/RolesView-CULIHWZ9.js.map +1 -0
  16. package/dist/{UsersView-YiTIcXkA.js → UsersView-D7_AtJ44.js} +7 -71
  17. package/dist/UsersView-D7_AtJ44.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/VectorPropertyField.d.ts +3 -0
  20. package/dist/collection_editor_ui.js +5 -5
  21. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
  22. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
  23. package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
  24. package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
  25. package/dist/components/EntityDetailView.d.ts +31 -0
  26. package/dist/components/EntityEditView.d.ts +3 -2
  27. package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
  28. package/dist/components/admin/CreationResultDialog.d.ts +5 -0
  29. package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
  30. package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
  31. package/dist/components/common/default_entity_actions.d.ts +7 -1
  32. package/dist/components/field_configs.d.ts +1 -1
  33. package/dist/components/index.d.ts +1 -0
  34. package/dist/data_import/utils/data.d.ts +1 -1
  35. package/dist/data_import/utils/file_headers.d.ts +6 -1
  36. package/dist/data_import/utils/file_to_json.d.ts +1 -11
  37. package/dist/data_import/utils/transforms.d.ts +11 -0
  38. package/dist/editor.js +2 -4
  39. package/dist/editor.js.map +1 -1
  40. package/dist/form/EntityForm.d.ts +1 -1
  41. package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
  42. package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
  43. package/dist/form/index.d.ts +1 -0
  44. package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
  45. package/dist/{index-CtzpHzMQ.js → index-BAM9KCmM.js} +4 -6
  46. package/dist/index-BAM9KCmM.js.map +1 -0
  47. package/dist/{index-DKlrVD1m.js → index-CoSNm3e3.js} +3 -3
  48. package/dist/index-CoSNm3e3.js.map +1 -0
  49. package/dist/{index-kHJXfLNI.js → index-D5OQhv-T.js} +3 -3
  50. package/dist/index-D5OQhv-T.js.map +1 -0
  51. package/dist/index.d.ts +4 -1
  52. package/dist/index.js +352 -148
  53. package/dist/index.js.map +1 -1
  54. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  55. package/dist/types/components/EntityFormProps.d.ts +2 -1
  56. package/dist/types/fields.d.ts +3 -3
  57. package/dist/util/navigation_utils.d.ts +1 -1
  58. package/dist/{util-CwLmSpGp.js → util-DtbWD7LF.js} +5312 -2580
  59. package/dist/util-DtbWD7LF.js.map +1 -0
  60. package/package.json +45 -39
  61. package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
  62. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
  63. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
  64. package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
  65. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
  66. package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
  67. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
  68. package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
  69. package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
  70. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
  71. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
  72. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
  73. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +22 -7
  74. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
  75. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
  76. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
  77. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
  78. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
  79. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
  80. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
  81. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
  82. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
  83. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
  84. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
  85. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
  86. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
  87. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
  88. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
  89. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
  90. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
  91. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
  92. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
  93. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
  94. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
  95. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
  96. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
  97. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
  98. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
  99. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
  100. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
  101. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
  102. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
  103. package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
  104. package/src/collection_editor/validateCollectionJson.ts +9 -9
  105. package/src/components/AdminModeSyncer.tsx +1 -1
  106. package/src/components/ArrayContainer.tsx +19 -15
  107. package/src/components/ClearFilterSortButton.tsx +1 -2
  108. package/src/components/CollectionEditorDialogs.tsx +1 -1
  109. package/src/components/DefaultAppBar.tsx +15 -3
  110. package/src/components/DefaultDrawer.tsx +3 -3
  111. package/src/components/DrawerNavigationGroup.tsx +1 -2
  112. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +19 -9
  113. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +2 -2
  114. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  115. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
  116. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
  117. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
  118. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
  119. package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
  120. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
  121. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +3 -4
  122. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
  123. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
  124. package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
  125. package/src/components/EntityCollectionView/Board.tsx +1 -2
  126. package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
  127. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
  128. package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
  129. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
  130. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
  131. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +90 -21
  132. package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
  133. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
  134. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
  135. package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
  136. package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
  137. package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
  138. package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
  139. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
  140. package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
  141. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
  142. package/src/components/EntityDetailView.tsx +619 -0
  143. package/src/components/EntityEditView.tsx +29 -10
  144. package/src/components/EntityEditViewFormActions.tsx +20 -7
  145. package/src/components/EntityPreview.tsx +14 -5
  146. package/src/components/EntitySidePanel.tsx +116 -62
  147. package/src/components/EntityView.tsx +1 -2
  148. package/src/components/HomePage/ContentHomePage.tsx +1 -1
  149. package/src/components/HomePage/FavouritesView.tsx +1 -2
  150. package/src/components/HomePage/NavigationCard.tsx +1 -2
  151. package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
  152. package/src/components/HomePage/NavigationGroup.tsx +1 -2
  153. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  154. package/src/components/PropertyIdCopyTooltip.tsx +1 -2
  155. package/src/components/RebaseAuthGate.tsx +2 -2
  156. package/src/components/RebaseNavigation.tsx +9 -7
  157. package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
  158. package/src/components/RelationSelector.tsx +34 -6
  159. package/src/components/SearchIconsView.tsx +10 -2
  160. package/src/components/SelectableTable/SelectableTable.tsx +4 -4
  161. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
  162. package/src/components/SideDialogs.tsx +63 -38
  163. package/src/components/UserSelector.tsx +30 -6
  164. package/src/components/admin/CreationResultDialog.tsx +135 -0
  165. package/src/components/admin/RolesFilterSelect.tsx +45 -0
  166. package/src/components/admin/RolesView.tsx +53 -14
  167. package/src/components/admin/UserRolesSelectField.tsx +50 -0
  168. package/src/components/admin/UsersView.tsx +41 -124
  169. package/src/components/app/Scaffold.tsx +1 -2
  170. package/src/components/common/default_entity_actions.tsx +119 -12
  171. package/src/components/field_configs.tsx +39 -3
  172. package/src/components/history/EntityHistoryEntry.tsx +1 -2
  173. package/src/components/history/EntityHistoryView.tsx +1 -2
  174. package/src/components/index.ts +2 -0
  175. package/src/data_export/export/BasicExportAction.tsx +35 -38
  176. package/src/data_export/export/ExportCollectionAction.tsx +39 -40
  177. package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
  178. package/src/data_import/components/ImportFileUpload.tsx +1 -2
  179. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
  180. package/src/data_import/import/ImportCollectionAction.tsx +21 -8
  181. package/src/data_import/utils/data.ts +23 -5
  182. package/src/data_import/utils/file_headers.ts +13 -89
  183. package/src/data_import/utils/file_to_json.ts +43 -68
  184. package/src/data_import/utils/transforms.ts +47 -0
  185. package/src/editor/components/SlashCommandMenu.tsx +17 -2
  186. package/src/editor/components/editor-bubble-item.tsx +1 -1
  187. package/src/editor/extensions/Image/index.ts +1 -1
  188. package/src/editor/extensions/Image.ts +1 -1
  189. package/src/editor/selectors/color-selector.tsx +1 -2
  190. package/src/editor/selectors/link-selector.tsx +1 -2
  191. package/src/editor/selectors/node-selector.tsx +16 -2
  192. package/src/editor/selectors/text-buttons.tsx +1 -2
  193. package/src/editor/utils/prosemirror-utils.ts +1 -1
  194. package/src/form/EntityForm.tsx +16 -6
  195. package/src/form/EntityFormActions.tsx +11 -3
  196. package/src/form/PropertyFieldBinding.tsx +5 -12
  197. package/src/form/components/FieldHelperText.tsx +1 -2
  198. package/src/form/components/LocalChangesMenu.tsx +17 -2
  199. package/src/form/components/StorageItemPreview.tsx +1 -2
  200. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
  201. package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
  202. package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
  203. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
  204. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
  205. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
  206. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
  207. package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
  208. package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
  209. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
  210. package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
  211. package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
  212. package/src/form/index.tsx +1 -0
  213. package/src/form/validation.ts +54 -2
  214. package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
  215. package/src/hooks/navigation/useResolvedViews.tsx +30 -15
  216. package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
  217. package/src/index.ts +6 -0
  218. package/src/preview/PropertyPreview.tsx +1 -1
  219. package/src/preview/components/ImagePreview.tsx +1 -1
  220. package/src/preview/components/UrlComponentPreview.tsx +1 -2
  221. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
  222. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
  223. package/src/routes/RebaseRoute.tsx +64 -35
  224. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  225. package/src/types/components/EntityFormProps.tsx +3 -1
  226. package/src/types/fields.tsx +4 -3
  227. package/src/util/navigation_utils.ts +4 -3
  228. package/src/util/previews.ts +1 -1
  229. package/src/util/property_utils.tsx +22 -6
  230. package/src/util/resolutions.ts +2 -2
  231. package/dist/CollectionEditorDialog-MbvXGzEq.js.map +0 -1
  232. package/dist/CollectionsStudioView-D9X6aiAr.js.map +0 -1
  233. package/dist/ContentHomePage-CfVB1eUo.js.map +0 -1
  234. package/dist/ExportCollectionAction-CUwJg4F9.js.map +0 -1
  235. package/dist/ImportCollectionAction-DGa_SF_8.js.map +0 -1
  236. package/dist/PropertyEditView-C4nlYmAc.js.map +0 -1
  237. package/dist/RolesView-CNWxnR8e.js.map +0 -1
  238. package/dist/UsersView-YiTIcXkA.js.map +0 -1
  239. package/dist/index-CtzpHzMQ.js.map +0 -1
  240. package/dist/index-DKlrVD1m.js.map +0 -1
  241. package/dist/index-kHJXfLNI.js.map +0 -1
  242. package/dist/util-CwLmSpGp.js.map +0 -1
@@ -1,10 +1,29 @@
1
1
 
2
- import * as PopoverPrimitive from "@radix-ui/react-popover";
2
+ import {
3
+ ArrowRightToLineIcon,
4
+ CheckIcon,
5
+ ChevronDownIcon,
6
+ Chip,
7
+ CircularProgress,
8
+ cls,
9
+ defaultBorderMixin,
10
+ fieldBackgroundDisabledMixin,
11
+ fieldBackgroundHoverMixin,
12
+ fieldBackgroundInvisibleMixin,
13
+ fieldBackgroundMixin,
14
+ focusedDisabled,
15
+ IconButton,
16
+ iconSize,
17
+ PopoverPrimitive,
18
+ SearchIcon,
19
+ Separator,
20
+ Tooltip,
21
+ useInjectStyles,
22
+ XIcon
23
+ } from "@rebasepro/ui";
3
24
  import * as React from "react";
4
25
  import { useCallback, useEffect, useRef, useState } from "react";
5
26
  import { Command as CommandPrimitive } from "cmdk";
6
- import { Chip, CircularProgress, cls, defaultBorderMixin, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundInvisibleMixin, fieldBackgroundMixin, focusedDisabled, IconButton, Separator, Tooltip, useInjectStyles , iconSize } from "@rebasepro/ui";
7
- import { CheckIcon, XIcon, ChevronDownIcon, ArrowRightToLineIcon, SearchIcon } from "lucide-react";
8
27
  import { Entity, EntityRelation, FilterValues, Relation } from "@rebasepro/types";
9
28
  import { EntityPreviewData } from "./EntityPreview";
10
29
  import { useData, useRelationSelector } from "@rebasepro/core";
@@ -105,7 +124,16 @@ export const RelationSelector = React.forwardRef<
105
124
  const scrollContainerRef = useRef<HTMLDivElement>(null);
106
125
  const sentinelRef = useRef<HTMLDivElement>(null);
107
126
  const observerRef = useRef<IntersectionObserver | null>(null);
108
- const triggerRef = (ref as React.RefObject<HTMLButtonElement>) || useRef<HTMLButtonElement>(null);
127
+ const localTriggerRef = useRef<HTMLButtonElement | null>(null);
128
+
129
+ const handleButtonRef = useCallback((node: HTMLButtonElement | null) => {
130
+ localTriggerRef.current = node;
131
+ if (typeof ref === "function") {
132
+ ref(node);
133
+ } else if (ref) {
134
+ ref.current = node;
135
+ }
136
+ }, [ref]);
109
137
  const contentRef = useRef<HTMLDivElement | null>(null);
110
138
  const searchInputRef = useRef<HTMLInputElement | null>(null);
111
139
 
@@ -367,7 +395,7 @@ relation } as RelationItem;
367
395
 
368
396
  function handlePointerDown(ev: MouseEvent) {
369
397
  const target = ev.target as Node;
370
- const triggerEl = triggerRef.current;
398
+ const triggerEl = localTriggerRef.current;
371
399
  const contentEl = contentRef.current;
372
400
  if (triggerEl?.contains(target)) return;
373
401
  if (contentEl?.contains(target)) return;
@@ -411,7 +439,7 @@ relation } as RelationItem;
411
439
  <PopoverPrimitive.Root open={isPopoverOpen} onOpenChange={handleRootOpenChange} modal={false}>
412
440
  <PopoverPrimitive.Trigger asChild>
413
441
  <button
414
- ref={triggerRef as React.Ref<HTMLButtonElement>}
442
+ ref={handleButtonRef}
415
443
  type="button"
416
444
  aria-haspopup="listbox"
417
445
  aria-expanded={isPopoverOpen}
@@ -1,7 +1,15 @@
1
1
  import React from "react";
2
2
 
3
- import { coolIconKeys, debounce, IconButton, iconKeys, SearchBar, Tooltip, iconSize } from "@rebasepro/ui";
4
- import { icons as lucideIcons } from "lucide-react";
3
+ import {
4
+ coolIconKeys,
5
+ debounce,
6
+ IconButton,
7
+ iconKeys,
8
+ iconSize,
9
+ lucideIcons,
10
+ SearchBar,
11
+ Tooltip
12
+ } from "@rebasepro/ui";
5
13
  import { iconsSearch, iconSynonyms } from "@rebasepro/core";
6
14
  import { useTranslation } from "@rebasepro/core";
7
15
 
@@ -213,7 +213,7 @@ export const SelectableTable = function SelectableTable<M extends Record<string,
213
213
  // on ESC key press
214
214
  useEffect(() => {
215
215
  const escFunction = (event: KeyboardEvent) => {
216
- if (event.keyCode === 27) {
216
+ if (event.key === "Escape") {
217
217
  unselect();
218
218
  }
219
219
  };
@@ -234,12 +234,12 @@ export const SelectableTable = function SelectableTable<M extends Record<string,
234
234
  onValueChange,
235
235
  size: size ?? "m",
236
236
  selectionStore
237
- } as unknown as EntityCollectionTableController<any>), [setPopupCell, select, onValueChange, size, selectionStore]);
237
+ } as EntityCollectionTableController<any>), [setPopupCell, select, onValueChange, size, selectionStore]);
238
238
 
239
239
  return (
240
240
  <SelectableTableContext.Provider
241
241
  value={contextValue}>
242
- <div className="h-full w-full flex flex-col bg-white dark:bg-surface-800"
242
+ <div className="h-full w-full flex flex-col bg-white dark:bg-surface-900"
243
243
  ref={ref}>
244
244
 
245
245
  <VirtualTable
@@ -264,7 +264,7 @@ export const SelectableTable = function SelectableTable<M extends Record<string,
264
264
  checkFilterCombination={checkFilterCombination}
265
265
  createFilterField={filterable ? createFilterField : undefined}
266
266
  rowClassName={useCallback((entity: Entity<M>) => {
267
- return highlightedRow?.(entity) ? "bg-surface-accent-50 dark:!bg-surface-accent-950" : "";
267
+ return highlightedRow?.(entity) ? "bg-surface-accent-50 dark:!bg-surface-accent-900" : "";
268
268
  }, [highlightedRow])}
269
269
  className="grow"
270
270
  emptyComponent={emptyComponent}
@@ -2,8 +2,7 @@
2
2
  import React, { useState } from "react";
3
3
  import { EnumValuesChip } from "../../../preview";
4
4
  import { VirtualTableWhereFilterOp } from "@rebasepro/ui";
5
- import { XIcon } from "lucide-react";
6
- import { IconButton, MultiSelect, MultiSelectItem, Select, SelectItem, TextField } from "@rebasepro/ui";
5
+ import { IconButton, MultiSelect, MultiSelectItem, Select, SelectItem, TextField, XIcon } from "@rebasepro/ui";
7
6
  import { EnumValueConfig } from "@rebasepro/types";
8
7
  import { useTranslation } from "@rebasepro/core";
9
8
 
@@ -1,10 +1,11 @@
1
1
  import type { SideDialogPanelProps } from "../hooks/useSideDialogsController";
2
2
  import React, { useCallback, useContext, useEffect, useState, useMemo } from "react";
3
3
  import { useSideDialogsController } from "../hooks";
4
- ;
5
- import { Sheet } from "@rebasepro/ui";
4
+ import { Sheet, Dialog } from "@rebasepro/ui";
6
5
  import { useUnsavedChangesDialog, UnsavedChangesDialog } from "@rebasepro/core";
7
6
  import { ErrorBoundary } from "@rebasepro/ui";
7
+ import type { EntitySidePanelProps } from "@rebasepro/types";
8
+
8
9
 
9
10
  export type SideDialogController = {
10
11
  blocked: boolean,
@@ -145,46 +146,70 @@ function SideDialogView({
145
146
  setPendingClose
146
147
  }), [blocked, setBlockedNavigationMessage, width, onCloseRequest, pendingClose]);
147
148
 
149
+ const additionalProps = panel?.additional as EntitySidePanelProps | undefined;
150
+ const isDialogMode = additionalProps?.collection?.openEntityMode === "dialog";
151
+
148
152
  return (
149
153
  <SideDialogContext.Provider value={contextValue}>
150
154
 
151
- <Sheet
152
- open={Boolean(panel)}
153
- includeBackgroundOverlay={true}
154
- overlayStyle={{ zIndex: 40 + panelIndex * 10 }}
155
- style={{ zIndex: 45 + panelIndex * 10 }}
156
- onOpenChange={(open) => {
157
- if (!open) {
158
- // Check if any suggestion menu is visible in DOM
159
- const suggestionMenu = document.querySelector("[data-suggestion-menu=\"true\"]");
160
- if (suggestionMenu && window.getComputedStyle(suggestionMenu).visibility !== "hidden") {
161
- // Don't close the sheet if a suggestion menu is visible
162
- // Let Tiptap handle closing the menu first
163
- return;
155
+ {isDialogMode ? (
156
+ <Dialog
157
+ open={Boolean(panel)}
158
+ onOpenChange={(open) => {
159
+ if (!open) {
160
+ onCloseRequest();
164
161
  }
165
- onCloseRequest();
166
- }
167
- }}
168
- onPointerDownOutside={!isTopPanel ? preventDismiss : undefined}
169
- onInteractOutside={!isTopPanel ? preventDismiss : undefined}
170
- title={"Side dialog " + panel?.key}
171
- >
172
- {panel &&
173
- <div
174
- className={"transform max-w-[100vw] lg:max-w-[95vw] flex flex-col h-full transition-all duration-250 ease-in-out bg-white dark:bg-surface-800 "}
175
- style={{
176
- width: panel.width,
177
- transform: `translateX(-${offsetPosition * 200}px)`
178
- }}
179
- >
180
- <ErrorBoundary>
181
- {panel.component}
182
- </ErrorBoundary>
183
- </div>}
184
-
185
- {!panel && <div style={{ width }}/>}
186
-
187
- </Sheet>
162
+ }}
163
+ maxWidth="4xl"
164
+ scrollable={false}
165
+ >
166
+ {panel && (
167
+ <div className="flex flex-col h-[75vh] min-h-[500px] min-w-[55vw] max-w-full overflow-hidden">
168
+ <ErrorBoundary>
169
+ {panel.component}
170
+ </ErrorBoundary>
171
+ </div>
172
+ )}
173
+ </Dialog>
174
+ ) : (
175
+ <Sheet
176
+ open={Boolean(panel)}
177
+ includeBackgroundOverlay={true}
178
+ overlayStyle={{ zIndex: 40 + panelIndex * 10 }}
179
+ style={{ zIndex: 45 + panelIndex * 10 }}
180
+ onOpenChange={(open) => {
181
+ if (!open) {
182
+ // Check if any suggestion menu is visible in DOM
183
+ const suggestionMenu = document.querySelector("[data-suggestion-menu=\"true\"]");
184
+ if (suggestionMenu && window.getComputedStyle(suggestionMenu).visibility !== "hidden") {
185
+ // Don't close the sheet if a suggestion menu is visible
186
+ // Let Tiptap handle closing the menu first
187
+ return;
188
+ }
189
+ onCloseRequest();
190
+ }
191
+ }}
192
+ onPointerDownOutside={!isTopPanel ? preventDismiss : undefined}
193
+ onInteractOutside={!isTopPanel ? preventDismiss : undefined}
194
+ title={"Side dialog " + panel?.key}
195
+ >
196
+ {panel &&
197
+ <div
198
+ className={"transform max-w-[100vw] lg:max-w-[95vw] flex flex-col h-full transition-all duration-250 ease-in-out bg-white dark:bg-surface-800 "}
199
+ style={{
200
+ width: panel.width,
201
+ transform: `translateX(-${offsetPosition * 200}px)`
202
+ }}
203
+ >
204
+ <ErrorBoundary>
205
+ {panel.component}
206
+ </ErrorBoundary>
207
+ </div>}
208
+
209
+ {!panel && <div style={{ width }}/>}
210
+
211
+ </Sheet>
212
+ )}
188
213
 
189
214
  <UnsavedChangesDialog
190
215
  {...dialogProps}
@@ -1,10 +1,25 @@
1
1
 
2
- import * as PopoverPrimitive from "@radix-ui/react-popover";
2
+ import {
3
+ ChevronDownIcon,
4
+ CircularProgress,
5
+ cls,
6
+ defaultBorderMixin,
7
+ fieldBackgroundDisabledMixin,
8
+ fieldBackgroundHoverMixin,
9
+ fieldBackgroundInvisibleMixin,
10
+ fieldBackgroundMixin,
11
+ focusedDisabled,
12
+ IconButton,
13
+ iconSize,
14
+ PopoverPrimitive,
15
+ SearchIcon,
16
+ Separator,
17
+ useInjectStyles,
18
+ XIcon
19
+ } from "@rebasepro/ui";
3
20
  import * as React from "react";
4
21
  import { useCallback, useEffect, useRef, useState } from "react";
5
22
  import { Command as CommandPrimitive } from "cmdk";
6
- import { CircularProgress, cls, defaultBorderMixin, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundInvisibleMixin, fieldBackgroundMixin, focusedDisabled, IconButton, Separator, useInjectStyles , iconSize } from "@rebasepro/ui";
7
- import { XIcon, ChevronDownIcon, SearchIcon } from "lucide-react";
8
23
  import { User } from "@rebasepro/types";
9
24
  import { useUserSelector, UserSelectorItem } from "@rebasepro/core";
10
25
  import { UserDisplay } from "@rebasepro/core";
@@ -64,7 +79,16 @@ export const UserSelector = React.forwardRef<
64
79
  const scrollContainerRef = useRef<HTMLDivElement>(null);
65
80
  const sentinelRef = useRef<HTMLDivElement>(null);
66
81
  const observerRef = useRef<IntersectionObserver | null>(null);
67
- const triggerRef = (ref as React.RefObject<HTMLButtonElement>) || useRef<HTMLButtonElement>(null);
82
+ const localTriggerRef = useRef<HTMLButtonElement | null>(null);
83
+
84
+ const handleButtonRef = useCallback((node: HTMLButtonElement | null) => {
85
+ localTriggerRef.current = node;
86
+ if (typeof ref === "function") {
87
+ ref(node);
88
+ } else if (ref) {
89
+ ref.current = node;
90
+ }
91
+ }, [ref]);
68
92
  const contentRef = useRef<HTMLDivElement | null>(null);
69
93
  const searchInputRef = useRef<HTMLInputElement | null>(null);
70
94
 
@@ -155,7 +179,7 @@ export const UserSelector = React.forwardRef<
155
179
 
156
180
  function handlePointerDown(ev: MouseEvent) {
157
181
  const target = ev.target as Node;
158
- const triggerEl = triggerRef.current;
182
+ const triggerEl = localTriggerRef.current;
159
183
  const contentEl = contentRef.current;
160
184
  if (triggerEl?.contains(target)) return;
161
185
  if (contentEl?.contains(target)) return;
@@ -184,7 +208,7 @@ export const UserSelector = React.forwardRef<
184
208
  <PopoverPrimitive.Root open={isPopoverOpen} onOpenChange={handleRootOpenChange} modal={false}>
185
209
  <PopoverPrimitive.Trigger asChild>
186
210
  <button
187
- ref={triggerRef as React.Ref<HTMLButtonElement>}
211
+ ref={handleButtonRef}
188
212
  type="button"
189
213
  aria-haspopup="listbox"
190
214
  aria-expanded={isPopoverOpen}
@@ -0,0 +1,135 @@
1
+ import React, { useState } from "react";
2
+ import {
3
+ Alert,
4
+ Button,
5
+ CheckCircleIcon,
6
+ CopyIcon,
7
+ Dialog,
8
+ DialogActions,
9
+ DialogContent,
10
+ DialogTitle,
11
+ IconButton,
12
+ MailIcon,
13
+ Tooltip,
14
+ Typography
15
+ } from "@rebasepro/ui";
16
+ import { useSnackbarController, useTranslation } from "@rebasepro/core";
17
+ import { UserCreationResult } from "@rebasepro/types";
18
+
19
+ export function CreationResultDialog({
20
+ result,
21
+ onClose
22
+ }: {
23
+ result: UserCreationResult;
24
+ onClose: () => void;
25
+ }) {
26
+ const { t } = useTranslation();
27
+ const snackbarController = useSnackbarController();
28
+ const [copied, setCopied] = useState(false);
29
+
30
+ const handleCopyPassword = async () => {
31
+ if (!result.temporaryPassword) return;
32
+ try {
33
+ await navigator.clipboard.writeText(result.temporaryPassword);
34
+ setCopied(true);
35
+ snackbarController.open({
36
+ type: "success",
37
+ message: t("password_copied") ?? "Password copied to clipboard"
38
+ });
39
+ setTimeout(() => setCopied(false), 3000);
40
+ } catch {
41
+ // Fallback for older browsers
42
+ const textArea = document.createElement("textarea");
43
+ textArea.value = result.temporaryPassword;
44
+ document.body.appendChild(textArea);
45
+ textArea.select();
46
+ document.execCommand("copy");
47
+ document.body.removeChild(textArea);
48
+ setCopied(true);
49
+ setTimeout(() => setCopied(false), 3000);
50
+ }
51
+ };
52
+
53
+ if (result.invitationSent) {
54
+ // Invitation sent via email
55
+ return (
56
+ <Dialog open={true} onOpenChange={(open) => !open ? onClose() : undefined} maxWidth="xl">
57
+ <DialogTitle variant="h5" gutterBottom={false}>
58
+ <div className="flex items-center gap-3">
59
+ <MailIcon/>
60
+ {t("invitation_sent_title") ?? "Invitation Sent"}
61
+ </div>
62
+ </DialogTitle>
63
+ <DialogContent>
64
+ <div className="flex flex-col gap-4 py-2">
65
+ <Alert color="success">
66
+ <Typography>
67
+ {(t("invitation_sent") ?? "An invitation email has been sent to {{email}}. They can use the link to set their password.")
68
+ .replace("{{email}}", result.user.email ?? "")}
69
+ </Typography>
70
+ </Alert>
71
+ </div>
72
+ </DialogContent>
73
+ <DialogActions>
74
+ <Button variant="filled" onClick={onClose}>
75
+ {t("ok")}
76
+ </Button>
77
+ </DialogActions>
78
+ </Dialog>
79
+ );
80
+ }
81
+
82
+ if (result.temporaryPassword) {
83
+ // No email — show temporary password
84
+ return (
85
+ <Dialog open={true} onOpenChange={(open) => !open ? onClose() : undefined} maxWidth="xl">
86
+ <DialogTitle variant="h5" gutterBottom={false}>
87
+ {t("temporary_password") ?? "Temporary Password"}
88
+ </DialogTitle>
89
+ <DialogContent>
90
+ <div className="flex flex-col gap-4 py-2">
91
+ <Alert color="warning">
92
+ <Typography variant="body2">
93
+ {t("temporary_password_description") ??
94
+ "Email is not configured. Share this temporary password with the user securely. It will not be shown again."}
95
+ </Typography>
96
+ </Alert>
97
+
98
+ <div>
99
+ <Typography variant="caption" color="secondary" className="mb-1">
100
+ {t("email")}
101
+ </Typography>
102
+ <Typography>
103
+ {result.user.email}
104
+ </Typography>
105
+ </div>
106
+
107
+ <div>
108
+ <Typography variant="caption" color="secondary" className="mb-1">
109
+ {t("temporary_password") ?? "Temporary Password"}
110
+ </Typography>
111
+ <div className="flex items-center gap-2 mt-1">
112
+ <code className="flex-grow bg-surface-100 dark:bg-surface-900 border border-surface-300 dark:border-surface-600 rounded px-3 py-2 font-mono text-base select-all">
113
+ {result.temporaryPassword}
114
+ </code>
115
+ <Tooltip title={t("copy_password") ?? "Copy password"} asChild>
116
+ <IconButton onClick={handleCopyPassword}>
117
+ {copied ? <CheckCircleIcon className="text-green-600"/> : <CopyIcon/>}
118
+ </IconButton>
119
+ </Tooltip>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </DialogContent>
124
+ <DialogActions>
125
+ <Button variant="filled" onClick={onClose}>
126
+ {t("ok")}
127
+ </Button>
128
+ </DialogActions>
129
+ </Dialog>
130
+ );
131
+ }
132
+
133
+ // Shouldn't happen, but fallback
134
+ return null;
135
+ }
@@ -0,0 +1,45 @@
1
+ import React from "react";
2
+ import { CollectionActionsProps } from "@rebasepro/types";
3
+ import { Select, SelectItem } from "@rebasepro/ui";
4
+ import { useTranslation, useInternalUserManagementController } from "@rebasepro/core";
5
+
6
+ export function RolesFilterSelect({
7
+ tableController
8
+ }: CollectionActionsProps<any>) {
9
+ const { t } = useTranslation();
10
+ const userManagement = useInternalUserManagementController();
11
+ const roles = userManagement?.roles || [];
12
+
13
+ const currentFilterValue = (tableController.filterValues?.roles?.[1] as string) || "";
14
+
15
+ const handleRoleChange = (newRole: string) => {
16
+ const filterVal = newRole === "" ? undefined : newRole;
17
+ if (filterVal) {
18
+ tableController.setFilterValues?.({
19
+ ...tableController.filterValues,
20
+ roles: ["array-contains", filterVal]
21
+ });
22
+ } else {
23
+ const nextFilters = { ...tableController.filterValues };
24
+ delete nextFilters.roles;
25
+ tableController.setFilterValues?.(nextFilters);
26
+ }
27
+ };
28
+
29
+ if (!roles || roles.length === 0) return null;
30
+
31
+ return (
32
+ <Select
33
+ value={currentFilterValue || "__all__"}
34
+ onValueChange={(v) => handleRoleChange(v === "__all__" ? "" : v)}
35
+ placeholder={t("all_roles") || "All Roles"}
36
+ size="small"
37
+ className="w-48"
38
+ >
39
+ <SelectItem value="__all__">{t("all_roles") || "All Roles"}</SelectItem>
40
+ {roles.map(role => (
41
+ <SelectItem key={role.id} value={role.id}>{role.name}</SelectItem>
42
+ ))}
43
+ </Select>
44
+ );
45
+ }
@@ -4,8 +4,34 @@ import { useCollectionRegistryController } from "../../index";
4
4
  import { useSnackbarController, useTranslation } from "@rebasepro/core";
5
5
  import { getDataSourceCapabilities, Role, SecurityRule, UserManagementDelegate } from "@rebasepro/types";
6
6
  import { useBreadcrumbsController } from "../../index";
7
- import { Button, Chip, Container, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Paper, Table, TableBody, TableCell, TableHeader, TableRow, TextField, Typography, CircularProgress, CenteredView, Tooltip, Checkbox, LoadingButton, defaultBorderMixin , iconSize } from "@rebasepro/ui";
8
- import { PlusIcon, Trash2Icon } from "lucide-react";
7
+ import {
8
+ Button,
9
+ CenteredView,
10
+ Checkbox,
11
+ Chip,
12
+ CircularProgress,
13
+ Container,
14
+ defaultBorderMixin,
15
+ Dialog,
16
+ DialogActions,
17
+ DialogContent,
18
+ DialogTitle,
19
+ IconButton,
20
+ iconSize,
21
+ Label,
22
+ LoadingButton,
23
+ Paper,
24
+ PlusIcon,
25
+ Table,
26
+ TableBody,
27
+ TableCell,
28
+ TableHeader,
29
+ TableRow,
30
+ TextField,
31
+ Tooltip,
32
+ Trash2Icon,
33
+ Typography
34
+ } from "@rebasepro/ui";
9
35
  import { RoleChip } from "./RoleChip";
10
36
  import { ConfirmationDialog } from "@rebasepro/core";
11
37
 
@@ -64,20 +90,33 @@ message: error instanceof Error ? error.message : t("error_deleting_role") });
64
90
  }
65
91
  };
66
92
 
67
- const createDefaultRoles = () => {
93
+ const createDefaultRoles = async () => {
68
94
  if (!saveRole) return;
69
95
  const defaultRoles: Role[] = [
70
96
  { id: "admin",
71
- name: "Admin",
72
- isAdmin: true },
97
+ name: "Admin",
98
+ isAdmin: true },
73
99
  { id: "editor",
74
- name: "Editor",
75
- isAdmin: false },
100
+ name: "Editor",
101
+ isAdmin: false },
76
102
  { id: "viewer",
77
- name: "Viewer",
78
- isAdmin: false }
103
+ name: "Viewer",
104
+ isAdmin: false }
79
105
  ];
80
- defaultRoles.forEach(role => saveRole(role));
106
+ try {
107
+ for (const role of defaultRoles) {
108
+ await saveRole(role);
109
+ }
110
+ snackbarController.open({
111
+ type: "success",
112
+ message: t("saved_correctly")
113
+ });
114
+ } catch (error: unknown) {
115
+ snackbarController.open({
116
+ type: "error",
117
+ message: error instanceof Error ? error.message : t("error_saving_role")
118
+ });
119
+ }
81
120
  };
82
121
 
83
122
  if (loading) {
@@ -285,13 +324,13 @@ height: "100%" }}>
285
324
  </div>
286
325
 
287
326
  <div className="col-span-12 sm:col-span-4 flex items-start pt-2">
288
- <label className="flex items-center gap-2 cursor-pointer mt-3">
327
+ <Label className="flex items-center gap-2 cursor-pointer mt-3">
289
328
  <Checkbox
290
329
  checked={isAdmin}
291
330
  onCheckedChange={(checked) => setIsAdmin(Boolean(checked))}
292
331
  />
293
- <span className="font-medium">{t("is_admin")}</span>
294
- </label>
332
+ <Typography variant="body2" className="font-medium">{t("is_admin")}</Typography>
333
+ </Label>
295
334
  </div>
296
335
 
297
336
  <div className="col-span-12">
@@ -307,7 +346,7 @@ height: "100%" }}>
307
346
  <LoadingButton
308
347
  variant="filled"
309
348
  type="submit"
310
- disabled={!isNewRole && !isAdmin}
349
+ disabled={isSubmitting}
311
350
  loading={isSubmitting}
312
351
  >
313
352
  {isNewRole ? t("create_role") : t("update")}
@@ -0,0 +1,50 @@
1
+ import React from "react";
2
+ import { FieldProps } from "../../types/fields";
3
+ import { MultiSelect, MultiSelectItem } from "@rebasepro/ui";
4
+ import { useTranslation, useInternalUserManagementController } from "@rebasepro/core";
5
+ import { RoleChip } from "./RoleChip";
6
+
7
+ export function UserRolesSelectField({
8
+ propertyKey,
9
+ value,
10
+ setValue,
11
+ disabled
12
+ }: FieldProps) {
13
+ const { t } = useTranslation();
14
+ const userManagement = useInternalUserManagementController();
15
+ const roles = userManagement?.roles || [];
16
+
17
+ const selectedRoleIds = (value || []).map((r: any) => {
18
+ if (typeof r === "object" && r !== null) {
19
+ return r.id;
20
+ }
21
+ return r;
22
+ });
23
+
24
+ const handleValueChange = (val: string[]) => {
25
+ const references = val.map(id => ({
26
+ id,
27
+ path: "roles",
28
+ __type: "relation"
29
+ }));
30
+ setValue(references);
31
+ };
32
+
33
+ return (
34
+ <div className="col-span-12">
35
+ <MultiSelect
36
+ className="w-full"
37
+ label={t("roles") || "Roles"}
38
+ value={selectedRoleIds}
39
+ onValueChange={handleValueChange}
40
+ disabled={disabled}
41
+ >
42
+ {roles.map(role => (
43
+ <MultiSelectItem key={role.id} value={role.id}>
44
+ <RoleChip role={role}/>
45
+ </MultiSelectItem>
46
+ ))}
47
+ </MultiSelect>
48
+ </div>
49
+ );
50
+ }