@gooddata/sdk-ui-dashboard 11.65.0-alpha.7 → 11.65.0-alpha.9

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 (98) hide show
  1. package/NOTICE +3 -91
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/index.d.ts +3 -2
  5. package/esm/index.d.ts.map +1 -1
  6. package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeDisplayFormHandler.d.ts.map +1 -1
  7. package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeDisplayFormHandler.js +8 -7
  8. package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.d.ts.map +1 -1
  9. package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.js +19 -28
  10. package/esm/model/commandHandlers/filterContext/attributeFilter/removeAttributeFiltersHandler.d.ts.map +1 -1
  11. package/esm/model/commandHandlers/filterContext/attributeFilter/removeAttributeFiltersHandler.js +4 -5
  12. package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.d.ts.map +1 -1
  13. package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.js +14 -15
  14. package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.d.ts +4 -1
  15. package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.d.ts.map +1 -1
  16. package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.js +11 -2
  17. package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.d.ts.map +1 -1
  18. package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.js +23 -45
  19. package/esm/model/commandHandlers/filterContext/common.d.ts +6 -5
  20. package/esm/model/commandHandlers/filterContext/common.d.ts.map +1 -1
  21. package/esm/model/commandHandlers/filterContext/common.js +12 -18
  22. package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.d.ts.map +1 -1
  23. package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.js +30 -36
  24. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.d.ts.map +1 -1
  25. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.js +11 -17
  26. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.d.ts.map +1 -1
  27. package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.js +7 -10
  28. package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.d.ts +15 -0
  29. package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.d.ts.map +1 -0
  30. package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.js +88 -0
  31. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.d.ts +11 -0
  32. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.d.ts.map +1 -0
  33. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.js +335 -0
  34. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.d.ts +52 -0
  35. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.d.ts.map +1 -0
  36. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.js +60 -0
  37. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.d.ts +69 -0
  38. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.d.ts.map +1 -0
  39. package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.js +2 -0
  40. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts +2 -1
  41. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts.map +1 -1
  42. package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.js +41 -10
  43. package/esm/model/commands/parameters.d.ts +11 -1
  44. package/esm/model/commands/parameters.d.ts.map +1 -1
  45. package/esm/model/commands/parameters.js +2 -1
  46. package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.d.ts +75 -5
  47. package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.d.ts.map +1 -1
  48. package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.js +35 -60
  49. package/esm/model/store/tabs/dateFilterConfigs/dateFilterConfigsReducers.js +1 -1
  50. package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts +139 -31
  51. package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts.map +1 -1
  52. package/esm/model/store/tabs/filterContext/filterContextReducers.js +314 -529
  53. package/esm/model/store/tabs/filterContext/filterSync.d.ts +35 -13
  54. package/esm/model/store/tabs/filterContext/filterSync.d.ts.map +1 -1
  55. package/esm/model/store/tabs/filterContext/filterSync.js +79 -58
  56. package/esm/model/store/tabs/index.d.ts +10 -12
  57. package/esm/model/store/tabs/index.d.ts.map +1 -1
  58. package/esm/model/store/tabs/layout/layoutReducers.d.ts +1 -0
  59. package/esm/model/store/tabs/layout/layoutReducers.d.ts.map +1 -1
  60. package/esm/model/store/tabs/measureValueFilterConfigs/measureValueFilterConfigsReducers.d.ts.map +1 -1
  61. package/esm/model/store/tabs/parameters/parametersReducers.d.ts +0 -5
  62. package/esm/model/store/tabs/parameters/parametersReducers.d.ts.map +1 -1
  63. package/esm/model/store/tabs/parameters/parametersReducers.js +8 -7
  64. package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +7 -0
  65. package/esm/model/store/tabs/parameters/parametersSelectors.d.ts.map +1 -1
  66. package/esm/model/store/tabs/parameters/parametersSelectors.js +16 -0
  67. package/esm/model/store/tabs/tabsReducers.d.ts +8 -4
  68. package/esm/model/store/tabs/tabsReducers.d.ts.map +1 -1
  69. package/esm/model/store/tabs/tabsReducers.js +15 -18
  70. package/esm/model/store/tabs/tabsState.d.ts +0 -10
  71. package/esm/model/store/tabs/tabsState.d.ts.map +1 -1
  72. package/esm/model/store/tabs/tabsState.js +0 -20
  73. package/esm/model/utils/attributeFilterMatching.d.ts +10 -0
  74. package/esm/model/utils/attributeFilterMatching.d.ts.map +1 -1
  75. package/esm/model/utils/attributeFilterMatching.js +14 -3
  76. package/esm/model/utils/attributeFilterSelectionTypeCompatibility.d.ts +8 -0
  77. package/esm/model/utils/attributeFilterSelectionTypeCompatibility.d.ts.map +1 -1
  78. package/esm/model/utils/attributeFilterSelectionTypeCompatibility.js +14 -4
  79. package/esm/presentation/dashboard/components/DashboardInner.js +1 -1
  80. package/esm/presentation/dashboard/components/DashboardInteractionComposing.d.ts +2 -1
  81. package/esm/presentation/dashboard/components/DashboardInteractionComposing.d.ts.map +1 -1
  82. package/esm/presentation/dashboard/components/DashboardInteractionComposing.js +9 -4
  83. package/esm/presentation/dashboard/types.d.ts +5 -0
  84. package/esm/presentation/dashboard/types.d.ts.map +1 -1
  85. package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.d.ts.map +1 -1
  86. package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.js +4 -1
  87. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +4 -0
  88. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  89. package/esm/presentation/localization/bundles/en-US.localization-bundle.js +4 -0
  90. package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/index.d.ts.map +1 -1
  91. package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/index.js +10 -1
  92. package/esm/sdk-ui-dashboard.d.ts +262 -43
  93. package/package.json +21 -21
  94. package/styles/css/dashboard.css +10 -2
  95. package/styles/css/dashboard.css.map +1 -1
  96. package/styles/css/main.css +10 -2
  97. package/styles/css/main.css.map +1 -1
  98. package/styles/scss/dashboard.scss +11 -2
