@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.
- package/LICENSE +21 -6
- package/dist/{CollectionEditorDialog-ywdxhs1L.js → CollectionEditorDialog-CmGXXSY9.js} +42 -209
- package/dist/CollectionEditorDialog-CmGXXSY9.js.map +1 -0
- package/dist/{CollectionsStudioView-BDzMFzqH.js → CollectionsStudioView-DcLHT5bU.js} +6 -8
- package/dist/CollectionsStudioView-DcLHT5bU.js.map +1 -0
- package/dist/{ContentHomePage-0tHuEIm_.js → ContentHomePage-C7vFqKSe.js} +5 -7
- package/dist/ContentHomePage-C7vFqKSe.js.map +1 -0
- package/dist/{ExportCollectionAction-BIrq92To.js → ExportCollectionAction-BfN34eWX.js} +36 -38
- package/dist/ExportCollectionAction-BfN34eWX.js.map +1 -0
- package/dist/{ImportCollectionAction-h8yg_To8.js → ImportCollectionAction-SZrInjhx.js} +5 -7
- package/dist/ImportCollectionAction-SZrInjhx.js.map +1 -0
- package/dist/{PropertyEditView-BuZrNnBN.js → PropertyEditView-Cvryrb3B.js} +563 -489
- package/dist/PropertyEditView-Cvryrb3B.js.map +1 -0
- package/dist/{RolesView-CMPsaIXo.js → RolesView-BCb7qwWs.js} +22 -11
- package/dist/RolesView-BCb7qwWs.js.map +1 -0
- package/dist/{UsersView-BkeblMVT.js → UsersView-Cex24r8H.js} +7 -71
- package/dist/UsersView-Cex24r8H.js.map +1 -0
- package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/properties/RelationPropertyField.d.ts +1 -7
- package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +3 -0
- package/dist/collection_editor_ui.js +5 -5
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
- package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
- package/dist/components/EntityDetailView.d.ts +31 -0
- package/dist/components/EntityEditView.d.ts +3 -2
- package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
- package/dist/components/admin/CreationResultDialog.d.ts +5 -0
- package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
- package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
- package/dist/components/common/default_entity_actions.d.ts +7 -1
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/data_import/utils/data.d.ts +1 -1
- package/dist/data_import/utils/file_headers.d.ts +6 -1
- package/dist/data_import/utils/file_to_json.d.ts +1 -11
- package/dist/data_import/utils/transforms.d.ts +11 -0
- package/dist/editor.js +2 -4
- package/dist/editor.js.map +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
- package/dist/form/index.d.ts +1 -0
- package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
- package/dist/{index-eRJbMvHi.js → index-DjduZG1T.js} +3 -3
- package/dist/index-DjduZG1T.js.map +1 -0
- package/dist/{index-BuZaHcyc.js → index-MKPc70-v.js} +3 -3
- package/dist/index-MKPc70-v.js.map +1 -0
- package/dist/{index-CS6uJ7oW.js → index-PLIQXpTt.js} +4 -6
- package/dist/index-PLIQXpTt.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +352 -148
- package/dist/index.js.map +1 -1
- package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
- package/dist/types/components/EntityFormProps.d.ts +2 -1
- package/dist/types/fields.d.ts +3 -3
- package/dist/util/navigation_utils.d.ts +1 -1
- package/dist/{util-zfU1zOCX.js → util-DbWax_sV.js} +5453 -2641
- package/dist/util-DbWax_sV.js.map +1 -0
- package/package.json +46 -39
- package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
- package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
- package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
- package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
- package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +23 -17
- package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
- package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +37 -57
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
- package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
- package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
- package/src/collection_editor/validateCollectionJson.ts +97 -10
- package/src/components/AdminModeSyncer.tsx +1 -1
- package/src/components/ArrayContainer.tsx +19 -15
- package/src/components/ClearFilterSortButton.tsx +1 -2
- package/src/components/CollectionEditorDialogs.tsx +1 -1
- package/src/components/DefaultAppBar.tsx +15 -3
- package/src/components/DefaultDrawer.tsx +3 -3
- package/src/components/DrawerNavigationGroup.tsx +1 -2
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +14 -6
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
- package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
- package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +1 -2
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
- package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
- package/src/components/EntityCollectionView/Board.tsx +1 -2
- package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
- package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
- package/src/components/EntityCollectionView/EntityCollectionListView.tsx +87 -18
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
- package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
- package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
- package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
- package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
- package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
- package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
- package/src/components/EntityDetailView.tsx +619 -0
- package/src/components/EntityEditView.tsx +29 -10
- package/src/components/EntityEditViewFormActions.tsx +20 -7
- package/src/components/EntityPreview.tsx +14 -5
- package/src/components/EntitySidePanel.tsx +116 -62
- package/src/components/EntityView.tsx +1 -2
- package/src/components/HomePage/ContentHomePage.tsx +1 -1
- package/src/components/HomePage/FavouritesView.tsx +1 -2
- package/src/components/HomePage/NavigationCard.tsx +1 -2
- package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
- package/src/components/HomePage/NavigationGroup.tsx +1 -2
- package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
- package/src/components/PropertyIdCopyTooltip.tsx +1 -2
- package/src/components/RebaseAuthGate.tsx +2 -2
- package/src/components/RebaseNavigation.tsx +9 -7
- package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
- package/src/components/RelationSelector.tsx +34 -6
- package/src/components/SearchIconsView.tsx +10 -2
- package/src/components/SelectableTable/SelectableTable.tsx +2 -2
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
- package/src/components/SideDialogs.tsx +63 -38
- package/src/components/UserSelector.tsx +30 -6
- package/src/components/admin/CreationResultDialog.tsx +135 -0
- package/src/components/admin/RolesFilterSelect.tsx +45 -0
- package/src/components/admin/RolesView.tsx +53 -14
- package/src/components/admin/UserRolesSelectField.tsx +50 -0
- package/src/components/admin/UsersView.tsx +41 -124
- package/src/components/app/Scaffold.tsx +1 -2
- package/src/components/common/default_entity_actions.tsx +119 -12
- package/src/components/field_configs.tsx +39 -3
- package/src/components/history/EntityHistoryEntry.tsx +1 -2
- package/src/components/history/EntityHistoryView.tsx +1 -2
- package/src/components/index.ts +2 -0
- package/src/data_export/export/BasicExportAction.tsx +35 -38
- package/src/data_export/export/ExportCollectionAction.tsx +39 -40
- package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
- package/src/data_import/components/ImportFileUpload.tsx +1 -2
- package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
- package/src/data_import/import/ImportCollectionAction.tsx +21 -8
- package/src/data_import/utils/data.ts +23 -5
- package/src/data_import/utils/file_headers.ts +13 -89
- package/src/data_import/utils/file_to_json.ts +43 -68
- package/src/data_import/utils/transforms.ts +47 -0
- package/src/editor/components/SlashCommandMenu.tsx +17 -2
- package/src/editor/components/editor-bubble-item.tsx +1 -1
- package/src/editor/extensions/Image/index.ts +1 -1
- package/src/editor/extensions/Image.ts +1 -1
- package/src/editor/selectors/color-selector.tsx +1 -2
- package/src/editor/selectors/link-selector.tsx +1 -2
- package/src/editor/selectors/node-selector.tsx +16 -2
- package/src/editor/selectors/text-buttons.tsx +1 -2
- package/src/editor/utils/prosemirror-utils.ts +1 -1
- package/src/form/EntityForm.tsx +16 -6
- package/src/form/EntityFormActions.tsx +11 -3
- package/src/form/PropertyFieldBinding.tsx +5 -12
- package/src/form/components/FieldHelperText.tsx +1 -2
- package/src/form/components/LocalChangesMenu.tsx +17 -2
- package/src/form/components/StorageItemPreview.tsx +1 -2
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
- package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
- package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
- package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
- package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
- package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
- package/src/form/index.tsx +1 -0
- package/src/form/validation.ts +54 -2
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
- package/src/hooks/navigation/useResolvedViews.tsx +30 -15
- package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
- package/src/index.ts +6 -0
- package/src/preview/PropertyPreview.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +1 -1
- package/src/preview/components/UrlComponentPreview.tsx +1 -2
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
- package/src/routes/RebaseRoute.tsx +64 -35
- package/src/types/components/EntityFormActionsProps.tsx +1 -1
- package/src/types/components/EntityFormProps.tsx +3 -1
- package/src/types/fields.tsx +4 -3
- package/src/util/navigation_utils.ts +4 -3
- package/src/util/previews.ts +1 -1
- package/src/util/property_utils.tsx +22 -6
- package/src/util/resolutions.ts +2 -2
- package/dist/CollectionEditorDialog-ywdxhs1L.js.map +0 -1
- package/dist/CollectionsStudioView-BDzMFzqH.js.map +0 -1
- package/dist/ContentHomePage-0tHuEIm_.js.map +0 -1
- package/dist/ExportCollectionAction-BIrq92To.js.map +0 -1
- package/dist/ImportCollectionAction-h8yg_To8.js.map +0 -1
- package/dist/PropertyEditView-BuZrNnBN.js.map +0 -1
- package/dist/RolesView-CMPsaIXo.js.map +0 -1
- package/dist/UsersView-BkeblMVT.js.map +0 -1
- package/dist/index-BuZaHcyc.js.map +0 -1
- package/dist/index-CS6uJ7oW.js.map +0 -1
- package/dist/index-eRJbMvHi.js.map +0 -1
- package/dist/util-zfU1zOCX.js.map +0 -1
|
@@ -1,10 +1,29 @@
|
|
|
1
1
|
|
|
2
|
-
import
|
|
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
|
|
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 =
|
|
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={
|
|
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 {
|
|
4
|
-
|
|
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.
|
|
216
|
+
if (event.key === "Escape") {
|
|
217
217
|
unselect();
|
|
218
218
|
}
|
|
219
219
|
};
|
|
@@ -234,7 +234,7 @@ export const SelectableTable = function SelectableTable<M extends Record<string,
|
|
|
234
234
|
onValueChange,
|
|
235
235
|
size: size ?? "m",
|
|
236
236
|
selectionStore
|
|
237
|
-
} as
|
|
237
|
+
} as EntityCollectionTableController<any>), [setPopupCell, select, onValueChange, size, selectionStore]);
|
|
238
238
|
|
|
239
239
|
return (
|
|
240
240
|
<SelectableTableContext.Provider
|
|
@@ -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 "
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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={
|
|
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 {
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
294
|
-
</
|
|
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={
|
|
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
|
+
}
|