@gooddata/sdk-ui-dashboard 11.57.0-alpha.2 → 11.57.0-alpha.4

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 (193) hide show
  1. package/NOTICE +4 -4
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/kdaDialog/dialog/hooks/useChangeAnalysis.js +1 -1
  5. package/esm/model/commandHandlers/common/validateDrillToCustomUrlParams.d.ts.map +1 -1
  6. package/esm/model/commandHandlers/common/validateDrillToCustomUrlParams.js +6 -5
  7. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.d.ts +1 -1
  8. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.d.ts.map +1 -1
  9. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.js +63 -3
  10. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.d.ts +2 -3
  11. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.d.ts.map +1 -1
  12. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.js +23 -17
  13. package/esm/model/commandHandlers/widgets/validation/insightDrillDefinitionUtils.d.ts.map +1 -1
  14. package/esm/model/commandHandlers/widgets/validation/insightDrillDefinitionUtils.js +5 -9
  15. package/esm/model/react/useDashboardAsyncRender.js +2 -2
  16. package/esm/model/react/useDashboardCommand.js +1 -1
  17. package/esm/model/react/useDashboardQueryProcessing.js +1 -1
  18. package/esm/model/react/useDispatchDashboardCommand.js +1 -1
  19. package/esm/model/react/useInitializeDashboardStore.js +1 -1
  20. package/esm/model/react/useWidgetFilters.js +7 -7
  21. package/esm/model/store/insights/insightsSelectors.d.ts +18 -0
  22. package/esm/model/store/insights/insightsSelectors.d.ts.map +1 -1
  23. package/esm/model/store/insights/insightsSelectors.js +51 -2
  24. package/esm/model/store/tabs/index.d.ts +12 -0
  25. package/esm/model/store/tabs/index.d.ts.map +1 -1
  26. package/esm/model/store/tabs/layout/layoutReducers.d.ts +36 -30
  27. package/esm/model/store/tabs/layout/layoutReducers.d.ts.map +1 -1
  28. package/esm/model/store/tabs/layout/layoutReducers.js +19 -0
  29. package/esm/model/store/tabs/layout/layoutSelectors.d.ts +17 -0
  30. package/esm/model/store/tabs/layout/layoutSelectors.d.ts.map +1 -1
  31. package/esm/model/store/tabs/layout/layoutSelectors.js +30 -1
  32. package/esm/model/store/ui/index.d.ts +3 -0
  33. package/esm/model/store/ui/index.d.ts.map +1 -1
  34. package/esm/model/store/ui/uiReducers.d.ts +3 -0
  35. package/esm/model/store/ui/uiReducers.d.ts.map +1 -1
  36. package/esm/model/store/ui/uiReducers.js +13 -0
  37. package/esm/model/store/ui/uiSelectors.d.ts +8 -0
  38. package/esm/model/store/ui/uiSelectors.d.ts.map +1 -1
  39. package/esm/model/store/ui/uiSelectors.js +8 -0
  40. package/esm/model/store/ui/uiState.d.ts +4 -0
  41. package/esm/model/store/ui/uiState.d.ts.map +1 -1
  42. package/esm/model/store/ui/uiState.js +4 -0
  43. package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialogAttribute.js +1 -1
  44. package/esm/presentation/automations/alerting/blocks/AlertingDialogFieldLabelWithTooltip.d.ts.map +1 -1
  45. package/esm/presentation/automations/alerting/blocks/AlertingDialogFieldLabelWithTooltip.js +1 -1
  46. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useElementHeightSnapshot.js +1 -1
  47. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts.map +1 -1
  48. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.js +1 -1
  49. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.js +3 -3
  50. package/esm/presentation/dashboard/DashboardHeader/DashboardHeader.d.ts.map +1 -1
  51. package/esm/presentation/dashboard/DashboardHeader/DashboardHeader.js +5 -1
  52. package/esm/presentation/dashboardSettingsDialog/DefaultDashboardSettingsDialog.d.ts.map +1 -1
  53. package/esm/presentation/dashboardSettingsDialog/DefaultDashboardSettingsDialog.js +4 -3
  54. package/esm/presentation/dragAndDrop/useDashboardDragScroll.js +2 -2
  55. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.d.ts.map +1 -1
  56. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.js +16 -23
  57. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditorParametersSections/DashboardParametersSection.d.ts.map +1 -1
  58. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditorParametersSections/DashboardParametersSection.js +3 -2
  59. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditorParametersSections/DisplayFormParam.d.ts.map +1 -1
  60. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditorParametersSections/DisplayFormParam.js +2 -1
  61. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditorParametersSections/InsightParametersSection.d.ts.map +1 -1
  62. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditorParametersSections/InsightParametersSection.js +2 -1
  63. package/esm/presentation/drill/utils/drillToCustomUrlUtils.d.ts.map +1 -1
  64. package/esm/presentation/drill/utils/drillToCustomUrlUtils.js +5 -3
  65. package/esm/presentation/filterBar/attributeFilter/DefaultDashboardAttributeFilter.js +1 -1
  66. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/AttributesDropdown.js +1 -1
  67. package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useTitleConfiguration.js +1 -1
  68. package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/limitValues/dialog/DateFiltersPage.js +1 -1
  69. package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.js +1 -1
  70. package/esm/presentation/filterBar/filterBar/useFiltersWithAddedPlaceholder.js +1 -1
  71. package/esm/presentation/flexibleLayout/DefaultDashboardLayoutRenderer/DashboardLayoutWidgetRenderer.js +1 -1
  72. package/esm/presentation/flexibleLayout/dragAndDrop/DragLayer.js +1 -1
  73. package/esm/presentation/flexibleLayout/dragAndDrop/Resize/HeightResizerHotspot.js +1 -1
  74. package/esm/presentation/insightList/InsightList.js +1 -1
  75. package/esm/presentation/insightNotSavedDialog/InsightNotSavedDialog.d.ts +5 -0
  76. package/esm/presentation/insightNotSavedDialog/InsightNotSavedDialog.d.ts.map +1 -0
  77. package/esm/presentation/insightNotSavedDialog/InsightNotSavedDialog.js +29 -0
  78. package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts +1 -0
  79. package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts.map +1 -1
  80. package/esm/presentation/localization/bundles/de-DE.localization-bundle.js +1 -0
  81. package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts +1 -0
  82. package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts.map +1 -1
  83. package/esm/presentation/localization/bundles/en-AU.localization-bundle.js +1 -0
  84. package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts +1 -0
  85. package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts.map +1 -1
  86. package/esm/presentation/localization/bundles/en-GB.localization-bundle.js +1 -0
  87. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +20 -0
  88. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  89. package/esm/presentation/localization/bundles/en-US.localization-bundle.js +22 -2
  90. package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts +1 -0
  91. package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts.map +1 -1
  92. package/esm/presentation/localization/bundles/es-419.localization-bundle.js +1 -0
  93. package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts +1 -0
  94. package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts.map +1 -1
  95. package/esm/presentation/localization/bundles/es-ES.localization-bundle.js +1 -0
  96. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts +1 -0
  97. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts.map +1 -1
  98. package/esm/presentation/localization/bundles/fi-FI.localization-bundle.js +1 -0
  99. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts +1 -0
  100. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts.map +1 -1
  101. package/esm/presentation/localization/bundles/fr-CA.localization-bundle.js +1 -0
  102. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts +1 -0
  103. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts.map +1 -1
  104. package/esm/presentation/localization/bundles/fr-FR.localization-bundle.js +1 -0
  105. package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts +1 -0
  106. package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts.map +1 -1
  107. package/esm/presentation/localization/bundles/id-ID.localization-bundle.js +1 -0
  108. package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts +1 -0
  109. package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts.map +1 -1
  110. package/esm/presentation/localization/bundles/it-IT.localization-bundle.js +1 -0
  111. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts +1 -0
  112. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts.map +1 -1
  113. package/esm/presentation/localization/bundles/ja-JP.localization-bundle.js +1 -0
  114. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts +1 -0
  115. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts.map +1 -1
  116. package/esm/presentation/localization/bundles/ko-KR.localization-bundle.js +1 -0
  117. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts +1 -0
  118. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts.map +1 -1
  119. package/esm/presentation/localization/bundles/nl-NL.localization-bundle.js +1 -0
  120. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts +1 -0
  121. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts.map +1 -1
  122. package/esm/presentation/localization/bundles/pl-PL.localization-bundle.js +1 -0
  123. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts +1 -0
  124. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts.map +1 -1
  125. package/esm/presentation/localization/bundles/pt-BR.localization-bundle.js +1 -0
  126. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts +1 -0
  127. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts.map +1 -1
  128. package/esm/presentation/localization/bundles/pt-PT.localization-bundle.js +1 -0
  129. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts +1 -0
  130. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts.map +1 -1
  131. package/esm/presentation/localization/bundles/ru-RU.localization-bundle.js +2 -1
  132. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts +1 -0
  133. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts.map +1 -1
  134. package/esm/presentation/localization/bundles/sl-SI.localization-bundle.js +1 -0
  135. package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts +1 -0
  136. package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts.map +1 -1
  137. package/esm/presentation/localization/bundles/th-TH.localization-bundle.js +1 -0
  138. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts +1 -0
  139. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts.map +1 -1
  140. package/esm/presentation/localization/bundles/tr-TR.localization-bundle.js +1 -0
  141. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts +1 -0
  142. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts.map +1 -1
  143. package/esm/presentation/localization/bundles/uk-UA.localization-bundle.js +1 -0
  144. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts +1 -0
  145. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts.map +1 -1
  146. package/esm/presentation/localization/bundles/vi-VN.localization-bundle.js +1 -0
  147. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts +1 -0
  148. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts.map +1 -1
  149. package/esm/presentation/localization/bundles/zh-HK.localization-bundle.js +1 -0
  150. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts +1 -0
  151. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts.map +1 -1
  152. package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.js +1 -0
  153. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts +1 -0
  154. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts.map +1 -1
  155. package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.js +1 -0
  156. package/esm/presentation/saveAs/DefaultSaveAsDialog/useSaveAs.js +1 -1
  157. package/esm/presentation/topBar/buttonBar/button/settingButton/DefaultSettingButton.d.ts.map +1 -1
  158. package/esm/presentation/topBar/buttonBar/button/settingButton/DefaultSettingButton.js +1 -1
  159. package/esm/presentation/topBar/menuButton/useDefaultMenuItems.js +4 -4
  160. package/esm/presentation/widget/common/configuration/useAttributeFilterConfigurationHandling.js +5 -5
  161. package/esm/presentation/widget/common/configuration/useDateFilterConfigurationHandling.js +5 -5
  162. package/esm/presentation/widget/common/configuration/useIsSelectedDatasetHidden.js +1 -1
  163. package/esm/presentation/widget/common/configuration/useMeasureValueFilterConfigurationHandling.js +5 -5
  164. package/esm/presentation/widget/common/useCustomWidgetInsightDataView.js +3 -3
  165. package/esm/presentation/widget/common/useExportHandler.js +1 -1
  166. package/esm/presentation/widget/common/useImageExportHandler.d.ts.map +1 -1
  167. package/esm/presentation/widget/common/useImageExportHandler.js +2 -2
  168. package/esm/presentation/widget/common/useInsightExport.js +11 -11
  169. package/esm/presentation/widget/common/useInsightWidgetDataView.js +2 -2
  170. package/esm/presentation/widget/common/useRawExportHandler.js +1 -1
  171. package/esm/presentation/widget/common/useSlidesExportHandler.js +1 -1
  172. package/esm/presentation/widget/common/useWidgetHighlighting.js +1 -1
  173. package/esm/presentation/widget/insight/ViewModeDashboardInsight/Insight/DashboardInsight.js +6 -6
  174. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/DrillDialogInsight.js +1 -1
  175. package/esm/presentation/widget/insight/ViewModeDashboardInsight/useResolveDashboardInsightProperties.js +1 -1
  176. package/esm/presentation/widget/insight/configuration/DrillTargets/useInvalidAttributeDisplayFormIdentifier.d.ts.map +1 -1
  177. package/esm/presentation/widget/insight/configuration/DrillTargets/useInvalidAttributeDisplayFormIdentifier.js +7 -6
  178. package/esm/presentation/widget/insight/configuration/DrillTargets/useInvalidFilteringParametersIdentifiers.d.ts.map +1 -1
  179. package/esm/presentation/widget/insight/configuration/DrillTargets/useInvalidFilteringParametersIdentifiers.js +16 -12
  180. package/esm/presentation/widget/insight/configuration/InsightDrillConfigPanel/useInsightDrillConfigPanel.js +2 -2
  181. package/esm/presentation/widget/visualizationSwitcher/configuration/Toolbar.js +2 -2
  182. package/esm/presentation/widget/visualizationSwitcher/configuration/VisualizationsList/VisualizationListMenu.js +2 -2
  183. package/esm/presentation/widget/widget/DashboardWidget.js +1 -1
  184. package/esm/presentation/widget/widget/DefaultDashboardWidget.js +1 -1
  185. package/esm/presentation/widget/widget/InsightWidget/useInsightMenu.js +1 -1
  186. package/esm/sdk-ui-dashboard.d.ts +19 -0
  187. package/package.json +23 -24
  188. package/styles/css/insightsNotSavedDialog.css +26 -0
  189. package/styles/css/insightsNotSavedDialog.css.map +1 -0
  190. package/styles/css/main.css +27 -2
  191. package/styles/css/main.css.map +1 -1
  192. package/styles/scss/insightsNotSavedDialog.scss +26 -0
  193. package/styles/scss/main.scss +1 -0
