@gooddata/sdk-ui-dashboard 11.35.0-alpha.5 → 11.35.0-alpha.6

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 (37) hide show
  1. package/NOTICE +8 -8
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/index.d.ts +3 -4
  5. package/esm/index.js +1 -2
  6. package/esm/model/commandHandlers/dashboard/common/parameterHydration.d.ts +11 -2
  7. package/esm/model/commandHandlers/dashboard/common/parameterHydration.js +21 -0
  8. package/esm/model/commandHandlers/dashboard/common/stateInitializers.js +44 -79
  9. package/esm/model/commandHandlers/dashboard/saveAsDashboardHandler.js +10 -5
  10. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.js +11 -7
  11. package/esm/model/store/dashboardStore.d.ts +0 -2
  12. package/esm/model/store/dashboardStore.js +0 -2
  13. package/esm/model/store/meta/metaSelectors.js +4 -3
  14. package/esm/model/store/tabs/index.d.ts +12 -0
  15. package/esm/model/store/tabs/index.js +2 -0
  16. package/esm/model/store/{parameters → tabs/parameters}/parametersReducers.d.ts +3 -7
  17. package/esm/model/store/tabs/parameters/parametersReducers.js +46 -0
  18. package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +72 -0
  19. package/esm/model/store/tabs/parameters/parametersSelectors.js +228 -0
  20. package/esm/model/store/{parameters → tabs/parameters}/parametersState.d.ts +11 -1
  21. package/esm/model/store/tabs/parameters/parametersState.js +20 -0
  22. package/esm/model/store/tabs/tabsState.d.ts +2 -0
  23. package/esm/model/store/types.d.ts +0 -6
  24. package/esm/presentation/dragAndDrop/draggableParameterFilter/DefaultParameterDraggingComponent.js +1 -1
  25. package/esm/presentation/dragAndDrop/useFilterDeleteDrop.js +2 -2
  26. package/esm/presentation/filterBar/filterBar/DefaultFilterBar.js +1 -1
  27. package/esm/presentation/filterBar/parameterFilter/DashboardParameterFilter.js +3 -3
  28. package/esm/presentation/filterBar/parameterFilter/DashboardParameterPicker.js +3 -3
  29. package/esm/presentation/widget/insight/ViewModeDashboardInsight/Insight/DashboardInsight.js +1 -1
  30. package/esm/sdk-ui-dashboard.d.ts +27 -26
  31. package/package.json +21 -21
  32. package/esm/model/store/parameters/index.d.ts +0 -12
  33. package/esm/model/store/parameters/index.js +0 -14
  34. package/esm/model/store/parameters/parametersReducers.js +0 -36
  35. package/esm/model/store/parameters/parametersSelectors.d.ts +0 -67
  36. package/esm/model/store/parameters/parametersSelectors.js +0 -122
  37. package/esm/model/store/parameters/parametersState.js +0 -4
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-5-4
10
+ Date generated: 2026-5-12
11
11
 
12
- Revision ID: 0c39c460e837a54efedde9d37131feb930e4b8a1
12
+ Revision ID: 52d6a5f81cbc391c8c918fe465fad2be3e3de86f
13
13
 
14
14
  ================================================================================
15
15
  ================================================================================
@@ -376,7 +376,7 @@ Revision ID: 0c39c460e837a54efedde9d37131feb930e4b8a1
376
376
  - bail (2.0.2) [MIT]
377
377
  - balanced-match (2.0.0) [MIT]
378
378
  - base64-js (1.5.1) [MIT]
379
- - baseline-browser-mapping (2.10.27) [Apache-2.0]
379
+ - baseline-browser-mapping (2.10.29) [Apache-2.0]
380
380
  - batch (0.6.1) [MIT]
381
381
  - binary-extensions (2.3.0) [MIT]
382
382
  - bl (4.1.0) [MIT]
@@ -710,7 +710,7 @@ Revision ID: 0c39c460e837a54efedde9d37131feb930e4b8a1
710
710
  - magic-string (0.30.21) [MIT]
711
711
  - make-dir (2.1.0) [MIT]
712
712
  - mapbox-gl (2.15.0) [BSD-3-Clause, MIT]
713
- - maplibre-gl (4.7.1) [MIT, BSD-3-Clause, ISC, 0BSD]
713
+ - maplibre-gl (4.7.1) [MIT, BSD-3-Clause, 0BSD, ISC]
714
714
  - markdown-table (3.0.4) [MIT]
715
715
  - matchmediaquery (0.4.2) [MIT]
716
716
  - math-intrinsics (1.1.0) [MIT]
@@ -5367,9 +5367,9 @@ MIT
5367
5367
 
5368
5368
 
5369
5369
  --------------------------------------------------------------------------------
5370
- Package Title: baseline-browser-mapping (2.10.27)
5370
+ Package Title: baseline-browser-mapping (2.10.29)
5371
5371
 
5372
- Package Locator: npm+baseline-browser-mapping$2.10.27
5372
+ Package Locator: npm+baseline-browser-mapping$2.10.29
5373
5373
 
5374
5374
  Package Depth: Transitive
5375
5375
  --------------------------------------------------------------------------------
@@ -9407,7 +9407,7 @@ MIT, BSD-3-Clause
9407
9407
 
9408
9408
 
9409
9409
  * Other Licenses *
9410
- ISC, 0BSD
9410
+ 0BSD, ISC
9411
9411
 
9412
9412
 
9413
9413
  --------------------------------------------------------------------------------
@@ -38277,4 +38277,4 @@ POSSIBILITY OF SUCH DAMAGE.
38277
38277
  --------------------------------------------------------------------------------
38278
38278
  --------------------------------------------------------------------------------
38279
38279
 
38280
- Report Generated by FOSSA on 2026-5-4
38280
+ Report Generated by FOSSA on 2026-5-12
@@ -1,3 +1,3 @@
1
- export declare const LIB_VERSION = "11.35.0-alpha.5";
1
+ export declare const LIB_VERSION = "11.35.0-alpha.6";
2
2
  export declare const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
