@gooddata/sdk-ui-ext 11.43.0-alpha.5 → 11.43.0

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.
@@ -1475,6 +1475,13 @@ export declare interface IObjectShareControllerActions {
1475
1475
  cancelGeneralAccessChange: () => void;
1476
1476
  /** Commit the pending general access change. Auto-saves. */
1477
1477
  confirmGeneralAccessChange: () => Promise<void>;
1478
+ /**
1479
+ * Change the all-workspace-members rule's permission level (VIEW/SHARE).
1480
+ * Only meaningful while general access is WORKSPACE. Auto-saves, no confirm —
1481
+ * unlike the high-impact RESTRICTED↔WORKSPACE toggle, this only re-grades an
1482
+ * already-granted rule.
1483
+ */
1484
+ changeWorkspaceLevel: (level: "VIEW" | "SHARE") => Promise<void>;
1478
1485
  }
1479
1486
 
1480
1487
  /**
@@ -1487,6 +1494,19 @@ export declare interface IObjectShareControllerState {
1487
1494
  summary: IObjectAccessSummary | undefined;
1488
1495
  grantees: IObjectShareGrantee[];
1489
1496
  generalAccess: GeneralAccessValue;
1497
+ /**
1498
+ * Permission level of the all-workspace-members rule when general access is
1499
+ * WORKSPACE. Drives the workspace row's permission dropdown. Meaningless (and
1500
+ * not shown) while general access is RESTRICTED. Capped at VIEW/SHARE — EDIT is
1501
+ * never offered for the workspace rule.
1502
+ */
1503
+ workspaceLevel: "VIEW" | "SHARE";
1504
+ /**
1505
+ * Whether a workspace-level re-grade is in flight. Consumers disable the
1506
+ * workspace permission dropdown while true so rapid toggles can't issue
1507
+ * overlapping writes that settle out of order.
1508
+ */
1509
+ workspaceLevelSaving: boolean;
1490
1510
  /**
1491
1511
  * Labels (display forms) of the shared attribute, in source order. Empty for
1492
1512
  * objects without labels (e.g. facts) — the labels picker is then hidden.
@@ -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;AAS1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD;;;;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,2CAwIzB"}
1
+ {"version":3,"file":"ObjectShareDialog.d.ts","sourceRoot":"","sources":["../../src/share/ObjectShareDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAS1E,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,2CAmKzB"}
@@ -5,6 +5,10 @@ import { useIntl } from "react-intl";
5
5
  import { UiAddGranteeDialog, UiConfirmDialog, UiGranteeRowControls, UiObjectShareDialog, } from "@gooddata/sdk-ui-kit";
6
6
  import { objectShareMessages } from "./messages.js";
7
7
  import { useObjectShareController } from "./useObjectShareController.js";
8
+ // The workspace row has no labels menu (see workspaceControls below), so its
9
+ // required onLabelsChange never fires; a stable no-op satisfies the prop type
10
+ // without churning the controls' identity each render.
11
+ const noop = () => { };
8
12
  /**
9
13
  * Connected share dialog. Renders the main share modal, the add-grantee
10
14
  * sub-dialog and the general-access confirm dialog, all driven by one
@@ -82,10 +86,27 @@ export function ObjectShareDialog({ target, objectTitle, isOpen, onClose, onSave
82
86
  void actions.removeGrantee(g.id);
83
87
  } })),
84
88
  })), onAddClick: actions.openAddGrantee, isAddDisabled: isAddDisabled, generalAccess: state.generalAccess, onGeneralAccessChange: actions.requestGeneralAccessChange,
89
+ // Permission dropdown on the "All workspace members" row — only while
90
+ // workspace access is on (the rule must exist to be re-graded). No
91
+ // labels (⋯) menu and no remove: per the Figma spec the workspace row
92
+ // carries the permission picker alone; the workspace rule's label
93
+ // scope is managed implicitly with the RESTRICTED↔WORKSPACE toggle.
94
+ workspaceControls: state.generalAccess === "WORKSPACE" ? (_jsx(UiGranteeRowControls, { labels: [], selectedLabelIds: [], permissionLevel: state.workspaceLevel,
95
+ // Also disabled while its own re-grade is committing, so
96
+ // rapid toggles can't queue overlapping writes.
97
+ isDisabled: !isMutable || state.workspaceLevelSaving, onLabelsChange: noop, onPermissionChange: (level) => {
98
+ void actions.changeWorkspaceLevel(level);
99
+ } })) : undefined,
100
+ // Keep the "All workspace members" description in sync with the picked
101
+ // level ("can view" vs "can view and share").
102
+ workspaceLevel: state.workspaceLevel,
85
103
  // Gated on the same condition as Add: changing general access also
86
104
  // mirrors the label scope, so it must wait for resolution and stay
87
- // disabled when label metadata failed to load.
88
- isGeneralAccessDisabled: !isMutable,
105
+ // disabled when label metadata failed to load. Also gated while a
106
+ // workspace-level re-grade is in flight: switching to Restricted then
107
+ // would issue an allWorkspaceUsers:none write that could race the
108
+ // pending re-grade and leave the backend on the wrong rule.
109
+ isGeneralAccessDisabled: !isMutable || state.workspaceLevelSaving,
89
110
  // On a failed load the empty grantee list + RESTRICTED radio are a
90
111
  // placeholder, not the real policy — show why instead of letting it
91
112
  // read as "no one has access".
@@ -80,7 +80,7 @@ export function toGranularGrantee(kind, granteeRef, level) {
80
80
  }
81
81
  export function granularGranteeFor(principal, level) {
82
82
  if ("allWorkspaceUsers" in principal) {
83
- const permissions = level === "none" ? [] : ["VIEW"];
83
+ const permissions = PERMISSIONS_BY_LEVEL[level];
84
84
  return { type: "allWorkspaceUsers", permissions, inheritedPermissions: [] };
85
85
  }
86
86
  return toGranularGrantee(principal.kind, principal.granteeRef, level);
@@ -54,6 +54,19 @@ export interface IObjectShareControllerState {
54
54
  summary: IObjectAccessSummary | undefined;
55
55
  grantees: IObjectShareGrantee[];
56
56
  generalAccess: GeneralAccessValue;
57
+ /**
58
+ * Permission level of the all-workspace-members rule when general access is
59
+ * WORKSPACE. Drives the workspace row's permission dropdown. Meaningless (and
60
+ * not shown) while general access is RESTRICTED. Capped at VIEW/SHARE — EDIT is
61
+ * never offered for the workspace rule.
62
+ */
63
+ workspaceLevel: "VIEW" | "SHARE";
64
+ /**
65
+ * Whether a workspace-level re-grade is in flight. Consumers disable the
66
+ * workspace permission dropdown while true so rapid toggles can't issue
67
+ * overlapping writes that settle out of order.
68
+ */
69
+ workspaceLevelSaving: boolean;
57
70
  /**
58
71
  * Labels (display forms) of the shared attribute, in source order. Empty for
59
72
  * objects without labels (e.g. facts) — the labels picker is then hidden.
@@ -108,6 +121,13 @@ export interface IObjectShareControllerActions {
108
121
  cancelGeneralAccessChange: () => void;
109
122
  /** Commit the pending general access change. Auto-saves. */