package/NOTICE CHANGED
@@ -7,9 +7,9 @@
7
7
 
8
8
  The following 3rd-party software packages may be used by or distributed with gooddata-ui-sdk. Any information relevant to third-party vendors listed below are collected using common, reasonable means.
9
9
 
10
- Date generated: 2026-9-13
10
+ Date generated: 2026-9-14
11
11
 
12
- Revision ID: 6137e079cb078a0bcfbae6cca294b0e3b8efb320
12
+ Revision ID: b22f44aea3e618f71ec62f6853d9310a210cb741
13
13
 
14
14
  ================================================================================
15
15
  ================================================================================
@@ -22305,7 +22305,7 @@ MIT
22305
22305
 
22306
22306
  Authors: ljharb@gmail.com
22307
22307
  Package Manager: NPM
22308
- Project URL: https://www.npmjs.com/package/call-bind
22308
+ Project URL: https://github.com/ljharb/call-bind#readme
22309
22309
  Package Download URL: https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz
22310
22310
  Dependency Path: @formatjs/cli-lib > @formatjs/ts-transformer > @types/json-stable-stringify > json-stable-stringify > call-bind > @formatjs/cli-lib > @formatjs/ts-transformer > json-stable-stringify > call-bind > @formatjs/cli-lib > @types/json-stable-stringify > json-stable-stringify > call-bind > @formatjs/cli-lib > json-stable-stringify > call-bind > json-stable-stringify > call-bind
22311
22311
  File Path(s): common/config/subspaces/sdk/pnpm-lock.yaml
@@ -64353,4 +64353,4 @@ File Path(s): common/config/subspaces/sdk/pnpm-lock.yaml
64353
64353
  --------------------------------------------------------------------------------
64354
64354
  --------------------------------------------------------------------------------
64355
64355
 
64356
- Report Generated by FOSSA on 2026-9-13
64356
+ Report Generated by FOSSA on 2026-9-14
@@ -1,4 +1,4 @@
1
- export declare const LIB_VERSION = "11.57.0-alpha.2";
1
+ export declare const LIB_VERSION = "11.57.0-alpha.4";
2
2
  export declare const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
