@gooddata/sdk-ui-ext 11.45.0-alpha.0 → 11.45.0-alpha.2
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/NOTICE +3 -3
- package/esm/insightPicker/InsightPickerCore.d.ts +1 -1
- package/esm/insightPicker/InsightPickerCore.d.ts.map +1 -1
- package/esm/insightPicker/InsightPickerCore.js +2 -2
- package/esm/insightPicker/InsightPickerRow.d.ts +1 -2
- package/esm/insightPicker/InsightPickerRow.d.ts.map +1 -1
- package/esm/insightPicker/InsightPickerRow.js +2 -2
- package/esm/insightPicker/types.d.ts +0 -1
- package/esm/insightPicker/types.d.ts.map +1 -1
- package/esm/internal/components/configurationPanels/ConfigurationPanelContent.d.ts.map +1 -1
- package/esm/internal/components/configurationPanels/ConfigurationPanelContent.js +4 -8
- package/esm/internal/components/dialogs/userManagementDialogs/DataSources/AddDataSourceSelect.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/DataSources/AddDataSourceSelect.js +6 -1
- package/esm/internal/components/dialogs/userManagementDialogs/DataSources/DataSourceItem.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/DataSources/DataSourceItem.js +10 -2
- package/esm/internal/components/dialogs/userManagementDialogs/DataSources/locales.d.ts +3 -0
- package/esm/internal/components/dialogs/userManagementDialogs/DataSources/locales.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/DataSources/locales.js +2 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Details/EditUserDetails.d.ts +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Details/EditUserDetails.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Details/detailsHooks.d.ts +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/UserEditDialog.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/UserEditDialog.js +11 -4
- package/esm/internal/components/dialogs/userManagementDialogs/UserGroupEditDialog.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/UserGroupEditDialog.js +8 -3
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddSingleWorkspaceSelect.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddSingleWorkspaceSelect.js +7 -2
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddWorkspaceSelect.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/AddWorkspaceSelect.js +5 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/GranularPermissionsWorkspaceItem.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/GranularPermissionsWorkspaceItem.js +9 -2
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/InheritedIcon.d.ts +12 -0
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/InheritedIcon.d.ts.map +1 -0
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/InheritedIcon.js +12 -0
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/locales.d.ts +6 -0
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/locales.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/Workspace/WorkspaceItem/locales.js +3 -1
- package/esm/internal/components/dialogs/userManagementDialogs/dialogHooks.d.ts +10 -2
- package/esm/internal/components/dialogs/userManagementDialogs/dialogHooks.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/dialogHooks.js +15 -11
- package/esm/internal/components/dialogs/userManagementDialogs/hooks/usePermissions.d.ts +10 -3
- package/esm/internal/components/dialogs/userManagementDialogs/hooks/usePermissions.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/hooks/usePermissions.js +59 -34
- package/esm/internal/components/dialogs/userManagementDialogs/locales.d.ts +3 -0
- package/esm/internal/components/dialogs/userManagementDialogs/locales.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/locales.js +1 -0
- package/esm/internal/components/dialogs/userManagementDialogs/types.d.ts +20 -1
- package/esm/internal/components/dialogs/userManagementDialogs/types.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/types.js +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/utils.d.ts +2 -0
- package/esm/internal/components/dialogs/userManagementDialogs/utils.d.ts.map +1 -1
- package/esm/internal/components/dialogs/userManagementDialogs/utils.js +40 -1
- package/esm/internal/components/pluggableVisualizations/baseChart/PluggableBaseChart.d.ts.map +1 -1
- package/esm/internal/components/pluggableVisualizations/baseChart/PluggableBaseChart.js +1 -1
- package/esm/internal/interfaces/Visualization.d.ts +1 -1
- package/esm/internal/interfaces/Visualization.d.ts.map +1 -1
- package/esm/internal/translations/en-US.localization-bundle.d.ts +24 -0
- package/esm/internal/translations/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/internal/translations/en-US.localization-bundle.js +24 -0
- package/esm/internal/utils/bucketHelper.d.ts.map +1 -1
- package/esm/internal/utils/bucketHelper.js +10 -3
- package/esm/sdk-ui-ext.d.ts +55 -5
- package/esm/share/ObjectShareDialog.d.ts.map +1 -1
- package/esm/share/ObjectShareDialog.js +37 -5
- package/esm/share/messages.d.ts +18 -0
- package/esm/share/messages.d.ts.map +1 -1
- package/esm/share/messages.js +6 -0
- package/esm/share/objectShareController.types.d.ts +45 -5
- package/esm/share/objectShareController.types.d.ts.map +1 -1
- package/esm/share/useAccessList.d.ts +14 -2
- package/esm/share/useAccessList.d.ts.map +1 -1
- package/esm/share/useAccessList.js +29 -6
- package/esm/share/useObjectShareController.d.ts.map +1 -1
- package/esm/share/useObjectShareController.js +200 -2
- package/package.json +21 -21
- package/styles/css/main.css +15 -0
- package/styles/css/main.css.map +1 -1
- package/styles/internal/css/user_management_dialogs.css +15 -0
- package/styles/internal/css/user_management_dialogs.css.map +1 -1
- package/styles/internal/scss/user_management_dialogs.scss +22 -0
package/esm/sdk-ui-ext.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { AutomationType } from '@gooddata/sdk-backend-spi';
|
|
|
15
15
|
import { ChartInlineVisualizationType } from '@gooddata/sdk-ui-charts';
|
|
16
16
|
import { ComponentType } from 'react';
|
|
17
17
|
import { CopyCodeOriginType } from '@gooddata/sdk-ui-kit';
|
|
18
|
+
import { DataSourceAccessSource } from '@gooddata/sdk-model';
|
|
18
19
|
import { Dispatch } from 'react';
|
|
19
20
|
import { EmbedType } from '@gooddata/sdk-ui-kit';
|
|
20
21
|
import { ExplicitDrill } from '@gooddata/sdk-ui';
|
|
@@ -47,6 +48,7 @@ import { IPivotTableConfig } from '@gooddata/sdk-ui-pivot';
|
|
|
47
48
|
import { ISettings } from '@gooddata/sdk-model';
|
|
48
49
|
import { ITab } from '@gooddata/sdk-ui-kit';
|
|
49
50
|
import { ITheme } from '@gooddata/sdk-model';
|
|
51
|
+
import type { IUiGranteeAsyncOption } from '@gooddata/sdk-ui-kit';
|
|
50
52
|
import type { IUiGranteeAsyncOptions } from '@gooddata/sdk-ui-kit';
|
|
51
53
|
import type { IUiPickedGrantee } from '@gooddata/sdk-ui-kit';
|
|
52
54
|
import { IUserWorkspaceSettings } from '@gooddata/sdk-backend-spi';
|
|
@@ -656,6 +658,15 @@ export declare interface IGrantedDataSource {
|
|
|
656
658
|
id: string;
|
|
657
659
|
title: string;
|
|
658
660
|
permission: DataSourcePermission;
|
|
661
|
+
/**
|
|
662
|
+
* True when the data source is accessible only indirectly - inherited through a user group rather
|
|
663
|
+
* than assigned directly. Such entries are shown read-only.
|
|
664
|
+
*/
|
|
665
|
+
isInherited?: boolean;
|
|
666
|
+
/**
|
|
667
|
+
* How the subject gains access to the data source (DIRECT, GROUP), when known.
|
|
668
|
+
*/
|
|
669
|
+
accessSource?: DataSourceAccessSource;
|
|
659
670
|
}
|
|
660
671
|
|
|
661
672
|
/**
|
|
@@ -729,7 +740,6 @@ export declare interface IInsightPickerProps {
|
|
|
729
740
|
author?: string;
|
|
730
741
|
enabledVisualizationClassesUrls?: string[];
|
|
731
742
|
selectedInsightId?: string;
|
|
732
|
-
enableDescriptions?: boolean;
|
|
733
743
|
metadataTimeZone?: string;
|
|
734
744
|
enableSemanticSearch?: boolean;
|
|
735
745
|
maxHeight?: number;
|
|
@@ -1454,11 +1464,13 @@ export declare interface IObjectShareControllerActions {
|
|
|
1454
1464
|
closeAddGrantee: () => void;
|
|
1455
1465
|
setPendingGrantees: (next: IUiPickedGrantee[]) => void;
|
|
1456
1466
|
/**
|
|
1457
|
-
* Loader for the
|
|
1467
|
+
* Loader for the grantee pickers. Wraps `getAvailableAssignees` with
|
|
1458
1468
|
* client-side search + already-picked filtering, returning the picker's
|
|
1459
|
-
* `{ groups, users }` shape.
|
|
1469
|
+
* `{ groups, users }` shape. By default excludes already-granted grantees
|
|
1470
|
+
* (add-grantee picker); pass `includeGranted` to keep them (transfer-ownership
|
|
1471
|
+
* picker, which may promote an existing viewer to owner).
|
|
1460
1472
|
*/
|
|
1461
|
-
loadOptions: (search: string) => Promise<IUiGranteeAsyncOptions>;
|
|
1473
|
+
loadOptions: (search: string, includeGranted?: boolean) => Promise<IUiGranteeAsyncOptions>;
|
|
1462
1474
|
/** Commit all pending grantees to the backend. */
|
|
1463
1475
|
confirmAddGrantees: () => Promise<void>;
|
|
1464
1476
|
/** Change the permission level for a single grantee. Auto-saves. */
|
|
@@ -1482,13 +1494,31 @@ export declare interface IObjectShareControllerActions {
|
|
|
1482
1494
|
* already-granted rule.
|
|
1483
1495
|
*/
|
|
1484
1496
|
changeWorkspaceLevel: (level: "VIEW" | "SHARE") => Promise<void>;
|
|
1497
|
+
/** Open the transfer-ownership subview with an empty picker. */
|
|
1498
|
+
openTransferOwnership: () => void;
|
|
1499
|
+
/** Close the transfer-ownership subview and clear its buffers; returns to main. */
|
|
1500
|
+
closeTransferOwnership: () => void;
|
|
1501
|
+
/**
|
|
1502
|
+
* Pick (or replace) the candidate new owner. Recomputes whether that user
|
|
1503
|
+
* already owns the object (`transferTargetIsOwner`).
|
|
1504
|
+
*/
|
|
1505
|
+
setTransferTarget: (owner: IUiGranteeAsyncOption) => void;
|
|
1506
|
+
/** Toggle "Also remove my access" in the transfer dialog. */
|
|
1507
|
+
setTransferAlsoRemoveSelf: (next: boolean) => void;
|
|
1508
|
+
/**
|
|
1509
|
+
* Commit the ownership transfer: grant the picked user EDIT and downgrade the
|
|
1510
|
+
* current user to VIEW (or remove them if "Also remove my access" is set), in
|
|
1511
|
+
* one write. When the picked user already owns the object this transfers
|
|
1512
|
+
* nothing and only applies the self-access choice. Auto-saves.
|
|
1513
|
+
*/
|
|
1514
|
+
confirmTransferOwnership: () => Promise<void>;
|
|
1485
1515
|
}
|
|
1486
1516
|
|
|
1487
1517
|
/**
|
|
1488
1518
|
* @internal
|
|
1489
1519
|
*/
|
|
1490
1520
|
export declare interface IObjectShareControllerState {
|
|
1491
|
-
subview: "main" | "addGrantee";
|
|
1521
|
+
subview: "main" | "addGrantee" | "transferOwnership";
|
|
1492
1522
|
status: "idle" | "loading" | "success" | "error" | "saving";
|
|
1493
1523
|
error?: Error;
|
|
1494
1524
|
/**
|
|
@@ -1537,6 +1567,26 @@ export declare interface IObjectShareControllerState {
|
|
|
1537
1567
|
pendingGeneralAccess?: GeneralAccessValue;
|
|
1538
1568
|
/** Grantees staged in the add-grantee dialog before confirmation. */
|
|
1539
1569
|
pendingGrantees: IUiPickedGrantee[];
|
|
1570
|
+
/**
|
|
1571
|
+
* The user picked as the new owner in the transfer-ownership subview, or
|
|
1572
|
+
* undefined before one is chosen. Only users can own an object, so this is
|
|
1573
|
+
* never a group.
|
|
1574
|
+
*/
|
|
1575
|
+
transferTarget: IUiGranteeAsyncOption | undefined;
|
|
1576
|
+
/**
|
|
1577
|
+
* Whether "Also remove my access" is checked in the transfer dialog. When
|
|
1578
|
+
* true the current user's grant is removed after the transfer; otherwise it
|
|
1579
|
+
* is downgraded to VIEW.
|
|
1580
|
+
*/
|
|
1581
|
+
transferAlsoRemoveSelf: boolean;
|
|
1582
|
+
/**
|
|
1583
|
+
* Whether `transferTarget` already owns the object (already holds EDIT). When
|
|
1584
|
+
* true there is nothing to transfer — consumers show the "already an owner"
|
|
1585
|
+
* variant offering to remove the current user's own access instead.
|
|
1586
|
+
*/
|
|
1587
|
+
transferTargetIsOwner: boolean;
|
|
1588
|
+
/** Whether the transfer write (or self-removal) is in flight. */
|
|
1589
|
+
transferSaving: boolean;
|
|
1540
1590
|
}
|
|
1541
1591
|
|
|
1542
1592
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectShareDialog.d.ts","sourceRoot":"","sources":["../../src/share/ObjectShareDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"ObjectShareDialog.d.ts","sourceRoot":"","sources":["../../src/share/ObjectShareDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAW1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAQpD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,gDAAgD;IAChD,MAAM,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC7C,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4FAA0F;IAC1F,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,EAC9B,MAAM,EACN,WAAW,EACX,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,aAAa,EACb,WAAW,EACX,UAAU,EACb,EAAE,uBAAuB,2CAkPzB"}
|
|
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
// (C) 2026 GoodData Corporation
|
|
3
3
|
import { useCallback } from "react";
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
|
-
import { UiAddGranteeDialog, UiConfirmDialog, UiGranteeRowControls, UiObjectShareDialog, } from "@gooddata/sdk-ui-kit";
|
|
5
|
+
import { UiAddGranteeDialog, UiConfirmDialog, UiGranteeRowControls, UiObjectShareDialog, UiRadioRow, UiTransferOwnershipDialog, } from "@gooddata/sdk-ui-kit";
|
|
6
6
|
import { objectShareMessages } from "./messages.js";
|
|
7
7
|
import { useObjectShareController } from "./useObjectShareController.js";
|
|
8
8
|
// The workspace row has no labels menu (see workspaceControls below), so its
|
|
@@ -43,8 +43,27 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
|
|
|
43
43
|
actions.reset();
|
|
44
44
|
onClose();
|
|
45
45
|
}, [actions, onClose]);
|
|
46
|
+
// Owner is always an individual user, so the transfer picker drops any groups
|
|
47
|
+
// the shared loader returns. `includeGranted` keeps already-granted users in
|
|
48
|
+
// the list — promoting an existing viewer to owner is a primary case.
|
|
49
|
+
//
|
|
50
|
+
// Depend on the stable `loadOptions` alone, not the whole `actions` object:
|
|
51
|
+
// `actions` changes identity as transfer state ticks (and as the picker's own
|
|
52
|
+
// name-cache writes re-derive grantees), and the autocomplete refetches page 0
|
|
53
|
+
// whenever its loader's identity changes — depending on `actions` here would
|
|
54
|
+
// self-feed into an infinite assignee-fetch loop.
|
|
55
|
+
const { loadOptions } = actions;
|
|
56
|
+
const loadOwnerOptions = useCallback(async (search) => {
|
|
57
|
+
const { users } = await loadOptions(search, true);
|
|
58
|
+
return { groups: [], users };
|
|
59
|
+
}, [loadOptions]);
|
|
46
60
|
const isAddGranteeOpen = isOpen && state.subview === "addGrantee";
|
|
47
|
-
|
|
61
|
+
// The transfer subview splits into two co-mounted dialogs: the transfer card
|
|
62
|
+
// while picking a non-owner, and the "already an owner" confirm once the picked
|
|
63
|
+
// user already owns the object.
|
|
64
|
+
const isTransferOpen = isOpen && state.subview === "transferOwnership" && !state.transferTargetIsOwner;
|
|
65
|
+
const isAlreadyOwnerOpen = isOpen && state.subview === "transferOwnership" && state.transferTargetIsOwner;
|
|
66
|
+
const isShareOpen = isOpen && state.subview === "main";
|
|
48
67
|
const isConfirmOpen = isOpen && !!state.pendingGeneralAccess;
|
|
49
68
|
// Don't allow mutations until the access list has loaded: before then the
|
|
50
69
|
// controller reports empty grantees + RESTRICTED, which is a placeholder, not
|
|
@@ -55,8 +74,13 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
|
|
|
55
74
|
// wrong labels). `labelsResolved` is false while labels are still loading and
|
|
56
75
|
// when their fetch failed, so a pending/failed label set blocks every
|
|
57
76
|
// access-changing control here — Add, row controls and general access alike.
|
|
77
|
+
// Also locked while a transfer-ownership write is committing: the transfer
|
|
78
|
+
// dialog can be dismissed (Back/Cancel/close) mid-save, so without this the
|
|
79
|
+
// user could return here and mutate other grantees concurrently with the
|
|
80
|
+
// in-flight ownership write — racing the same object's permissions with no
|
|
81
|
+
// refetch to reconcile. `transferSaving` clears when the transfer settles.
|
|
58
82
|
const isLoaded = state.status === "success";
|
|
59
|
-
const isMutable = isLoaded && state.labelsResolved;
|
|
83
|
+
const isMutable = isLoaded && state.labelsResolved && !state.transferSaving;
|
|
60
84
|
const isAddDisabled = !isMutable;
|
|
61
85
|
// Map the controller's labels to the picker's item shape; the primary label
|
|
62
86
|
// is rendered locked (always selected, can't be unchecked).
|
|
@@ -78,13 +102,13 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
|
|
|
78
102
|
// probe in flight) — removing or re-scoping before then
|
|
79
103
|
// would diff against the "assume all"/empty placeholder
|
|
80
104
|
// and silently orphan real per-label grants.
|
|
81
|
-
isDisabled: g.pending !== undefined || !state.labelsResolved, onLabelsChange: (selectedIds) => {
|
|
105
|
+
isDisabled: g.pending !== undefined || !state.labelsResolved || state.transferSaving, onLabelsChange: (selectedIds) => {
|
|
82
106
|
void actions.changeGranteeLabels(g.id, selectedIds);
|
|
83
107
|
}, onPermissionChange: (level) => {
|
|
84
108
|
void actions.changePermissionLevel(g.id, level);
|
|
85
109
|
}, onRemoveAccess: () => {
|
|
86
110
|
void actions.removeGrantee(g.id);
|
|
87
|
-
} })),
|
|
111
|
+
}, onTransferOwnership: actions.openTransferOwnership })),
|
|
88
112
|
})), onAddClick: actions.openAddGrantee, isAddDisabled: isAddDisabled, generalAccess: state.generalAccess, onGeneralAccessChange: actions.requestGeneralAccessChange,
|
|
89
113
|
// Permission dropdown on the "All workspace members" row — only while
|
|
90
114
|
// workspace access is on (the rule must exist to be re-graded). No
|
|
@@ -112,6 +136,14 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
|
|
|
112
136
|
// read as "no one has access".
|
|
113
137
|
error: state.status === "error" ? intl.formatMessage(objectShareMessages.loadError) : undefined }), _jsx(UiAddGranteeDialog, { isOpen: isAddGranteeOpen, objectTitle: objectTitle, loadOptions: actions.loadOptions, selectedGrantees: state.pendingGrantees, onSelectedGranteesChange: actions.setPendingGrantees, onBack: actions.closeAddGrantee, onClose: handleClose, onCancel: actions.closeAddGrantee, onShare: () => {
|
|
114
138
|
void actions.confirmAddGrantees();
|
|
139
|
+
} }), _jsx(UiTransferOwnershipDialog, { isOpen: isTransferOpen, objectTitle: objectTitle, loadOptions: loadOwnerOptions, selectedOwner: state.transferTarget, onSelectedOwnerChange: actions.setTransferTarget, alsoRemoveMyAccess: state.transferAlsoRemoveSelf, onAlsoRemoveMyAccessChange: actions.setTransferAlsoRemoveSelf, onBack: actions.closeTransferOwnership, onClose: handleClose, onCancel: actions.closeTransferOwnership, onTransfer: () => {
|
|
140
|
+
void actions.confirmTransferOwnership();
|
|
141
|
+
}, isSaving: state.transferSaving }), _jsx(UiConfirmDialog, { isOpen: isAlreadyOwnerOpen, title: intl.formatMessage(objectShareMessages.transferAlreadyOwnerTitle, {
|
|
142
|
+
name: state.transferTarget?.name ?? "",
|
|
143
|
+
}), description: _jsxs(_Fragment, { children: [
|
|
144
|
+
_jsx("p", { children: intl.formatMessage(objectShareMessages.transferAlreadyOwnerDescription) }), _jsx(UiRadioRow, { name: "transfer-already-owner", checked: !state.transferAlsoRemoveSelf, onChange: () => actions.setTransferAlsoRemoveSelf(false), title: intl.formatMessage(objectShareMessages.transferAlreadyOwnerKeepAccess) }), _jsx(UiRadioRow, { name: "transfer-already-owner", checked: state.transferAlsoRemoveSelf, onChange: () => actions.setTransferAlsoRemoveSelf(true), title: intl.formatMessage(objectShareMessages.transferAlreadyOwnerRemoveAccess) })
|
|
145
|
+
] }), confirmLabel: intl.formatMessage(objectShareMessages.transferConfirmButton), confirmVariant: "primary", onCancel: actions.closeTransferOwnership, onClose: actions.closeTransferOwnership, onConfirm: () => {
|
|
146
|
+
void actions.confirmTransferOwnership();
|
|
115
147
|
} }), _jsx(UiConfirmDialog, { isOpen: isConfirmOpen, title: intl.formatMessage(state.pendingGeneralAccess === "RESTRICTED"
|
|
116
148
|
? objectShareMessages.confirmRestrictTitle
|
|
117
149
|
: objectShareMessages.confirmGrantWorkspaceTitle), description: intl.formatMessage(state.pendingGeneralAccess === "RESTRICTED"
|
package/esm/share/messages.d.ts
CHANGED
|
@@ -22,6 +22,21 @@ export declare const objectShareMessages: {
|
|
|
22
22
|
confirmButton: {
|
|
23
23
|
id: string;
|
|
24
24
|
};
|
|
25
|
+
transferAlreadyOwnerTitle: {
|
|
26
|
+
id: string;
|
|
27
|
+
};
|
|
28
|
+
transferAlreadyOwnerDescription: {
|
|
29
|
+
id: string;
|
|
30
|
+
};
|
|
31
|
+
transferAlreadyOwnerKeepAccess: {
|
|
32
|
+
id: string;
|
|
33
|
+
};
|
|
34
|
+
transferAlreadyOwnerRemoveAccess: {
|
|
35
|
+
id: string;
|
|
36
|
+
};
|
|
37
|
+
transferConfirmButton: {
|
|
38
|
+
id: string;
|
|
39
|
+
};
|
|
25
40
|
toastGranteeAdded: {
|
|
26
41
|
id: string;
|
|
27
42
|
};
|
|
@@ -31,6 +46,9 @@ export declare const objectShareMessages: {
|
|
|
31
46
|
toastGeneralAccessUpdated: {
|
|
32
47
|
id: string;
|
|
33
48
|
};
|
|
49
|
+
toastOwnershipTransferred: {
|
|
50
|
+
id: string;
|
|
51
|
+
};
|
|
34
52
|
toastError: {
|
|
35
53
|
id: string;
|
|
36
54
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/share/messages.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/share/messages.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkB9B,CAAC"}
|
package/esm/share/messages.js
CHANGED
|
@@ -14,9 +14,15 @@ export const objectShareMessages = defineMessages({
|
|
|
14
14
|
confirmGrantWorkspaceTitle: { id: "objectShare.confirm.grantWorkspace.title" },
|
|
15
15
|
confirmGrantWorkspaceDescription: { id: "objectShare.confirm.grantWorkspace.description" },
|
|
16
16
|
confirmButton: { id: "objectShare.confirm.button" },
|
|
17
|
+
transferAlreadyOwnerTitle: { id: "objectShare.transfer.alreadyOwner.title" },
|
|
18
|
+
transferAlreadyOwnerDescription: { id: "objectShare.transfer.alreadyOwner.description" },
|
|
19
|
+
transferAlreadyOwnerKeepAccess: { id: "objectShare.transfer.alreadyOwner.keepAccess" },
|
|
20
|
+
transferAlreadyOwnerRemoveAccess: { id: "objectShare.transfer.alreadyOwner.removeAccess" },
|
|
21
|
+
transferConfirmButton: { id: "objectShare.transfer.confirmButton" },
|
|
17
22
|
toastGranteeAdded: { id: "objectShare.toast.granteeAdded" },
|
|
18
23
|
toastAccessUpdated: { id: "objectShare.toast.accessUpdated" },
|
|
19
24
|
toastGeneralAccessUpdated: { id: "objectShare.toast.generalAccessUpdated" },
|
|
25
|
+
toastOwnershipTransferred: { id: "objectShare.toast.ownershipTransferred" },
|
|
20
26
|
toastError: { id: "objectShare.toast.error" },
|
|
21
27
|
toastLabelScopePartial: { id: "objectShare.toast.labelScopePartial" },
|
|
22
28
|
loadError: { id: "objectShare.loadError" },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AccessGranularPermission, ObjRef } from "@gooddata/sdk-model";
|
|
2
|
-
import type { GeneralAccessValue, IUiGranteeAsyncOptions, IUiPickedGrantee } from "@gooddata/sdk-ui-kit";
|
|
2
|
+
import type { GeneralAccessValue, IUiGranteeAsyncOption, IUiGranteeAsyncOptions, IUiPickedGrantee } from "@gooddata/sdk-ui-kit";
|
|
3
3
|
import type { IObjectAccessSummary, IObjectShareLabel } from "./types.js";
|
|
4
4
|
/**
|
|
5
5
|
* Permission level surfaced in the share dialog — the model's granular access
|
|
@@ -48,7 +48,7 @@ export interface IObjectShareGrantee {
|
|
|
48
48
|
* @internal
|
|
49
49
|
*/
|
|
50
50
|
export interface IObjectShareControllerState {
|
|
51
|
-
subview: "main" | "addGrantee";
|
|
51
|
+
subview: "main" | "addGrantee" | "transferOwnership";
|
|
52
52
|
status: "idle" | "loading" | "success" | "error" | "saving";
|
|
53
53
|
error?: Error;
|
|
54
54
|
/**
|
|
@@ -97,6 +97,26 @@ export interface IObjectShareControllerState {
|
|
|
97
97
|
pendingGeneralAccess?: GeneralAccessValue;
|
|
98
98
|
/** Grantees staged in the add-grantee dialog before confirmation. */
|
|
99
99
|
pendingGrantees: IUiPickedGrantee[];
|
|
100
|
+
/**
|
|
101
|
+
* The user picked as the new owner in the transfer-ownership subview, or
|
|
102
|
+
* undefined before one is chosen. Only users can own an object, so this is
|
|
103
|
+
* never a group.
|
|
104
|
+
*/
|
|
105
|
+
transferTarget: IUiGranteeAsyncOption | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Whether "Also remove my access" is checked in the transfer dialog. When
|
|
108
|
+
* true the current user's grant is removed after the transfer; otherwise it
|
|
109
|
+
* is downgraded to VIEW.
|
|
110
|
+
*/
|
|
111
|
+
transferAlsoRemoveSelf: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Whether `transferTarget` already owns the object (already holds EDIT). When
|
|
114
|
+
* true there is nothing to transfer — consumers show the "already an owner"
|
|
115
|
+
* variant offering to remove the current user's own access instead.
|
|
116
|
+
*/
|
|
117
|
+
transferTargetIsOwner: boolean;
|
|
118
|
+
/** Whether the transfer write (or self-removal) is in flight. */
|
|
119
|
+
transferSaving: boolean;
|
|
100
120
|
}
|
|
101
121
|
/**
|
|
102
122
|
* @internal
|
|
@@ -108,11 +128,13 @@ export interface IObjectShareControllerActions {
|
|
|
108
128
|
closeAddGrantee: () => void;
|
|
109
129
|
setPendingGrantees: (next: IUiPickedGrantee[]) => void;
|
|
110
130
|
/**
|
|
111
|
-
* Loader for the
|
|
131
|
+
* Loader for the grantee pickers. Wraps `getAvailableAssignees` with
|
|
112
132
|
* client-side search + already-picked filtering, returning the picker's
|
|
113
|
-
* `{ groups, users }` shape.
|
|
133
|
+
* `{ groups, users }` shape. By default excludes already-granted grantees
|
|
134
|
+
* (add-grantee picker); pass `includeGranted` to keep them (transfer-ownership
|
|
135
|
+
* picker, which may promote an existing viewer to owner).
|
|
114
136
|
*/
|
|
115
|
-
loadOptions: (search: string) => Promise<IUiGranteeAsyncOptions>;
|
|
137
|
+
loadOptions: (search: string, includeGranted?: boolean) => Promise<IUiGranteeAsyncOptions>;
|
|
116
138
|
/** Commit all pending grantees to the backend. */
|
|
117
139
|
confirmAddGrantees: () => Promise<void>;
|
|
118
140
|
/** Change the permission level for a single grantee. Auto-saves. */
|
|
@@ -136,6 +158,24 @@ export interface IObjectShareControllerActions {
|
|
|
136
158
|
* already-granted rule.
|
|
137
159
|
*/
|
|
138
160
|
changeWorkspaceLevel: (level: "VIEW" | "SHARE") => Promise<void>;
|
|
161
|
+
/** Open the transfer-ownership subview with an empty picker. */
|
|
162
|
+
openTransferOwnership: () => void;
|
|
163
|
+
/** Close the transfer-ownership subview and clear its buffers; returns to main. */
|
|
164
|
+
closeTransferOwnership: () => void;
|
|
165
|
+
/**
|
|
166
|
+
* Pick (or replace) the candidate new owner. Recomputes whether that user
|
|
167
|
+
* already owns the object (`transferTargetIsOwner`).
|
|
168
|
+
*/
|
|
169
|
+
setTransferTarget: (owner: IUiGranteeAsyncOption) => void;
|
|
170
|
+
/** Toggle "Also remove my access" in the transfer dialog. */
|
|
171
|
+
setTransferAlsoRemoveSelf: (next: boolean) => void;
|
|
172
|
+
/**
|
|
173
|
+
* Commit the ownership transfer: grant the picked user EDIT and downgrade the
|
|
174
|
+
* current user to VIEW (or remove them if "Also remove my access" is set), in
|
|
175
|
+
* one write. When the picked user already owns the object this transfers
|
|
176
|
+
* nothing and only applies the self-access choice. Auto-saves.
|
|
177
|
+
*/
|
|
178
|
+
confirmTransferOwnership: () => Promise<void>;
|
|
139
179
|
}
|
|
140
180
|
/**
|
|
141
181
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objectShareController.types.d.ts","sourceRoot":"","sources":["../../src/share/objectShareController.types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"objectShareController.types.d.ts","sourceRoot":"","sources":["../../src/share/objectShareController.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,8 +36,20 @@ export interface IAccessList {
|
|
|
36
36
|
commit: (mutate: IGranularAccessGrantee[], successMessage: {
|
|
37
37
|
id: string;
|
|
38
38
|
}) => Promise<boolean>;
|
|
39
|
-
/**
|
|
40
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Picker loader — available assignees filtered by query. By default excludes
|
|
41
|
+
* already-granted grantees (add-grantee picker); pass `includeGranted` to keep
|
|
42
|
+
* them (transfer-ownership picker, which may promote an existing viewer).
|
|
43
|
+
*/
|
|
44
|
+
loadOptions: (search: string, includeGranted?: boolean) => Promise<IUiGranteeAsyncOptions>;
|
|
45
|
+
/**
|
|
46
|
+
* The current user's ref, resolved on demand (and cached). Used by the
|
|
47
|
+
* transfer-ownership flow to write the current user's own grant change. The
|
|
48
|
+
* add-grantee *picker* excludes the current user, but `getAccessList` does
|
|
49
|
+
* not, so a self grant can still appear as a row. Rejects if the profile
|
|
50
|
+
* can't be read.
|
|
51
|
+
*/
|
|
52
|
+
getCurrentUserRef: () => Promise<ObjRef>;
|
|
41
53
|
/** Resolve a grantee id back to the picker's original ObjRef (preserves Uri vs Id ref). */
|
|
42
54
|
refForId: (id: string) => ObjRef;
|
|
43
55
|
/** Write through a local grantee-row change (insert / level / remove); rolled back by the caller. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAccessList.d.ts","sourceRoot":"","sources":["../../src/share/useAccessList.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,MAAM,EAEd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAmB,MAAM,sBAAsB,CAAC;AAW7G,OAAO,KAAK,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACzG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,iFAAiF;IACjF,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,wFAAwF;IACxF,OAAO,EAAE,OAAO,CAAC;IACjB,iGAA+F;IAC/F,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,uFAAqF;IACrF,aAAa,EAAE,kBAAkB,CAAC;IAClC,6FAA2F;IAC3F,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,iEAAiE;IACjE,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,MAAM,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAC9C,iDAAiD;IACjD,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAE3B,mFAAmF;IACnF,MAAM,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,EAAE,cAAc,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/F
|
|
1
|
+
{"version":3,"file":"useAccessList.d.ts","sourceRoot":"","sources":["../../src/share/useAccessList.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,MAAM,EAEd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAmB,MAAM,sBAAsB,CAAC;AAW7G,OAAO,KAAK,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACzG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,iFAAiF;IACjF,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,wFAAwF;IACxF,OAAO,EAAE,OAAO,CAAC;IACjB,iGAA+F;IAC/F,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,uFAAqF;IACrF,aAAa,EAAE,kBAAkB,CAAC;IAClC,6FAA2F;IAC3F,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,iEAAiE;IACjE,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,MAAM,EAAE,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAC9C,iDAAiD;IACjD,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAE3B,mFAAmF;IACnF,MAAM,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,EAAE,cAAc,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/F;;;;OAIG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC3F;;;;;;OAMG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,2FAA2F;IAC3F,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IAEjC,qGAAqG;IACrG,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACzE,8EAA8E;IAC9E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC3E;;;;OAIG;IACH,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAC1E,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC/E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAClC,WAAW,CAoSb"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { objRefToString, } from "@gooddata/sdk-model";
|
|
4
4
|
import { useBackendStrict, useCancelablePromise, useWorkspaceStrict } from "@gooddata/sdk-ui";
|
|
5
5
|
import { useToastMessage } from "@gooddata/sdk-ui-kit";
|
|
@@ -41,6 +41,9 @@ export function useAccessList(target, onSaved) {
|
|
|
41
41
|
// Original ObjRef per grantee id, learned from the picker (the access-list id
|
|
42
42
|
// is a serialized `kind:identifier`, which loses Uri-vs-Id). Reused for writes.
|
|
43
43
|
const [knownRefs, setKnownRefs] = useState({});
|
|
44
|
+
// Memoized current-user-ref fetch — the profile doesn't change while mounted,
|
|
45
|
+
// so resolve it at most once and share the promise across callers.
|
|
46
|
+
const currentUserRefCache = useRef(undefined);
|
|
44
47
|
const targetKey = target ? objRefToString(target.ref) : undefined;
|
|
45
48
|
// Learn each assignee's real name + ref into the caches, keyed by the same
|
|
46
49
|
// grantee id the rows use. Written from both the picker (loadOptions) and the
|
|
@@ -190,10 +193,14 @@ export function useAccessList(target, onSaved) {
|
|
|
190
193
|
}
|
|
191
194
|
}, [backend, workspace, target, toast, onSaved]);
|
|
192
195
|
// Picker loader — fetches available assignees on demand, filters by the typed
|
|
193
|
-
// query, excludes anything already granted. Depends only on the
|
|
194
|
-
// (grantees), so its identity changes only when that set actually
|
|
195
|
-
// must NOT write state that feeds its own deps.
|
|
196
|
-
|
|
196
|
+
// query, and by default excludes anything already granted. Depends only on the
|
|
197
|
+
// granted set (grantees), so its identity changes only when that set actually
|
|
198
|
+
// changes. It must NOT write state that feeds its own deps.
|
|
199
|
+
//
|
|
200
|
+
// `includeGranted` keeps already-granted grantees in the result. The
|
|
201
|
+
// transfer-ownership picker needs this: promoting an existing viewer to owner
|
|
202
|
+
// is a primary case, and the add-grantee exclusion would otherwise hide them.
|
|
203
|
+
const loadOptions = useCallback(async (search, includeGranted = false) => {
|
|
197
204
|
if (!target) {
|
|
198
205
|
return { groups: [], users: [] };
|
|
199
206
|
}
|
|
@@ -210,7 +217,7 @@ export function useAccessList(target, onSaved) {
|
|
|
210
217
|
// even when the access-list grant later returns only a raw id. Safe here:
|
|
211
218
|
// the caches aren't dependencies of loadOptions, so this won't re-trigger it.
|
|
212
219
|
cacheAssignees(assignees);
|
|
213
|
-
const excluded = new Set(excludedIdsKey ? excludedIdsKey.split(",")
|
|
220
|
+
const excluded = new Set(includeGranted || !excludedIdsKey ? [] : excludedIdsKey.split(","));
|
|
214
221
|
const selectable = withIds
|
|
215
222
|
.filter(({ id }) => !excluded.has(id)) // hide anyone already granted
|
|
216
223
|
.filter(({ assignee }) => assigneeMatchesQuery(assignee, query));
|
|
@@ -231,6 +238,21 @@ export function useAccessList(target, onSaved) {
|
|
|
231
238
|
// Reuse the picker's original ref (preserves UriRef vs IdentifierRef);
|
|
232
239
|
// fall back to the serialized id only if it wasn't cached.
|
|
233
240
|
const refForId = useCallback((id) => knownRefs[id] ?? { identifier: id.split(":", 2)[1] }, [knownRefs]);
|
|
241
|
+
const getCurrentUserRef = useCallback(async () => {
|
|
242
|
+
if (!currentUserRefCache.current) {
|
|
243
|
+
currentUserRefCache.current = backend
|
|
244
|
+
.currentUser()
|
|
245
|
+
.getUser()
|
|
246
|
+
.then((user) => user.ref)
|
|
247
|
+
.catch((error) => {
|
|
248
|
+
// Don't cache a rejected promise, or a transient profile-read
|
|
249
|
+
// failure would make every later transfer fail immediately.
|
|
250
|
+
currentUserRefCache.current = undefined;
|
|
251
|
+
throw error;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
return currentUserRefCache.current;
|
|
255
|
+
}, [backend]);
|
|
234
256
|
return {
|
|
235
257
|
targetKey,
|
|
236
258
|
hasList,
|
|
@@ -244,6 +266,7 @@ export function useAccessList(target, onSaved) {
|
|
|
244
266
|
commit,
|
|
245
267
|
loadOptions,
|
|
246
268
|
refForId,
|
|
269
|
+
getCurrentUserRef,
|
|
247
270
|
setGrantees,
|
|
248
271
|
setGeneralAccess,
|
|
249
272
|
setWorkspaceLevel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useObjectShareController.d.ts","sourceRoot":"","sources":["../../src/share/useObjectShareController.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"useObjectShareController.d.ts","sourceRoot":"","sources":["../../src/share/useObjectShareController.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAkB1E,OAAO,EACH,KAAK,sBAAsB,EAI3B,KAAK,sBAAsB,EAE9B,MAAM,kCAAkC,CAAC;AAI1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,wBAAwB,GAAG,SAAS,EAC5C,OAAO,CAAC,EAAE,sBAAsB,GACjC,sBAAsB,CAwyBxB"}
|