3
3
  export declare const LIB_NAME = "@gooddata/sdk-ui-dashboard";
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.35.0-alpha.5";
3
+ export const LIB_VERSION = "11.35.0-alpha.6";
4
4
  export const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
5
5
  export const LIB_NAME = "@gooddata/sdk-ui-dashboard";
package/esm/index.d.ts CHANGED
@@ -142,10 +142,9 @@ export type { CatalogState, CatalogParametersStatus, ICatalogParametersState, }
142
142
  export { selectCatalogIsLoaded, selectAttributesWithDrillDown, selectCatalogAttributes, selectCatalogAttributeDisplayForms, selectCatalogDateDatasets, selectCatalogFacts, selectCatalogMeasures, selectAllCatalogAttributesMap, selectAllCatalogDisplayFormsMap, selectAllCatalogDateDatasetsMap, selectAllCatalogMeasuresMap, selectHasCatalogAttributes, selectHasCatalogMeasures, selectHasCatalogDateDatasets, selectHasCatalogFacts, selectCatalogAttributeHierarchies, selectCatalogDateAttributes, selectDateHierarchyTemplates, selectAdhocDateHierarchies, selectAllCatalogAttributeHierarchies, selectCatalogAttributeDisplayFormsById, selectCatalogParameters, selectCatalogParametersStatus, selectCatalogParametersIsLoaded, } from "./model/store/catalog/catalogSelectors.js";
143
143
  export { catalogActions } from "./model/store/catalog/index.js";
144
144
  export type { SetCatalogMeasuresAndFactsPayload, SetCatalogItemsPayload, } from "./model/store/catalog/catalogReducers.js";
145
- export { parametersActions } from "./model/store/parameters/index.js";
146
- export type { IAddParameterPayload, IRemoveParameterPayload, ISetParameterRuntimeValuePayload, } from "./model/store/parameters/parametersReducers.js";
147
- export type { IDashboardParameterEntry, IParametersState } from "./model/store/parameters/parametersState.js";
148
- export { selectDashboardParameterEntries, selectDashboardParameters, selectEffectiveParameterValuesForWidget, selectIsParametersChanged, selectParameterRuntimeOverrideByRef, } from "./model/store/parameters/parametersSelectors.js";
145
+ export type { IAddParameterPayload, IRemoveParameterPayload, ISetParameterRuntimeValuePayload, } from "./model/store/tabs/parameters/parametersReducers.js";
146
+ export type { IDashboardParameterEntry, IParametersState, } from "./model/store/tabs/parameters/parametersState.js";
147
+ export { selectDashboardParameterEntries, selectDashboardParameters, selectEffectiveParameterValuesForWidget, selectIsParametersChanged, selectParameterRuntimeOverrideByRef, } from "./model/store/tabs/parameters/parametersSelectors.js";
149
148
  export { drillActions } from "./model/store/drill/index.js";
150
149
  export { selectDrillableItems, selectIsCrossFiltering, selectCrossFilteringItems, selectCrossFilteringItemByWidgetRef, selectCrossFilteringFiltersLocalIdentifiers, selectCrossFilteringFiltersLocalIdentifiersByWidgetRef, selectCrossFilteringSelectedPointsByWidgetRef, selectIsFilterFromCrossFilteringByLocalIdentifier, } from "./model/store/drill/drillSelectors.js";
151
150
  export type { IDrillState } from "./model/store/drill/drillState.js";
