@gooddata/sdk-ui-dashboard 11.62.0-alpha.1 → 11.62.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/NOTICE +40 -618
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/_staging/dashboard/dashboardFilterContext.d.ts.map +1 -1
  5. package/esm/_staging/dashboard/dashboardFilterContext.js +4 -2
  6. package/esm/_staging/dashboard/dashboardFilterContextValidation.js +1 -1
  7. package/esm/index.d.ts +5 -3
  8. package/esm/index.d.ts.map +1 -1
  9. package/esm/index.js +1 -1
  10. package/esm/kdaDialog/composition/KdaAttributesDropdown.d.ts +2 -1
  11. package/esm/kdaDialog/composition/KdaAttributesDropdown.d.ts.map +1 -1
  12. package/esm/kdaDialog/composition/KdaAttributesDropdown.js +4 -5
  13. package/esm/kdaDialog/composition/KeyDriversFooter.d.ts.map +1 -1
  14. package/esm/kdaDialog/composition/KeyDriversFooter.js +12 -4
  15. package/esm/model/commandHandlers/dashboard/common/filterViews.d.ts +3 -2
  16. package/esm/model/commandHandlers/dashboard/common/filterViews.d.ts.map +1 -1
  17. package/esm/model/commandHandlers/dashboard/common/filterViews.js +12 -6
  18. package/esm/model/commandHandlers/dashboard/common/stateInitializers.d.ts.map +1 -1
  19. package/esm/model/commandHandlers/dashboard/common/stateInitializers.js +5 -6
  20. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.d.ts.map +1 -1
  21. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.js +1 -1
  22. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadUnavailableReferences.d.ts.map +1 -1
  23. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadUnavailableReferences.js +2 -0
  24. package/esm/model/commandHandlers/dashboard/resetDashboardHandler.d.ts.map +1 -1
  25. package/esm/model/commandHandlers/dashboard/resetDashboardHandler.js +3 -1
  26. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.d.ts.map +1 -1
  27. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.js +27 -10
  28. package/esm/model/commandHandlers/drill/drillToDashboardHandler.d.ts.map +1 -1
  29. package/esm/model/commandHandlers/drill/drillToDashboardHandler.js +4 -1
  30. package/esm/model/commandHandlers/drill/keyDriverAnalysisHandler.d.ts.map +1 -1
  31. package/esm/model/commandHandlers/drill/keyDriverAnalysisHandler.js +5 -3
  32. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.d.ts +21 -1
  33. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.d.ts.map +1 -1
  34. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.js +56 -54
  35. package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.d.ts.map +1 -1
  36. package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.js +17 -4
  37. package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.d.ts.map +1 -1
  38. package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.js +6 -1
  39. package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.d.ts.map +1 -1
  40. package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.js +188 -70
  41. package/esm/model/commandHandlers/filterContext/common.d.ts +14 -2
  42. package/esm/model/commandHandlers/filterContext/common.d.ts.map +1 -1
  43. package/esm/model/commandHandlers/filterContext/common.js +43 -6
  44. package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.d.ts.map +1 -1
  45. package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.js +13 -3
  46. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.d.ts.map +1 -1
  47. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.js +11 -2
  48. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.d.ts.map +1 -1
  49. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.js +3 -0
  50. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts +10 -2
  51. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts.map +1 -1
  52. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.js +20 -3
  53. package/esm/model/commandHandlers/scheduledEmail/initializeAutomationsHandler.d.ts.map +1 -1
  54. package/esm/model/commandHandlers/scheduledEmail/initializeAutomationsHandler.js +21 -4
  55. package/esm/model/commandHandlers/tabs/createDashboardTabHandler.d.ts.map +1 -1
  56. package/esm/model/commandHandlers/tabs/createDashboardTabHandler.js +27 -3
  57. package/esm/model/commands/filters.d.ts +16 -1
  58. package/esm/model/commands/filters.d.ts.map +1 -1
  59. package/esm/model/commands/filters.js +4 -3
  60. package/esm/model/commands/parameters.d.ts +4 -3
  61. package/esm/model/commands/parameters.d.ts.map +1 -1
  62. package/esm/model/commands/parameters.js +3 -2
  63. package/esm/model/events/dashboard.d.ts +17 -1
  64. package/esm/model/events/dashboard.d.ts.map +1 -1
  65. package/esm/model/events/dashboard.js +2 -1
  66. package/esm/model/store/drill/drillSelectors.d.ts +6 -0
  67. package/esm/model/store/drill/drillSelectors.d.ts.map +1 -1
  68. package/esm/model/store/drill/drillSelectors.js +9 -0
  69. package/esm/model/store/filtering/dashboardFilterSelectors.d.ts +6 -1
  70. package/esm/model/store/filtering/dashboardFilterSelectors.d.ts.map +1 -1
  71. package/esm/model/store/filtering/dashboardFilterSelectors.js +21 -19
  72. package/esm/model/store/filtering/restrictedFilterUtils.d.ts +26 -1
  73. package/esm/model/store/filtering/restrictedFilterUtils.d.ts.map +1 -1
  74. package/esm/model/store/filtering/restrictedFilterUtils.js +74 -6
  75. package/esm/model/store/meta/metaSelectors.d.ts +6 -0
  76. package/esm/model/store/meta/metaSelectors.d.ts.map +1 -1
  77. package/esm/model/store/meta/metaSelectors.js +13 -3
  78. package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts +48 -0
  79. package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts.map +1 -1
  80. package/esm/model/store/tabs/filterContext/filterContextReducers.js +362 -102
  81. package/esm/model/store/tabs/filterContext/filterContextSelectors.d.ts +74 -1
  82. package/esm/model/store/tabs/filterContext/filterContextSelectors.d.ts.map +1 -1
  83. package/esm/model/store/tabs/filterContext/filterContextSelectors.js +27 -21
  84. package/esm/model/store/tabs/filterContext/filterSync.d.ts +101 -0
  85. package/esm/model/store/tabs/filterContext/filterSync.d.ts.map +1 -0
  86. package/esm/model/store/tabs/filterContext/filterSync.js +361 -0
  87. package/esm/model/store/tabs/index.d.ts +2 -0
  88. package/esm/model/store/tabs/index.d.ts.map +1 -1
  89. package/esm/model/store/tabs/parameters/parametersReducers.d.ts +5 -0
  90. package/esm/model/store/tabs/parameters/parametersReducers.d.ts.map +1 -1
  91. package/esm/model/store/tabs/parameters/parametersReducers.js +9 -5
  92. package/esm/model/store/tabs/tabsReducers.d.ts +6 -0
  93. package/esm/model/store/tabs/tabsReducers.d.ts.map +1 -1
  94. package/esm/model/store/tabs/tabsReducers.js +14 -6
  95. package/esm/model/store/tabs/tabsState.d.ts +10 -0
  96. package/esm/model/store/tabs/tabsState.d.ts.map +1 -1
  97. package/esm/model/store/tabs/tabsState.js +20 -0
  98. package/esm/model/store/unavailableObjects/copyBlockingReferences.d.ts +5 -3
  99. package/esm/model/store/unavailableObjects/copyBlockingReferences.d.ts.map +1 -1
  100. package/esm/model/store/unavailableObjects/copyBlockingReferences.js +9 -16
  101. package/esm/model/store/unavailableObjects/unavailableObjectsSelectors.d.ts +0 -16
  102. package/esm/model/store/unavailableObjects/unavailableObjectsSelectors.d.ts.map +1 -1
  103. package/esm/model/store/unavailableObjects/unavailableObjectsSelectors.js +0 -18
  104. package/esm/model/utils/attributeFilterMatching.d.ts +38 -0
  105. package/esm/model/utils/attributeFilterMatching.d.ts.map +1 -0
  106. package/esm/model/utils/attributeFilterMatching.js +110 -0
  107. package/esm/model/utils/attributeFilterSelectionTypeCompatibility.d.ts.map +1 -0
  108. package/esm/presentation/automations/alerting/state/types.d.ts +2 -2
  109. package/esm/presentation/automations/alerting/state/types.d.ts.map +1 -1
  110. package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.d.ts.map +1 -1
  111. package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.js +7 -3
  112. package/esm/presentation/automations/contexts/AutomationsContext.d.ts +6 -2
  113. package/esm/presentation/automations/contexts/AutomationsContext.d.ts.map +1 -1
  114. package/esm/presentation/automations/scheduledEmail/state/types.d.ts +2 -2
  115. package/esm/presentation/automations/scheduledEmail/state/types.d.ts.map +1 -1
  116. package/esm/presentation/automations/scheduledEmail/types.d.ts +2 -2
  117. package/esm/presentation/automations/scheduledEmail/types.d.ts.map +1 -1
  118. package/esm/presentation/automations/shared/automationFilters/automationParameters.d.ts +11 -1
  119. package/esm/presentation/automations/shared/automationFilters/automationParameters.d.ts.map +1 -1
  120. package/esm/presentation/automations/shared/automationFilters/automationParameters.js +2 -0
  121. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts +3 -3
  122. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts.map +1 -1
  123. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.js +3 -13
  124. package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.d.ts +1 -1
  125. package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.d.ts.map +1 -1
  126. package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.js +1 -1
  127. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts.map +1 -1
  128. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.js +1 -1
  129. package/esm/presentation/automations/shared/automationFilters/useAutomationAlertParameters.d.ts +2 -2
  130. package/esm/presentation/automations/shared/automationFilters/useAutomationAlertParameters.d.ts.map +1 -1
  131. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.d.ts +6 -2
  132. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.d.ts.map +1 -1
  133. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.d.ts.map +1 -1
  134. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.js +2 -2
  135. package/esm/presentation/automations/shared/automationFilters/utils.d.ts.map +1 -1
  136. package/esm/presentation/automations/shared/automationFilters/utils.js +8 -0
  137. package/esm/presentation/automations/shared/filters/conversions.d.ts +1 -1
  138. package/esm/presentation/automations/shared/filters/conversions.d.ts.map +1 -1
  139. package/esm/presentation/automations/shared/filters/conversions.js +5 -3
  140. package/esm/presentation/automations/shared/slots/types.d.ts +2 -2
  141. package/esm/presentation/automations/shared/slots/types.d.ts.map +1 -1
  142. package/esm/presentation/dashboardSettingsDialog/useDialogData.js +1 -1
  143. package/esm/presentation/filterBar/attributeFilter/DefaultDashboardAttributeFilter.d.ts.map +1 -1
  144. package/esm/presentation/filterBar/attributeFilter/DefaultDashboardAttributeFilter.js +1 -4
  145. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/AttributesDropdown.d.ts +2 -11
  146. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/AttributesDropdown.d.ts.map +1 -1
  147. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/AttributesDropdown.js +17 -16
  148. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/staticListItems.d.ts +11 -0
  149. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/staticListItems.d.ts.map +1 -0
  150. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/staticListItems.js +7 -0
  151. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/useMetricDropdownItems.d.ts +2 -11
  152. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/useMetricDropdownItems.d.ts.map +1 -1
  153. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/useMetricDropdownItems.js +0 -6
  154. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/useParameterDropdownItems.d.ts +34 -0
  155. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/useParameterDropdownItems.d.ts.map +1 -0
  156. package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/useParameterDropdownItems.js +41 -0
  157. package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useLimitingItemsConfiguration.d.ts.map +1 -1
  158. package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useLimitingItemsConfiguration.js +4 -17
  159. package/esm/presentation/filterBar/attributeFilter/useDependentDateFilters.d.ts.map +1 -1
  160. package/esm/presentation/filterBar/attributeFilter/useDependentDateFilters.js +4 -13
  161. package/esm/presentation/filterBar/attributeFilter/useParentFilters.d.ts.map +1 -1
  162. package/esm/presentation/filterBar/attributeFilter/useParentFilters.js +3 -10
  163. package/esm/presentation/filterBar/filterBar/DefaultDashboardFilterGroup.d.ts.map +1 -1
  164. package/esm/presentation/filterBar/filterBar/DefaultDashboardFilterGroup.js +0 -9
  165. package/esm/presentation/filterBar/filterBar/DefaultFilterBarItem.d.ts.map +1 -1
  166. package/esm/presentation/filterBar/filterBar/DefaultFilterBarItem.js +15 -3
  167. package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.d.ts.map +1 -1
  168. package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.js +4 -0
  169. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +8 -0
  170. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  171. package/esm/presentation/localization/bundles/en-US.localization-bundle.js +8 -0
  172. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/DrillDialogExportDropdown.d.ts.map +1 -1
  173. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/DrillDialogExportDropdown.js +1 -1
  174. package/esm/presentation/widget/insight/configuration/DrillFilters/drillFiltersConfigUtils.d.ts +2 -3
  175. package/esm/presentation/widget/insight/configuration/DrillFilters/drillFiltersConfigUtils.d.ts.map +1 -1
  176. package/esm/presentation/widget/insight/configuration/DrillFilters/drillFiltersConfigUtils.js +29 -133
  177. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapDashboardFilterToOption.d.ts.map +1 -1
  178. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapDashboardFilterToOption.js +1 -1
  179. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapSourceInsightFilterToOption.d.ts.map +1 -1
  180. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapSourceInsightFilterToOption.js +1 -1
  181. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapSourceMeasureFilterToOption.d.ts.map +1 -1
  182. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapSourceMeasureFilterToOption.js +1 -1
  183. package/esm/sdk-ui-dashboard.d.ts +151 -13
  184. package/package.json +23 -23
  185. package/styles/css/drillDialog.css +4 -0
  186. package/styles/css/drillDialog.css.map +1 -1
  187. package/styles/css/main.css +8 -0
  188. package/styles/css/main.css.map +1 -1
  189. package/styles/scss/drillDialog.scss +5 -0
  190. package/esm/model/commandHandlers/dashboard/common/attributeFilterSelectionTypeCompatibility.d.ts.map +0 -1
  191. /package/esm/model/{commandHandlers/dashboard/common → utils}/attributeFilterSelectionTypeCompatibility.d.ts +0 -0
  192. /package/esm/model/{commandHandlers/dashboard/common → utils}/attributeFilterSelectionTypeCompatibility.js +0 -0