3
3
  export declare const LIB_NAME = "@gooddata/sdk-ui-dashboard";
4
4
  //# sourceMappingURL=__version.d.ts.map
package/esm/__version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // (C) 2021 GoodData Corporation
2
2
  // DO NOT CHANGE THIS FILE, IT IS RE-GENERATED ON EVERY BUILD
3
- export const LIB_VERSION = "11.57.0-alpha.2";
3
+ export const LIB_VERSION = "11.57.0-alpha.4";
4
4
  export const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
5
5
  export const LIB_NAME = "@gooddata/sdk-ui-dashboard";
@@ -15,7 +15,7 @@ export function useChangeAnalysis() {
15
15
  const definition = state.definition;
16
16
  const attributes = useMemo(() => {
17
17
  return state.selectedAttributes;
18
- // eslint-disable-next-line react-hooks/exhaustive-deps
18
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
19
19
  }, [state.selectedUpdated]);
20
20
  const filters = useRelevantFilters();
21
21
  const measureValueFilters = state.measureValueFilters;
@@ -1 +1 @@
1
- {"version":3,"file":"validateDrillToCustomUrlParams.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/common/validateDrillToCustomUrlParams.ts"],"names":[],"mappings":"AAKA,OAAO,EAGH,KAAK,iBAAiB,EAEtB,KAAK,cAAc,EAWtB,MAAM,qBAAqB,CAAC;AAkB7B,UAAU,kBAAkB;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB,aAAa,EAAE,iBAAiB,EAAE,CAAC;CACtC;AAGD,wBAAiB,8BAA8B,CAAC,OAAO,EAAE,cAAc,EAAE;;;;;;;;;gCAYxE"}
1
+ {"version":3,"file":"validateDrillToCustomUrlParams.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/common/validateDrillToCustomUrlParams.ts"],"names":[],"mappings":"AAKA,OAAO,EAGH,KAAK,iBAAiB,EAEtB,KAAK,cAAc,EAUtB,MAAM,qBAAqB,CAAC;AAmB7B,UAAU,kBAAkB;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB,aAAa,EAAE,iBAAiB,EAAE,CAAC;CACtC;AAGD,wBAAiB,8BAA8B,CAAC,OAAO,EAAE,cAAc,EAAE;;;;;;;;;gCAYxE"}
@@ -1,6 +1,7 @@
1
1
  // (C) 2022-2026 GoodData Corporation
2
2
  import { all, call, put, select } from "redux-saga/effects";
3
- import { areObjRefsEqual, dashboardAttributeFilterItemToAttributeFilter, filterObjRef, idRef, isArbitraryAttributeFilter, isAttributeFilter, isDrillToCustomUrl, isMatchAttributeFilter, isNegativeAttributeFilter, widgetRef, } from "@gooddata/sdk-model";
3
+ import { areObjRefsEqual, dashboardAttributeFilterItemToAttributeFilter, filterObjRef, isArbitraryAttributeFilter, isAttributeFilter, isDrillToCustomUrl, isMatchAttributeFilter, isNegativeAttributeFilter, widgetRef, } from "@gooddata/sdk-model";
4
+ import { displayFormPlaceholderRef } from "@gooddata/sdk-model/internal";
4
5
  import { queryWidgetFilters } from "../../queries/widgets.js";
5
6
  import { query } from "../../store/_infra/queryCall.js";
6
7
  import { selectAllCatalogDisplayFormsMap } from "../../store/catalog/catalogSelectors.js";
@@ -84,7 +85,7 @@ function sanitizeAttributeFilter(filter, displayFormMap) {
84
85
  ...filter,
85
86
  negativeAttributeFilter: {
86
87
  ...filter.negativeAttributeFilter,
87
- displayForm: idRef(displayForm.id, "displayForm"),
88
+ displayForm: displayFormPlaceholderRef(displayForm),
88
89
  },
89
90
  };
90
91
  }
@@ -93,7 +94,7 @@ function sanitizeAttributeFilter(filter, displayFormMap) {
93
94
  ...filter,
94
95
  arbitraryAttributeFilter: {
95
96
  ...filter.arbitraryAttributeFilter,
96
- displayForm: idRef(displayForm.id, "displayForm"),
97
+ displayForm: displayFormPlaceholderRef(displayForm),
97
98
  },
98
99
  };
99
100
  }
@@ -102,7 +103,7 @@ function sanitizeAttributeFilter(filter, displayFormMap) {
102
103
  ...filter,
103
104
  matchAttributeFilter: {
104
105
  ...filter.matchAttributeFilter,
105
- displayForm: idRef(displayForm.id, "displayForm"),
106
+ displayForm: displayFormPlaceholderRef(displayForm),
106
107
  },
107
108
  };
108
109
  }
@@ -111,7 +112,7 @@ function sanitizeAttributeFilter(filter, displayFormMap) {
111
112
  ...filter,
112
113
  positiveAttributeFilter: {
113
114
  ...filter.positiveAttributeFilter,
114
- displayForm: idRef(displayForm.id, "displayForm"),
115
+ displayForm: displayFormPlaceholderRef(displayForm),
115
116
  },
116
117
  };
117
118
  }
@@ -6,5 +6,5 @@ import { type DashboardContext } from "../../types/commonTypes.js";
6
6
  import { type ExtendedDashboardWidget } from "../../types/layoutTypes.js";
7
7
  export declare function getDashboardWithSharing(dashboard: IDashboardDefinition, sharingSupported: boolean | undefined, isNewDashboard: boolean): IDashboardDefinition;
8
8
  export declare function processLayout(layout: IDashboardLayout<ExtendedDashboardWidget>): IDashboardLayout;
9
- export declare function saveDashboardHandler(ctx: DashboardContext, cmd: ISaveDashboard): SagaIterator<DashboardSaved>;
9
+ export declare function saveDashboardHandler(ctx: DashboardContext, cmd: ISaveDashboard): SagaIterator<DashboardSaved | undefined>;
10
10
  //# sourceMappingURL=saveDashboardHandler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"saveDashboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/dashboard/saveDashboardHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAGH,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAQxB,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,2BAA2B,CAAC;AAoBhF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAyG1E,wBAAgB,uBAAuB,CACnC,SAAS,EAAE,oBAAoB,EAC/B,gBAAgB,EAAE,OAAO,YAAO,EAChC,cAAc,EAAE,OAAO,GACxB,oBAAoB,CAkBtB;AAyED,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,CAAC,uBAAuB,CAAC,GAAG,gBAAgB,CAEjG;AAoUD,wBAAiB,oBAAoB,CACjC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,cAAc,GACpB,YAAY,CAAC,cAAc,CAAC,CAyD9B"}
1
+ {"version":3,"file":"saveDashboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/dashboard/saveDashboardHandler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAGH,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAWxB,MAAM,qBAAqB,CAAC;AAS7B,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,2BAA2B,CAAC;AAkChF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AA2J1E,wBAAgB,uBAAuB,CACnC,SAAS,EAAE,oBAAoB,EAC/B,gBAAgB,EAAE,OAAO,YAAO,EAChC,cAAc,EAAE,OAAO,GACxB,oBAAoB,CAkBtB;AAyED,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,CAAC,uBAAuB,CAAC,GAAG,gBAAgB,CAEjG;AAoUD,wBAAiB,oBAAoB,CACjC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,cAAc,GACpB,YAAY,CAAC,cAAc,GAAG,SAAS,CAAC,CA+F1C"}
@@ -1,9 +1,9 @@
1
1
  // (C) 2021-2026 GoodData Corporation
2
2
  import { batchActions } from "redux-batched-actions";
3
- import { call, put, select } from "redux-saga/effects";
3
+ import { call, put, select, take } from "redux-saga/effects";
4
4
  import { invariant } from "ts-invariant";
5
5
  import { isUnexpectedResponseError } from "@gooddata/sdk-backend-spi";