@@ -0,0 +1,60 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { batchActions } from "redux-batched-actions";
3
+ import { call, put, select } from "redux-saga/effects";
4
+ import { selectCrossFilteringFiltersLocalIdentifiersByTab } from "../../../store/drill/drillSelectors.js";
5
+ import { selectEnablePersistentFiltersAcrossTabs, selectPersistedDashboardAttributeFilterConfigsByTab, } from "../../../store/meta/metaSelectors.js";
6
+ import { selectActiveTabLocalIdentifier, selectTabsState } from "../../../store/tabs/tabsSelectors.js";
7
+ import { captureFilterContextByTabSnapshot, dispatchFilterContextChanged, dispatchFilterContextChangedForMutatedTabs, } from "../common.js";
8
+ import { expandActionsForTabSync } from "./expandActionsForTabSync.js";
9
+ /**
10
+ * Starts tab sync for a command. Call before reading the state that the command changes.
11
+ *
12
+ * @internal
13
+ */
14
+ export function* beginTabSync(options = {}) {
15
+ const enablePersistentFiltersAcrossTabs = yield select(selectEnablePersistentFiltersAcrossTabs);
16
+ const activeTabLocalIdentifier = yield select(selectActiveTabLocalIdentifier);
17
+ const enabled = !!enablePersistentFiltersAcrossTabs && (options.enabled ?? true);
18
+ const sourceTabLocalIdentifier = options.tabLocalIdentifier ?? activeTabLocalIdentifier;
19
+ const crossFilteringLocalIdsByTab = enabled ? yield select(selectCrossFilteringFiltersLocalIdentifiersByTab) : {};
20
+ const persistedAttributeFilterConfigsByTab = enabled ? yield select(selectPersistedDashboardAttributeFilterConfigsByTab) : {};
21
+ const snapshot = enabled
22
+ ? yield call(captureFilterContextByTabSnapshot)
23
+ : undefined;
24
+ return {
25
+ scope: {
26
+ enabled,
27
+ sourceTabLocalIdentifier,
28
+ crossFilteringLocalIdsByTab,
29
+ persistedAttributeFilterConfigsByTab,
30
+ },
31
+ snapshot,
32
+ };
33
+ }
34
+ /**
35
+ * Dispatches `actions` together with their copies for the other tabs, as one batch.
36
+ *
37
+ * @returns every dispatched action, copies included
38
+ * @internal
39
+ */
40
+ export function* putTabSynced(session, actions) {
41
+ if (actions.length === 0) {
42
+ return [];
43
+ }
44
+ const tabsState = yield select(selectTabsState);
45
+ const expanded = expandActionsForTabSync(tabsState, actions, session.scope);
46
+ yield put(expanded.length === 1 ? expanded[0] : batchActions(expanded));
47
+ return expanded;
48
+ }
49
+ /**
50
+ * Emits a filter context changed event for the source tab, also when the command changed nothing,
51
+ * and when sync is enabled one more for every other tab the command changed.
52
+ *
53
+ * @internal
54
+ */
55
+ export function* endTabSync(ctx, cmd, session, tabLocalIdentifier) {
56
+ yield call(dispatchFilterContextChanged, ctx, cmd, tabLocalIdentifier);
57
+ if (session.snapshot) {
58
+ yield call(dispatchFilterContextChangedForMutatedTabs, ctx, cmd, session.snapshot, session.scope.sourceTabLocalIdentifier);
59
+ }
60
+ }
@@ -0,0 +1,69 @@
1
+ import { type PayloadAction } from "@reduxjs/toolkit";
2
+ import { type IDashboardAttributeFilterConfig } from "@gooddata/sdk-model";
3
+ import { type CrossFilteringLocalIdsByTab } from "../../../store/tabs/filterContext/filterSync.js";
4
+ import { type ITabState, type ITabsState } from "../../../store/tabs/tabsState.js";
5
+ /**
6
+ * Everything the tab sync planner needs to know about the command being handled.
7
+ * Built once per command by {@link beginTabSync}.
8
+ *
9
+ * @internal
10
+ */
11
+ export interface ITabSyncScope {
12
+ /**
13
+ * False when filters are not persisted across tabs, or when the handler opts out
14
+ * for this command (e.g. cross-filtering virtual filters). Nothing is mirrored then.
15
+ */
16
+ readonly enabled: boolean;
17
+ /**
18
+ * Tab the command was issued on. Synced actions without `tabLocalIdentifier` in their payload
19
+ * are addressed to this tab; the active tab is used when undefined.
20
+ */
21
+ readonly sourceTabLocalIdentifier: string | undefined;
22
+ /**
23
+ * Cross-filtering virtual filters, which are never mirrored to or from other tabs.
24
+ */
25
+ readonly crossFilteringLocalIdsByTab: CrossFilteringLocalIdsByTab;
26
+ /**
27
+ * Attribute filter configs of the saved dashboard keyed by tab local identifier. A tab that is
28
+ * missing has no saved configs, so a reset leaves its display-as labels unchanged.
29
+ */
30
+ readonly persistedAttributeFilterConfigsByTab?: Readonly<Record<string, readonly IDashboardAttributeFilterConfig[]>>;
31
+ }
32
+ /**
33
+ * Input of a single tab sync rule.
34
+ *
35
+ * @internal
36
+ */
37
+ export interface ITabSyncRuleContext {
38
+ readonly scope: ITabSyncScope;
39
+ /**
40
+ * Tabs state before the source action is applied. Mirrored actions of previous
41
+ * actions in the same batch are already applied.
42
+ */
43
+ readonly state: ITabsState;
44
+ /**
45
+ * Source tab before the source action is applied.
46
+ */
47
+ readonly source: ITabState;
48
+ /**
49
+ * Source tab after the source action is applied.
50
+ */
51
+ readonly sourceAfter: ITabState;
52
+ }
53
+ /**
54
+ * Translates the payload of an action applied on the source tab into the payload
55
+ * of the same action for `target`. Returns undefined when `target` is left untouched.
56
+ * The planner sets `tabLocalIdentifier` of the returned payload.
57
+ *
58
+ * @internal
59
+ */
60
+ export type TabSyncRule<P> = (payload: P, target: ITabState, ctx: ITabSyncRuleContext) => P | undefined;
61
+ /**
62
+ * Translates the payload of an action applied on the source tab into the actions that apply it
63
+ * to `target`. Returns an empty array when `target` is left untouched.
64
+ * The planner sets `tabLocalIdentifier` of every returned payload.
65
+ *
66
+ * @internal
67
+ */
68
+ export type TabSyncActionsRule<P> = (payload: P, target: ITabState, ctx: ITabSyncRuleContext) => PayloadAction<object>[];
69
+ //# sourceMappingURL=tabSyncScope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabSyncScope.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/filterContext/tabSync/tabSyncScope.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,KAAK,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,KAAK,2BAA2B,EAAE,MAAM,iDAAiD,CAAC;AACnG,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAEnF;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtD;;OAEG;IACH,QAAQ,CAAC,2BAA2B,EAAE,2BAA2B,CAAC;IAClE;;;OAGG;IACH,QAAQ,CAAC,oCAAoC,CAAC,EAAE,QAAQ,CACpD,MAAM,CAAC,MAAM,EAAE,SAAS,+BAA+B,EAAE,CAAC,CAC7D,CAAC;CACL;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC;CACnC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,mBAAmB,KAAK,CAAC,GAAG,SAAS,CAAC;AAExG;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAChC,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,mBAAmB,KACvB,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ // (C) 2026 GoodData Corporation
2
+ export {};
@@ -5,7 +5,8 @@ import { type IChangeParameterValues } from "../../commands/parameters.js";
5
5
  import { type DashboardContext } from "../../types/commonTypes.js";