package/esm/index.js CHANGED
@@ -105,8 +105,7 @@ export { selectDateFilterConfigsOverrides, selectDateFilterConfigsOverridesByTab
105
105
  export { selectInsights, selectInsightRefs, selectInsightsMap, selectInsightByRef, selectInsightByWidgetRef, selectRawExportOverridesForInsightByRef, } from "./model/store/insights/insightsSelectors.js";
106
106
  export { selectCatalogIsLoaded, selectAttributesWithDrillDown, selectCatalogAttributes, selectCatalogAttributeDisplayForms, selectCatalogDateDatasets, selectCatalogFacts, selectCatalogMeasures, selectAllCatalogAttributesMap, selectAllCatalogDisplayFormsMap, selectAllCatalogDateDatasetsMap, selectAllCatalogMeasuresMap, selectHasCatalogAttributes, selectHasCatalogMeasures, selectHasCatalogDateDatasets, selectHasCatalogFacts, selectCatalogAttributeHierarchies, selectCatalogDateAttributes, selectDateHierarchyTemplates, selectAdhocDateHierarchies, selectAllCatalogAttributeHierarchies, selectCatalogAttributeDisplayFormsById, selectCatalogParameters, selectCatalogParametersStatus, selectCatalogParametersIsLoaded, } from "./model/store/catalog/catalogSelectors.js";
107
107
  export { catalogActions } from "./model/store/catalog/index.js";
108
- export { parametersActions } from "./model/store/parameters/index.js";
109
- export { selectDashboardParameterEntries, selectDashboardParameters, selectEffectiveParameterValuesForWidget, selectIsParametersChanged, selectParameterRuntimeOverrideByRef, } from "./model/store/parameters/parametersSelectors.js";
108
+ export { selectDashboardParameterEntries, selectDashboardParameters, selectEffectiveParameterValuesForWidget, selectIsParametersChanged, selectParameterRuntimeOverrideByRef, } from "./model/store/tabs/parameters/parametersSelectors.js";
110
109
  export { drillActions } from "./model/store/drill/index.js";
111
110
  export { selectDrillableItems, selectIsCrossFiltering, selectCrossFilteringItems, selectCrossFilteringItemByWidgetRef, selectCrossFilteringFiltersLocalIdentifiers, selectCrossFilteringFiltersLocalIdentifiersByWidgetRef, selectCrossFilteringSelectedPointsByWidgetRef, selectIsFilterFromCrossFilteringByLocalIdentifier, } from "./model/store/drill/drillSelectors.js";
112
111
  export { selectCurrentUser, selectCurrentUserRef } from "./model/store/user/userSelectors.js";
@@ -1,5 +1,5 @@
1
- import { type IDashboardParameter, type IParameterMetadataObject } from "@gooddata/sdk-model";
2
- import { type IDashboardParameterEntry } from "../../../store/parameters/parametersState.js";
1
+ import { type IDashboardParameter, type IDashboardTab, type IParameterMetadataObject } from "@gooddata/sdk-model";
2
+ import { type IDashboardParameterEntry } from "../../../store/tabs/parameters/parametersState.js";
3
3
  /**
4
4
  * Builds the parameter slice entries from the dashboard's persisted parameters and the
5
5
  * workspace parameter catalog.
@@ -10,3 +10,12 @@ import { type IDashboardParameterEntry } from "../../../store/parameters/paramet
10
10
  * stays `undefined` so the backend keeps using the parameter's own default at execution time.
11
11
  */
12
12
  export declare function hydrateParameterEntries(dashboardParameters: IDashboardParameter[] | undefined, workspaceParameters: IParameterMetadataObject[]): IDashboardParameterEntry[];
13
+ /**
14
+ * Distributes the dashboard's persisted parameters into per-tab hydrated entry lists, applying
15
+ * the V1 → per-tab migration rule (see {@link pickTabParametersSource}). Each tab's parameter
16
+ * list is hydrated against the workspace catalog via {@link hydrateParameterEntries}.
17
+ *
18
+ * For legacy single-tab dashboards (no `tabs[]`), a synthetic tab with `DEFAULT_TAB_ID` is used
19
+ * so the V1 root-level `parameters` migrate transparently.
20
+ */
21
+ export declare function distributeParametersToTabs(tabs: IDashboardTab[] | undefined, rootParameters: IDashboardParameter[] | undefined, workspaceParameters: IParameterMetadataObject[]): Record<string, IDashboardParameterEntry[]>;
@@ -1,5 +1,7 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { isNumberParameterDefinition, objRefToString, } from "@gooddata/sdk-model";
3
+ import { pickTabParametersSource, } from "../../../store/tabs/parameters/parametersState.js";
4
+ import { DEFAULT_TAB_ID } from "../../../store/tabs/tabsState.js";
3
5
  /**
4
6
  * Builds the parameter slice entries from the dashboard's persisted parameters and the
5
7
  * workspace parameter catalog.
@@ -25,3 +27,22 @@ export function hydrateParameterEntries(dashboardParameters, workspaceParameters
25
27
  return { parameter, runtimeOverride: workspaceDefault };
26
28
  });
27
29
  }
30
+ /**
31
+ * Distributes the dashboard's persisted parameters into per-tab hydrated entry lists, applying
32
+ * the V1 → per-tab migration rule (see {@link pickTabParametersSource}). Each tab's parameter
33
+ * list is hydrated against the workspace catalog via {@link hydrateParameterEntries}.
34
+ *
35
+ * For legacy single-tab dashboards (no `tabs[]`), a synthetic tab with `DEFAULT_TAB_ID` is used
36
+ * so the V1 root-level `parameters` migrate transparently.
37
+ */
38
+ export function distributeParametersToTabs(tabs, rootParameters, workspaceParameters) {
39
+ const effectiveTabs = tabs ?? [
40
+ { localIdentifier: DEFAULT_TAB_ID, title: "", parameters: rootParameters },
41
+ ];
42
+ const result = {};
43
+ for (const tab of effectiveTabs) {
44
+ const source = pickTabParametersSource(tab, effectiveTabs, rootParameters);
45
+ result[tab.localIdentifier] = hydrateParameterEntries(source, workspaceParameters);
46
+ }
47
+ return result;
48
+ }
@@ -14,7 +14,6 @@ import { drillActions } from "../../../store/drill/index.js";
14
14
  import { insightsActions } from "../../../store/insights/index.js";
15
15
  import { metaActions } from "../../../store/meta/index.js";
16
16
  import { selectIsNewDashboard } from "../../../store/meta/metaSelectors.js";
17
- import { parametersActions } from "../../../store/parameters/index.js";
18
17
  import { filterContextInitialState, } from "../../../store/tabs/filterContext/filterContextState.js";
19
18
  import { tabsActions } from "../../../store/tabs/index.js";
20
19
  import { selectScreen } from "../../../store/tabs/layout/layoutSelectors.js";
@@ -25,7 +24,7 @@ import { resolveFilterDisplayForms } from "../../../utils/filterResolver.js";
25
24
  import { EmptyDashboardLayout, dashboardInitialize } from "./dashboardInitialize.js";
26
25
  import { loadAvailableDisplayFormRefs } from "./loadAvailableDisplayFormRefs.js";
27
26
  import { mergedMigratedAttributeFilters } from "./migratedAttributeFilters.js";
28
- import { hydrateParameterEntries } from "./parameterHydration.js";
27
+ import { distributeParametersToTabs } from "./parameterHydration.js";
29
28
  /**
30
29
  * Processes a single tab's filterContext and returns initialized FilterContextState.
31
30
  * This includes sanitization, migration, merging with overrides, and display form resolution.
@@ -134,84 +133,48 @@ export function* actionsToInitializeNewDashboard(ctx, settings, dateFilterConfig
134
133
  dateFilterConfigs: [],
135
134
  attributeFilterConfigs: [],
136
135
  layout: dashboardLayout ?? EmptyDashboardLayout,
136
+ parameters: dashboard?.parameters,
137
137
  },
138
138
  ];
139
+ const parametersByTab = distributeParametersToTabs(tabs, dashboard?.parameters, workspaceParameters);
139
140
  // Prepare tabs action with complete filterContext for each tab
140
- const tabsAction = tabs
141
- ? [
142
- tabsActions.setTabs({
143
- tabs: tabs.map((tab) => ({
144
- title: tab.title,
145
- localIdentifier: tab.localIdentifier,
146
- filterContext: {
147
- ...filterContextInitialState,
148
- filterContextDefinition,
149
- originalFilterContextDefinition,
150
- filterContextIdentity,
151
- attributeFilterDisplayForms,
152
- },
153
- dateFilterConfig: {
154
- dateFilterConfig: tab.dateFilterConfig,
155
- effectiveDateFilterConfig: dateFilterConfig,
156
- isUsingDashboardOverrides: false,
157
- dateFilterConfigValidationWarnings: undefined,
158
- },
159
- dateFilterConfigs: {
160
- dateFilterConfigs: tab.dateFilterConfigs ?? [],
161
- },
162
- attributeFilterConfigs: {
163
- attributeFilterConfigs: tab.attributeFilterConfigs ?? [],
164
- },
165
- measureValueFilterConfigs: {
166
- measureValueFilterConfigs: tab.measureValueFilterConfigs ?? [],
167
- },
168
- layout: {
169
- ...layoutInitialState,
170
- layout: tab.layout ?? dashboardLayout ?? EmptyDashboardLayout,
171
- },
172
- filterGroupsConfig: tab.filterGroupsConfig,
173
- })),
174
- activeTabLocalIdentifier: initialTabId ?? dashboard?.activeTabLocalIdentifier ?? DEFAULT_TAB_ID,
175
- }),
176
- ]
177
- : [
178
- // For dashboards without tabs, create a single default tab
179
- tabsActions.setTabs({
180
- tabs: [
181
- {
182
- localIdentifier: DEFAULT_TAB_ID,
183
- title: "",
184
- filterContext: {
185
- ...filterContextInitialState,
186
- filterContextDefinition,
187
- originalFilterContextDefinition,
188
- filterContextIdentity,
189
- attributeFilterDisplayForms,
190
- },
191
- layout: {
192
- ...layoutInitialState,
193
- layout: dashboardLayout ?? EmptyDashboardLayout,
194
- },
195
- dateFilterConfig: {
196
- dateFilterConfig: dashboard?.dateFilterConfig,
197
- effectiveDateFilterConfig: dateFilterConfig,
198
- isUsingDashboardOverrides: false,
199
- dateFilterConfigValidationWarnings: undefined,
200
- },
201
- dateFilterConfigs: {
202
- dateFilterConfigs: dashboard?.dateFilterConfigs ?? [],
203
- },
204
- attributeFilterConfigs: {
205
- attributeFilterConfigs: dashboard?.attributeFilterConfigs ?? [],
206
- },
207
- measureValueFilterConfigs: {
208
- measureValueFilterConfigs: dashboard?.measureValueFilterConfigs ?? [],
209
- },
210
- },
211
- ],
212
- activeTabLocalIdentifier: DEFAULT_TAB_ID,
213
- }),
214
- ];
141
+ const tabsAction = [
142
+ tabsActions.setTabs({
143
+ tabs: tabs.map((tab) => ({
144
+ title: tab.title,
145
+ localIdentifier: tab.localIdentifier,
146
+ filterContext: {
147
+ ...filterContextInitialState,
148
+ filterContextDefinition,
149
+ originalFilterContextDefinition,
150
+ filterContextIdentity,
151
+ attributeFilterDisplayForms,
152
+ },
153
+ dateFilterConfig: {
154
+ dateFilterConfig: tab.dateFilterConfig,
155
+ effectiveDateFilterConfig: dateFilterConfig,
156
+ isUsingDashboardOverrides: false,
157
+ dateFilterConfigValidationWarnings: undefined,
158
+ },
159
+ dateFilterConfigs: {
160
+ dateFilterConfigs: tab.dateFilterConfigs ?? [],
161
+ },
162
+ attributeFilterConfigs: {
163
+ attributeFilterConfigs: tab.attributeFilterConfigs ?? [],
164
+ },
165
+ measureValueFilterConfigs: {
166
+ measureValueFilterConfigs: tab.measureValueFilterConfigs ?? [],
167
+ },
168
+ layout: {
169
+ ...layoutInitialState,
170
+ layout: tab.layout ?? dashboardLayout ?? EmptyDashboardLayout,
171
+ },
172
+ filterGroupsConfig: tab.filterGroupsConfig,
173
+ parameters: { parameters: parametersByTab[tab.localIdentifier] ?? [] },
174
+ })),
175
+ activeTabLocalIdentifier: initialTabId ?? dashboard?.activeTabLocalIdentifier ?? DEFAULT_TAB_ID,
176
+ }),
177
+ ];
215
178
  return {
216
179
  initActions: [
217
180
  ...tabsAction,
@@ -232,7 +195,6 @@ export function* actionsToInitializeNewDashboard(ctx, settings, dateFilterConfig
232
195
  insightsActions.setInsights(insights),
233
196
  drillActions.resetCrossFiltering(),
234
197
  ]),
235
- parametersActions.setParameterEntries(hydrateParameterEntries(dashboard?.parameters, workspaceParameters)),
236
198
  ],
237
199
  dashboard: initialContent ? dashboard : undefined,
238
200
  insights: initialContent ? insights : [],
@@ -432,6 +394,8 @@ export function* actionsToInitializeExistingDashboard(ctx, dashboard, insights,
432
394
  */
433
395
  const dashboardLayout = dashboardLayoutSanitize(customizedDashboard.layout ?? EmptyDashboardLayout, insights, settings);
434
396
  const screen = yield select(selectScreen);
397
+ const parameterSourceDashboard = persistedDashboard ?? dashboard;
398
+ const parametersByTab = distributeParametersToTabs(parameterSourceDashboard.tabs, parameterSourceDashboard.parameters, workspaceParameters);
435
399
  // Process tabs with complete filterContext initialization for each tab
436
400
  let tabsAction = null;
437
401
  const validationResults = [];
@@ -477,6 +441,7 @@ export function* actionsToInitializeExistingDashboard(ctx, dashboard, insights,
477
441
  layout: tabLayout,
478
442
  screen, // Preserve only screen from current state
479
443
  },
444
+ parameters: { parameters: parametersByTab[tab.localIdentifier] ?? [] },
480
445
  };