6
- import { isTempFilterContext, } from "@gooddata/sdk-model";
6
+ import { areObjRefsEqual, insightRef, isTempFilterContext, } from "@gooddata/sdk-model";
7
7
  import { dashboardFilterContextIdentity } from "../../../_staging/dashboard/dashboardFilterContext.js";
8
8
  import { dashboardLayoutRemoveIdentity, dashboardLayoutWidgetIdentityMap, } from "../../../_staging/dashboard/dashboardLayout.js";
9
9
  import { createListedDashboard } from "../../../_staging/listedDashboard/listedDashboardUtils.js";
@@ -15,6 +15,8 @@ import { dispatchDashboardEvent } from "../../store/_infra/eventDispatcher.js";
15
15
  import { accessibleDashboardsActions } from "../../store/accessibleDashboards/index.js";
16
16
  import { selectBackendCapabilities } from "../../store/backendCapabilities/backendCapabilitiesSelectors.js";
17
17
  import { selectLocale } from "../../store/config/configSelectors.js";
18
+ import { insightsActions } from "../../store/insights/index.js";
19
+ import { selectDraftInsightsUsedOnDashboard, selectInsights, } from "../../store/insights/insightsSelectors.js";
18
20
  import { listedDashboardsActions } from "../../store/listedDashboards/index.js";
19
21
  import { metaActions } from "../../store/meta/index.js";
20
22
  import { selectDashboardDescriptor, selectPersistedDashboard } from "../../store/meta/metaSelectors.js";
@@ -25,15 +27,52 @@ import { selectDateFilterConfigOverridesByTab } from "../../store/tabs/dateFilte
25
27
  import { selectDateFilterConfigsOverridesByTab } from "../../store/tabs/dateFilterConfigs/dateFilterConfigsSelectors.js";
26
28
  import { selectFilterContextStatesByTab } from "../../store/tabs/filterContext/filterContextSelectors.js";
27
29
  import { tabsActions } from "../../store/tabs/index.js";
28
- import { filterOutCustomWidgets, selectBasicLayoutByTab } from "../../store/tabs/layout/layoutSelectors.js";
30
+ import { filterOutCustomWidgets, selectAllInsightWidgetRefsByTab, selectBasicLayoutByTab, } from "../../store/tabs/layout/layoutSelectors.js";
29
31
  import { selectMeasureValueFilterConfigsOverridesByTab } from "../../store/tabs/measureValueFilterConfigs/measureValueFilterConfigsSelectors.js";
30
32
  import { selectSmartPersistedTabsParameters } from "../../store/tabs/parameters/parametersSelectors.js";
31
33
  import { selectTabs } from "../../store/tabs/tabsSelectors.js";
32
34
  import { DEFAULT_TAB_ID } from "../../store/tabs/tabsState.js";
35
+ import { uiActions } from "../../store/ui/index.js";
36
+ import { selectIsInsightNotSavedDialogOpen, selectIsInsightNotSavedDialogSaveConfirmed, } from "../../store/ui/uiSelectors.js";
33
37
  import { isTemporaryIdentity } from "../../utils/dashboardItemUtils.js";
34
38
  import { generateTabLocalIdentifier } from "../../utils/tabLocalIdentifier.js";
35
39
  import { changeRenderModeHandler } from "../renderMode/changeRenderModeHandler.js";
36
40
  import { switchDashboardTabHandler } from "../tabs/switchDashboardTabHandler.js";