6
6
  /**
7
7
  * Parameters not present on a written tab are ignored by the reducer. When persistent filters
8
- * across tabs are on, the same values are written to every tab. A change event is emitted for
8
+ * across tabs are on, the same values are written to every tab, or with `restorePerTabOriginals`
9
+ * every other tab resets them to its own reset values. A change event is emitted for
9
10
  * each tab whose applied values differ from the snapshot, source tab first.
10
11
  *
11
12
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"changeParameterValuesHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/parameters/changeParameterValuesHandler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAElE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAQ3E,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;;;;GAMG;AACH,wBAAiB,4BAA4B,CACzC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,sBAAsB,GAC5B,YAAY,CAAC,IAAI,CAAC,CAsBpB;AAED;;;;;GAKG;AACH,wBAAiB,wCAAwC,CACrD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,EAAE,GAAG,SAAS,CAAC,EAClE,WAAW,EAAE,MAAM,GACpB,YAAY,CAAC,IAAI,CAAC,CAOpB;AAED;;;;;GAKG;AACH,wBAAiB,yBAAyB,CACtC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,iBAAiB,EACtB,kBAAkB,EAAE,MAAM,EAC1B,YAAY,EAAE,sBAAsB,EAAE,GAAG,SAAS,GACnD,YAAY,CAAC,IAAI,CAAC,CASpB"}
1
+ {"version":3,"file":"changeParameterValuesHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/parameters/changeParameterValuesHandler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAE,KAAK,sBAAsB,EAAmB,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAY3E,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE;;;;;;;GAOG;AACH,wBAAiB,4BAA4B,CACzC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,sBAAsB,GAC5B,YAAY,CAAC,IAAI,CAAC,CAwBpB;AAoCD;;;;;GAKG;AACH,wBAAiB,wCAAwC,CACrD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,EAAE,GAAG,SAAS,CAAC,EAClE,WAAW,EAAE,MAAM,GACpB,YAAY,CAAC,IAAI,CAAC,CAOpB;AAED;;;;;GAKG;AACH,wBAAiB,yBAAyB,CACtC,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,iBAAiB,EACtB,kBAAkB,EAAE,MAAM,EAC1B,YAAY,EAAE,sBAAsB,EAAE,GAAG,SAAS,GACnD,YAAY,CAAC,IAAI,CAAC,CASpB"}
@@ -1,16 +1,19 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { isEqual } from "lodash-es";
3
- import { call, put, select } from "redux-saga/effects";
3
+ import { call, select } from "redux-saga/effects";
4
+ import { areObjRefsEqual } from "@gooddata/sdk-model";
4
5
  import { parametersChanged } from "../../events/parameters.js";
5
6
  import { dispatchDashboardEvent } from "../../store/_infra/eventDispatcher.js";
6
7
  import { selectEnableParameters } from "../../store/config/configSelectors.js";
7
8
  import { selectEnablePersistentFiltersAcrossTabs } from "../../store/meta/metaSelectors.js";
8
9
  import { tabsActions } from "../../store/tabs/index.js";
9
- import { selectParameterValuesByTab } from "../../store/tabs/parameters/parametersSelectors.js";
10
+ import { selectDashboardParametersByTab, selectParameterResetTargetsByTab, selectParameterValuesByTab, } from "../../store/tabs/parameters/parametersSelectors.js";
10
11
  import { selectActiveOrDefaultTabLocalIdentifier } from "../../store/tabs/tabsSelectors.js";
12
+ import { beginTabSync, putTabSynced } from "../filterContext/tabSync/tabSyncSaga.js";
11
13
  /**
12
14
  * Parameters not present on a written tab are ignored by the reducer. When persistent filters
13
- * across tabs are on, the same values are written to every tab. A change event is emitted for
15
+ * across tabs are on, the same values are written to every tab, or with `restorePerTabOriginals`
16
+ * every other tab resets them to its own reset values. A change event is emitted for
14
17
  * each tab whose applied values differ from the snapshot, source tab first.
15
18
  *
16
19
  * @internal
@@ -20,16 +23,44 @@ export function* changeParameterValuesHandler(ctx, cmd) {
20
23
  if (!enableParameters) {
21
24
  return;
22
25
  }
23
- const tabId = cmd.payload.tabLocalIdentifier ?? (yield select(selectActiveOrDefaultTabLocalIdentifier));
24
- const enablePersistentFiltersAcrossTabs = yield select(selectEnablePersistentFiltersAcrossTabs);
26
+ const { parameters, tabLocalIdentifier, restorePerTabOriginals } = cmd.payload;
27
+ const tabId = tabLocalIdentifier ?? (yield select(selectActiveOrDefaultTabLocalIdentifier));
25
28
  const valuesBefore = yield select(selectParameterValuesByTab);
26
- yield put(tabsActions.setParameterRuntimeValues({
27
- values: cmd.payload.parameters,
28
- tabLocalIdentifier: cmd.payload.tabLocalIdentifier,
29
- enablePersistentFiltersAcrossTabs,
30
- }));
29
+ const session = yield call(beginTabSync, {
30
+ tabLocalIdentifier,
31
+ enabled: !restorePerTabOriginals,
32
+ });
33
+ const restoreActions = restorePerTabOriginals
34
+ ? yield call(getOtherTabsParameterResetActions, tabId)
35
+ : [];
36
+ yield call(putTabSynced, session, [
37
+ tabsActions.setParameterRuntimeValues({ values: parameters, tabLocalIdentifier }),
38
+ ...restoreActions,
39
+ ]);
31
40
  yield call(dispatchParametersChangedForAffectedTabs, ctx, cmd, valuesBefore, tabId);
32
41
  }
42
+ /**
43
+ * When filters persist across tabs, every other tab resets the parameters that `sourceTabId` defines
44
+ * to its own reset values.
45
+ */
46
+ function* getOtherTabsParameterResetActions(sourceTabId) {
47
+ const persistAcrossTabs = yield select(selectEnablePersistentFiltersAcrossTabs);
48
+ if (!persistAcrossTabs) {
49
+ return [];
50
+ }
51
+ const parametersByTab = yield select(selectDashboardParametersByTab);
52
+ const resetTargetsByTab = yield select(selectParameterResetTargetsByTab);
53
+ const sourceParameters = parametersByTab[sourceTabId] ?? [];
54
+ return Object.entries(resetTargetsByTab).flatMap(([tabLocalIdentifier, targets]) => {
55
+ if (tabLocalIdentifier === sourceTabId) {
56
+ return [];
57
+ }
58
+ const values = targets.filter((target) => sourceParameters.some((parameter) => areObjRefsEqual(parameter.ref, target.ref)));
59
+ return values.length > 0
60
+ ? [tabsActions.setParameterRuntimeValues({ values, tabLocalIdentifier })]
61
+ : [];
62
+ });
63
+ }
33
64
  /**
34
65
  * Emits one `GDC.DASH/EVT.PARAMETERS.CHANGED` per tab whose applied values changed. Local parameter
35
66
  * state is stored from that event, so every written tab has to emit or its saved value stays stale.
@@ -21,6 +21,10 @@ export type ChangeParameterValuesParams = {
21
21
  */