481
446
  processedTabs.push(tabState);
482
447
  }
@@ -532,6 +497,7 @@ export function* actionsToInitializeExistingDashboard(ctx, dashboard, insights,
532
497
  measureValueFilterConfigs: dashboard.measureValueFilterConfigs,
533
498
  }
534
499
  : undefined,
500
+ parameters: { parameters: parametersByTab[tabIdentifier] ?? [] },
535
501
  };
536
502
  tabsAction = tabsActions.setTabs({
537
503
  tabs: [defaultTab],
@@ -550,7 +516,6 @@ export function* actionsToInitializeExistingDashboard(ctx, dashboard, insights,
550
516
  uiActions.setWidgetsOverlay(modifiedWidgets),
551
517
  validationResults.length > 0 ? uiActions.setIncompatibleDefaultFiltersOverrideMessage() : null,
552
518
  drillActions.resetCrossFiltering(),
553
- parametersActions.setParameterEntries(hydrateParameterEntries((persistedDashboard ?? dashboard).parameters, workspaceParameters)),
554
519
  ]);
555
520
  }
556
521
  function updateDashboard(ds, title, hideWidgetTitles) {
@@ -14,7 +14,6 @@ import { selectCrossFilteringFiltersLocalIdentifiers } from "../../store/drill/d
14
14
  import { listedDashboardsActions } from "../../store/listedDashboards/index.js";
15
15
  import { metaActions } from "../../store/meta/index.js";
16
16
  import { selectDashboardDescriptor, selectPersistedDashboard, selectPersistedDashboardFilterContextAsFilterContextDefinition, } from "../../store/meta/metaSelectors.js";
17
- import { selectSmartPersistedDashboardParameters } from "../../store/parameters/parametersSelectors.js";
18
17
  import { selectIsInViewMode } from "../../store/renderMode/renderModeSelectors.js";
19
18
  import { savingActions } from "../../store/saving/index.js";
20
19
  import { selectAttributeFilterConfigsOverrides } from "../../store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
@@ -24,6 +23,7 @@ import { selectFilterContextAttributeFilters, selectFilterContextDefinition, } f
24
23
  import { tabsActions } from "../../store/tabs/index.js";
25
24
  import { filterOutCustomWidgets, selectBasicLayout } from "../../store/tabs/layout/layoutSelectors.js";
26
25
  import { selectMeasureValueFilterConfigsOverrides } from "../../store/tabs/measureValueFilterConfigs/measureValueFilterConfigsSelectors.js";
26
+ import { selectSmartPersistedTabsParameters } from "../../store/tabs/parameters/parametersSelectors.js";
27
27
  import { selectTabs } from "../../store/tabs/tabsSelectors.js";
28
28
  import { selectCurrentUser } from "../../store/user/userSelectors.js";
29
29
  import { changeRenderModeHandler } from "../renderMode/changeRenderModeHandler.js";
@@ -39,7 +39,7 @@ function createDashboard(ctx, saveAsCtx) {
39
39
  * @param tabs - Array of TabState objects from the dashboard state
40
40
  * @returns Array of IDashboardTab objects ready for saving to backend
41
41
  */
42
- function processExistingTabsForSaveAs(tabs, useOriginalFilterContext) {
42
+ function processExistingTabsForSaveAs(tabs, parametersByTab, useOriginalFilterContext) {
43
43
  return tabs.map((tab) => {
44
44
  const dateFilterConfig = tab.dateFilterConfig?.dateFilterConfig;
45
45
  const dateFilterConfigs = tab.dateFilterConfigs?.dateFilterConfigs;
@@ -61,6 +61,7 @@ function processExistingTabsForSaveAs(tabs, useOriginalFilterContext) {
61
61
  : tab.filterContext.filterContextDefinition),
62
62
  }
63
63
  : undefined;
64
+ const tabParameters = parametersByTab[tab.localIdentifier] ?? [];
64
65
  const result = {
65
66
  // explicitly type the result to avoid type errors caused by spread operators
66
67
  localIdentifier: tab.localIdentifier,
@@ -72,6 +73,9 @@ function processExistingTabsForSaveAs(tabs, useOriginalFilterContext) {
72
73
  ...dateFilterConfigsProp,
73
74
  ...attributeFilterConfigsProp,
74
75
  ...measureValueFilterConfigsProp,
76
+ // Always persist `parameters` (incl. `[]`) so V1 root fallback never re-hydrates stale
77
+ // root parameters when every tab has been emptied.
78
+ parameters: tabParameters,
75
79
  };
76
80
  return result;
77
81
  });
@@ -108,11 +112,13 @@ function* createDashboardSaveAsContext(cmd) {
108
112
  const dateFilterConfigs = yield select(selectDateFilterConfigsOverrides);
109
113
  const measureValueFilterConfigs = yield select(selectMeasureValueFilterConfigsOverrides);
110
114
  const tabs = yield select(selectTabs);
111
- const parameters = yield select(selectSmartPersistedDashboardParameters);
115
+ const parametersByTab = yield select(selectSmartPersistedTabsParameters);
112
116
  const capabilities = yield select(selectBackendCapabilities);
113
117
  const { isUnderStrictControl: _unusedProp, ...dashboardDescriptorRest } = dashboardDescriptor;
114
118
  // Process tabs if tabs exist
115
- const processedTabs = tabs && tabs.length > 0 ? processExistingTabsForSaveAs(tabs, useOriginalFilterContext) : undefined;
119
+ const processedTabs = tabs && tabs.length > 0
120
+ ? processExistingTabsForSaveAs(tabs, parametersByTab, useOriginalFilterContext)
121
+ : undefined;
116
122
  const dashboardFromState = {
117
123
  type: "IDashboard",
118
124
  ...dashboardDescriptorRest,
@@ -125,7 +131,6 @@ function* createDashboardSaveAsContext(cmd) {
125
131
  ...(dateFilterConfigs?.length ? { dateFilterConfigs } : {}),
126
132
  ...(measureValueFilterConfigs?.length ? { measureValueFilterConfigs } : {}),
127
133
  ...(processedTabs ? { tabs: processedTabs } : {}),
128
- ...(parameters.length ? { parameters } : {}),
129
134
  };
130
135
  const pluginsProp = persistedDashboard?.plugins ? { plugins: persistedDashboard.plugins } : {};
131
136
  const shareProp = capabilities.supportsAccessControl
@@ -18,7 +18,6 @@ import { selectLocale } from "../../store/config/configSelectors.js";
18
18
  import { listedDashboardsActions } from "../../store/listedDashboards/index.js";
19
19
  import { metaActions } from "../../store/meta/index.js";
20
20
  import { selectDashboardDescriptor, selectPersistedDashboard } from "../../store/meta/metaSelectors.js";
21
- import { selectSmartPersistedDashboardParameters } from "../../store/parameters/parametersSelectors.js";
22
21
  import { selectIsInViewMode } from "../../store/renderMode/renderModeSelectors.js";
23
22
  import { savingActions } from "../../store/saving/index.js";
24
23
  import { selectAttributeFilterConfigsOverrides } from "../../store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
@@ -28,6 +27,7 @@ import { selectFilterContextDefinition, selectFilterContextIdentity, } from "../
28
27
  import { tabsActions } from "../../store/tabs/index.js";
29
28
  import { filterOutCustomWidgets, selectBasicLayout } from "../../store/tabs/layout/layoutSelectors.js";
30
29
  import { selectMeasureValueFilterConfigsOverrides } from "../../store/tabs/measureValueFilterConfigs/measureValueFilterConfigsSelectors.js";
30
+ import { selectSmartPersistedTabsParameters } from "../../store/tabs/parameters/parametersSelectors.js";
31
31
  import { selectTabs } from "../../store/tabs/tabsSelectors.js";
32
32
  import { isTemporaryIdentity } from "../../utils/dashboardItemUtils.js";
33
33
  import { changeRenderModeHandler } from "../renderMode/changeRenderModeHandler.js";
@@ -66,9 +66,10 @@ export function getDashboardWithSharing(dashboard, sharingSupported = true, isNe
66
66
  * Converts TabState[] from the dashboard state into IDashboardTab[] for saving.
67
67
  *
68
68
  * @param tabs - Array of TabState objects from the dashboard state
69
+ * @param parametersByTab - Smart-persisted parameters keyed by tab localIdentifier
69
70
  * @returns Array of IDashboardTab objects ready for saving to backend
70
71
  */
71
- function processExistingTabs(tabs) {
72
+ function processExistingTabs(tabs, parametersByTab) {
72
73
  return tabs.map((tab) => {
73
74
  const dateFilterConfig = tab.dateFilterConfig?.dateFilterConfig;
74
75
  const dateFilterConfigProp = dateFilterConfig ? { dateFilterConfig } : {};
@@ -93,6 +94,7 @@ function processExistingTabs(tabs) {
93
94
  ...tab.filterContext.filterContextDefinition,
94
95
  }
95
96
  : undefined;
97
+ const tabParameters = parametersByTab[tab.localIdentifier] ?? [];
96
98
  const result = {
97
99
  // explicitly type the result to avoid type errors caused by spread operators
98
100
  localIdentifier: tab.localIdentifier,
@@ -105,6 +107,9 @@ function processExistingTabs(tabs) {
105
107
  ...attributeFilterConfigsProp,
106
108
  ...measureValueFilterConfigsProp,
107
109
  ...filterGroupsConfigProp,
110
+ // Always persist `parameters` (incl. `[]`) so V1 root fallback never re-hydrates stale
111
+ // root parameters when every tab has been emptied.
112
+ parameters: tabParameters,
108
113
  };
109
114
  return result;
110
115
  });
@@ -131,14 +136,14 @@ function createDefaultTab(layout, rootFilterContext, dateFilterConfig, attribute
131
136
  },
132
137
  ];
133
138
  }
134
- function resolveProcessedTabs(tabs, rootFilterContext, layout, dateFilterConfig, attributeFilterConfigs, dateFilterConfigs, measureValueFilterConfigs) {
139
+ function resolveProcessedTabs(tabs, rootFilterContext, layout, dateFilterConfig, attributeFilterConfigs, dateFilterConfigs, measureValueFilterConfigs, parametersByTab) {
135
140
  // If no tabs exist, create a default tab with root-level properties
136
141
  const shouldCreateDefaultTab = !tabs || tabs.length === 0;
137
142
  if (shouldCreateDefaultTab && rootFilterContext) {
138
143
  return createDefaultTab(layout, rootFilterContext, dateFilterConfig, attributeFilterConfigs, dateFilterConfigs, measureValueFilterConfigs);
139
144
  }
140
145
  if (tabs) {
141
- return processExistingTabs(tabs);
146
+ return processExistingTabs(tabs, parametersByTab);
142
147
  }
143
148
  return undefined;
144
149
  }
@@ -159,7 +164,7 @@ function* createDashboardSaveContext(cmd, isNewDashboard) {
159
164
  const dateFilterConfigs = yield select(selectDateFilterConfigsOverrides);
160
165
  const measureValueFilterConfigs = yield select(selectMeasureValueFilterConfigsOverrides);
161
166
  const tabs = yield select(selectTabs);
162
- const parameters = yield select(selectSmartPersistedDashboardParameters);
167
+ const parametersByTab = yield select(selectSmartPersistedTabsParameters);
163
168
  const capabilities = yield select(selectBackendCapabilities);
164
169
  /*
165
170
  * When updating an existing dashboard, the services expect that the dashboard definition to use for
@@ -179,7 +184,7 @@ function* createDashboardSaveContext(cmd, isNewDashboard) {
179
184
  ...filterContextDefinition,
180
185
  }
181
186
  : undefined;
182
- const processedTabs = resolveProcessedTabs(tabs, rootFilterContext, layout, dateFilterConfig, attributeFilterConfigs, dateFilterConfigs, measureValueFilterConfigs);
187
+ const processedTabs = resolveProcessedTabs(tabs, rootFilterContext, layout, dateFilterConfig, attributeFilterConfigs, dateFilterConfigs, measureValueFilterConfigs, parametersByTab);
183
188
  const locale = yield select(selectLocale);
184
189
  const translations = yield call(resolveMessages, locale);
185
190
  const title = (cmd.payload.title ?? dashboardDescriptor.title) || translations[messages.untitled.id];
@@ -198,7 +203,6 @@ function* createDashboardSaveContext(cmd, isNewDashboard) {
198
203
  dateFilterConfig,
199
204
  ...buildOptionalFilterConfigsProps(attributeFilterConfigs, dateFilterConfigs, measureValueFilterConfigs),
200
205
  ...(processedTabs ? { tabs: processedTabs } : {}),
201
- ...(parameters.length > 0 ? { parameters } : {}),
202
206
  ...pluginsProp,
203
207
  };
204
208
  const dashboardToSave = {
@@ -127,7 +127,6 @@ export declare function createDashboardRootReducer({ queryCache }?: {
127
127
  dashboardPermissions: import("./dashboardPermissions/dashboardPermissionsState.js").DashboardPermissionsState;
128
128
  showWidgetAsTable: import("./showWidgetAsTable/showWidgetAsTableState.js").IShowWidgetAsTableState;
129
129
  notificationChannels: import("./notificationChannels/notificationChannelsState.js").INotificationChannelsState;
130
- parameters: import("./parameters/parametersState.js").IParametersState;
131
130
  automations: import("./automations/automationsState.js").IAutomationsState;
132
131
  users: import("./users/usersState.js").IUsersState;
133
132
  filterViews: import("./filterViews/filterViewsState.js").IFilterViewsState;
@@ -157,7 +156,6 @@ export declare function createDashboardRootReducer({ queryCache }?: {
157
156
  dashboardPermissions: import("./dashboardPermissions/dashboardPermissionsState.js").DashboardPermissionsState | undefined;
158
157
  showWidgetAsTable: import("./showWidgetAsTable/showWidgetAsTableState.js").IShowWidgetAsTableState | undefined;
159
158
  notificationChannels: import("./notificationChannels/notificationChannelsState.js").INotificationChannelsState | undefined;
160
- parameters: import("./parameters/parametersState.js").IParametersState | undefined;
161
159
  automations: import("./automations/automationsState.js").IAutomationsState | undefined;
162
160
  users: import("./users/usersState.js").IUsersState | undefined;
163
161
  filterViews: import("./filterViews/filterViewsState.js").IFilterViewsState | undefined;
@@ -31,7 +31,6 @@ import { listedDashboardsSliceReducer } from "./listedDashboards/index.js";
31
31
  import { loadingSliceReducer } from "./loading/index.js";
32
32
  import { metaSliceReducer } from "./meta/index.js";
33
33
  import { notificationChannelsSliceReducer } from "./notificationChannels/index.js";
34
- import { parametersSliceReducer } from "./parameters/index.js";
35
34
  import { permissionsSliceReducer } from "./permissions/index.js";
36
35
  import { renderModeSliceReducer } from "./renderMode/index.js";
37
36
  import { savingSliceReducer } from "./saving/index.js";
@@ -162,7 +161,6 @@ export function createDashboardRootReducer({ queryCache = (state = {}) => state,
162
161
  dashboardPermissions: dashboardPermissionsSliceReducer,
163
162
  showWidgetAsTable: showWidgetAsTableSliceReducer,
164
163
  notificationChannels: notificationChannelsSliceReducer,
165
- parameters: parametersSliceReducer,
166
164
  automations: automationsSliceReducer,
167
165
  users: usersSliceReducer,
168
166
  filterViews: filterViewsSliceReducer,
@@ -4,13 +4,13 @@ import { isEqual } from "lodash-es";
4
4
  import { invariant } from "ts-invariant";
5
5
  import { isDashboardLayoutEmpty } from "@gooddata/sdk-backend-spi";
6
6
  import { idRef, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDashboardDateFilterWithDimension, isDashboardMeasureValueFilter, isDashboardTextAttributeFilter, isTempFilterContext, uriRef, } from "@gooddata/sdk-model";
7
- import { selectIsParametersChanged, selectSmartPersistedDashboardParameters, } from "../parameters/parametersSelectors.js";
8
7
  import { selectAttributeFilterConfigsOverridesByTab } from "../tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
9
8
  import { selectDateFilterConfigOverrides, selectDateFilterConfigOverridesByTab, } from "../tabs/dateFilterConfig/dateFilterConfigSelectors.js";
10
9
  import { selectDateFilterConfigsOverridesByTab } from "../tabs/dateFilterConfigs/dateFilterConfigsSelectors.js";
11
10
  import { selectFilterContextDefinition, selectFilterContextDefinitionsByTab, selectFilterContextIdentity, } from "../tabs/filterContext/filterContextSelectors.js";
12
11
  import { filterOutCustomWidgets, selectBasicLayout, selectBasicLayoutByTab, } from "../tabs/layout/layoutSelectors.js";
13
12
  import { selectMeasureValueFilterConfigsOverridesByTab } from "../tabs/measureValueFilterConfigs/measureValueFilterConfigsSelectors.js";
13
+ import { selectIsParametersChanged, selectSmartPersistedTabsParameters, } from "../tabs/parameters/parametersSelectors.js";
14
14
  import { selectActiveTabLocalIdentifier, selectTabs } from "../tabs/tabsSelectors.js";
15
15
  import { DEFAULT_TAB_ID } from "../tabs/tabsState.js";
16
16
  const selectSelf = createSelector((state) => state, (state) => state.meta);
@@ -71,6 +71,7 @@ export const selectPersistedDashboardTabs = createSelector(selectSelf, (state) =
71
71
  dateFilterConfig: persistedDashboard.dateFilterConfig,
72
72
  dateFilterConfigs: persistedDashboard.dateFilterConfigs,
73
73
  layout: persistedDashboard.layout,
74
+ parameters: persistedDashboard.parameters,
74
75
  },
75
76
  ];
76
77
  });
@@ -731,7 +732,7 @@ export const selectIsDashboardDirty = createSelector(selectIsNewDashboard, selec
731
732
  /**
732
733
  * @internal
733
734
  */
734
- export const selectDashboardWorkingDefinition = createSelector(selectPersistedDashboard, selectDashboardDescriptor, selectFilterContextDefinition, selectFilterContextIdentity, selectBasicLayout, selectDateFilterConfigOverrides, selectTabs, selectSmartPersistedDashboardParameters, (persistedDashboard, dashboardDescriptor, filterContextDefinition, filterContextIdentity, layout, dateFilterConfig, tabs, parameters) => {
735
+ export const selectDashboardWorkingDefinition = createSelector(selectPersistedDashboard, selectDashboardDescriptor, selectFilterContextDefinition, selectFilterContextIdentity, selectBasicLayout, selectDateFilterConfigOverrides, selectTabs, selectSmartPersistedTabsParameters, (persistedDashboard, dashboardDescriptor, filterContextDefinition, filterContextIdentity, layout, dateFilterConfig, tabs, parametersByTab) => {
735
736
  const dashboardIdentity = {
736
737
  ref: persistedDashboard?.ref,
737
738
  uri: persistedDashboard?.uri,
@@ -748,7 +749,6 @@ export const selectDashboardWorkingDefinition = createSelector(selectPersistedDa
748
749
  },
749
750
  layout,
750
751
  dateFilterConfig,
751
- ...(parameters.length > 0 ? { parameters } : {}),
752
752
  ...(tabs
753
753
  ? {
754
754
  tabs: tabs.map((tab) => ({
@@ -768,6 +768,7 @@ export const selectDashboardWorkingDefinition = createSelector(selectPersistedDa
768
768
  attributeFilterConfigs: tab.attributeFilterConfigs?.attributeFilterConfigs,
769
769
  measureValueFilterConfigs: tab.measureValueFilterConfigs?.measureValueFilterConfigs,
770
770
  filterGroupsConfig: tab.filterGroupsConfig,
771
+ parameters: parametersByTab[tab.localIdentifier] ?? [],
771
772
  })),
772
773
  }
773
774
  : {}),
@@ -561,4 +561,16 @@ export declare const tabsActions: import("@reduxjs/toolkit").CaseReducerActions<
561
561
  payload: string;
562
562
  type: string;
563
563
  }) => void | import("./tabsState.js").ITabsState | import("immer").WritableDraft<import("./tabsState.js").ITabsState>;
564
+ readonly addParameter: (state: import("immer").WritableDraft<import("./tabsState.js").ITabsState>, action: {
565
+ payload: import("./parameters/parametersReducers.js").IAddParameterPayload;
566
+ type: string;
567
+ }) => void | import("./tabsState.js").ITabsState | import("immer").WritableDraft<import("./tabsState.js").ITabsState>;
568
+ readonly setParameterRuntimeValue: (state: import("immer").WritableDraft<import("./tabsState.js").ITabsState>, action: {
569
+ payload: import("./parameters/parametersReducers.js").ISetParameterRuntimeValuePayload;
570
+ type: string;
571
+ }) => void | import("./tabsState.js").ITabsState | import("immer").WritableDraft<import("./tabsState.js").ITabsState>;
572
+ readonly removeParameter: (state: import("immer").WritableDraft<import("./tabsState.js").ITabsState>, action: {
573
+ payload: import("./parameters/parametersReducers.js").IRemoveParameterPayload;
574
+ type: string;
575
+ }) => void | import("./tabsState.js").ITabsState | import("immer").WritableDraft<import("./tabsState.js").ITabsState>;
564
576
  }, "tabs">;
@@ -6,6 +6,7 @@ import { dateFilterConfigsReducers } from "./dateFilterConfigs/dateFilterConfigs
6
6
  import { filterContextReducers } from "./filterContext/filterContextReducers.js";
7
7
  import { layoutReducers } from "./layout/layoutReducers.js";
8
8
  import { measureValueFilterConfigsReducers } from "./measureValueFilterConfigs/measureValueFilterConfigsReducers.js";
9
+ import { parametersReducers } from "./parameters/parametersReducers.js";
9
10
  import { tabsReducers } from "./tabsReducers.js";
10
11
  import { tabsInitialState } from "./tabsState.js";
11
12
  const allReducers = {
@@ -16,6 +17,7 @@ const allReducers = {
16
17
  ...measureValueFilterConfigsReducers,
17
18
  ...filterContextReducers,
18
19
  ...layoutReducers,
20
+ ...parametersReducers,
19
21
  };
20
22
  const tabsSlice = createSlice({
21
23
  name: "tabs",
@@ -1,9 +1,9 @@
1
1
  import { type Action, type CaseReducer } from "@reduxjs/toolkit";
2
2
  import { type IDashboardParameter, type ObjRef } from "@gooddata/sdk-model";
3
- import { type IDashboardParameterEntry, type IParametersState } from "./parametersState.js";
4
- type ParametersReducer<A extends Action> = CaseReducer<IParametersState, A>;
3
+ import { type ITabsState } from "../tabsState.js";
4
+ type ParametersReducer<A extends Action> = CaseReducer<ITabsState, A>;
5
5
  /**
6
- * Add a parameter to the dashboard. Initial `runtimeOverride` is `parameter.value`
6
+ * Add a parameter to the active tab. Initial `runtimeOverride` is `parameter.value`
7
7
  * (when pinned) otherwise the workspace default supplied by the caller.
8
8
  *
9
9
  * @alpha
@@ -38,9 +38,5 @@ export declare const parametersReducers: {
38
38
  payload: IRemoveParameterPayload;
39
39
  type: string;
40
40
  }>;
41
- setParameterEntries: ParametersReducer<{
42
- payload: IDashboardParameterEntry[];
43
- type: string;
44
- }>;
45
41
  };
46
42
  export {};