@gooddata/sdk-ui-dashboard 11.61.0-alpha.4 → 11.61.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/NOTICE +409 -550
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/index.d.ts +1 -0
  5. package/esm/index.d.ts.map +1 -1
  6. package/esm/model/commandHandlers/dashboard/deleteDashboardHandler.d.ts.map +1 -1
  7. package/esm/model/commandHandlers/dashboard/deleteDashboardHandler.js +6 -1
  8. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.d.ts.map +1 -1
  9. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.js +2 -0
  10. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadUnavailableReferences.d.ts.map +1 -1
  11. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadUnavailableReferences.js +2 -0
  12. package/esm/model/commandHandlers/widgets/refreshInsightWidgetHandler.d.ts.map +1 -1
  13. package/esm/model/commandHandlers/widgets/refreshInsightWidgetHandler.js +4 -1
  14. package/esm/model/queryServices/queryWidgetFilters.d.ts.map +1 -1
  15. package/esm/model/queryServices/queryWidgetFilters.js +18 -96
  16. package/esm/model/react/useIsWidgetRestricted.d.ts +10 -0
  17. package/esm/model/react/useIsWidgetRestricted.d.ts.map +1 -1
  18. package/esm/model/react/useIsWidgetRestricted.js +26 -9
  19. package/esm/model/react/useWidgetExecutionsHandler.d.ts.map +1 -1
  20. package/esm/model/react/useWidgetExecutionsHandler.js +27 -5
  21. package/esm/model/store/dashboardStore.d.ts +2 -0
  22. package/esm/model/store/dashboardStore.d.ts.map +1 -1
  23. package/esm/model/store/dashboardStore.js +2 -0
  24. package/esm/model/store/executionResults/index.js +1 -1
  25. package/esm/model/store/filtering/dashboardFilterSelectors.d.ts.map +1 -1
  26. package/esm/model/store/filtering/dashboardFilterSelectors.js +1 -0
  27. package/esm/model/store/filtering/types.d.ts +5 -0
  28. package/esm/model/store/filtering/types.d.ts.map +1 -1
  29. package/esm/model/store/restrictedData/index.d.ts +9 -0
  30. package/esm/model/store/restrictedData/index.d.ts.map +1 -0
  31. package/esm/model/store/restrictedData/index.js +24 -0
  32. package/esm/model/store/restrictedData/restrictedDataSelectors.d.ts +19 -0
  33. package/esm/model/store/restrictedData/restrictedDataSelectors.d.ts.map +1 -0
  34. package/esm/model/store/restrictedData/restrictedDataSelectors.js +56 -0
  35. package/esm/model/store/restrictedData/restrictedDataState.d.ts +35 -0
  36. package/esm/model/store/restrictedData/restrictedDataState.d.ts.map +1 -0
  37. package/esm/model/store/restrictedData/restrictedDataState.js +4 -0
  38. package/esm/model/store/types.d.ts +7 -0
  39. package/esm/model/store/types.d.ts.map +1 -1
  40. package/esm/model/store/unavailableObjects/copyBlockingReferences.d.ts +4 -5
  41. package/esm/model/store/unavailableObjects/copyBlockingReferences.d.ts.map +1 -1
  42. package/esm/model/store/unavailableObjects/copyBlockingReferences.js +16 -9
  43. package/esm/model/store/unavailableObjects/unavailableObjectsSelectors.d.ts +16 -0
  44. package/esm/model/store/unavailableObjects/unavailableObjectsSelectors.d.ts.map +1 -1
  45. package/esm/model/store/unavailableObjects/unavailableObjectsSelectors.js +18 -0
  46. package/esm/model/utils/widgetFilters.d.ts +45 -2
  47. package/esm/model/utils/widgetFilters.d.ts.map +1 -1
  48. package/esm/model/utils/widgetFilters.js +89 -1
  49. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts +7 -1
  50. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts.map +1 -1
  51. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.js +4 -2
  52. package/esm/presentation/filterBar/attributeFilter/DefaultDashboardAttributeFilter.d.ts.map +1 -1
  53. package/esm/presentation/filterBar/attributeFilter/DefaultDashboardAttributeFilter.js +4 -1
  54. package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useLimitingItemsConfiguration.d.ts.map +1 -1
  55. package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useLimitingItemsConfiguration.js +17 -4
  56. package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts +0 -2
  57. package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts.map +1 -1
  58. package/esm/presentation/localization/bundles/de-DE.localization-bundle.js +0 -2
  59. package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts +0 -2
  60. package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts.map +1 -1
  61. package/esm/presentation/localization/bundles/en-AU.localization-bundle.js +0 -2
  62. package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts +0 -2
  63. package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts.map +1 -1
  64. package/esm/presentation/localization/bundles/en-GB.localization-bundle.js +0 -2
  65. package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts +0 -2
  66. package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts.map +1 -1
  67. package/esm/presentation/localization/bundles/es-419.localization-bundle.js +0 -2
  68. package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts +0 -2
  69. package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts.map +1 -1
  70. package/esm/presentation/localization/bundles/es-ES.localization-bundle.js +0 -2
  71. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts +0 -2
  72. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts.map +1 -1
  73. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.js +0 -2
  74. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts +0 -2
  75. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts.map +1 -1
  76. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.js +0 -2
  77. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts +0 -2
  78. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts.map +1 -1
  79. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.js +0 -2
  80. package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts +0 -2
  81. package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts.map +1 -1
  82. package/esm/presentation/localization/bundles/id-ID.localization-bundle.js +0 -2
  83. package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts +0 -2
  84. package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts.map +1 -1
  85. package/esm/presentation/localization/bundles/it-IT.localization-bundle.js +0 -2
  86. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts +0 -2
  87. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts.map +1 -1
  88. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.js +0 -2
  89. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts +0 -2
  90. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts.map +1 -1
  91. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.js +0 -2
  92. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts +0 -2
  93. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts.map +1 -1
  94. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.js +0 -2
  95. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts +0 -2
  96. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts.map +1 -1
  97. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.js +0 -2
  98. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts +0 -2
  99. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts.map +1 -1
  100. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.js +0 -2
  101. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts +0 -2
  102. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts.map +1 -1
  103. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.js +0 -2
  104. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts +0 -2
  105. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts.map +1 -1
  106. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.js +0 -2
  107. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts +0 -2
  108. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts.map +1 -1
  109. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.js +0 -2
  110. package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts +0 -2
  111. package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts.map +1 -1
  112. package/esm/presentation/localization/bundles/th-TH.localization-bundle.js +0 -2
  113. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts +0 -2
  114. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts.map +1 -1
  115. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.js +0 -2
  116. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts +0 -2
  117. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts.map +1 -1
  118. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.js +0 -2
  119. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts +0 -2
  120. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts.map +1 -1
  121. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.js +0 -2
  122. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts +0 -2
  123. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts.map +1 -1
  124. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.js +0 -2
  125. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts +0 -2
  126. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts.map +1 -1
  127. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.js +0 -2
  128. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts +0 -2
  129. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts.map +1 -1
  130. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.js +0 -2
  131. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/InsightDrillDialog.d.ts.map +1 -1
  132. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/InsightDrillDialog.js +2 -0
  133. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/useDrillDialogTooltipsOverride.d.ts +4 -0
  134. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/useDrillDialogTooltipsOverride.d.ts.map +1 -0
  135. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/useDrillDialogTooltipsOverride.js +26 -0
  136. package/esm/presentation/widget/visualizationSwitcher/EditModeDashboardVisualizationSwitcher.js +3 -3
  137. package/esm/presentation/widget/visualizationSwitcher/ViewModeDashboardVisualizationSwitcher.js +3 -3
  138. package/esm/presentation/widget/visualizationSwitcher/configuration/VisualizationConfig.d.ts.map +1 -1
  139. package/esm/presentation/widget/visualizationSwitcher/configuration/VisualizationConfig.js +3 -1
  140. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/VisualizationSwitcherNavigationHeader.d.ts.map +1 -1
  141. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/VisualizationSwitcherNavigationHeader.js +5 -6
  142. package/esm/sdk-ui-dashboard.d.ts +45 -0
  143. package/package.json +21 -21
  144. package/styles/css/drillDialog.css +1 -1
  145. package/styles/css/main.css +87 -5
  146. package/styles/css/main.css.map +1 -1
  147. package/styles/scss/drillDialog.scss +1 -1