22
22
  tabLocalIdentifier?: string;
23
23
  correlationId?: string;
24
+ /**
25
+ * See {@link IChangeParameterValuesPayload.restorePerTabOriginals}.
26
+ */
27
+ restorePerTabOriginals?: boolean;
24
28
  };
25
29
  /**
26
30
  * Payload of the {@link IChangeParameterValues} command.
@@ -30,6 +34,12 @@ export type ChangeParameterValuesParams = {
30
34
  export interface IChangeParameterValuesPayload {
31
35
  readonly parameters: IParameterValueChange[];
32
36
  readonly tabLocalIdentifier?: string;
37
+ /**
38
+ * When true, tabs other than the one this command addresses reset the parameters that tab
39
+ * defines to their own reset values instead of receiving this payload. Used by filter reset
40
+ * when filters are persisted across tabs.
41
+ */
42
+ readonly restorePerTabOriginals?: boolean;
33
43
  }
34
44
  /**
35
45
  * Command for setting runtime parameter overrides.
@@ -58,5 +68,5 @@ export interface IChangeParameterValues extends IDashboardCommand {
58
68
  * @param params - params for the command creator
59
69
  * @internal
60
70
  */
61
- export declare function changeParameterValues({ parameters, tabLocalIdentifier, correlationId, }: ChangeParameterValuesParams): IChangeParameterValues;
71
+ export declare function changeParameterValues({ parameters, tabLocalIdentifier, correlationId, restorePerTabOriginals, }: ChangeParameterValuesParams): IChangeParameterValues;
62
72
  //# sourceMappingURL=parameters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../../src/model/commands/parameters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACtC,UAAU,EAAE,qBAAqB,EAAE,CAAC;IACpC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC1C,QAAQ,CAAC,UAAU,EAAE,qBAAqB,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,IAAI,EAAE,uCAAuC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,6BAA6B,CAAC;CACnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,EAClC,UAAU,EACV,kBAAkB,EAClB,aAAa,GAChB,EAAE,2BAA2B,GAAG,sBAAsB,CAStD"}