110
123
  confirmGeneralAccessChange: () => Promise<void>;
124
+ /**
125
+ * Change the all-workspace-members rule's permission level (VIEW/SHARE).
126
+ * Only meaningful while general access is WORKSPACE. Auto-saves, no confirm —
127
+ * unlike the high-impact RESTRICTED↔WORKSPACE toggle, this only re-grades an
128
+ * already-granted rule.
129
+ */
130
+ changeWorkspaceLevel: (level: "VIEW" | "SHARE") => Promise<void>;
111
131
  }
112
132
  /**
113
133
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"objectShareController.types.d.ts","sourceRoot":"","sources":["../../src/share/objectShareController.types.ts"],"names":[],"mappings":"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"}
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,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEzG,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,MAAM,0BAA0B,GAAG,wBAAwB,CAAC;AAElE;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,0BAA0B,CAAC;IAClC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,0BAA0B,CAAC;IACjD;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IACxC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;IAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5D,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAE1C,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,aAAa,EAAE,kBAAkB,CAAC;IAClC;;;;;OAKG;IACH,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC;;;;OAIG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAE9B;;;OAGG;IACH,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEpD,mEAAiE;IACjE,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;IAC1C,qEAAqE;IACrE,eAAe,EAAE,gBAAgB,EAAE,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC1C,sFAAsF;IACtF,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD;;;;OAIG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACjE,kDAAkD;IAClD,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC,oEAAoE;IACpE,qBAAqB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,0BAA0B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/F,oCAAoC;IACpC,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD;;;OAGG;IACH,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtF,+DAA+D;IAC/D,0BAA0B,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/D,yBAAyB,EAAE,MAAM,IAAI,CAAC;IACtC,4DAA4D;IAC5D,0BAA0B,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;;;;OAKG;IACH,oBAAoB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,2BAA2B,CAAC;IACnC,OAAO,EAAE,6BAA6B,CAAC;CAC1C;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC7B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B"}
@@ -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;AAa1E,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,CAggBxB"}
1
+ {"version":3,"file":"useObjectShareController.d.ts","sourceRoot":"","sources":["../../src/share/useObjectShareController.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAa1E,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,CAyjBxB"}
@@ -35,6 +35,11 @@ export function useObjectShareController(target, options) {
35
35
  const [subview, setSubview] = useState("main");
36
36
  const [pendingGrantees, setPendingGrantees] = useState([]);
37
37
  const [pendingGeneralAccess, setPendingGeneralAccess] = useState(undefined);
38
+ // True while a workspace-level re-grade is committing. The workspace rule has no
39
+ // grantee row to carry a `pending` flag (unlike named grantees), so this gates
40
+ // re-entry and disables the dropdown to keep rapid VIEW↔SHARE toggles from issuing
41
+ // overlapping writes that could settle out of order.
42
+ const [workspaceLevelSaving, setWorkspaceLevelSaving] = useState(false);
38
43
  // The backend access list, seeded into local state (rows, general access,
39
44
  // summary, the commit/picker primitives) lives in its own hook.
40
45
  const { targetKey, hasList, grantees, generalAccess, workspaceLevel, summary, status, loadError, commit, loadOptions, refForId, setGrantees, setGeneralAccess, setWorkspaceLevel, setKnownNames, } = useAccessList(target, onSaved);
@@ -63,11 +68,13 @@ export function useObjectShareController(target, options) {
63
68
  setSubview("main");
64
69
  setPendingGrantees([]);
65
70
  setPendingGeneralAccess(undefined);
71
+ setWorkspaceLevelSaving(false);
66
72
  }
67
73
  const reset = useCallback(() => {
68
74
  setSubview("main");
69
75
  setPendingGrantees([]);
70
76
  setPendingGeneralAccess(undefined);
77
+ setWorkspaceLevelSaving(false);
71
78
  }, []);
72
79
  const openAddGrantee = useCallback(() => {
73
80
  setSubview("addGrantee");
@@ -332,6 +339,13 @@ export function useObjectShareController(target, options) {
332
339
  setPendingGeneralAccess(undefined);
333
340
  return;
334
341
  }
342
+ // Don't toggle general access while a workspace-level re-grade is committing:
343
+ // the two write the same allWorkspaceUsers rule, so a late re-grade could land
344
+ // after this and leave the backend broader than the UI shows. The dialog also
345
+ // disables the radio in this window; this guards the controller directly.
346
+ if (workspaceLevelSaving) {
347
+ return;
348
+ }
335
349
  const startedFor = targetKey;
336
350
  const previous = generalAccess;
337
351
  const previousWorkspaceLevel = workspaceLevel;
@@ -379,6 +393,7 @@ export function useObjectShareController(target, options) {
379
393
  pendingGeneralAccess,
380
394
  generalAccess,
381
395
  workspaceLevel,
396
+ workspaceLevelSaving,
382
397
  targetKey,
383
398
  applyAccessChange,
384
399
  effectiveLabels,
@@ -386,6 +401,32 @@ export function useObjectShareController(target, options) {
386
401
  setGeneralAccess,
387
402
  setWorkspaceLevel,
388
403
  ]);
404
+ const changeWorkspaceLevel = useCallback(async (level) => {
405
+ // Only re-grade an already-granted workspace rule; ignore no-ops, calls made
406
+ // while access is restricted (no rule to re-grade), and re-entry while a
407
+ // previous re-grade is still in flight (would overlap writes).
408
+ if (generalAccess !== "WORKSPACE" || level === workspaceLevel || workspaceLevelSaving) {
409
+ return;
410
+ }
411
+ const startedFor = targetKey;
412
+ const previousLevel = workspaceLevel;
413
+ // Reflect the new level immediately and mark the write in flight, then commit
414
+ // it. Labels are untouched — they were already mirrored when workspace access
415
+ // was granted; this changes only the rule's permission grade.
416
+ setWorkspaceLevel(level);
417
+ setWorkspaceLevelSaving(true);
418
+ const ok = await commit([granularGranteeFor({ allWorkspaceUsers: true }, level)], objectShareMessages.toastGeneralAccessUpdated);
419
+ // Bail if the target switched mid-write — the workspace level now belongs to
420
+ // the other object, so neither keeping nor rolling back applies here. The
421
+ // saving flag is reset on the new target's seed, so don't touch it.
422
+ if (targetKeyRef.current !== startedFor) {
423
+ return;
424
+ }
425
+ if (!ok) {
426
+ setWorkspaceLevel(previousLevel);
427
+ }
428
+ setWorkspaceLevelSaving(false);
429
+ }, [generalAccess, workspaceLevel, workspaceLevelSaving, targetKey, commit, setWorkspaceLevel]);
389
430
  const actions = useMemo(() => ({
390
431
  reset,
391
432
  openAddGrantee,
@@ -399,6 +440,7 @@ export function useObjectShareController(target, options) {
399
440
  requestGeneralAccessChange,
400
441
  cancelGeneralAccessChange: () => setPendingGeneralAccess(undefined),
401
442
  confirmGeneralAccessChange,
443
+ changeWorkspaceLevel,
402
444
  }), [
403
445
  reset,
404
446
  openAddGrantee,
@@ -410,6 +452,7 @@ export function useObjectShareController(target, options) {
410
452
  changeGranteeLabels,
411
453
  requestGeneralAccessChange,
412
454
  confirmGeneralAccessChange,
455
+ changeWorkspaceLevel,
413
456
  ]);
414
457
  const state = useMemo(() => ({
415
458
  subview,
@@ -418,6 +461,11 @@ export function useObjectShareController(target, options) {
418
461
  summary,
419
462
  grantees,
420
463
  generalAccess,
464
+ // The workspace rule isn't granted while restricted, so its level is
465
+ // meaningless then — pin to VIEW so the (hidden) dropdown never shows a
466
+ // stale SHARE left over from a prior workspace grant.
467
+ workspaceLevel: generalAccess === "WORKSPACE" ? workspaceLevel : "VIEW",
468
+ workspaceLevelSaving,
421
469
  labels: effectiveLabels,
422
470
  labelsResolved,
423
471
  selectedLabelIdsByGrantee,
@@ -430,6 +478,8 @@ export function useObjectShareController(target, options) {
430
478
  summary,
431
479
  grantees,
432
480
  generalAccess,
481
+ workspaceLevel,
482
+ workspaceLevelSaving,
433
483
  effectiveLabels,
434
484
  labelsResolved,
435
485
  selectedLabelIdsByGrantee,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-ext",
3
- "version": "11.43.0-alpha.5",
3
+ "version": "11.43.0",
4
4
  "description": "GoodData.UI SDK - Extensions",
5
5
  "license": "LicenseRef-LICENSE",
6
6
  "author": "GoodData Corporation",
@@ -63,20 +63,20 @@
63
63
  "ts-invariant": "0.10.3",
64
64
  "tslib": "2.8.1",
65
65
  "uuid": "11.1.1",
66
- "@gooddata/sdk-backend-base": "11.43.0-alpha.5",
67
- "@gooddata/sdk-embedding": "11.43.0-alpha.5",
68
- "@gooddata/sdk-backend-spi": "11.43.0-alpha.5",
69
- "@gooddata/sdk-model": "11.43.0-alpha.5",
70
- "@gooddata/sdk-ui": "11.43.0-alpha.5",
71
- "@gooddata/sdk-ui-charts": "11.43.0-alpha.5",
72
- "@gooddata/sdk-ui-filters": "11.43.0-alpha.5",
73
- "@gooddata/sdk-ui-geo": "11.43.0-alpha.5",
74
- "@gooddata/sdk-ui-kit": "11.43.0-alpha.5",
75
- "@gooddata/sdk-ui-pivot": "11.43.0-alpha.5",
76
- "@gooddata/sdk-ui-semantic-search": "11.43.0-alpha.5",
77
- "@gooddata/sdk-ui-vis-commons": "11.43.0-alpha.5",
78
- "@gooddata/sdk-ui-theme-provider": "11.43.0-alpha.5",
79
- "@gooddata/util": "11.43.0-alpha.5"
66
+ "@gooddata/sdk-backend-base": "11.43.0",
67
+ "@gooddata/sdk-backend-spi": "11.43.0",
68
+ "@gooddata/sdk-embedding": "11.43.0",
69
+ "@gooddata/sdk-model": "11.43.0",
70
+ "@gooddata/sdk-ui": "11.43.0",
71
+ "@gooddata/sdk-ui-charts": "11.43.0",
72
+ "@gooddata/sdk-ui-geo": "11.43.0",
73
+ "@gooddata/sdk-ui-kit": "11.43.0",
74
+ "@gooddata/sdk-ui-pivot": "11.43.0",
75
+ "@gooddata/sdk-ui-filters": "11.43.0",
76
+ "@gooddata/sdk-ui-semantic-search": "11.43.0",
77
+ "@gooddata/sdk-ui-theme-provider": "11.43.0",
78
+ "@gooddata/util": "11.43.0",
79
+ "@gooddata/sdk-ui-vis-commons": "11.43.0"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@microsoft/api-documenter": "^7.17.0",
@@ -124,12 +124,12 @@
124
124
  "typescript": "5.9.3",
125
125
  "vitest": "4.1.8",
126
126
  "vitest-dom": "0.1.1",
127
- "@gooddata/eslint-config": "11.43.0-alpha.5",
128
- "@gooddata/i18n-toolkit": "11.43.0-alpha.5",
129
- "@gooddata/oxlint-config": "11.43.0-alpha.5",
130
- "@gooddata/reference-workspace": "11.43.0-alpha.5",
131
- "@gooddata/sdk-backend-mockingbird": "11.43.0-alpha.5",
132
- "@gooddata/stylelint-config": "11.43.0-alpha.5"
127
+ "@gooddata/eslint-config": "11.43.0",
128
+ "@gooddata/i18n-toolkit": "11.43.0",
129
+ "@gooddata/oxlint-config": "11.43.0",
130
+ "@gooddata/reference-workspace": "11.43.0",
131
+ "@gooddata/sdk-backend-mockingbird": "11.43.0",
132
+ "@gooddata/stylelint-config": "11.43.0"
133
133
  },
134
134
  "peerDependencies": {
135
135
  "react": "^18.0.0 || ^19.0.0",