@@ -11,7 +11,7 @@ import { DEFAULT_FISCAL_DATE_FILTER_PRESET } from "../../../../_staging/dateFilt
11
11
  import { configHasFiscalPresets } from "../../../../_staging/dateFilterConfig/validation.js";
12
12
  import { getPrivateContext } from "../../../store/_infra/contexts.js";
13
13
  import { drillActions } from "../../../store/drill/index.js";
14
- import { isDashboardFilterRestricted, isDashboardObjectRestricted, } from "../../../store/filtering/restrictedFilterUtils.js";
14
+ import { isDashboardFilterUsingRestrictedObject, isDashboardObjectRestricted, } from "../../../store/filtering/restrictedFilterUtils.js";
15
15
  import { insightsActions } from "../../../store/insights/index.js";
16
16
  import { metaActions } from "../../../store/meta/index.js";
17
17
  import { selectIsNewDashboard } from "../../../store/meta/metaSelectors.js";
@@ -70,7 +70,7 @@ function* processExistingTabFilterContext(ctx, tab, effectiveDateFilterConfig, d
70
70
  const storeUnavailableObjects = yield select(selectUnavailableObjects);
71
71
  const unavailableObjects = unavailableObjectsOverride ?? storeUnavailableObjects;
72
72
  // Resolve display forms for filters
73
- const attributeFilterDisplayForms = yield call(resolveFilterDisplayForms, ctx, migratedFilterContext.filters.filter((filter) => !isDashboardFilterRestricted(filter, unavailableObjects)), displayAsLabels.filter((displayForm) => !isDashboardObjectRestricted(displayForm, "displayForm", unavailableObjects)), displayForms);
73
+ const attributeFilterDisplayForms = yield call(resolveFilterDisplayForms, ctx, migratedFilterContext.filters.filter((filter) => !isDashboardFilterUsingRestrictedObject(filter, unavailableObjects)), displayAsLabels.filter((displayForm) => !isDashboardObjectRestricted(displayForm, "displayForm", unavailableObjects)), displayForms);
74
74
  // Return the complete FilterContextState for this tab
75
75
  return [
76
76
  {
@@ -256,7 +256,7 @@ function* actionsToInitializeOrFillNewDashboard(ctx, settings, dateFilterConfig,
256
256
  const displayAsLabels = getDisplayAsLabels(effectiveAttributeFilterConfigs);
257
257
  const unavailableObjects = yield select(selectUnavailableObjects);
258
258
  // load DFs for both filter refs and displayAsLabels
259
- const attributeFilterDisplayForms = yield call(resolveFilterDisplayForms, ctx, filterContextDefinition.filters.filter((filter) => !isDashboardFilterRestricted(filter, unavailableObjects)), displayAsLabels.filter((displayForm) => !isDashboardObjectRestricted(displayForm, "displayForm", unavailableObjects)), displayForms);
259
+ const attributeFilterDisplayForms = yield call(resolveFilterDisplayForms, ctx, filterContextDefinition.filters.filter((filter) => !isDashboardFilterUsingRestrictedObject(filter, unavailableObjects)), displayAsLabels.filter((displayForm) => !isDashboardObjectRestricted(displayForm, "displayForm", unavailableObjects)), displayForms);
260
260
  /*
261
261
  * NOTE: cannot do without the cast here. The layout in IDashboard is parameterized with IDashboardWidget
262
262
  * which also includes KPI and Insight widget definitions = those without identity. That is however
@@ -278,7 +278,7 @@ function* actionsToInitializeOrFillNewDashboard(ctx, settings, dateFilterConfig,
278
278
  };
279
279
  }
280
280
  const keepOnlyFiltersWithValidRef = (filter, availableDfRefs, validDataSetIds, unavailableObjects) => {
281
- if (isDashboardFilterRestricted(filter, unavailableObjects)) {
281
+ if (isDashboardFilterUsingRestrictedObject(filter, unavailableObjects)) {
282
282
  return true;
283
283
  }
284
284
  if (!isDashboardAttributeFilter(filter)) {
@@ -306,7 +306,7 @@ function* sanitizeFilterContext(ctx, filterContext, dataSets = [], displayForms,
306
306
  const unavailableObjects = unavailableObjectsOverride ?? storeUnavailableObjects;
307
307
  const usedFilterDisplayForms = filterContext.filters
308
308
  .filter(isDashboardAttributeFilter)
309
- .filter((filter) => !isDashboardFilterRestricted(filter, unavailableObjects))
309
+ .filter((filter) => !isDashboardFilterUsingRestrictedObject(filter, unavailableObjects))
310
310
  .map((f) => f.attributeFilter.displayForm);
311
311
  // With enableDashboardPartialRendering on, the unavailableObjects store already knows which of
312
312
  // these display forms are missing (resolved from the filter-context labels), so the lookups
@@ -334,7 +334,6 @@ function* sanitizeFilterContext(ctx, filterContext, dataSets = [], displayForms,
334
334
  const additionalDateFilters = filterContext.filters
335
335
  .filter((filter) => !isDashboardAttributeFilter(filter))
336
336
  .filter(isDashboardDateFilterWithDimension)
337
- .filter((filter) => !isDashboardFilterRestricted(filter, unavailableObjects))
338
337
  .map((filter) => filter.dateFilter.dataSet);
339
338
  // check which are missing and load them
340
339
  const missingDataSets = additionalDateFilters
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/dashboard/initializeDashboardHandler/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,OAAO,EACH,KAAK,UAAU,EAIf,KAAK,sBAAsB,EAW9B,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AA0B1E,OAAO,EACH,KAAK,gBAAgB,EAGxB,MAAM,+BAA+B,CAAC;AAofvC,wBAAiB,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB;;;uIAyB9E;AAkCD,wBAAiB,2BAA2B,CAAC,GAAG,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU;;;8KAOxF;AAED,wBAAiB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,sNAW3D;AAoCD,wBAAiB,0BAA0B,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB,GAAG,YAAY,CAoCzG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/dashboard/initializeDashboardHandler/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,OAAO,EACH,KAAK,UAAU,EAIf,KAAK,sBAAsB,EAW9B,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AA0B1E,OAAO,EACH,KAAK,gBAAgB,EAGxB,MAAM,+BAA+B,CAAC;AAyfvC,wBAAiB,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB;;;uIAyB9E;AAkCD,wBAAiB,2BAA2B,CAAC,GAAG,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU;;;8KAOxF;AAED,wBAAiB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,sNAW3D;AAoCD,wBAAiB,0BAA0B,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB,GAAG,YAAY,CAoCzG"}
@@ -191,7 +191,7 @@ function* loadExistingDashboard(ctx, cmd, dashboardRef) {
191
191
  // FF off => nothing is ever marked unavailable and behavior is unchanged
192
192
  const unavailableReferences = yield call(loadUnavailableReferences, ctx, loadedDashboard, unavailable, Boolean(config.settings?.enableDashboardPartialRendering), !!cmd.payload.persistedDashboard);
193
193
  yield put(unavailableObjectsActions.setUnavailableObjects(unavailableReferences));
194
- const dashboardWithFilterView = applyDefaultFilterView(loadedDashboard, filterViews, config.exportId);
194
+ const dashboardWithFilterView = applyDefaultFilterView(loadedDashboard, filterViews, config.exportId, unavailableReferences);
195
195
  // Resolve active tab: URL's initialTabId takes precedence, otherwise default to first tab
196
196
  // Note: activeTabLocalIdentifier is app state only, NOT persisted to/read from dashboard MD
197
197
  const resolvedActiveTabId = resolveActiveTabId(dashboardWithFilterView.tabs, cmd.payload.initialTabId, undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"loadUnavailableReferences.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/dashboard/initializeDashboardHandler/loadUnavailableReferences.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACR,8BAA8B,EAC9B,gCAAgC,EACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA6BtE;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC1C,uBAAuB,EAAE,OAAO,GACjC,gCAAgC,EAAE,CAEpC;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,gBAAgB,GAAG,gCAAgC,EAAE,CAErG;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC3C,GAAG,EAAE,gBAAgB,EACrB,SAAS,EAAE,UAAU,EACrB,eAAe,EAAE,8BAA8B,EAAE,GAAG,SAAS,EAC7D,uBAAuB,EAAE,OAAO,EAChC,qBAAqB,EAAE,OAAO,GAC/B,OAAO,CAAC,8BAA8B,EAAE,CAAC,CAkB3C"}
1
+ {"version":3,"file":"loadUnavailableReferences.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/dashboard/initializeDashboardHandler/loadUnavailableReferences.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACR,8BAA8B,EAC9B,gCAAgC,EACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA+BtE;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC1C,uBAAuB,EAAE,OAAO,GACjC,gCAAgC,EAAE,CAEpC;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,gBAAgB,GAAG,gCAAgC,EAAE,CAErG;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC3C,GAAG,EAAE,gBAAgB,EACrB,SAAS,EAAE,UAAU,EACrB,eAAe,EAAE,8BAA8B,EAAE,GAAG,SAAS,EAC7D,uBAAuB,EAAE,OAAO,EAChC,qBAAqB,EAAE,OAAO,GAC/B,OAAO,CAAC,8BAA8B,EAAE,CAAC,CAkB3C"}
@@ -7,6 +7,7 @@ const ALL_TYPES = [
7
7
  "analyticalDashboard",
8
8
  "measure",
9
9
  "fact",
10
+ "attribute",
10
11
  "computedAttribute",
11
12
  ];
12
13
  const ENRICHED_TYPES = [
@@ -14,6 +15,7 @@ const ENRICHED_TYPES = [
14
15
  "analyticalDashboard",
15
16
  "measure",
16
17
  "fact",
18
+ "attribute",
17
19
  "computedAttribute",
18
20
  ];
19
21
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"resetDashboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/dashboard/resetDashboardHandler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAa/C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,KAAK,kBAAkB,EAAqB,MAAM,2BAA2B,CAAC;AAevF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAWnE,wBAAiB,qBAAqB,CAClC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,eAAe,GACrB,YAAY,CAAC,kBAAkB,CAAC,CAOlC;AAED,wBAAiB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,eAAe;;;;;;;;;;;;;;;GASjF"}
1
+ {"version":3,"file":"resetDashboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/dashboard/resetDashboardHandler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAa/C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,KAAK,kBAAkB,EAAqB,MAAM,2BAA2B,CAAC;AAgBvF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAWnE,wBAAiB,qBAAqB,CAClC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,eAAe,GACrB,YAAY,CAAC,kBAAkB,CAAC,CAOlC;AAED,wBAAiB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,eAAe;;;;;;;;;;;;;;;GASjF"}
@@ -11,6 +11,7 @@ import { selectFilterViews } from "../../store/filterViews/filterViewsReducersSe
11
11
  import { selectPersistedDashboard } from "../../store/meta/metaSelectors.js";
12
12
  import { selectActiveTabLocalIdentifier, selectTabs } from "../../store/tabs/tabsSelectors.js";
13
13
  import { DEFAULT_TAB_ID } from "../../store/tabs/tabsState.js";
14
+ import { selectUnavailableObjects } from "../../store/unavailableObjects/unavailableObjectsSelectors.js";
14
15
  import { resolveInsights } from "../../utils/insightResolver.js";
15
16
  import { applyDefaultFilterView } from "./common/filterViews.js";
16
17
  import { insightReferencesFromDashboard } from "./common/insightReferences.js";
@@ -111,7 +112,8 @@ function* resetDashboardFromPersisted(ctx) {
111
112
  // end of ad-hoc migration content
112
113
  const settings = yield select(selectSettings);
113
114
  const filterViews = yield select(selectFilterViews);
114
- const dashboardWithUpdatedFilterContext = applyDefaultFilterView(persistedDashboard, filterViews, ctx.config?.exportId);
115
+ const unavailableObjects = yield select(selectUnavailableObjects);
116
+ const dashboardWithUpdatedFilterContext = applyDefaultFilterView(persistedDashboard, filterViews, ctx.config?.exportId, unavailableObjects);
115
117
  const insightRefsFromWidgets = insightReferencesFromDashboard(dashboardWithUpdatedFilterContext);
116
118
  const uniqueInsightRefsFromWidgets = uniqWith(insightRefsFromWidgets, areObjRefsEqual);
117
119
  const resolvedInsights = yield call(resolveInsights, ctx, uniqueInsightRefsFromWidgets);
@@ -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,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;AA2L1E,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;AAsUD,wBAAiB,oBAAoB,CACjC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,cAAc,GACpB,YAAY,CAAC,cAAc,GAAG,SAAS,CAAC,CAsG1C"}
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,EAYxB,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;AA4M1E,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;AAwUD,wBAAiB,oBAAoB,CACjC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,cAAc,GACpB,YAAY,CAAC,cAAc,GAAG,SAAS,CAAC,CA2G1C"}
@@ -3,7 +3,7 @@ import { batchActions } from "redux-batched-actions";
3
3
  import { all, 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 { areObjRefsEqual, insightRef, isTempFilterContext, } from "@gooddata/sdk-model";
6
+ import { areObjRefsEqual, insightRef, isIdentifierRef, 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";
@@ -14,7 +14,7 @@ import { dashboardSaved } from "../../events/dashboard.js";
14
14
  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
- import { selectLocale } from "../../store/config/configSelectors.js";
17
+ import { selectIsAiMode, selectLocale } from "../../store/config/configSelectors.js";
18
18
  import { insightsActions } from "../../store/insights/index.js";
19
19
  import { selectDraftInsightsUsedOnDashboard, selectInsights, } from "../../store/insights/insightsSelectors.js";
20
20
  import { listedDashboardsActions } from "../../store/listedDashboards/index.js";
@@ -40,6 +40,7 @@ import { changeRenderModeHandler } from "../renderMode/changeRenderModeHandler.j
40
40
  import { switchDashboardTabHandler } from "../tabs/switchDashboardTabHandler.js";
41
41
  import { dashboardWithDrillReferences } from "./dashboardDrillReferences.js";
42
42
  function* persistDraftInsights(ctx, cmd, insights) {
43
+ const savedInsights = [];
43
44
  for (const draftInsight of insights) {
44
45
  const persistedInsight = yield call(async () => {
45
46
  return ctx.backend.workspace(ctx.workspace).insights().createInsight(draftInsight, false);
@@ -72,7 +73,19 @@ function* persistDraftInsights(ctx, cmd, insights) {
72
73
  }));
73
74
  }
74
75
  yield put(insightsActions.setInsights(updatedInsights));
76
+ const originalInsightRef = insightRef(draftInsight);
77
+ const savedInsightRef = insightRef(persistedInsight);
78
+ const originalInsightId = isIdentifierRef(originalInsightRef)
79
+ ? originalInsightRef.identifier
80
+ : draftInsight.insight.identifier;
81
+ const savedInsightId = isIdentifierRef(savedInsightRef)
82
+ ? savedInsightRef.identifier
83
+ : persistedInsight.insight.identifier;
84
+ if (originalInsightId && savedInsightId) {
85
+ savedInsights.push({ originalInsightId, savedInsightId });
86
+ }
75
87
  }
88
+ return savedInsights;
76
89
  }
77
90
  async function draftInsightExistsOnBackend(ctx, draftInsight) {
78
91
  const ref = insightRef(draftInsight);
@@ -128,7 +141,7 @@ function saveDashboard(ctx, saveCtx) {
128
141
  return ctx.backend
129
142
  .workspace(ctx.workspace)
130
143
  .dashboards()
131
- .createDashboard(dashboardToSave, !ctx.config?.isAiMode)
144
+ .createDashboard(dashboardToSave, !saveCtx.isAiMode)
132
145
  .then((dashboard) => ({ dashboard, created: true }));
133
146
  }
134
147
  throw error;
@@ -246,7 +259,7 @@ function resolveProcessedTabs(tabs, rootFilterContext, layout, dateFilterConfig,
246
259
  * capability, this code should use either the selectBasicLayout (that strips any custom widgets) or
247
260
  * selectLayout (that keeps custom widgets).
248
261
  */
249
- function* createDashboardSaveContext(cmd, isNewDashboard) {
262
+ function* createDashboardSaveContext(cmd, isNewDashboard, isAiMode) {
250
263
  const persistedDashboard = yield select(selectPersistedDashboard);
251
264
  const dashboardDescriptor = yield select(selectDashboardDescriptor);
252
265
  const tabs = yield select(selectTabs);
@@ -324,6 +337,7 @@ function* createDashboardSaveContext(cmd, isNewDashboard) {
324
337
  const insights = yield select(selectInsights);
325
338
  return {
326
339
  cmd,
340
+ isAiMode,
327
341
  persistedDashboard,
328
342
  dashboardFromState,
329
343
  dashboardToSave: getDashboardWithSharing(dashboardWithDrillReferences(dashboardToSave, insights), capabilities.supportsAccessControl, isNewDashboard),
@@ -431,13 +445,13 @@ export function* saveDashboardHandler(ctx, cmd) {
431
445
  if (isInsightNotSavedDialogOpen) {
432
446
  yield put(uiActions.closeInsightNotSavedDialog());
433
447
  }
434
- if (shouldPersistDraftInsights && draftInsightsToPersist.length > 0) {
435
- yield call(persistDraftInsights, ctx, cmd, draftInsightsToPersist);
436
- }
448
+ const savedInsights = shouldPersistDraftInsights && draftInsightsToPersist.length > 0
449
+ ? yield call(persistDraftInsights, ctx, cmd, draftInsightsToPersist)
450
+ : [];
437
451
  const persistedDashboard = yield select(selectPersistedDashboard);
438
452
  const isNewDashboard = persistedDashboard === undefined;
439
- const isAiBuilder = ctx.config?.isAiMode;
440
- const saveCtx = yield call(createDashboardSaveContext, cmd, isNewDashboard);
453
+ const isAiBuilder = yield select(selectIsAiMode);
454
+ const saveCtx = yield call(createDashboardSaveContext, cmd, isNewDashboard, isAiBuilder);
441
455
  let result;
442
456
  if (isAiBuilder) {
443
457
  result = yield call(save, ctx, saveCtx, saveDashboard, "@@GDC.DASH.SAVE_BUILDED");
@@ -470,7 +484,10 @@ export function* saveDashboardHandler(ctx, cmd) {
470
484
  yield dispatchDashboardEvent(switchedEvent);
471
485
  }
472
486
  yield put(savingActions.setSavingSuccess());
473
- return dashboardSaved(ctx, dashboard, created, cmd.correlationId);
487
+ return dashboardSaved(ctx, dashboard, created, cmd.correlationId, {
488
+ ...(isAiBuilder ? { originalDashboardId: saveCtx.dashboardFromState.identifier } : {}),
489
+ ...(savedInsights.length > 0 ? { savedInsights } : {}),
490
+ });
474
491
  }
475
492
  catch (e) {
476
493
  yield put(savingActions.setSavingError(e));
@@ -1 +1 @@
1
- {"version":3,"file":"drillToDashboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/drill/drillToDashboardHandler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAiC/C,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EACH,KAAK,kCAAkC,EAG1C,MAAM,uBAAuB,CAAC;AAkB/B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAWnE,wBAAiB,uBAAuB,CACpC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,iBAAiB,GACvB,YAAY,CAAC,kCAAkC,CAAC,CA+HlD"}
1
+ {"version":3,"file":"drillToDashboardHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/drill/drillToDashboardHandler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAiC/C,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EACH,KAAK,kCAAkC,EAG1C,MAAM,uBAAuB,CAAC;AAmB/B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAWnE,wBAAiB,uBAAuB,CACpC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,iBAAiB,GACvB,YAAY,CAAC,kCAAkC,CAAC,CAoIlD"}
@@ -8,6 +8,7 @@ import { drillToDashboardRequested, drillToDashboardResolved, } from "../../even
8
8
  import { generateFilterLocalIdentifier } from "../../store/_infra/generators.js";
9
9
  import { selectSupportsMultipleDateFilters } from "../../store/backendCapabilities/backendCapabilitiesSelectors.js";
10
10
  import { selectCatalogDateAttributes } from "../../store/catalog/catalogSelectors.js";
11
+ import { selectRestrictedDashboardFilterLocalIdentifiers } from "../../store/filtering/dashboardFilterSelectors.js";
11
12
  import { selectInsightByRef } from "../../store/insights/insightsSelectors.js";
12
13
  import { selectAttributeFilterConfigsDisplayAsLabelMap, selectAttributeFilterConfigsOverrides, } from "../../store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
13
14
  import { selectFilterContextAttributeFilterItems, selectFilterContextDateFilter, selectFilterContextDraggableFilterItems, selectFilterContextMeasureValueFilters, } from "../../store/tabs/filterContext/filterContextSelectors.js";
@@ -40,7 +41,9 @@ export function* drillToDashboardHandler(ctx, cmd) {
40
41
  const allAttributeFilters = yield select(selectAllAttributeFilters);
41
42
  const allMeasureValueFilters = yield select(selectAllMeasureValueFilters);
42
43
  const allNonDateFilters = [...allAttributeFilters, ...allMeasureValueFilters];
43
- const dashboardFiltersToResolve = includeOtherDateFilters ? allDraggableFilters : allNonDateFilters;
44
+ const restrictedLocalIdentifiers = yield select(selectRestrictedDashboardFilterLocalIdentifiers);
45
+ // a restricted filter is applied nowhere, so the target dashboard does not get it either
46
+ const dashboardFiltersToResolve = (includeOtherDateFilters ? allDraggableFilters : allNonDateFilters).filter((filter) => !restrictedLocalIdentifiers.has(dashboardFilterLocalIdentifier(filter) ?? ""));
44
47
  const widgetAwareFilters = isDrillingToSelf
45
48
  ? []
46
49
  : yield call(getWidgetAwareDashboardFilters, ctx, widget, dashboardFiltersToResolve);
@@ -1 +1 @@
1
- {"version":3,"file":"keyDriverAnalysisHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/drill/keyDriverAnalysisHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAc/C,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EACH,KAAK,mCAAmC,EAG3C,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAKnE,wBAAiB,wBAAwB,CACrC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,kBAAkB,GACxB,YAAY,CAAC,mCAAmC,CAAC,CA0HnD"}
1
+ {"version":3,"file":"keyDriverAnalysisHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/drill/keyDriverAnalysisHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAc/C,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EACH,KAAK,mCAAmC,EAG3C,MAAM,uBAAuB,CAAC;AAW/B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAKnE,wBAAiB,wBAAwB,CACrC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,kBAAkB,GACxB,YAAY,CAAC,mCAAmC,CAAC,CA4HnD"}
@@ -5,7 +5,8 @@ import { keyDriverAnalysisRequested, keyDriverAnalysisResolved, } from "../../ev
5
5
  import { invalidArgumentsProvided } from "../../events/general.js";
6
6
  import { generateFilterLocalIdentifier } from "../../store/_infra/generators.js";
7
7
  import { selectCatalogDateAttributes } from "../../store/catalog/catalogSelectors.js";
8
- import { isDashboardFilterRestricted } from "../../store/filtering/restrictedFilterUtils.js";
8
+ import { selectRestrictedDashboardFilterLocalIdentifiers } from "../../store/filtering/dashboardFilterSelectors.js";
9
+ import { isDashboardFilterCopyRestricted, isDashboardFilterUsingRestrictedObject, } from "../../store/filtering/restrictedFilterUtils.js";
9
10
  import { selectWidgetByRef } from "../../store/tabs/layout/layoutSelectors.js";
10
11
  import { selectUnavailableObjects } from "../../store/unavailableObjects/unavailableObjectsSelectors.js";
11
12
  import { getAttributeFilters, removeIgnoredWidgetFilters } from "../../utils/widgetFilters.js";
@@ -55,14 +56,15 @@ export function* keyDriverAnalysisHandler(ctx, cmd) {
55
56
  });
56
57
  const widget = yield select(selectWidgetByRef(drillEvent.widgetRef));
57
58
  const unavailableObjects = yield select(selectUnavailableObjects);
58
- const executableFilters = availableFilters.filter((filter) => !isDashboardFilterRestricted(filter, unavailableObjects));
59
+ const restrictedLocalIdentifiers = yield select(selectRestrictedDashboardFilterLocalIdentifiers);
60
+ const executableFilters = availableFilters.filter((filter) => !isDashboardFilterCopyRestricted(filter, restrictedLocalIdentifiers, unavailableObjects));
59
61
  const widgetFilters = removeIgnoredWidgetFilters(executableFilters, widget);
60
62
  // KDA defines its own date range — drop date filters. Keep attribute and measure value
61
63
  // filters so the change analysis respects the rest of the dashboard filter context.
62
64
  const attributeFilters = getAttributeFilters(widgetFilters);
63
65
  const measureValueFilters = widgetFilters.filter(isDashboardMeasureValueFilter);
64
66
  // the drill intersection brings its own attribute filters, which the check above did not see
65
- const filters = mergeFilters(intersectionFilters, attributeFilters).filter((filter) => !isDashboardFilterRestricted(filter, unavailableObjects));
67
+ const filters = mergeFilters(intersectionFilters, attributeFilters).filter((filter) => !isDashboardFilterUsingRestrictedObject(filter, unavailableObjects));
66
68
  return keyDriverAnalysisResolved(ctx, cmd.payload.drillDefinition, cmd.payload.drillEvent, {
67
69
  metric: {
68
70
  ...metric,
@@ -1,7 +1,9 @@
1
1
  import { type SagaIterator } from "redux-saga";
2
- import { type DashboardTextAttributeFilter, type IAttributeDisplayFormMetadataObject, type IDrillToCustomUrl as IDrillToCustomUrlModel, type MeasureValueFilterCondition, type ObjRef, type TextAttributeFilter } from "@gooddata/sdk-model";
2
+ import { type DashboardAttributeFilterItem, type DashboardTextAttributeFilter, type IAttributeDisplayFormMetadataObject, type IDashboardAttributeFilter, type IDrillToCustomUrl as IDrillToCustomUrlModel, type MeasureValueFilterCondition, type ObjRef, type TextAttributeFilter } from "@gooddata/sdk-model";
3
3
  import { type IDrillEvent, type IDrillEventIntersectionElement } from "@gooddata/sdk-ui";
4
4
  import { type IDrillToCustomUrl } from "../../commands/drill.js";
5
+ import { selectAllCatalogDisplayFormsMap } from "../../store/catalog/catalogSelectors.js";
6
+ import { selectAttributeFilterConfigsOverrides } from "../../store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
5
7
  import { type DashboardContext } from "../../types/commonTypes.js";
6
8
  interface IDrillToUrlPlaceholderReplacement {
7
9
  toBeReplaced: string;
@@ -24,6 +26,24 @@ export declare function splitDFToLoadingAndMapping(attributesDisplayForms: IAttr
24
26
  }>;
25
27
  export declare function loadAttributeElementsForDrillIntersection(drillIntersectionElements: IDrillEventIntersectionElement[], attributesDisplayForms: IAttributeDisplayFormMetadataObject[], ctx: DashboardContext): SagaIterator<IDrillToUrlElement[]>;
26
28
  export declare function getAttributeIdentifiersReplacements(url: string, drillIntersectionElements: IDrillEventIntersectionElement[], ctx: DashboardContext): SagaIterator<IDrillToUrlPlaceholderReplacement[]>;
29
+ /**
30
+ * The filter a dashboard attribute filter placeholder names. A readable filter wins: a text filter with
31
+ * the placeholder's label, then a list filter with it, then a list filter displayed by it. A restricted
32
+ * filter matched in any of these ways is applied nowhere, so it filters nothing.
33
+ */
34
+ export type DashboardAttributeFilterPlaceholderMatch = {
35
+ type: "text";
36
+ filter: DashboardTextAttributeFilter;
37
+ } | {
38
+ type: "label";
39
+ filter: IDashboardAttributeFilter;
40
+ } | {
41
+ type: "displayAsLabel";
42
+ filter: IDashboardAttributeFilter;
43
+ } | {
44
+ type: "restricted";
45
+ };
46
+ export declare function findDashboardAttributeFilterPlaceholderMatch(ref: ObjRef, attributeFilters: DashboardAttributeFilterItem[], restrictedLocalIdentifiers: ReadonlySet<string>, catalogDisplayForms: ReturnType<typeof selectAllCatalogDisplayFormsMap>, attributeFilterConfigs: ReturnType<typeof selectAttributeFilterConfigsOverrides>): DashboardAttributeFilterPlaceholderMatch | undefined;
27
47
  export declare function getDashboardAttributeFilterReplacements(url: string, ctx: DashboardContext): SagaIterator<IDrillToUrlPlaceholderReplacement[]>;
28
48
  export declare function getDashboardMeasureValueFilterReplacements(url: string): SagaIterator<IDrillToUrlPlaceholderReplacement[]>;
29
49
  export declare function getInsightMeasureValueFilterReplacements(url: string, widgetRef: ObjRef): 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,12 +2,13 @@
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, insightFilters as insightDefinitionFilters, insightId, isArbitraryAttributeFilter, isAttributeDescriptor, isAttributeElementsByValue, isAttributeFilter, isComparisonCondition, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardTextAttributeFilter, isIdentifierRef, isMeasureValueFilter, isNegativeAttributeFilter, isRangeCondition, isTextAttributeFilter, isUriRef, measureValueFilterConditions, measureValueFilterMeasure, } from "@gooddata/sdk-model";
5
+ import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemLocalIdentifier, dashboardFilterLocalIdentifier, dashboardMeasureValueFilterLocalIdentifier, 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
6
  import { DRILL_TO_URL_PLACEHOLDER, displayFormPlaceholderRef, getAttributeIdentifiersPlaceholdersFromUrl, getDashboardAttributeFilterPlaceholdersFromUrl, getDashboardMeasureValueFilterPlaceholdersFromUrl, getDrillUrlPlaceholderTypes, 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";
10
10
  import { selectEnableMeasureValueFilterKD } from "../../store/config/configSelectors.js";
11
+ import { selectRestrictedDashboardFilterLocalIdentifiers } from "../../store/filtering/dashboardFilterSelectors.js";
11
12
  import { selectInsightByRef } from "../../store/insights/insightsSelectors.js";
12
13
  import { selectDashboardId } from "../../store/meta/metaSelectors.js";
13
14
  import { selectAttributeFilterConfigsOverrides } from "../../store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
@@ -167,55 +168,51 @@ export function* getAttributeIdentifiersReplacements(url, drillIntersectionEleme
167
168
  };
168
169
  });
169
170
  }
170
- function* resolveDashboardAttributeFilterReplacement({ placeholder: toBeReplaced, ref }, attributeFilters, catalogDisplayForms, attributeFilterConfigs, ctx) {
171
- // Check for text filters (arbitrary/match) first — they use different value structures.
172
- const textFilter = attributeFilters.find((filter) => {
173
- if (!isDashboardTextAttributeFilter(filter)) {
174
- return false;
175
- }
171
+ export function findDashboardAttributeFilterPlaceholderMatch(ref, attributeFilters, restrictedLocalIdentifiers, catalogDisplayForms, attributeFilterConfigs) {
172
+ const isReadable = (filter) => !restrictedLocalIdentifiers.has(dashboardFilterLocalIdentifier(filter) ?? "");
173
+ const hasLabel = (filter) => {
176
174
  const df = catalogDisplayForms.get(dashboardAttributeFilterItemDisplayForm(filter));
177
- return df && areObjRefsEqual(displayFormPlaceholderRef(df), ref);
178
- });
179
- if (textFilter && isDashboardTextAttributeFilter(textFilter)) {
180
- const parsedFilter = stringifyTextFilterSelection(textFilter);
181
- const replacement = encodeParameterIfSet(parsedFilter);
182
- return {
183
- toBeReplaced,
184
- replacement: replacement,
185
- };
175
+ return !!df && areObjRefsEqual(displayFormPlaceholderRef(df), ref);
176
+ };
177
+ const isDisplayedByLabel = (filter) => attributeFilterConfigs.some((config) => config.localIdentifier === dashboardAttributeFilterItemLocalIdentifier(filter) &&
178
+ !!config.displayAsLabel &&
179
+ areObjRefsEqual(config.displayAsLabel, ref));
180
+ const textFilter = attributeFilters.find((filter) => isDashboardTextAttributeFilter(filter) && isReadable(filter) && hasLabel(filter));
181
+ if (textFilter) {
182
+ return { type: "text", filter: textFilter };
186
183
  }
187
- // Standard (element-based) attribute filters
188
- const standardFilters = attributeFilters.filter(isDashboardAttributeFilter);
189
- let usedFilter = standardFilters.find((filter) => {
190
- const df = catalogDisplayForms.get(filter.attributeFilter.displayForm);
191
- return df && areObjRefsEqual(displayFormPlaceholderRef(df), ref);
192
- });
193
- let attributeElementsValues = [];
194
- if (usedFilter) {
195
- const elements = usedFilter?.attributeFilter.attributeElements;
196
- attributeElementsValues = isAttributeElementsByValue(elements)
197
- ? elements.values
198
- : (elements?.uris ?? []);
184
+ const labelFilter = attributeFilters.find((filter) => isDashboardAttributeFilter(filter) && isReadable(filter) && hasLabel(filter));
185
+ if (labelFilter) {
186
+ return { type: "label", filter: labelFilter };
199
187
  }
200
- else {
201
- const usedConfig = attributeFilterConfigs.find((config) => {
202
- return config.displayAsLabel && areObjRefsEqual(config.displayAsLabel, ref);
203
- });
204
- usedFilter = standardFilters.find((filter) => {
205
- return filter.attributeFilter.localIdentifier === usedConfig?.localIdentifier;
206
- });
207
- const elements = usedFilter?.attributeFilter.attributeElements;
208
- const primaryElementsValues = elements
209
- ? isAttributeElementsByValue(elements)
210
- ? elements.values
211
- : elements.uris
212
- : [];
213
- attributeElementsValues = yield call(loadSecondaryElementTitles, ref, primaryElementsValues, ctx);
188
+ const displayedFilter = attributeFilters.find((filter) => isDashboardAttributeFilter(filter) && isReadable(filter) && isDisplayedByLabel(filter));
189
+ if (displayedFilter) {
190
+ return { type: "displayAsLabel", filter: displayedFilter };
214
191
  }
215
- const isNegative = usedFilter?.attributeFilter.negativeSelection;
216
- const parsedFilter = usedFilter
217
- ? stringifyAttributeFilterSelection(attributeElementsValues, isNegative)
192
+ return attributeFilters.some((filter) => !isReadable(filter) && (hasLabel(filter) || isDisplayedByLabel(filter)))
193
+ ? { type: "restricted" }
218
194
  : undefined;
195
+ }
196
+ function* resolveDashboardAttributeFilterReplacement({ placeholder: toBeReplaced, ref }, attributeFilters, restrictedLocalIdentifiers, catalogDisplayForms, attributeFilterConfigs, ctx) {
197
+ const match = findDashboardAttributeFilterPlaceholderMatch(ref, attributeFilters, restrictedLocalIdentifiers, catalogDisplayForms, attributeFilterConfigs);
198
+ // a placeholder whose filter is missing from the dashboard stays unresolved, which rejects the drill
199
+ let parsedFilter;
200
+ if (match?.type === "text") {
201
+ parsedFilter = stringifyTextFilterSelection(match.filter);
202
+ }
203
+ else if (match?.type === "label") {
204
+ const elements = match.filter.attributeFilter.attributeElements;
205
+ parsedFilter = stringifyAttributeFilterSelection(isAttributeElementsByValue(elements) ? elements.values : elements.uris, match.filter.attributeFilter.negativeSelection);
206
+ }
207
+ else if (match?.type === "displayAsLabel") {
208
+ const elements = match.filter.attributeFilter.attributeElements;
209
+ const primaryElementsValues = isAttributeElementsByValue(elements) ? elements.values : elements.uris;
210
+ const elementTitles = yield call(loadSecondaryElementTitles, ref, primaryElementsValues, ctx);
211
+ parsedFilter = stringifyAttributeFilterSelection(elementTitles, match.filter.attributeFilter.negativeSelection);
212
+ }
213
+ else if (match?.type === "restricted") {
214
+ parsedFilter = stringifyAttributeFilterSelection([], true);
215
+ }
219
216
  const replacement = encodeParameterIfSet(parsedFilter);
220
217
  return {
221
218
  toBeReplaced,
@@ -228,17 +225,21 @@ export function* getDashboardAttributeFilterReplacements(url, ctx) {
228
225
  return [];
229
226
  }
230
227
  const attributeFilters = yield select(selectFilterContextAttributeFilterItems);
228
+ const restrictedLocalIdentifiers = yield select(selectRestrictedDashboardFilterLocalIdentifiers);
231
229
  const catalogDisplayForms = yield select(selectAllCatalogDisplayFormsMap);
232
230
  const attributeFilterConfigs = yield select(selectAttributeFilterConfigsOverrides);
233
- return yield all(attributeFilterPlaceholders.map((placeholder) => call(resolveDashboardAttributeFilterReplacement, placeholder, attributeFilters, catalogDisplayForms, attributeFilterConfigs, ctx)));
231
+ return yield all(attributeFilterPlaceholders.map((placeholder) => call(resolveDashboardAttributeFilterReplacement, placeholder, attributeFilters, restrictedLocalIdentifiers, catalogDisplayForms, attributeFilterConfigs, ctx)));
234
232
  }
235
- function resolveDashboardMeasureValueFilterReplacement({ placeholder: toBeReplaced, identifier }, measureValueFilters, catalogMeasures) {
236
- const usedFilter = measureValueFilters.find((filter) => {
237
- const measureRef = dashboardFilterObjRef(filter);
238
- return dashboardMeasureValueFilterMatchesIdentifier(measureRef, identifier, catalogMeasures);
239
- });
240
- const parsedFilter = stringifyMeasureValueFilterCondition(usedFilter?.dashboardMeasureValueFilter.conditions);
241
- const replacement = usedFilter ? encodeParameterIfSet(parsedFilter) : undefined;
233
+ function resolveDashboardMeasureValueFilterReplacement({ placeholder: toBeReplaced, identifier }, measureValueFilters, restrictedLocalIdentifiers, catalogMeasures) {
234
+ const isPlaceholderFilter = (filter) => dashboardMeasureValueFilterMatchesIdentifier(filter.dashboardMeasureValueFilter.measure, identifier, catalogMeasures);
235
+ const usedFilter = measureValueFilters.find((filter) => !restrictedLocalIdentifiers.has(dashboardMeasureValueFilterLocalIdentifier(filter)) &&
236
+ isPlaceholderFilter(filter));
237
+ // A restricted filter is applied nowhere, so it filters nothing and resolves as "ALL". A
238
+ // placeholder whose filter is missing from the dashboard stays unresolved, which rejects the drill.
239
+ const parsedFilter = usedFilter || measureValueFilters.some(isPlaceholderFilter)
240
+ ? stringifyMeasureValueFilterCondition(usedFilter?.dashboardMeasureValueFilter.conditions)
241
+ : undefined;
242
+ const replacement = encodeParameterIfSet(parsedFilter);
242
243
  return {
243
244
  toBeReplaced,
244
245
  replacement: replacement,
@@ -250,8 +251,9 @@ export function* getDashboardMeasureValueFilterReplacements(url) {
250
251
  return [];
251
252
  }
252
253
  const measureValueFilters = yield select(selectFilterContextMeasureValueFilters);
254
+ const restrictedLocalIdentifiers = yield select(selectRestrictedDashboardFilterLocalIdentifiers);
253
255
  const catalogMeasures = yield select(selectAllCatalogMeasuresMap);
254
- return measureValueFilterPlaceholders.map((placeholder) => resolveDashboardMeasureValueFilterReplacement(placeholder, measureValueFilters, catalogMeasures));
256
+ return measureValueFilterPlaceholders.map((placeholder) => resolveDashboardMeasureValueFilterReplacement(placeholder, measureValueFilters, restrictedLocalIdentifiers, catalogMeasures));
255
257
  }
256
258
  function resolveInsightMeasureValueFilterReplacement({ placeholder: toBeReplaced, identifier }, measureValueFilters) {
257
259
  const usedFilter = measureValueFilters.find((filter) => {
@@ -1 +1 @@
1
- {"version":3,"file":"changeAttributeFilterSelectionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAiBnF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,wBAAiB,qCAAqC,CAClD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,8BAA8B,GACpC,YAAY,CAAC,IAAI,CAAC,CA4EpB"}
1
+ {"version":3,"file":"changeAttributeFilterSelectionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAmBnF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAStE,wBAAiB,qCAAqC,CAClD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,8BAA8B,GACpC,YAAY,CAAC,IAAI,CAAC,CA4FpB"}
@@ -1,14 +1,15 @@
1
- // (C) 2021-2025 GoodData Corporation
1
+ // (C) 2021-2026 GoodData Corporation
2
2
  import { all, call, put, select } from "redux-saga/effects";
3
3
  import { invariant } from "ts-invariant";
4
4
  import { attributeFilterSelectionChanged } from "../../../events/filters.js";
5
5
  import { invalidArgumentsProvided } from "../../../events/general.js";
6
6
  import { dispatchDashboardEvent } from "../../../store/_infra/eventDispatcher.js";
7
7
  import { selectEnableImmediateAttributeFilterDisplayAsLabelMigration, selectIsApplyFiltersAllAtOnceEnabledAndSet, } from "../../../store/config/configSelectors.js";
8
- import { selectIsCrossFiltering, selectIsFilterFromCrossFilteringByLocalIdentifier, } from "../../../store/drill/drillSelectors.js";
8
+ import { selectCrossFilteringFiltersLocalIdentifiersByTab, selectIsCrossFiltering, selectIsFilterFromCrossFilteringByLocalIdentifier, } from "../../../store/drill/drillSelectors.js";
9
+ import { selectEnablePersistentFiltersAcrossTabs } from "../../../store/meta/metaSelectors.js";
9
10
  import { selectAttributeFilterDescendants, selectFilterContextAttributeFilterByLocalId, } from "../../../store/tabs/filterContext/filterContextSelectors.js";
10
11
  import { tabsActions } from "../../../store/tabs/index.js";
11
- import { dispatchFilterContextChanged, resetCrossFiltering } from "../common.js";
12
+ import { captureFilterContextByTabSnapshot, dispatchFilterContextChanged, dispatchFilterContextChangedForMutatedTabs, resetCrossFiltering, } from "../common.js";
12
13
  export function* changeAttributeFilterSelectionHandler(ctx, cmd) {
13
14
  const { elements, filterLocalId, selectionType, isWorkingSelectionChange, isResultOfMigration, isSelectionInvalid, } = cmd.payload;
14
15
  // validate filterLocalId
@@ -18,6 +19,9 @@ export function* changeAttributeFilterSelectionHandler(ctx, cmd) {
18
19
  }
19
20
  const isApplyAllAtOnceEnabledAndSet = yield select(selectIsApplyFiltersAllAtOnceEnabledAndSet);
20
21
  const enableImmediateAttributeFilterDisplayAsLabelMigration = yield select(selectEnableImmediateAttributeFilterDisplayAsLabelMigration);
22
+ const crossFilteringLocalIdsByTab = yield select(selectCrossFilteringFiltersLocalIdentifiersByTab);
23
+ const enablePersistentFiltersAcrossTabs = yield select(selectEnablePersistentFiltersAcrossTabs);
24
+ const filterContextSnapshot = yield call(captureFilterContextByTabSnapshot);
21
25
  yield put(tabsActions.updateAttributeFilterSelection({
22
26
  elements,
23
27
  filterLocalId,
@@ -26,6 +30,8 @@ export function* changeAttributeFilterSelectionHandler(ctx, cmd) {
26
30
  enableImmediateAttributeFilterDisplayAsLabelMigration,
27
31
  isResultOfMigration,
28
32
  isSelectionInvalid,
33
+ crossFilteringLocalIdsByTab,
34
+ enablePersistentFiltersAcrossTabs,
29
35
  }));
30
36
  const changedFilter = yield select(selectFilterContextAttributeFilterByLocalId(cmd.payload.filterLocalId));
31
37
  invariant(changedFilter, "Inconsistent state in attributeFilterChangeSelectionCommandHandler");
@@ -38,6 +44,8 @@ export function* changeAttributeFilterSelectionHandler(ctx, cmd) {
38
44
  },
39
45
  negativeSelection: true,
40
46
  isWorkingSelectionChange: isWorkingSelectionChange && isApplyAllAtOnceEnabledAndSet,
47
+ crossFilteringLocalIdsByTab,
48
+ enablePersistentFiltersAcrossTabs,
41
49
  }))));
42
50
  }
43
51
  const isCrossFiltering = yield select(selectIsCrossFiltering);
@@ -48,5 +56,10 @@ export function* changeAttributeFilterSelectionHandler(ctx, cmd) {
48
56
  yield call(resetCrossFiltering, cmd);
49
57
  }
50
58
  yield dispatchDashboardEvent(attributeFilterSelectionChanged(ctx, changedFilter, cmd.correlationId));
51
- yield call(dispatchFilterContextChanged, ctx, cmd);
59
+ if (enablePersistentFiltersAcrossTabs) {
60
+ yield call(dispatchFilterContextChangedForMutatedTabs, ctx, cmd, filterContextSnapshot);
61
+ }
62
+ else {
63
+ yield call(dispatchFilterContextChanged, ctx, cmd);
64
+ }
52
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"replaceAttributeFilterItemSelectionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAAE,KAAK,mCAAmC,EAAE,MAAM,8BAA8B,CAAC;AAWxF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKtE,wBAAiB,0CAA0C,CACvD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,mCAAmC,GACzC,YAAY,CAAC,IAAI,CAAC,CAoDpB"}
1
+ {"version":3,"file":"replaceAttributeFilterItemSelectionHandler.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAAE,KAAK,mCAAmC,EAAE,MAAM,8BAA8B,CAAC;AAaxF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKtE,wBAAiB,0CAA0C,CACvD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,mCAAmC,GACzC,YAAY,CAAC,IAAI,CAAC,CA0DpB"}
@@ -5,7 +5,8 @@ import { attributeFilterItemSelectionReplaced } from "../../../events/filters.js
5
5
  import { invalidArgumentsProvided } from "../../../events/general.js";
6
6
  import { dispatchDashboardEvent } from "../../../store/_infra/eventDispatcher.js";
7
7
  import { selectIsApplyFiltersAllAtOnceEnabledAndSet } from "../../../store/config/configSelectors.js";
8
- import { selectIsCrossFiltering, selectIsFilterFromCrossFilteringByLocalIdentifier, } from "../../../store/drill/drillSelectors.js";
8
+ import { selectCrossFilteringFiltersLocalIdentifiersByTab, selectIsCrossFiltering, selectIsFilterFromCrossFilteringByLocalIdentifier, } from "../../../store/drill/drillSelectors.js";
9
+ import { selectEnablePersistentFiltersAcrossTabs } from "../../../store/meta/metaSelectors.js";
9
10
  import { selectFilterContextAttributeFilterItemByLocalId } from "../../../store/tabs/filterContext/filterContextSelectors.js";
10
11
  import { tabsActions } from "../../../store/tabs/index.js";
11
12
  import { dispatchFilterContextChanged, resetCrossFiltering } from "../common.js";
@@ -18,11 +19,15 @@ export function* replaceAttributeFilterItemSelectionHandler(ctx, cmd) {
18
19
  throw invalidArgumentsProvided(ctx, cmd, `Filter with filterLocalId ${filterLocalId} not found.`);
19
20
  }
20
21
  const isApplyAllAtOnceEnabledAndSet = yield select(selectIsApplyFiltersAllAtOnceEnabledAndSet);
22
+ const crossFilteringLocalIdsByTab = yield select(selectCrossFilteringFiltersLocalIdentifiersByTab);
23
+ const enablePersistentFiltersAcrossTabs = yield select(selectEnablePersistentFiltersAcrossTabs);
21
24
  yield put(tabsActions.replaceAttributeFilterItem({
22
25
  filterLocalId,
23
26
  filter,
24
27
  isWorkingSelectionChange: isWorkingSelectionChange && isApplyAllAtOnceEnabledAndSet,
25
28
  isSelectionInvalid,
29
+ crossFilteringLocalIdsByTab,
30
+ enablePersistentFiltersAcrossTabs,
26
31
  }));
27
32
  // Ensure the new filter's displayForm is registered in the displayFormsMap.
28
33
  // This is needed for cross-type migration (e.g. text→list) where the new filter's