1
+ {"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../../src/model/commands/parameters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACtC,UAAU,EAAE,qBAAqB,EAAE,CAAC;IACpC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC1C,QAAQ,CAAC,UAAU,EAAE,qBAAqB,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAC7C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC7D,QAAQ,CAAC,IAAI,EAAE,uCAAuC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,6BAA6B,CAAC;CACnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,EAClC,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,sBAAsB,GACzB,EAAE,2BAA2B,GAAG,sBAAsB,CAUtD"}
@@ -14,13 +14,14 @@
14
14
  * @param params - params for the command creator
15
15
  * @internal
16
16
  */
17
- export function changeParameterValues({ parameters, tabLocalIdentifier, correlationId, }) {
17
+ export function changeParameterValues({ parameters, tabLocalIdentifier, correlationId, restorePerTabOriginals, }) {
18
18
  return {
19
19
  type: "GDC.DASH/CMD.PARAMETERS.CHANGE_VALUES",
20
20
  correlationId,
21
21
  payload: {
22
22
  parameters,
23
23
  tabLocalIdentifier,
24
+ ...(restorePerTabOriginals ? { restorePerTabOriginals } : {}),
24
25
  },
25
26
  };
26
27
  }
@@ -1,15 +1,85 @@
1
1
  import { type Action, type CaseReducer } from "@reduxjs/toolkit";
2
- import { type ISetDashboardAttributeFilterConfigDisplayAsLabelPayload, type ISetDashboardAttributeFilterConfigModePayload, type ISetDashboardAttributeFilterSelectionTypePayload } from "../../../../model/commands/dashboard.js";
2
+ import { type DashboardAttributeFilterConfigMode, type DashboardAttributeFilterSelectionType, type ObjRef } from "@gooddata/sdk-model";
3
3
  import { type TabsReducer } from "../tabsReducers.js";
4
4
  import { type ITabsState } from "../tabsState.js";
5
5
  type AttributeFilterConfigReducer<A extends Action> = CaseReducer<ITabsState, A>;
6
+ /**
7
+ * @internal
8
+ */
9
+ export interface IChangeAttributeFilterConfigModePayload {
10
+ /**
11
+ * Local identifier of the filter to change mode.
12
+ */
13
+ localIdentifier: string;
14
+ /**
15
+ * Mode of the attribute filter.
16
+ */
17
+ mode?: DashboardAttributeFilterConfigMode;
18
+ /**
19
+ * Optional tab local identifier to target a specific tab.
20
+ * If not provided, the active tab will be used.
21
+ */
22
+ tabLocalIdentifier?: string;
23
+ }
24
+ /**
25
+ * @internal
26
+ */
27
+ export interface IChangeAttributeFilterSelectionTypePayload {
28
+ /**
29
+ * Local identifier of the filter to change available mode.
30
+ */
31
+ localIdentifier: string;
32
+ /**
33
+ * Available mode of the attribute filter — controls which presentation modes
34
+ * (list, text, or both) are available to the user in Dashboard View mode.
35
+ */
36
+ selectionType?: DashboardAttributeFilterSelectionType;
37
+ /**
38
+ * Optional tab local identifier to target a specific tab.
39
+ * If not provided, the active tab will be used.
40
+ */
41
+ tabLocalIdentifier?: string;
42
+ }
43
+ /**
44
+ * @internal
45
+ */
46
+ export interface IChangeAttributeFilterDisplayAsLabelPayload {
47
+ /**
48
+ * Local identifier of the filter to change display as label (= display form).
49
+ */
50
+ localIdentifier: string;
51
+ /**
52
+ * Display as label of the attribute filter. Used to present filter in UI
53
+ */
54
+ displayAsLabel: ObjRef | undefined;
55
+ /**
56
+ * Optional tab local identifier to target a specific tab.
57
+ * If not provided, the active tab will be used.
58
+ */
59
+ tabLocalIdentifier?: string;
60
+ /**
61
+ * When true, tabs this change is synced to restore their own saved display as label instead of this payload.
62
+ */
63
+ restoreTargetOriginal?: boolean;
64
+ }
65
+ /**
66
+ * @internal
67
+ */
68
+ export interface IRemoveAttributeFilterConfigPayload {
69
+ readonly localIdentifier: string;
70
+ /**
71
+ * Optional tab local identifier to target a specific tab.
72
+ * If not provided, the active tab will be used.
73
+ */
74
+ readonly tabLocalIdentifier?: string;
75
+ }
6
76
  export declare const attributeFilterConfigsReducers: {
7
77
  changeAttributeFilterConfigMode: AttributeFilterConfigReducer<{
8
- payload: ISetDashboardAttributeFilterConfigModePayload;
78
+ payload: IChangeAttributeFilterConfigModePayload;
9
79
  type: string;
10
80
  }>;
11
81
  changeAttributeFilterSelectionType: AttributeFilterConfigReducer<{
12
- payload: ISetDashboardAttributeFilterSelectionTypePayload;
82
+ payload: IChangeAttributeFilterSelectionTypePayload;
13
83
  type: string;
14
84
  }>;
15
85
  setAttributeFilterConfigs: AttributeFilterConfigReducer<{
@@ -17,11 +87,11 @@ export declare const attributeFilterConfigsReducers: {
17
87
  type: string;
18
88
  }>;
19
89
  removeAttributeFilterConfig: TabsReducer<{
20
- payload: string;
90
+ payload: IRemoveAttributeFilterConfigPayload;
21
91
  type: string;
22
92
  }>;
23
93
  changeDisplayAsLabel: AttributeFilterConfigReducer<{
24
- payload: ISetDashboardAttributeFilterConfigDisplayAsLabelPayload;
94
+ payload: IChangeAttributeFilterDisplayAsLabelPayload;
25
95
  type: string;
26
96
  }>;
27
97
  };
@@ -1 +1 @@
1
- {"version":3,"file":"attributeFilterConfigsReducers.d.ts","sourceRoot":"","sources":["../../../../../src/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AAErF,OAAO,EACH,KAAK,uDAAuD,EAC5D,KAAK,6CAA6C,EAClD,KAAK,gDAAgD,EACxD,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,iBAAiB,CAAC;AAEhF,KAAK,4BAA4B,CAAC,CAAC,SAAS,MAAM,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AA6HjF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;CAM1C,CAAC"}
1
+ {"version":3,"file":"attributeFilterConfigsReducers.d.ts","sourceRoot":"","sources":["../../../../../src/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AAErF,OAAO,EACH,KAAK,kCAAkC,EACvC,KAAK,qCAAqC,EAE1C,KAAK,MAAM,EACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAkB,KAAK,UAAU,EAAgC,MAAM,iBAAiB,CAAC;AAEhG,KAAK,4BAA4B,CAAC,CAAC,SAAS,MAAM,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,uCAAuC;IACpD;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,kCAAkC,CAAC;IAC1C;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,0CAA0C;IACvD;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,qCAAqC,CAAC;IACtD;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,2CAA2C;IACxD;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,mCAAmC;IAChD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACxC;AAyGD,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;CAM1C,CAAC"}
@@ -4,27 +4,12 @@ import { getActiveTab, getTabOrActive } from "../tabsState.js";
4
4
  * Changes the config mode for the attribute filter given by its local identifier.
5
5
  */
6
6
  const changeAttributeFilterConfigMode = (state, action) => {
7
- const { localIdentifier } = action.payload;
8
- const activeTab = getActiveTab(state);
9
- if (!activeTab) {
7
+ const { localIdentifier, mode, tabLocalIdentifier } = action.payload;
8
+ const targetTab = getTabOrActive(state, tabLocalIdentifier);
9
+ if (!targetTab) {
10
10
  return;
11
11
  }
12
- if (!activeTab.attributeFilterConfigs) {
13
- activeTab.attributeFilterConfigs = { attributeFilterConfigs: [] };
14
- }
15
- const existingConfig = activeTab.attributeFilterConfigs.attributeFilterConfigs?.find((item) => item.localIdentifier === localIdentifier);
16
- if (existingConfig) {
17
- existingConfig.mode = action.payload.mode;
18
- activeTab.attributeFilterConfigs.attributeFilterConfigs = [
19
- ...(activeTab.attributeFilterConfigs.attributeFilterConfigs ?? []),
20
- ];
21
- }
22
- else {
23
- activeTab.attributeFilterConfigs.attributeFilterConfigs = [
24
- ...(activeTab.attributeFilterConfigs.attributeFilterConfigs || []),
25
- action.payload,
26
- ];
27
- }
12
+ upsertAttributeFilterConfig(targetTab, localIdentifier, { mode });
28
13
  };
29
14
  /**
30
15
  * Changes the config mode for the filter given by its local identifier.
@@ -35,48 +20,18 @@ const changeDisplayAsLabel = (state, action) => {
35
20
  if (!targetTab) {
36
21
  return;
37
22
  }
38
- if (!targetTab.attributeFilterConfigs) {
39
- targetTab.attributeFilterConfigs = { attributeFilterConfigs: [] };
40
- }
41
- const existingConfig = targetTab.attributeFilterConfigs.attributeFilterConfigs?.find((item) => item.localIdentifier === localIdentifier);
42
- if (existingConfig) {
43
- existingConfig.displayAsLabel = displayAsLabel;
44
- targetTab.attributeFilterConfigs.attributeFilterConfigs = [
45
- ...(targetTab.attributeFilterConfigs.attributeFilterConfigs ?? []),
46
- ];
47
- }
48
- else {
49
- targetTab.attributeFilterConfigs.attributeFilterConfigs = [
50
- ...(targetTab.attributeFilterConfigs.attributeFilterConfigs || []),
51
- action.payload,
52
- ];
53
- }
23
+ upsertAttributeFilterConfig(targetTab, localIdentifier, { displayAsLabel });
54
24
  };
55
25
  /**
56
26
  * Changes the available mode for the attribute filter given by its local identifier.
57
27
  */
58
28
  const changeAttributeFilterSelectionType = (state, action) => {
59
- const { localIdentifier } = action.payload;
60
- const activeTab = getActiveTab(state);
61
- if (!activeTab) {
29
+ const { localIdentifier, selectionType, tabLocalIdentifier } = action.payload;
30
+ const targetTab = getTabOrActive(state, tabLocalIdentifier);
31
+ if (!targetTab) {
62
32
  return;
63
33
  }
64
- if (!activeTab.attributeFilterConfigs) {
65
- activeTab.attributeFilterConfigs = { attributeFilterConfigs: [] };
66
- }
67
- const existingConfig = activeTab.attributeFilterConfigs.attributeFilterConfigs?.find((item) => item.localIdentifier === localIdentifier);
68
- if (existingConfig) {
69
- existingConfig.selectionType = action.payload.selectionType;
70
- activeTab.attributeFilterConfigs.attributeFilterConfigs = [
71
- ...(activeTab.attributeFilterConfigs.attributeFilterConfigs ?? []),
72
- ];
73
- }
74
- else {
75
- activeTab.attributeFilterConfigs.attributeFilterConfigs = [
76
- ...(activeTab.attributeFilterConfigs.attributeFilterConfigs || []),
77
- action.payload,
78
- ];
79
- }
34
+ upsertAttributeFilterConfig(targetTab, localIdentifier, { selectionType });
80
35
  };
81
36
  const setAttributeFilterConfigs = (state, action) => {
82
37
  const { attributeFilterConfigs } = action.payload;
@@ -91,15 +46,35 @@ const setAttributeFilterConfigs = (state, action) => {
91
46
  : undefined;
92
47
  };
93
48
  const removeAttributeFilterConfig = (state, action) => {
94
- const activeTab = getActiveTab(state);
95
- if (!activeTab) {
49
+ const { localIdentifier, tabLocalIdentifier } = action.payload;
50
+ const configs = getTabOrActive(state, tabLocalIdentifier)?.attributeFilterConfigs;
51
+ if (!configs?.attributeFilterConfigs) {
96
52
  return;
97
53
  }
98
- if (activeTab.attributeFilterConfigs?.attributeFilterConfigs) {
99
- activeTab.attributeFilterConfigs.attributeFilterConfigs =
100
- activeTab.attributeFilterConfigs.attributeFilterConfigs.filter((attributeFilterConfig) => attributeFilterConfig.localIdentifier !== action.payload);
101
- }
54
+ configs.attributeFilterConfigs = configs.attributeFilterConfigs.filter((config) => config.localIdentifier !== localIdentifier);
102
55
  };
56
+ function upsertAttributeFilterConfig(tab, localIdentifier, patch) {
57
+ if (!tab.attributeFilterConfigs) {
58
+ tab.attributeFilterConfigs = { attributeFilterConfigs: [] };
59
+ }
60
+ const configs = tab.attributeFilterConfigs.attributeFilterConfigs ?? [];
61
+ // const existingConfig = configs.find((item) => item.localIdentifier === localIdentifier);
62
+ const existingConfig = tab.attributeFilterConfigs.attributeFilterConfigs?.find((item) => item.localIdentifier === localIdentifier);
63
+ if (existingConfig) {
64
+ if ("mode" in patch) {
65
+ existingConfig.mode = patch.mode;
66
+ }
67
+ if ("displayAsLabel" in patch) {
68
+ existingConfig.displayAsLabel = patch.displayAsLabel;
69
+ }
70
+ if ("selectionType" in patch) {
71
+ existingConfig.selectionType = patch.selectionType;
72
+ }
73
+ tab.attributeFilterConfigs.attributeFilterConfigs = [...configs];
74
+ return;
75
+ }
76
+ tab.attributeFilterConfigs.attributeFilterConfigs = [...configs, { localIdentifier, ...patch }];
77
+ }
103
78
  export const attributeFilterConfigsReducers = {
104
79
  changeAttributeFilterConfigMode,
105
80
  changeAttributeFilterSelectionType,
@@ -3,7 +3,7 @@ import { invariant } from "ts-invariant";
3
3
  import { areObjRefsEqual } from "@gooddata/sdk-model";
4
4
  import { getActiveTab } from "../tabsState.js";
5
5
  /**
6
- * Changes the config mode for the date filter given by its data seet.
6
+ * Changes the config mode for the date filter given by its data set.
7
7
  */
8
8
  const changeDateFilterConfigsMode = (state, action) => {
9
9
  const { dataSet } = action.payload;