@@ -1,6 +1,8 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { areObjRefsEqual, isInsightWidget, isRichTextWidget, isVisualizationSwitcherWidget, } from "@gooddata/sdk-model";
2
+ import { useCallback } from "react";
3
+ import { areObjRefsEqual, isInsightWidget, isRichTextWidget, isVisualizationSwitcherWidget, serializeObjRef, } from "@gooddata/sdk-model";
3
4
  import { collectReferences } from "@gooddata/sdk-ui-kit";
5
+ import { selectWidgetsWithRestrictedData } from "../store/restrictedData/restrictedDataSelectors.js";
4
6
  import { selectRestrictedInsightsMap, selectRestrictedRichTextReferences, } from "../store/unavailableObjects/unavailableObjectsSelectors.js";
5
7
  import { isExtendedDashboardLayoutWidget } from "../types/layoutTypes.js";
6
8
  import { useDashboardSelector } from "./DashboardStoreProvider.js";
@@ -10,12 +12,12 @@ import { useDashboardSelector } from "./DashboardStoreProvider.js";
10
12
  * rich text widget counts once its text references an object that is withheld, and a container once
11
13
  * anything inside it does, because its own resize reaches every descendant.
12
14
  */
13
- function isWidgetRestricted(widget, restrictedInsights, restrictedReferences) {
15
+ function isWidgetRestricted(widget, isInsightWidgetRestricted, restrictedReferences) {
14
16
  if (isInsightWidget(widget)) {
15
- return restrictedInsights.has(widget.insight);
17
+ return isInsightWidgetRestricted(widget);
16
18
  }
17
19
  if (isVisualizationSwitcherWidget(widget)) {
18
- return widget.visualizations.some((visualization) => restrictedInsights.has(visualization.insight));
20
+ return widget.visualizations.some(isInsightWidgetRestricted);
19
21
  }
20
22
  if (isRichTextWidget(widget)) {
21
23
  return Object.values(collectReferences(widget.content)).some((reference) => restrictedReferences.some((restricted) => areObjRefsEqual(restricted, reference.ref)));
@@ -23,10 +25,25 @@ function isWidgetRestricted(widget, restrictedInsights, restrictedReferences) {
23
25
  if (isExtendedDashboardLayoutWidget(widget)) {
24
26
  // resizing a container writes its new width to every widget inside it, so a container holding
25
27
  // a restricted widget cannot be resized either
26
- return widget.sections.some((section) => section.items.some((item) => item.widget && isWidgetRestricted(item.widget, restrictedInsights, restrictedReferences)));
28
+ return widget.sections.some((section) => section.items.some((item) => item.widget &&
29
+ isWidgetRestricted(item.widget, isInsightWidgetRestricted, restrictedReferences)));
27
30
  }
28
31
  return false;
29
32
  }
33
+ /**
34
+ * Returns the check whether an insight widget renders as restricted: its insight is one the current
35
+ * user is not allowed to read, or its execution was refused because the user may not read some of
36
+ * the data. The design makes no difference between the two; the second is known only once the
37
+ * widget has executed.
38
+ *
39
+ * @internal
40
+ */
41
+ export function useIsInsightWidgetRestricted() {
42
+ const restrictedInsights = useDashboardSelector(selectRestrictedInsightsMap);
43
+ const widgetsWithRestrictedData = useDashboardSelector(selectWidgetsWithRestrictedData);
44
+ return useCallback((widget) => restrictedInsights.has(widget.insight) ||
45
+ widgetsWithRestrictedData.has(serializeObjRef(widget.ref)), [restrictedInsights, widgetsWithRestrictedData]);
46
+ }
30
47
  /**
31
48
  * Tells whether the widget renders something the current user is not allowed to see. A widget whose
32
49
  * insight is merely deleted is not restricted — that one keeps rendering the missing-visualization tile.
@@ -34,9 +51,9 @@ function isWidgetRestricted(widget, restrictedInsights, restrictedReferences) {
34
51
  * @alpha
35
52
  */
36
53
  export function useIsWidgetRestricted(widget) {
37
- const restrictedInsights = useDashboardSelector(selectRestrictedInsightsMap);
54
+ const isInsightWidgetRestricted = useIsInsightWidgetRestricted();
38
55
  const restrictedReferences = useDashboardSelector(selectRestrictedRichTextReferences);
39
- return isWidgetRestricted(widget, restrictedInsights, restrictedReferences);
56
+ return isWidgetRestricted(widget, isInsightWidgetRestricted, restrictedReferences);
40
57
  }
41
58
  /**
42
59
  * Tells whether any of the widgets is restricted. Used where an action covers several widgets at once,
@@ -45,7 +62,7 @@ export function useIsWidgetRestricted(widget) {
45
62
  * @internal
46
63
  */
47
64
  export function useIsAnyWidgetRestricted(widgets) {
48
- const restrictedInsights = useDashboardSelector(selectRestrictedInsightsMap);
65
+ const isInsightWidgetRestricted = useIsInsightWidgetRestricted();
49
66
  const restrictedReferences = useDashboardSelector(selectRestrictedRichTextReferences);
50
- return widgets.some((widget) => isWidgetRestricted(widget, restrictedInsights, restrictedReferences));
67
+ return widgets.some((widget) => isWidgetRestricted(widget, isInsightWidgetRestricted, restrictedReferences));
51
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useWidgetExecutionsHandler.d.ts","sourceRoot":"","sources":["../../../src/model/react/useWidgetExecutionsHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAE,KAAK,0BAA0B,EAAE,KAAK,cAAc,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAgBzG;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM;;;iCA2B/B,gBAAgB,YACvB,cAAc,EAAE,GAAG,SAAS,gBACxB,0BAA0B,EAAE;uBAQvC,SAAS,KAAG,IAAI;EAwB9B"}
1
+ {"version":3,"file":"useWidgetExecutionsHandler.d.ts","sourceRoot":"","sources":["../../../src/model/react/useWidgetExecutionsHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AACjG,OAAO,EACH,KAAK,0BAA0B,EAC/B,KAAK,cAAc,EACnB,KAAK,MAAM,EAEd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACH,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,gBAAgB,EAGxB,MAAM,kBAAkB,CAAC;AAmB1B;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM;;;iCAiD/B,gBAAgB,YACvB,cAAc,EAAE,GAAG,SAAS,gBACxB,0BAA0B,EAAE;uBASvC,SAAS,KAAG,IAAI;EAyB9B"}
@@ -1,8 +1,12 @@
1
1
  // (C) 2021-2026 GoodData Corporation
2
- import { useCallback } from "react";
2
+ import { useCallback, useRef } from "react";
3
3
  import { isNoDataError } from "@gooddata/sdk-backend-spi";
4
- import { isNoDataSdkError } from "@gooddata/sdk-ui";
4
+ import { serializeObjRef, } from "@gooddata/sdk-model";
5
+ import { isNoDataSdkError, isProtectedReport, } from "@gooddata/sdk-ui";
5
6
  import { setExecutionResultData, setExecutionResultError, setExecutionResultErrorWithResult, setExecutionResultLoading, } from "../commands/executionResults.js";
7
+ import { restrictedDataActions } from "../store/restrictedData/index.js";
8
+ import { selectWidgetExecutionInputsKey } from "../store/restrictedData/restrictedDataSelectors.js";
9
+ import { useDashboardDispatch, useDashboardSelector } from "./DashboardStoreProvider.js";
6
10
  import { useDispatchDashboardCommand } from "./useDispatchDashboardCommand.js";
7
11
  function getLimitBreaks(dataView) {
8
12
  const limitBreaks = dataView.metadata?.limitBreaks;
@@ -13,11 +17,27 @@ function getLimitBreaks(dataView) {
13
17
  * @internal
14
18
  */
15
19
  export function useWidgetExecutionsHandler(widgetRef) {
20
+ const dispatch = useDashboardDispatch();
21
+ const inputsKey = useDashboardSelector(selectWidgetExecutionInputsKey(widgetRef));
22
+ // the inputs of the running execution; the loader drops the outcome of an execution it replaced, so
23
+ // an outcome reported here always belongs to them
24
+ const executionInputsKey = useRef(undefined);
16
25
  const startLoading = useDispatchDashboardCommand(setExecutionResultLoading);
17
26
  const setData = useDispatchDashboardCommand(setExecutionResultData);
18
27
  const setError = useDispatchDashboardCommand(setExecutionResultError);
19
28
  const setErrorWithResult = useDispatchDashboardCommand(setExecutionResultErrorWithResult);
29
+ // Restrictions are recorded right away rather than through the command queue, so they keep the order
30
+ // in which executions start and finish even when the queue is busy.
31
+ const recordOutcome = useCallback((isRefused) => {
32
+ dispatch(isRefused
33
+ ? restrictedDataActions.executionRefused({
34
+ ref: widgetRef,
35
+ inputsKey: executionInputsKey.current ?? inputsKey,
36
+ })
37
+ : restrictedDataActions.clearRefusal(serializeObjRef(widgetRef)));
38
+ }, [dispatch, inputsKey, widgetRef]);
20
39
  const onError = useCallback((error) => {
40
+ recordOutcome(isProtectedReport(error));
21
41
  // A no-data error may carry the computed (empty) result, which has a valid resultId
22
42
  // (a result computed to emptiness, as opposed to e.g. an unsatisfiable filter that
23
43
  // never executes). When present, record both so consumers can reference the result
@@ -31,10 +51,11 @@ export function useWidgetExecutionsHandler(widgetRef) {
31
51
  else {
32
52
  setError(widgetRef, error);
33
53
  }
34
- }, [setError, setErrorWithResult, widgetRef]);
54
+ }, [recordOutcome, setError, setErrorWithResult, widgetRef]);
35
55
  const onSuccess = useCallback((executionResult, warnings, limitBreaks) => {
56
+ recordOutcome(false);
36
57
  setData(widgetRef, executionResult, warnings, limitBreaks);
37
- }, [setData, widgetRef]);
58
+ }, [recordOutcome, setData, widgetRef]);
38
59
  const onPushData = useCallback((data) => {
39
60
  if (data.dataView) {
40
61
  const limitBreaks = getLimitBreaks(data.dataView);
@@ -43,9 +64,10 @@ export function useWidgetExecutionsHandler(widgetRef) {
43
64
  }, [onSuccess]);
44
65
  const onLoadingChanged = useCallback(({ isLoading }) => {
45
66
  if (isLoading) {
67
+ executionInputsKey.current = inputsKey;
46
68
  startLoading(widgetRef);
47
69
  }
48
- }, [startLoading, widgetRef]);
70
+ }, [inputsKey, startLoading, widgetRef]);
49
71
  return {
50
72
  onLoadingChanged,
51
73
  onError,
@@ -123,6 +123,7 @@ export declare function createDashboardRootReducer({ queryCache, }?: {
123
123
  inaccessibleDashboards: import("@reduxjs/toolkit").EntityState<import("../types/inaccessibleDashboardTypes.js").IInaccessibleDashboard, import("@reduxjs/toolkit").EntityId> & object;
124
124
  unavailableObjects: import("@reduxjs/toolkit").EntityState<import("@gooddata/sdk-model").IUnavailableReference, import("@reduxjs/toolkit").EntityId> & object;
125
125
  executionResults: import("@reduxjs/toolkit").EntityState<import("./executionResults/types.js").IExecutionResultEnvelope, import("@reduxjs/toolkit").EntityId> & object;
126
+ restrictedData: import("./restrictedData/restrictedDataState.js").IRestrictedDataState;
126
127
  renderMode: import("./renderMode/renderModeState.js").IRenderModeState;
127
128
  ui: import("./ui/uiState.js").IUiState;
128
129
  dashboardPermissions: import("./dashboardPermissions/dashboardPermissionsState.js").DashboardPermissionsState;
@@ -152,6 +153,7 @@ export declare function createDashboardRootReducer({ queryCache, }?: {
152
153
  inaccessibleDashboards: (import("@reduxjs/toolkit").EntityState<import("../types/inaccessibleDashboardTypes.js").IInaccessibleDashboard, import("@reduxjs/toolkit").EntityId> & object) | undefined;
153
154
  unavailableObjects: (import("@reduxjs/toolkit").EntityState<import("@gooddata/sdk-model").IUnavailableReference, import("@reduxjs/toolkit").EntityId> & object) | undefined;
154
155
  executionResults: (import("@reduxjs/toolkit").EntityState<import("./executionResults/types.js").IExecutionResultEnvelope, import("@reduxjs/toolkit").EntityId> & object) | undefined;
156
+ restrictedData: import("./restrictedData/restrictedDataState.js").IRestrictedDataState | undefined;
155
157
  renderMode: import("./renderMode/renderModeState.js").IRenderModeState | undefined;
156
158
  ui: import("./ui/uiState.js").IUiState | undefined;
157
159
  dashboardPermissions: import("./dashboardPermissions/dashboardPermissionsState.js").DashboardPermissionsState | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"dashboardStore.d.ts","sourceRoot":"","sources":["../../../src/model/store/dashboardStore.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,OAAO,EAGf,MAAM,kBAAkB,CAAC;AAI1B,OAAyB,EAAa,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAMvF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAG9E,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAI9F,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AA2BvE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAwEzE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACpC;;OAEG;IACH,oBAAoB,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAE/C;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAE7E;;;;;;;;OAQG;IACH,qBAAqB,CAAC,EAAE,CACpB,oBAAoB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,EAC9D,sBAAsB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,KAC/D,IAAI,CAAC;CACb;AAED,MAAM,WAAW,qBAAqB;IAClC;;;;;;;;;;;OAWG;IACH,gBAAgB,EAAE,gBAAgB,CAAC;IAEnC;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,uBAAuB,CAAC;IAEzC;;OAEG;IACH,oBAAoB,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IAEnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IAEnD;;;;;;;OAOG;IACH,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,gBAAgB,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAEzE;;;;;;;OAOG;IACH,iBAAiB,EAAE,UAAU,CAAC;IAE9B;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAsBD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,cAAc,CAAC;IACtB,oBAAoB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC/D,sBAAsB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACjE,YAAY,EAAE,IAAI,CAAC;CACtB;AA2CD,wBAAgB,0BAA0B,CAAC,EACvC,UAAkC,GACrC,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+B/B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,sBAAsB,CAuF1F"}
1
+ {"version":3,"file":"dashboardStore.d.ts","sourceRoot":"","sources":["../../../src/model/store/dashboardStore.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,OAAO,EAGf,MAAM,kBAAkB,CAAC;AAI1B,OAAyB,EAAa,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAMvF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAG9E,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAI9F,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AA4BvE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAwEzE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACpC;;OAEG;IACH,oBAAoB,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAE/C;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAE7E;;;;;;;;OAQG;IACH,qBAAqB,CAAC,EAAE,CACpB,oBAAoB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,EAC9D,sBAAsB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,KAC/D,IAAI,CAAC;CACb;AAED,MAAM,WAAW,qBAAqB;IAClC;;;;;;;;;;;OAWG;IACH,gBAAgB,EAAE,gBAAgB,CAAC;IAEnC;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,uBAAuB,CAAC;IAEzC;;OAEG;IACH,oBAAoB,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IAEnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IAEnD;;;;;;;OAOG;IACH,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,gBAAgB,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAEzE;;;;;;;OAOG;IACH,iBAAiB,EAAE,UAAU,CAAC;IAE9B;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAsBD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,cAAc,CAAC;IACtB,oBAAoB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC/D,sBAAsB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACjE,YAAY,EAAE,IAAI,CAAC;CACtB;AA2CD,wBAAgB,0BAA0B,CAAC,EACvC,UAAkC,GACrC,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAgC/B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,sBAAsB,CAuF1F"}
@@ -33,6 +33,7 @@ import { metaSliceReducer } from "./meta/index.js";
33
33
  import { notificationChannelsSliceReducer } from "./notificationChannels/index.js";
34
34
  import { permissionsSliceReducer } from "./permissions/index.js";
35
35
  import { renderModeSliceReducer } from "./renderMode/index.js";
36
+ import { restrictedDataSliceReducer } from "./restrictedData/index.js";
36
37
  import { savingSliceReducer } from "./saving/index.js";
37
38
  import { showWidgetAsTableSliceReducer } from "./showWidgetAsTable/index.js";
38
39
  import { tabsSliceReducer } from "./tabs/index.js";
@@ -158,6 +159,7 @@ export function createDashboardRootReducer({ queryCache = (state = {}) => state,
158
159
  inaccessibleDashboards: inaccessibleDashboardsSliceReducer,
159
160
  unavailableObjects: unavailableObjectsSliceReducer,
160
161
  executionResults: executionResultsSliceReducer,
162
+ restrictedData: restrictedDataSliceReducer,
161
163
  renderMode: renderModeSliceReducer,
162
164
  ui: uiSliceReducer,
163
165
  dashboardPermissions: dashboardPermissionsSliceReducer,
@@ -1,4 +1,4 @@
1
- // (C) 2021-2025 GoodData Corporation
1
+ // (C) 2021-2026 GoodData Corporation
2
2
  import { createSlice } from "@reduxjs/toolkit";
3
3
  import { executionResultsAdapter } from "./executionResultsEntityAdapter.js";
4
4
  const executionResultsSlice = createSlice({
@@ -1 +1 @@
1
- {"version":3,"file":"dashboardFilterSelectors.d.ts","sourceRoot":"","sources":["../../../../src/model/store/filtering/dashboardFilterSelectors.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,+BAA+B,EACpC,KAAK,0BAA0B,EAC/B,KAAK,8BAA8B,EAYtC,MAAM,qBAAqB,CAAC;AAuB7B,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAOxD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAMxF;AASD;;;;GAIG;AACH,eAAO,MAAM,+CAA+C,EAAE,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CACvB,CAAC;AAE7E;;;GAGG;AACH,eAAO,MAAM,wCAAwC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CA0BvF,CAAC;AAEN;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,EAAE,iBAAiB,CAAC,MAAM,CAG1E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAKnF,CAAC;AAYF;;;GAGG;AACH,eAAO,MAAM,mCAAmC,EAAE,iBAAiB,CAAC,OAAO,CAI1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qDAAqD,EAAE,CAChE,kBAAkB,EAAE,MAAM,KACzB,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CAIzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAQpG,CAAC;AAaN;;;;GAIG;AACH,eAAO,MAAM,qDAAqD,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAKpG,CAAC;AAEN;;;GAGG;AACH,eAAO,MAAM,8CAA8C,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAK7F,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAmB/E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAmB/E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,yCAAyC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAwBxF,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,sCAAsC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAIzF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kCAAkC,EAAE,iBAAiB,CAAC,MAAM,GAAG,SAAS,CAMpF,CAAC;AAoEF,eAAO,MAAM,yBAAyB,WAC1B,iBAAiB,wBACH;IAClB,sBAAsB,CAAC,EAAE,0BAA0B,CAAC;IACpD,8BAA8B,EAAE,8BAA8B,EAAE,CAAC;IACjE,sBAAsB,EAAE,+BAA+B,EAAE,CAAC;CAC7D,KACF,OAyBF,CAAC;AAEF,eAAO,MAAM,yBAAyB,WAC1B,iBAAiB,wBACH;IAClB,sBAAsB,CAAC,EAAE,0BAA0B,CAAC;IACpD,8BAA8B,EAAE,8BAA8B,EAAE,CAAC;IACjE,sBAAsB,EAAE,+BAA+B,EAAE,CAAC;CAC7D,KACF,OAyBF,CAAC;AAMF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,CAAC,qBAAqB,EAAE,CAwFnF,CAAC"}
1
+ {"version":3,"file":"dashboardFilterSelectors.d.ts","sourceRoot":"","sources":["../../../../src/model/store/filtering/dashboardFilterSelectors.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,+BAA+B,EACpC,KAAK,0BAA0B,EAC/B,KAAK,8BAA8B,EAYtC,MAAM,qBAAqB,CAAC;AAuB7B,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAOxD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAMxF;AASD;;;;GAIG;AACH,eAAO,MAAM,+CAA+C,EAAE,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CACvB,CAAC;AAE7E;;;GAGG;AACH,eAAO,MAAM,wCAAwC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CA0BvF,CAAC;AAEN;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,EAAE,iBAAiB,CAAC,MAAM,CAG1E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAKnF,CAAC;AAYF;;;GAGG;AACH,eAAO,MAAM,mCAAmC,EAAE,iBAAiB,CAAC,OAAO,CAI1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qDAAqD,EAAE,CAChE,kBAAkB,EAAE,MAAM,KACzB,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CAIzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAQpG,CAAC;AAaN;;;;GAIG;AACH,eAAO,MAAM,qDAAqD,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAKpG,CAAC;AAEN;;;GAGG;AACH,eAAO,MAAM,8CAA8C,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAK7F,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAmB/E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAmB/E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,yCAAyC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAwBxF,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,sCAAsC,EAAE,iBAAiB,CAAC,iBAAiB,EAAE,CAIzF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kCAAkC,EAAE,iBAAiB,CAAC,MAAM,GAAG,SAAS,CAMpF,CAAC;AAoEF,eAAO,MAAM,yBAAyB,WAC1B,iBAAiB,wBACH;IAClB,sBAAsB,CAAC,EAAE,0BAA0B,CAAC;IACpD,8BAA8B,EAAE,8BAA8B,EAAE,CAAC;IACjE,sBAAsB,EAAE,+BAA+B,EAAE,CAAC;CAC7D,KACF,OAyBF,CAAC;AAEF,eAAO,MAAM,yBAAyB,WAC1B,iBAAiB,wBACH;IAClB,sBAAsB,CAAC,EAAE,0BAA0B,CAAC;IACpD,8BAA8B,EAAE,8BAA8B,EAAE,CAAC;IACjE,sBAAsB,EAAE,+BAA+B,EAAE,CAAC;CAC7D,KACF,OAyBF,CAAC;AAMF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,CAAC,qBAAqB,EAAE,CAyFnF,CAAC"}
@@ -261,6 +261,7 @@ export const selectAutomationFiltersByTab = createSelector(selectTabs, selectFil
261
261
  defaultSelectedFilters,
262
262
  lockedFilters,
263
263
  hiddenFilters,
264
+ allFilters: filtersWithCommonDate,
264
265
  };
265
266
  });
266
267
  });
@@ -34,5 +34,10 @@ export interface IAutomationFiltersTab {
34
34
  * Hidden filters for the tab.
35
35
  */
36
36
  hiddenFilters: FilterContextItem[];
37
+ /**
38
+ * Every filter of the tab except cross-filtering ones, hidden and restricted ones included.
39
+ * A filter stored in an automation but missing here was removed from the dashboard.
40
+ */
41
+ allFilters: FilterContextItem[];
37
42
  }
38
43
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/model/store/filtering/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IAClC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC;;;OAGG;IACH,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;IACvC;;;OAGG;IACH,sBAAsB,EAAE,iBAAiB,EAAE,CAAC;IAC5C;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAC;CACtC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/model/store/filtering/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IAClC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC;;;OAGG;IACH,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;IACvC;;;OAGG;IACH,sBAAsB,EAAE,iBAAiB,EAAE,CAAC;IAC5C;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC;;;OAGG;IACH,UAAU,EAAE,iBAAiB,EAAE,CAAC;CACnC"}
@@ -0,0 +1,9 @@
1
+ import { type Reducer } from "@reduxjs/toolkit";
2
+ import { type IRefusedExecution, type IRestrictedDataState } from "./restrictedDataState.js";
3
+ export declare const restrictedDataSliceReducer: Reducer<IRestrictedDataState>;
4
+ export declare const restrictedDataActions: {
5
+ executionRefused: import("@reduxjs/toolkit").ActionCreatorWithPayload<IRefusedExecution, "restrictedData/executionRefused">;
6
+ clearRefusal: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "restrictedData/clearRefusal">;
7
+ clearRestrictedData: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"restrictedData/clearRestrictedData">;
8
+ };
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/model/store/restrictedData/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,OAAO,EAAe,MAAM,kBAAkB,CAAC;AAIjF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAE5B,MAAM,0BAA0B,CAAC;AAoBlC,eAAO,MAAM,0BAA0B,EAAE,OAAO,CAAC,oBAAoB,CAA+B,CAAC;AAGrG,eAAO,MAAM,qBAAqB;;;;CAAqC,CAAC"}
@@ -0,0 +1,24 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { createSlice } from "@reduxjs/toolkit";
3
+ import { serializeObjRef } from "@gooddata/sdk-model";
4
+ import { restrictedDataInitialState, } from "./restrictedDataState.js";
5
+ const restrictedDataSlice = createSlice({
6
+ name: "restrictedData",
7
+ initialState: restrictedDataInitialState,
8
+ reducers: {
9
+ executionRefused: (state, action) => {
10
+ state.refusedExecutions[serializeObjRef(action.payload.ref)] = action.payload;
11
+ },
12
+ // the widget's execution finished otherwise, or the widget was refreshed
13
+ clearRefusal: (state, action) => {
14
+ // only touch the map when needed, so its reference stays the same for unrestricted widgets
15
+ if (action.payload in state.refusedExecutions) {
16
+ delete state.refusedExecutions[action.payload];
17
+ }
18
+ },
19
+ clearRestrictedData: () => restrictedDataInitialState,
20
+ },
21
+ });
22
+ export const restrictedDataSliceReducer = restrictedDataSlice.reducer;
23
+ // Spread "fixes" TS2742 error
24
+ export const restrictedDataActions = { ...restrictedDataSlice.actions };
@@ -0,0 +1,19 @@
1
+ import { type ObjRef } from "@gooddata/sdk-model";
2
+ import { type DashboardSelector } from "../types.js";
3
+ /**
4
+ * Identifies what the widget with the given ref executes: its insight with the widget's own
5
+ * visualization properties, the dashboard filters it does not ignore and the parameter values its
6
+ * insight depends on, resolved the same way as for its execution.
7
+ *
8
+ * @internal
9
+ */
10
+ export declare const selectWidgetExecutionInputsKey: (ref: ObjRef) => DashboardSelector<string>;
11
+ /**
12
+ * Selects the widgets whose execution was refused because the current user may not read some of
13
+ * the data, as serialized widget refs. A widget stays in it while its insight, its own filters and its
14
+ * parameters are the ones it was refused with; once any of them changes, it executes again.
15
+ *
16
+ * @internal
17
+ */
18
+ export declare const selectWidgetsWithRestrictedData: DashboardSelector<ReadonlySet<string>>;
19
+ //# sourceMappingURL=restrictedDataSelectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restrictedDataSelectors.d.ts","sourceRoot":"","sources":["../../../../src/model/store/restrictedData/restrictedDataSelectors.ts"],"names":[],"mappings":"AAKA,OAAO,EAIH,KAAK,MAAM,EAId,MAAM,qBAAqB,CAAC;AAa7B,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,aAAa,CAAC;AAqB1E;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,iBAAiB,CAAC,MAAM,CAuBjF,CAAC;AAkBN;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,EAAE,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CAKlF,CAAC"}
@@ -0,0 +1,56 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { createSelector, lruMemoize } from "@reduxjs/toolkit";
3
+ import stringify from "json-stable-stringify";
4
+ import { insightFilters, insightRef, isInsightWidget, } from "@gooddata/sdk-model";
5
+ import { resolveWidgetDashboardFilters } from "../../utils/widgetFilters.js";
6
+ import { createMemoizedSelector } from "../_infra/selectors.js";
7
+ import { selectInsightByWidgetRef } from "../insights/insightsSelectors.js";
8
+ import { selectAttributeFilterConfigsDisplayAsLabelMap } from "../tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
9
+ import { selectAllFiltersForWidgetByRefAcrossTabs, selectFilterableWidgetByRef, } from "../tabs/layout/layoutSelectors.js";
10
+ import { resolveEffectiveParameterValuesForRoots } from "../tabs/parameters/parametersHelpers.js";
11
+ import { selectWidgetParameterContext } from "../tabs/parameters/parametersSelectors.js";
12
+ // the dashboard filters the widget's execution applies
13
+ function resolveExecutedDashboardFilters(widgetAwareFilters, widget, displayAsLabelMap, insight) {
14
+ if (!widget) {
15
+ return widgetAwareFilters.flat();
16
+ }
17
+ const { dateFilters, attributeFilters, measureValueFilters } = resolveWidgetDashboardFilters(widget, widgetAwareFilters, displayAsLabelMap, insight ? insightFilters(insight) : []);
18
+ return [...dateFilters.map(({ filter }) => filter), ...attributeFilters, ...measureValueFilters];
19
+ }
20
+ /**
21
+ * Identifies what the widget with the given ref executes: its insight with the widget's own
22
+ * visualization properties, the dashboard filters it does not ignore and the parameter values its
23
+ * insight depends on, resolved the same way as for its execution.
24
+ *
25
+ * @internal
26
+ */
27
+ export const selectWidgetExecutionInputsKey = createMemoizedSelector((ref) => createSelector(selectAllFiltersForWidgetByRefAcrossTabs(ref), selectFilterableWidgetByRef(ref), selectAttributeFilterConfigsDisplayAsLabelMap, selectWidgetParameterContext(ref), selectInsightByWidgetRef(ref), (filters, widget, displayAsLabelMap, parameterContext, insight) => stringify({
28
+ // a replaced or updated visualization executes again, even under the same ref
29
+ insight: insight?.insight,
30
+ widgetProperties: isInsightWidget(widget) ? widget.properties : undefined,
31
+ filters: resolveExecutedDashboardFilters(filters, widget, displayAsLabelMap, insight),
32
+ parameters: insight
33
+ ? resolveEffectiveParameterValuesForRoots(parameterContext, [insightRef(insight)], insight)
34
+ : [],
35
+ }) ?? ""));
36
+ const NO_WIDGET_IDS = [];
37
+ const selectRefusedExecutions = (state) => state.restrictedData.refusedExecutions;
38
+ const selectWidgetIdsRefusedWithCurrentInputs = (state) => {
39
+ const refusedExecutions = Object.entries(selectRefusedExecutions(state));
40
+ return refusedExecutions.length === 0
41
+ ? NO_WIDGET_IDS
42
+ : refusedExecutions
43
+ .filter(([, { ref, inputsKey }]) => selectWidgetExecutionInputsKey(ref)(state) === inputsKey)
44
+ .map(([id]) => id);
45
+ };
46
+ const haveSameWidgetIds = (first, second) => first.length === second.length && first.every((id, index) => id === second[index]);
47
+ /**
48
+ * Selects the widgets whose execution was refused because the current user may not read some of
49
+ * the data, as serialized widget refs. A widget stays in it while its insight, its own filters and its
50
+ * parameters are the ones it was refused with; once any of them changes, it executes again.
51
+ *
52
+ * @internal
53
+ */
54
+ export const selectWidgetsWithRestrictedData = createSelector(selectWidgetIdsRefusedWithCurrentInputs, (ids) => new Set(ids),
55
+ // the same set while the restricted widgets stay the same, so other updates do not re-render its users
56
+ { memoize: lruMemoize, memoizeOptions: { equalityCheck: haveSameWidgetIds } });
@@ -0,0 +1,35 @@
1
+ import { type ObjRef } from "@gooddata/sdk-model";
2
+ /**
3
+ * An execution of a widget that was refused because the current user may not read some of the data.
4
+ *
5
+ * @internal
6
+ */
7
+ export interface IRefusedExecution {
8
+ /**
9
+ * Ref of the widget.
10
+ */
11
+ ref: ObjRef;
12
+ /**
13
+ * What the refused execution ran: the widget's insight, its own filters and its parameters, as
14
+ * produced by `selectWidgetExecutionInputsKey`.
15
+ */
16
+ inputsKey: string;
17
+ }
18
+ /**
19
+ * Widgets whose execution was refused because the current user may not read some of the data.
20
+ *
21
+ * @internal
22
+ */
23
+ export interface IRestrictedDataState {
24
+ /**
25
+ * The refused executions, keyed by serialized widget ref.
26
+ *
27
+ * @remarks
28
+ * A widget renders as restricted while its insight, its own filters and its parameters are the ones
29
+ * it was refused with. A later execution leaves the entry in place until it finishes, so the widget does not show
30
+ * its content between attempts.
31
+ */
32
+ refusedExecutions: Record<string, IRefusedExecution>;
33
+ }
34
+ export declare const restrictedDataInitialState: IRestrictedDataState;
35
+ //# sourceMappingURL=restrictedDataState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restrictedDataState.d.ts","sourceRoot":"","sources":["../../../../src/model/store/restrictedData/restrictedDataState.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAC9B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC;;;;;;;OAOG;IACH,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CACxD;AAED,eAAO,MAAM,0BAA0B,EAAE,oBAExC,CAAC"}
@@ -0,0 +1,4 @@
1
+ // (C) 2026 GoodData Corporation
2
+ export const restrictedDataInitialState = {
3
+ refusedExecutions: {},
4
+ };
@@ -20,6 +20,7 @@ import { type IDashboardMetaState } from "./meta/metaState.js";
20
20
  import { type INotificationChannelsState } from "./notificationChannels/notificationChannelsState.js";
21
21
  import { type PermissionsState } from "./permissions/permissionsState.js";
22
22
  import { type IRenderModeState } from "./renderMode/renderModeState.js";
23
+ import { type IRestrictedDataState } from "./restrictedData/restrictedDataState.js";
23
24
  import { type SavingState } from "./saving/savingState.js";
24
25
  import { type IShowWidgetAsTableState } from "./showWidgetAsTable/showWidgetAsTableState.js";
25
26
  import { type ITabsState } from "./tabs/tabsState.js";
@@ -95,6 +96,12 @@ export type DashboardState = {
95
96
  * @beta
96
97
  */
97
98
  executionResults: EntityState<IExecutionResultEnvelope, EntityId>;
99
+ /**
100
+ * Widgets whose execution was refused because the current user may not read some of the data.
101
+ *
102
+ * @internal
103
+ */
104
+ restrictedData: IRestrictedDataState;
98
105
  /**
99
106
  * Part of state where the different dashboard component queries may cache their results.
100
107
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/model/store/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/model/store/types.ts"],"names":[],"mappings":"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"}
@@ -17,11 +17,10 @@ export interface IDashboardCopySourceTab {
17
17
  * place the backend checks when it creates the copy, so it would refuse the copy.
18
18
  *
19
19
  * @remarks
20
- * The backend accepts a copy that keeps a drill to a dashboard the user cannot open, an ignored
21
- * drill-down hierarchy, or a metric the user may not read in a measure value filter or in the
22
- * limit of a filter's values, so none of these count. A widget ignoring that measure value filter
23
- * does count, and every widget that does not use the filter's metric ignores it automatically.
24
- * A merely deleted object does not count either.
20
+ * The backend accepts a copy that keeps a drill to a dashboard the user cannot open or an ignored
21
+ * drill-down hierarchy, so neither counts. It refuses a copy whose filters use a label, metric or fact
22
+ * the user may not read: an attribute filter's label, a measure value filter's metric, or a metric or
23
+ * fact limiting a filter's values. A merely deleted object does not count.
25
24
  *
26
25
  * @internal
27
26
  */
@@ -1 +1 @@
1
- {"version":3,"file":"copyBlockingReferences.d.ts","sourceRoot":"","sources":["../../../../src/model/store/unavailableObjects/copyBlockingReferences.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EACH,KAAK,iBAAiB,EAEtB,KAAK,+BAA+B,EACpC,KAAK,gBAAgB,EAErB,KAAK,QAAQ,EAgBhB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,KAAK,uBAAuB,EAAmC,MAAM,4BAA4B,CAAC;AAK3G,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,MAAM,CAAC,EAAE,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IACnD,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,sBAAsB,EAAE,+BAA+B,EAAE,CAAC;CAC7D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACpC,IAAI,EAAE,uBAAuB,EAAE,EAC/B,QAAQ,EAAE,QAAQ,EAAE,EACpB,kBAAkB,EAAE,8BAA8B,EAAE,GACrD,OAAO,CAoET;AAED;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,EAAE,iBAAiB,CAAC,OAAO,CAqBtE,CAAC"}
1
+ {"version":3,"file":"copyBlockingReferences.d.ts","sourceRoot":"","sources":["../../../../src/model/store/unavailableObjects/copyBlockingReferences.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EACH,KAAK,iBAAiB,EAEtB,KAAK,+BAA+B,EACpC,KAAK,gBAAgB,EAErB,KAAK,QAAQ,EAkBhB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,KAAK,uBAAuB,EAAmC,MAAM,4BAA4B,CAAC;AAK3G,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,MAAM,CAAC,EAAE,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IACnD,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,sBAAsB,EAAE,+BAA+B,EAAE,CAAC;CAC7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACpC,IAAI,EAAE,uBAAuB,EAAE,EAC/B,QAAQ,EAAE,QAAQ,EAAE,EACpB,kBAAkB,EAAE,8BAA8B,EAAE,GACrD,OAAO,CA8ET;AAED;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,EAAE,iBAAiB,CAAC,OAAO,CAqBtE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { createSelector } from "@reduxjs/toolkit";
3
- import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, insightRef, isComputedAttributeRef, isDashboardAttributeFilterItem, isDashboardAttributeFilterReference, isDashboardMeasureValueFilterReference, isDrillToDashboard, isInsightWidget, isKpiWidget, isRichTextWidget, isVisualizationSwitcherWidget, } from "@gooddata/sdk-model";
3
+ import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemValidateElementsBy, insightRef, isComputedAttributeRef, isDashboardAttributeFilterItem, isDashboardAttributeFilterReference, isDashboardMeasureValueFilter, isDashboardMeasureValueFilterReference, isDrillToDashboard, isInsightWidget, isKpiWidget, isRichTextWidget, isVisualizationSwitcherWidget, } from "@gooddata/sdk-model";
4
4
  import { collectReferences } from "@gooddata/sdk-ui-kit";
5
5
  import { isExtendedDashboardLayoutWidget } from "../../types/layoutTypes.js";
6
6
  import { isDashboardObjectRestricted } from "../filtering/restrictedFilterUtils.js";
@@ -8,17 +8,16 @@ import { selectInsights } from "../insights/insightsSelectors.js";
8
8
  import { selectIsInViewMode } from "../renderMode/renderModeSelectors.js";
9
9
  import { selectTabs } from "../tabs/tabsSelectors.js";
10
10
  import { isDrillRestricted } from "../widgetDrills/drillRestrictionUtils.js";
11
- import { selectUnavailableObjects } from "./unavailableObjectsSelectors.js";
11
+ import { newRestrictedLimitingItemsMap, selectUnavailableObjects } from "./unavailableObjectsSelectors.js";
12
12
  /**
13
13
  * Tells whether a copy of the dashboard would reference an object the current user may not read in a
14
14
  * place the backend checks when it creates the copy, so it would refuse the copy.
15
15
  *
16
16
  * @remarks
17
- * The backend accepts a copy that keeps a drill to a dashboard the user cannot open, an ignored
18
- * drill-down hierarchy, or a metric the user may not read in a measure value filter or in the
19
- * limit of a filter's values, so none of these count. A widget ignoring that measure value filter
20
- * does count, and every widget that does not use the filter's metric ignores it automatically.
21
- * A merely deleted object does not count either.
17
+ * The backend accepts a copy that keeps a drill to a dashboard the user cannot open or an ignored
18
+ * drill-down hierarchy, so neither counts. It refuses a copy whose filters use a label, metric or fact
19
+ * the user may not read: an attribute filter's label, a measure value filter's metric, or a metric or
20
+ * fact limiting a filter's values. A merely deleted object does not count.
22
21
  *
23
22
  * @internal
24
23
  */
@@ -56,12 +55,20 @@ export function hasCopyBlockingReference(tabs, insights, unavailableObjects) {
56
55
  }
57
56
  return false;
58
57
  };
58
+ const restrictedLimitingItems = newRestrictedLimitingItemsMap(unavailableObjects);
59
+ const isFilterForbidden = (filter) => {
60
+ if (isDashboardMeasureValueFilter(filter)) {
61
+ return isForbidden(filter.dashboardMeasureValueFilter.measure, "measure");
62
+ }
63
+ return (isDashboardAttributeFilterItem(filter) &&
64
+ (isLabelForbidden(dashboardAttributeFilterItemDisplayForm(filter)) ||
65
+ (dashboardAttributeFilterItemValidateElementsBy(filter) ?? []).some((item) => restrictedLimitingItems.has(item))));
66
+ };
59
67
  const isSectionForbidden = (section) => isTextForbidden(section.header?.description) ||
60
68
  section.items.some((item) => item.widget !== undefined && isWidgetForbidden(item.widget));
61
69
  return tabs.some((tab) => (tab.layout?.sections ?? []).some(isSectionForbidden) ||
62
70
  tab.attributeFilterConfigs.some((config) => isLabelForbidden(config.displayAsLabel)) ||
63
- tab.filters.some((filter) => isDashboardAttributeFilterItem(filter) &&
64
- isLabelForbidden(dashboardAttributeFilterItemDisplayForm(filter))));
71
+ tab.filters.some(isFilterForbidden));
65
72
  }
66
73
  /**
67
74
  * Selects whether "Save as new" would fail because the dashboard, as it stands now, references objects
@@ -23,6 +23,22 @@ export declare const selectUnavailableObjectsMapByType: (type: ObjectType) => Da
23
23
  * @alpha
24
24
  */
25
25
  export declare const selectRestrictedInsightsMap: DashboardSelector<ObjRefMap<IUnavailableDashboardReference>>;
26
+ /**
27
+ * Maps the metrics and facts the current user is not allowed to read: the items limiting an attribute
28
+ * filter's values ("Filter values by") that drop out of its values request and of its configuration
29
+ * panel. Merely deleted ones are not included. Lookups match the type too, as a metric and a fact may
30
+ * share an identifier.
31
+ *
32
+ * @internal
33
+ */
34
+ export declare function newRestrictedLimitingItemsMap(objects: ReadonlyArray<IUnavailableDashboardReference>): ObjRefMap<IUnavailableDashboardReference>;
35
+ /**
36
+ * Selects the metrics and facts limiting attribute filter values that the current user is not allowed to
37
+ * read, see {@link newRestrictedLimitingItemsMap}.
38
+ *
39
+ * @internal
40
+ */
41
+ export declare const selectRestrictedLimitingItemsMap: DashboardSelector<ObjRefMap<IUnavailableDashboardReference>>;
26
42
  /**
27
43
  * Selects the refs a rich text widget references but the current user is not allowed to read. A
28
44
  * reference that is merely deleted is not included — that keeps rendering today's error value,
@@ -1 +1 @@
1
- {"version":3,"file":"unavailableObjectsSelectors.d.ts","sourceRoot":"","sources":["../../../../src/model/store/unavailableObjects/unavailableObjectsSelectors.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,SAAS,EAA0B,MAAM,yCAAyC,CAAC;AAEjG,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,aAAa,CAAC;AAW1E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBAAiB,CAAC,8BAA8B,EAAE,CAC3D,CAAC;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,EAAE,CAC5C,IAAI,EAAE,UAAU,KACf,iBAAiB,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAQ/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,iBAAiB,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAMhG,CAAC;AAQN;;;;;;GAMG;AACH,eAAO,MAAM,kCAAkC,EAAE,iBAAiB,CAAC,MAAM,EAAE,CAQ1E,CAAC"}
1
+ {"version":3,"file":"unavailableObjectsSelectors.d.ts","sourceRoot":"","sources":["../../../../src/model/store/unavailableObjects/unavailableObjectsSelectors.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,SAAS,EAA0B,MAAM,yCAAyC,CAAC;AAEjG,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,aAAa,CAAC;AAW1E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBAAiB,CAAC,8BAA8B,EAAE,CAC3D,CAAC;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,EAAE,CAC5C,IAAI,EAAE,UAAU,KACf,iBAAiB,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAQ/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,iBAAiB,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAMhG,CAAC;AAEN;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CACzC,OAAO,EAAE,aAAa,CAAC,8BAA8B,CAAC,GACvD,SAAS,CAAC,8BAA8B,CAAC,CAS3C;AAED;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,EAAE,iBAAiB,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAC/B,CAAC;AAQ5E;;;;;;GAMG;AACH,eAAO,MAAM,kCAAkC,EAAE,iBAAiB,CAAC,MAAM,EAAE,CAQ1E,CAAC"}
@@ -26,6 +26,24 @@ export const selectUnavailableObjectsMapByType = createMemoizedSelector((type) =
26
26
  * @alpha
27
27
  */
28
28
  export const selectRestrictedInsightsMap = createSelector(selectUnavailableObjects, (objects) => newMapForObjectWithRef(objects.filter((object) => object.type === "insight" && object.reason === "forbidden"), "insight"));
29
+ /**
30
+ * Maps the metrics and facts the current user is not allowed to read: the items limiting an attribute
31
+ * filter's values ("Filter values by") that drop out of its values request and of its configuration
32
+ * panel. Merely deleted ones are not included. Lookups match the type too, as a metric and a fact may
33
+ * share an identifier.
34
+ *
35
+ * @internal
36
+ */
37
+ export function newRestrictedLimitingItemsMap(objects) {
38
+ return newMapForObjectWithRef(objects.filter((object) => object.reason === "forbidden" && (object.type === "measure" || object.type === "fact")), undefined, true);
39
+ }
40
+ /**
41
+ * Selects the metrics and facts limiting attribute filter values that the current user is not allowed to
42
+ * read, see {@link newRestrictedLimitingItemsMap}.
43
+ *
44
+ * @internal
45
+ */
46
+ export const selectRestrictedLimitingItemsMap = createSelector(selectUnavailableObjects, newRestrictedLimitingItemsMap);
29
47
  /**
30
48
  * Object types a rich text widget can reference: `{metric/id}`, `{label/id}` and
31
49
  * `{computed_attribute/id}`.