41
+ function* persistDraftInsights(ctx, cmd, insights) {
42
+ for (const draftInsight of insights) {
43
+ const persistedInsight = yield call(async () => {
44
+ return ctx.backend.workspace(ctx.workspace).insights().createInsight(draftInsight, false);
45
+ });
46
+ const persistedInsightWithDraftState = {
47
+ ...persistedInsight,
48
+ insight: {
49
+ ...persistedInsight.insight,
50
+ isDraft: false,
51
+ },
52
+ };
53
+ const currentInsights = yield select(selectInsights);
54
+ const updatedInsights = currentInsights.map((insight) => {
55
+ if (areObjRefsEqual(insightRef(insight), insightRef(draftInsight))) {
56
+ return persistedInsightWithDraftState;
57
+ }
58
+ return insight;
59
+ });
60
+ const widgetRefsWithDraftInsightByTab = yield select(selectAllInsightWidgetRefsByTab(insightRef(draftInsight)));
61
+ for (const { tabId, widgetRef } of widgetRefsWithDraftInsightByTab) {
62
+ yield put(tabsActions.replaceInsightWidgetInsightForTab({
63
+ tabId,
64
+ ref: widgetRef,
65
+ insightRef: insightRef(persistedInsightWithDraftState),
66
+ properties: undefined,
67
+ header: undefined,
68
+ undo: {
69
+ cmd,
70
+ },
71
+ }));
72
+ }
73
+ yield put(insightsActions.setInsights(updatedInsights));
74
+ }
75
+ }
37
76
  function createDashboard(ctx, saveCtx) {
38
77
  return ctx.backend
39
78
  .workspace(ctx.workspace)
@@ -349,7 +388,28 @@ function* save(ctx, saveCtx, saveFn, saveActionName) {
349
388
  }
350
389
  export function* saveDashboardHandler(ctx, cmd) {
351
390
  try {
391
+ const isInsightNotSavedDialogSaveConfirmed = yield select(selectIsInsightNotSavedDialogSaveConfirmed);
392
+ const draftInsightsOnDashboard = yield select(selectDraftInsightsUsedOnDashboard);
393
+ let shouldPersistDraftInsights = isInsightNotSavedDialogSaveConfirmed;
394
+ if (draftInsightsOnDashboard.length > 0 && !shouldPersistDraftInsights) {
395
+ yield put(uiActions.openInsightNotSavedDialog());
396
+ const draftInsightDialogAction = yield take([
397
+ uiActions.confirmInsightNotSavedDialogSubmit.type,
398
+ uiActions.closeInsightNotSavedDialog.type,
399
+ ]);
400
+ if (draftInsightDialogAction.type === uiActions.closeInsightNotSavedDialog.type) {
401
+ return undefined;
402
+ }
403
+ shouldPersistDraftInsights = true;
404
+ }
352
405
  yield put(savingActions.setSavingStart());
406
+ const isInsightNotSavedDialogOpen = yield select(selectIsInsightNotSavedDialogOpen);
407
+ if (isInsightNotSavedDialogOpen) {
408
+ yield put(uiActions.closeInsightNotSavedDialog());
409
+ }
410
+ if (shouldPersistDraftInsights && draftInsightsOnDashboard.length > 0) {
411
+ yield call(persistDraftInsights, ctx, cmd, draftInsightsOnDashboard);
412
+ }
353
413
  const persistedDashboard = yield select(selectPersistedDashboard);
354
414
  const isNewDashboard = persistedDashboard === undefined;
355
415
  const isAiBuilder = ctx.config?.isAiMode;
@@ -9,10 +9,10 @@ interface IDrillToUrlPlaceholderReplacement {
9
9
  replaceGlobally?: boolean;
10
10
  }
11
11
  interface IDrillToUrlElement {
12
- identifier: string;
12
+ ref: ObjRef;
13
13
  elementTitle: string | null;
14
14
  }
15
- export declare function loadElementTitle(dfRef: ObjRef, dfIdentifier: string, attrElementUri: string, ctx: DashboardContext): SagaIterator<IDrillToUrlElement>;
15
+ export declare function loadElementTitle(dfRef: ObjRef, placeholderRef: ObjRef, attrElementUri: string, ctx: DashboardContext): SagaIterator<IDrillToUrlElement>;
16
16
  export declare function loadSecondaryElementTitles(dfRef: ObjRef, attrElementValues: (string | null)[], ctx: DashboardContext): SagaIterator<Array<string | null>>;
17
17
  /**
18
18
  * @internal
@@ -23,7 +23,6 @@ export declare function splitDFToLoadingAndMapping(attributesDisplayForms: IAttr
23
23
  displayFormForValueLoad: IAttributeDisplayFormMetadataObject[];
24
24
  }>;
25
25
  export declare function loadAttributeElementsForDrillIntersection(drillIntersectionElements: IDrillEventIntersectionElement[], attributesDisplayForms: IAttributeDisplayFormMetadataObject[], ctx: DashboardContext): SagaIterator<IDrillToUrlElement[]>;
26
- export declare function getAttributeDisplayForms(projectId: string, objRefs: ObjRef[], ctx: DashboardContext): Promise<IAttributeDisplayFormMetadataObject[]>;
27
26
  export declare function getAttributeIdentifiersReplacements(url: string, drillIntersectionElements: IDrillEventIntersectionElement[], ctx: DashboardContext): SagaIterator<IDrillToUrlPlaceholderReplacement[]>;
28
27
  export declare function getDashboardAttributeFilterReplacements(url: string, ctx: DashboardContext): SagaIterator<IDrillToUrlPlaceholderReplacement[]>;
29
28
  export declare function getDashboardMeasureValueFilterReplacements(url: string): SagaIterator<IDrillToUrlPlaceholderReplacement[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"resolveDrillToCustomUrl.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/drill/resolveDrillToCustomUrl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolveDrillToCustomUrl.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/drill/resolveDrillToCustomUrl.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,8 @@
2
2
  import stringify from "json-stable-stringify";
3
3
  import { groupBy } from "lodash-es";
4
4
  import { all, call, select } from "redux-saga/effects";
5
- import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, dashboardFilterObjRef, filterAttributeElements, filterObjRef, idRef, insightFilters as insightDefinitionFilters, insightId, isArbitraryAttributeFilter, isAttributeDescriptor, isAttributeElementsByValue, isAttributeFilter, isComparisonCondition, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardTextAttributeFilter, isIdentifierRef, isMeasureValueFilter, isNegativeAttributeFilter, isRangeCondition, isTextAttributeFilter, isUriRef, measureValueFilterConditions, measureValueFilterMeasure, } from "@gooddata/sdk-model";
6
- import { getAttributeIdentifiersPlaceholdersFromUrl, getDashboardAttributeFilterPlaceholdersFromUrl, getDashboardMeasureValueFilterPlaceholdersFromUrl, getInsightAttributeFilterPlaceholdersFromUrl, getInsightMeasureValueFilterPlaceholdersFromUrl, } from "@gooddata/sdk-model/internal";
5
+ import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, dashboardFilterObjRef, filterAttributeElements, filterObjRef, insightFilters as insightDefinitionFilters, insightId, isArbitraryAttributeFilter, isAttributeDescriptor, isAttributeElementsByValue, isAttributeFilter, isComparisonCondition, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardTextAttributeFilter, isIdentifierRef, isMeasureValueFilter, isNegativeAttributeFilter, isRangeCondition, isTextAttributeFilter, isUriRef, measureValueFilterConditions, measureValueFilterMeasure, } from "@gooddata/sdk-model";
6
+ import { displayFormPlaceholderRef, getAttributeIdentifiersPlaceholdersFromUrl, getDashboardAttributeFilterPlaceholdersFromUrl, getDashboardMeasureValueFilterPlaceholdersFromUrl, getInsightAttributeFilterPlaceholdersFromUrl, getInsightMeasureValueFilterPlaceholdersFromUrl, } from "@gooddata/sdk-model/internal";
7
7
  import { isDrillIntersectionAttributeItem, } from "@gooddata/sdk-ui";
8
8
  import { invalidArgumentsProvided } from "../../events/general.js";
9
9
  import { selectAllCatalogDisplayFormsMap, selectAllCatalogMeasuresMap, selectCatalogDateAttributes, } from "../../store/catalog/catalogSelectors.js";
@@ -14,12 +14,13 @@ import { selectAttributeFilterConfigsOverrides } from "../../store/tabs/attribut
14
14
  import { selectFilterContextAttributeFilterItems, selectFilterContextMeasureValueFilters, } from "../../store/tabs/filterContext/filterContextSelectors.js";
15
15
  import { selectAnalyticalWidgetByRef } from "../../store/tabs/layout/layoutSelectors.js";
16
16
  import { DRILL_TO_URL_PLACEHOLDER } from "../../types/drillTypes.js";
17
+ import { resolveDisplayFormMetadata } from "../../utils/displayFormResolver.js";
17
18
  import { dashboardMeasureValueFilterMatchesIdentifier, insightMeasureValueFilterMatchesIdentifier, } from "../../utils/measureValueFilterUtils.js";
18
19
  import { getElementTitle, getElementsSecondaryTitles } from "./getElementTitle.js";
19
- export function* loadElementTitle(dfRef, dfIdentifier, attrElementUri, ctx) {
20
+ export function* loadElementTitle(dfRef, placeholderRef, attrElementUri, ctx) {
20
21
  const elementTitle = yield call(getElementTitle, ctx.workspace, dfRef, attrElementUri, ctx);
21
22
  return {
22
- identifier: dfIdentifier,
23
+ ref: placeholderRef,
23
24
  elementTitle,
24
25
  };
25
26
  }
@@ -126,35 +127,40 @@ export function* loadAttributeElementsForDrillIntersection(drillIntersectionElem
126
127
  return acc;
127
128
  }
128
129
  acc.push({
129
- identifier: displayForm.id,
130
+ ref: displayFormPlaceholderRef(displayForm),
130
131
  elementTitle: attributeHeaderItem.uri,
131
132
  });
132
133
  return acc;
133
134
  }, []);
134
135
  const loadedElement = yield all(displayFormForValueLoad.reduce((acc, displayForm) => {
135
- const { id: dfIdentifier, ref: dfRef } = displayForm;
136
136
  const attributeHeaderItem = findDrillIntersectionAttributeHeaderItem(drillIntersectionElements, displayForm);
137
137
  if (!attributeHeaderItem) {
138
138
  return acc;
139
139
  }
140
- acc.push(call(loadElementTitle, dfRef, dfIdentifier, attributeHeaderItem.uri, ctx));
140
+ acc.push(call(loadElementTitle, displayForm.ref, displayFormPlaceholderRef(displayForm), attributeHeaderItem.uri, ctx));
141
141
  return acc;
142
142
  }, []));
143
143
  return [...mappedElements, ...loadedElement];
144
144
  }
145
145
  const encodeParameterIfSet = (parameter) => parameter === null || parameter === undefined ? parameter : encodeURIComponent(parameter);
146
- export function getAttributeDisplayForms(projectId, objRefs, ctx) {
147
- return ctx.backend.workspace(projectId).attributes().getAttributeDisplayForms(objRefs);
148
- }
149
146
  export function* getAttributeIdentifiersReplacements(url, drillIntersectionElements, ctx) {
150
147
  const attributeIdentifiersPlaceholders = getAttributeIdentifiersPlaceholdersFromUrl(url);
151
148
  if (attributeIdentifiersPlaceholders.length === 0) {
152
149
  return [];
153
150
  }
154
- const displayForms = yield call(getAttributeDisplayForms, ctx.workspace, attributeIdentifiersPlaceholders.map((placeholder) => idRef(placeholder.identifier)), ctx);
155
- const elements = yield call(loadAttributeElementsForDrillIntersection, drillIntersectionElements, displayForms, ctx);
156
- return attributeIdentifiersPlaceholders.map(({ placeholder: toBeReplaced, identifier, toBeEncoded }) => {
157
- const elementTitle = elements.find((element) => element.identifier === identifier)?.elementTitle;
151
+ // The placeholder refs carry their own type, so this resolves a label through the labels API and a
152
+ // computed attribute through the computedAttributes service - the labels API cannot describe one.
153
+ // It reads the catalog first but falls back to loading, so a computed attribute that the catalog
154
+ // does not carry (excluded by tags, or created after the dashboard was initialised) still resolves.
155
+ const { resolved, missing } = yield call(resolveDisplayFormMetadata, ctx, attributeIdentifiersPlaceholders.map(({ ref }) => ref));
156
+ if (missing.length > 0) {
157
+ console.warn("Drill to custom URL: no metadata found for attributes referenced by attribute_title placeholders; those placeholders cannot be resolved.", { missing });
158
+ }
159
+ const elements = yield call(loadAttributeElementsForDrillIntersection, drillIntersectionElements, [...resolved.values()], ctx);
160
+ return attributeIdentifiersPlaceholders.map(({ placeholder: toBeReplaced, ref, toBeEncoded }) => {
161
+ // Matched by reference, not by identifier alone: a computed attribute and a label can
162
+ // share an identifier, and they must not resolve to each other's element titles.
163
+ const elementTitle = elements.find((element) => areObjRefsEqual(element.ref, ref))?.elementTitle;
158
164
  const replacement = toBeEncoded ? encodeParameterIfSet(elementTitle) : elementTitle;
159
165
  return {
160
166
  toBeReplaced,
@@ -169,7 +175,7 @@ function* resolveDashboardAttributeFilterReplacement({ placeholder: toBeReplaced
169
175
  return false;
170
176
  }
171
177
  const df = catalogDisplayForms.get(dashboardAttributeFilterItemDisplayForm(filter));
172
- return df && areObjRefsEqual(idRef(df.id), ref);
178
+ return df && areObjRefsEqual(displayFormPlaceholderRef(df), ref);
173
179
  });
174
180
  if (textFilter && isDashboardTextAttributeFilter(textFilter)) {
175
181
  const parsedFilter = stringifyTextFilterSelection(textFilter);
@@ -183,7 +189,7 @@ function* resolveDashboardAttributeFilterReplacement({ placeholder: toBeReplaced
183
189
  const standardFilters = attributeFilters.filter(isDashboardAttributeFilter);
184
190
  let usedFilter = standardFilters.find((filter) => {
185
191
  const df = catalogDisplayForms.get(filter.attributeFilter.displayForm);
186
- return df && areObjRefsEqual(idRef(df.id), ref);
192
+ return df && areObjRefsEqual(displayFormPlaceholderRef(df), ref);
187
193
  });
188
194
  let attributeElementsValues = [];
189
195
  if (usedFilter) {
@@ -288,7 +294,7 @@ export function* getInsightAttributeFilterReplacements(url, widgetRef) {
288
294
  const usedFilter = insightAttributeFilters.find((filter) => {
289
295
  const filterRef = filterObjRef(filter);
290
296
  const df = filterRef && catalogDisplayForms.get(filterRef);
291
- return df && areObjRefsEqual(idRef(df.id), ref);
297
+ return df && areObjRefsEqual(displayFormPlaceholderRef(df), ref);
292
298
  });
293
299
  let parsedFilter;
294
300
  if (usedFilter && isTextAttributeFilter(usedFilter)) {
@@ -1 +1 @@
1
- {"version":3,"file":"insightDrillDefinitionUtils.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/widgets/validation/insightDrillDefinitionUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,mCAAmC,EACxC,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAGtB,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,MAAM,EAYd,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAQ/D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAC5E,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AAG3F,wBAAgB,6BAA6B,CACzC,eAAe,EAAE,sBAAsB,EACvC,YAAY,EAAE,sBAAsB,GACrC,sBAAsB,CA8BxB;AAED,wBAAgB,4BAA4B,CACxC,eAAe,EAAE,sBAAsB,EACvC,oBAAoB,GAAE,sBAAsB,EAAO,GACpD,OAAO,CAIT;AAED,wBAAgB,2BAA2B,CACvC,eAAe,EAAE,sBAAsB,EACvC,oBAAoB,GAAE,sBAAsB,EAAO,GACpD,sBAAsB,GAAG,SAAS,CAIpC;AAED,wBAAgB,wCAAwC,CACpD,GAAG,EAAE,UAAU,EACf,oBAAoB,GAAE,sBAAsB,EAAO,GACpD,sBAAsB,CAUxB;AAED,wBAAgB,oCAAoC,CAChD,uBAAuB,EAAE,sBAAsB,EAC/C,wBAAwB,EAAE,sBAAsB,GACjD,OAAO,CA+BT;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,CAAC,sBAAsB,CAAC,GAAG,MAAM,EAAE,CAEzF;AAED,wBAAgB,6BAA6B,CAAC,gBAAgB,EAAE,sBAAsB,EAAE,GAAG,MAAM,EAAE,CAalG;AAED,wBAAgB,4CAA4C,CACxD,gBAAgB,EAAE,sBAAsB,EAAE,GAC3C,MAAM,EAAE,CAWV;AAED,wBAAgB,0CAA0C,CACtD,gBAAgB,EAAE,sBAAsB,EAAE,GAC3C,MAAM,EAAE,CASV;AAED,MAAM,WAAW,qCAAqC;IAClD,uBAAuB,EAAE,UAAU,EAAE,CAAC;IACtC,oBAAoB,EAAE,OAAO,EAAE,CAAC;IAChC,qBAAqB,EAAE,QAAQ,EAAE,CAAC;IAClC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,aAAa,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC3C,WAAW,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjC,eAAe,EAAE,SAAS,CAAC,mCAAmC,CAAC,CAAC;IAChE,qBAAqB,EAAE,sBAAsB,CAAC;IAC9C,yBAAyB,EAAE,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAC7D,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,oBAAoB,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC;CACrD;AAED,wBAAgB,8BAA8B,CAC1C,eAAe,EAAE,sBAAsB,EACvC,iBAAiB,EAAE,qCAAqC,GACzD,sBAAsB,CAkBxB;AAyMD,wBAAgB,kCAAkC,CAC9C,eAAe,EAAE,iBAAiB,EAClC,iBAAiB,EAAE,qCAAqC,GACzD,iBAAiB,CAenB;AAED,wBAAgB,qCAAqC,CACjD,eAAe,EAAE,oBAAoB,EACrC,iBAAiB,EAAE,qCAAqC,GACzD,oBAAoB,CAwCtB"}
1
+ {"version":3,"file":"insightDrillDefinitionUtils.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/widgets/validation/insightDrillDefinitionUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,mCAAmC,EACxC,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAGtB,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,MAAM,EAYd,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAQ/D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,4CAA4C,CAAC;AAC5E,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AAG3F,wBAAgB,6BAA6B,CACzC,eAAe,EAAE,sBAAsB,EACvC,YAAY,EAAE,sBAAsB,GACrC,sBAAsB,CA8BxB;AAED,wBAAgB,4BAA4B,CACxC,eAAe,EAAE,sBAAsB,EACvC,oBAAoB,GAAE,sBAAsB,EAAO,GACpD,OAAO,CAIT;AAED,wBAAgB,2BAA2B,CACvC,eAAe,EAAE,sBAAsB,EACvC,oBAAoB,GAAE,sBAAsB,EAAO,GACpD,sBAAsB,GAAG,SAAS,CAIpC;AAED,wBAAgB,wCAAwC,CACpD,GAAG,EAAE,UAAU,EACf,oBAAoB,GAAE,sBAAsB,EAAO,GACpD,sBAAsB,CAUxB;AAED,wBAAgB,oCAAoC,CAChD,uBAAuB,EAAE,sBAAsB,EAC/C,wBAAwB,EAAE,sBAAsB,GACjD,OAAO,CA+BT;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,CAAC,sBAAsB,CAAC,GAAG,MAAM,EAAE,CAEzF;AAED,wBAAgB,6BAA6B,CAAC,gBAAgB,EAAE,sBAAsB,EAAE,GAAG,MAAM,EAAE,CAalG;AAED,wBAAgB,4CAA4C,CACxD,gBAAgB,EAAE,sBAAsB,EAAE,GAC3C,MAAM,EAAE,CAOV;AAED,wBAAgB,0CAA0C,CACtD,gBAAgB,EAAE,sBAAsB,EAAE,GAC3C,MAAM,EAAE,CAOV;AAED,MAAM,WAAW,qCAAqC;IAClD,uBAAuB,EAAE,UAAU,EAAE,CAAC;IACtC,oBAAoB,EAAE,OAAO,EAAE,CAAC;IAChC,qBAAqB,EAAE,QAAQ,EAAE,CAAC;IAClC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,aAAa,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC3C,WAAW,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjC,eAAe,EAAE,SAAS,CAAC,mCAAmC,CAAC,CAAC;IAChE,qBAAqB,EAAE,sBAAsB,CAAC;IAC9C,yBAAyB,EAAE,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAC7D,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,oBAAoB,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC;CACrD;AAED,wBAAgB,8BAA8B,CAC1C,eAAe,EAAE,sBAAsB,EACvC,iBAAiB,EAAE,qCAAqC,GACzD,sBAAsB,CAkBxB;AAyMD,wBAAgB,kCAAkC,CAC9C,eAAe,EAAE,iBAAiB,EAClC,iBAAiB,EAAE,qCAAqC,GACzD,iBAAiB,CAenB;AAED,wBAAgB,qCAAqC,CACjD,eAAe,EAAE,oBAAoB,EACrC,iBAAiB,EAAE,qCAAqC,GACzD,oBAAoB,CAwCtB"}
@@ -65,9 +65,9 @@ export function extractDisplayFormIdentifiers(drillDefinitions) {
65
65
  .flatMap((drillItem) => {
66
66
  if (isDrillToCustomUrl(drillItem)) {
67
67
  const params = getAttributeIdentifiersPlaceholdersFromUrl(drillItem.target.url);
68
- // normalize ref take the value from state ...
69
- // md object has to be identifier
70
- return params.map((param) => idRef(param.identifier, "displayForm"));
68
+ // the placeholder's own ref already names the object by identifier and carries its
69
+ // type, which a computed attribute needs to resolve as anything other than a label
70
+ return params.map((param) => param.ref);
71
71
  }
72
72
  else {
73
73
  return [drillItem.target.displayForm, drillItem.target.hyperlinkDisplayForm];
@@ -77,17 +77,13 @@ export function extractDisplayFormIdentifiers(drillDefinitions) {
77
77
  export function extractDashboardFilterDisplayFormIdentifiers(drillDefinitions) {
78
78
  return drillDefinitions.filter(isDrillToCustomUrl).flatMap((drillItem) => {
79
79
  const dashboardAttributeFilterPlaceholdersFromUrl = getDashboardAttributeFilterPlaceholdersFromUrl(drillItem.target.url);
80
- // normalize ref take the value from state ...
81
- // md object has to be identifier
82
- return dashboardAttributeFilterPlaceholdersFromUrl.map((param) => idRef(param.identifier, "displayForm"));
80
+ return dashboardAttributeFilterPlaceholdersFromUrl.map((param) => param.ref);
83
81
  });
84
82
  }
85
83
  export function extractInsightFilterDisplayFormIdentifiers(drillDefinitions) {
86
84
  return drillDefinitions.filter(isDrillToCustomUrl).flatMap((drillItem) => {
87
85
  const insightAttributeFilterPlaceholders = getInsightAttributeFilterPlaceholdersFromUrl(drillItem.target.url);
88
- // normalize ref take the value from state ...
89
- // md object has to be identifier
90
- return insightAttributeFilterPlaceholders.map((param) => idRef(param.identifier, "displayForm"));
86
+ return insightAttributeFilterPlaceholders.map((param) => param.ref);
91
87
  });
92
88
  }
93
89
  export function validateInsightDrillDefinition(drillDefinition, validationContext) {
@@ -29,11 +29,11 @@ export const useDashboardAsyncRender = (id) => {
29
29
  const resolveDashboardAsyncRender = useDispatchDashboardCommand(resolveAsyncRender);
30
30
  const onRequestAsyncRender = useCallback(() => {
31
31
  requestDashboardAsyncRender(id);
32
- // eslint-disable-next-line react-hooks/exhaustive-deps
32
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
33
33
  }, [id]);
34
34
  const onResolveAsyncRender = useCallback(() => {
35
35
  resolveDashboardAsyncRender(id);
36
- // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
37
37
  }, [id]);
38
38
  return {
39
39
  onRequestAsyncRender,
@@ -54,6 +54,6 @@ export const useDashboardCommand = (commandCreator, eventHandlers, onBeforeRun)
54
54
  }
55
55
  onBeforeRun?.(command);
56
56
  dispatch(command);
57
- // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
58
58
  }, []);
59
59
  };
@@ -67,7 +67,7 @@ export const useDashboardQueryProcessing = ({ queryCreator, onSuccess, onError,
67
67
  }
68
68
  });
69
69
  },
70
- // eslint-disable-next-line react-hooks/exhaustive-deps
70
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
71
71
  [queryCreator, onSuccess, onError, onRejected, onBeforeRun]);
72
72
  // cancel any "in-flight" queries once the parent component is unmounting to prevent react warnings
73
73
  // about updating unmounted components
@@ -28,6 +28,6 @@ export const useDispatchDashboardCommand = (commandCreator) => {
28
28
  const command = commandCreator(...args);
29
29
  dispatch(command);
30
30
  },
31
- // eslint-disable-next-line react-hooks/exhaustive-deps
31
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
32
32
  [commandCreator]);
33
33
  };
@@ -80,7 +80,7 @@ export const useInitializeDashboardStore = (props) => {
80
80
  dashboardStore.store.dispatch(configActions.setIsAiMode(!!props.config?.isAiMode));
81
81
  }
82
82
  }, [dashboardStore, props.config?.isAiMode]);
83
- // eslint-disable-next-line react-hooks/exhaustive-deps
83
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
84
84
  useEffect(() => {
85
85
  if (!shallowEqualObjects(previousInitProps, currentInitProps) || !dashboardStore) {
86
86
  if (dashboardStore) {
@@ -63,11 +63,11 @@ function useWidgetFiltersImpl(widget, insight) {
63
63
  runFiltersQuery(widget.ref, insight);
64
64
  }
65
65
  },
66
- // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
67
67
  [
68
- // eslint-disable-next-line react-hooks/exhaustive-deps
68
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
69
69
  safeSerializeObjRef(widget?.ref),
70
- // eslint-disable-next-line react-hooks/exhaustive-deps
70
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
71
71
  fullFiltersDigest(nonIgnoredFilters),
72
72
  insight,
73
73
  nonIgnoredFiltersStatus,
@@ -152,13 +152,13 @@ function useNonIgnoredFilters(widget) {
152
152
  // force ignore the insight -> this way we get only the dashboard level filters even for InsightWidgets
153
153
  run(widget.ref, null);
154
154
  }
155
- // eslint-disable-next-line react-hooks/exhaustive-deps
155
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
156
156
  }, [
157
- // eslint-disable-next-line react-hooks/exhaustive-deps
157
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
158
158
  safeSerializeObjRef(widget?.ref),
159
- // eslint-disable-next-line react-hooks/exhaustive-deps
159
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
160
160
  stringify(widget?.ignoreDashboardFilters),
161
- // eslint-disable-next-line react-hooks/exhaustive-deps
161
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
162
162
  filtersDigest(usedFilters, widgetIgnoresDateFilter, isInEditMode),
163
163
  ]);
164
164
  const nonIgnoredFilters = useMemo(() => usedFilters.filter((filter) => {
@@ -22,12 +22,30 @@ export declare const selectInsights: (state: DashboardState) => IInsight[];
22
22
  * @alpha
23
23
  */
24
24
  export declare const selectInsightRefs: DashboardSelector<ObjRef[]>;
25
+ /**
26
+ * Selects refs of insights referenced by dashboard state (widgets, visualization switcher visualizations, and drills).
27
+ *
28
+ * @internal
29
+ */
30
+ export declare const selectDashboardInsightRefs: DashboardSelector<ObjRef[]>;
25
31
  /**
26
32
  * Selects all insights and returns them in a mapping of obj ref to the insight object.
27
33
  *
28
34
  * @alpha
29
35
  */
30
36
  export declare const selectInsightsMap: DashboardSelector<ObjRefMap<IInsight>>;
37
+ /**
38
+ * Selects insights referenced by dashboard state (widgets, visualization switcher visualizations, and drills).
39
+ *
40
+ * @internal
41
+ */
42
+ export declare const selectInsightsUsedOnDashboard: DashboardSelector<IInsight[]>;
43
+ /**
44
+ * Selects draft insights referenced by dashboard state (widgets, visualization switcher visualizations, and drills).
45
+ *
46
+ * @internal
47
+ */
48
+ export declare const selectDraftInsightsUsedOnDashboard: DashboardSelector<IInsight[]>;
31
49
  /**
32
50
  * Selects insight used on a dashboard by its ref.
33
51
  *
@@ -1 +1 @@
1
- {"version":3,"file":"insightsSelectors.d.ts","sourceRoot":"","sources":["../../../../src/model/store/insights/insightsSelectors.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiC,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC1G,OAAO,EAEH,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAEvB,KAAK,MAAM,EAYd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,yCAAyC,CAAC;AAWxF,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAM1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,uCAA4B,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,EAAE,CAExD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAMpE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,iBAAiB,CAAC,QAAQ,GAAG,SAAS,CAK9F,CAAC;AAEP;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,iBAAiB,CAAC,QAAQ,GAAG,SAAS,CAMpG,CAAC;AA6SP;;;;;GAKG;AACH,eAAO,MAAM,uCAAuC,EAAE,CAClD,GAAG,EAAE,MAAM,GAAG,SAAS,KACtB,iBAAiB,CAAC,yBAAyB,GAAG,SAAS,CAa3D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,EAAE,CAC7C,OAAO,EAAE,kBAAkB,GAAG,SAAS,KACtC,iBAAiB,CAAC,yBAAyB,GAAG,SAAS,CAa3D,CAAC"}
1
+ {"version":3,"file":"insightsSelectors.d.ts","sourceRoot":"","sources":["../../../../src/model/store/insights/insightsSelectors.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiC,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC1G,OAAO,EAEH,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAEvB,KAAK,MAAM,EAad,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,yCAAyC,CAAC;AAWxF,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAM1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,uCAA4B,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,EAAE,CAExD,CAAC;AAQH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,iBAAiB,CAAC,MAAM,EAAE,CAgBlE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAMpE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,iBAAiB,CAAC,QAAQ,EAAE,CAoBvE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,EAAE,iBAAiB,CAAC,QAAQ,EAAE,CAK5E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,iBAAiB,CAAC,QAAQ,GAAG,SAAS,CAK9F,CAAC;AAEP;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,iBAAiB,CAAC,QAAQ,GAAG,SAAS,CAMpG,CAAC;AA6SP;;;;;GAKG;AACH,eAAO,MAAM,uCAAuC,EAAE,CAClD,GAAG,EAAE,MAAM,GAAG,SAAS,KACtB,iBAAiB,CAAC,yBAAyB,GAAG,SAAS,CAa3D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,EAAE,CAC7C,OAAO,EAAE,kBAAkB,GAAG,SAAS,KACtC,iBAAiB,CAAC,yBAAyB,GAAG,SAAS,CAa3D,CAAC"}
@@ -1,12 +1,12 @@
1
1
  // (C) 2021-2026 GoodData Corporation
2
2
  import { createSelector } from "@reduxjs/toolkit";
3
- import { areObjRefsEqual, attributeAlias, attributeDisplayFormRef, attributeLocalId, insightAttributes, insightMeasures, insightRef, measureAlias, measureItem, measureLocalId, measureTitle, } from "@gooddata/sdk-model";
3
+ import { areObjRefsEqual, attributeAlias, attributeDisplayFormRef, attributeLocalId, insightAttributes, insightMeasures, insightRef, isDrillToInsight, measureAlias, measureItem, measureLocalId, measureTitle, } from "@gooddata/sdk-model";
4
4
  import { newInsightMap } from "../../../_staging/metadata/objRefMap.js";
5
5
  import { createMemoizedSelector } from "../_infra/selectors.js";
6
6
  import { selectBackendCapabilities } from "../backendCapabilities/backendCapabilitiesSelectors.js";
7
7
  import { selectCatalogAttributeDisplayForms, selectCatalogAttributesWithComputed, selectCatalogDateDatasets, selectCatalogMeasures, } from "../catalog/catalogSelectors.js";
8
8
  import { selectLocale } from "../config/configSelectors.js";
9
- import { selectWidgetByRef } from "../tabs/layout/layoutSelectors.js";
9
+ import { selectAllTabsInsightWidgetContexts, selectWidgetByRef } from "../tabs/layout/layoutSelectors.js";
10
10
  import { insightsAdapter } from "./insightsEntityAdapter.js";
11
11
  const entitySelectors = insightsAdapter.getSelectors((state) => state.insights);
12
12
  /**
@@ -31,6 +31,28 @@ export const selectInsights = entitySelectors.selectAll;
31
31
  export const selectInsightRefs = createSelector(selectInsights, (insights) => {
32
32
  return insights.map(insightRef);
33
33
  });
34
+ const addUniqueInsightRef = (insightRefs, ref) => {
35
+ if (!insightRefs.some((existingRef) => areObjRefsEqual(existingRef, ref))) {
36
+ insightRefs.push(ref);
37
+ }
38
+ };
39
+ /**
40
+ * Selects refs of insights referenced by dashboard state (widgets, visualization switcher visualizations, and drills).
41
+ *
42
+ * @internal
43
+ */
44
+ export const selectDashboardInsightRefs = createSelector(selectAllTabsInsightWidgetContexts, (contexts) => {
45
+ const insightRefs = [];
46
+ contexts.forEach(({ widget }) => {
47
+ addUniqueInsightRef(insightRefs, widget.insight);
48
+ widget.drills.forEach((drill) => {
49
+ if (isDrillToInsight(drill)) {
50
+ addUniqueInsightRef(insightRefs, drill.target);
51
+ }
52
+ });
53
+ });
54
+ return insightRefs;
55
+ });
34
56
  /**
35
57
  * Selects all insights and returns them in a mapping of obj ref to the insight object.
36
58
  *
@@ -39,6 +61,33 @@ export const selectInsightRefs = createSelector(selectInsights, (insights) => {
39
61
  export const selectInsightsMap = createSelector(selectInsights, selectBackendCapabilities, (insights, capabilities) => {
40
62
  return newInsightMap(insights, capabilities.hasTypeScopedIdentifiers);
41
63
  });
64
+ /**
65
+ * Selects insights referenced by dashboard state (widgets, visualization switcher visualizations, and drills).
66
+ *
67
+ * @internal
68
+ */
69
+ export const selectInsightsUsedOnDashboard = createSelector(selectDashboardInsightRefs, selectInsightsMap, selectInsights, (insightRefs, insightsMap, insights) => {
70
+ return insightRefs
71
+ .map((ref) => {
72
+ return (insightsMap.get(ref) ??
73
+ insights.find((currentInsight) => {
74
+ return currentInsight.insight.ref
75
+ ? areObjRefsEqual(currentInsight.insight.ref, ref)
76
+ : false;
77
+ }));
78
+ })
79
+ .filter((insight) => {
80
+ return Boolean(insight);
81
+ });
82
+ });
83
+ /**
84
+ * Selects draft insights referenced by dashboard state (widgets, visualization switcher visualizations, and drills).
85
+ *
86
+ * @internal
87
+ */
88
+ export const selectDraftInsightsUsedOnDashboard = createSelector(selectInsightsUsedOnDashboard, (insights) => {
89
+ return insights.filter((insight) => insight.insight.isDraft);
90
+ });
42
91
  /**
43
92
  * Selects insight used on a dashboard by its ref.
44
93
  *