@gooddata/sdk-ui-dashboard 11.36.0-alpha.1 → 11.36.0-alpha.2

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 (53) hide show
  1. package/esm/__version.d.ts +1 -1
  2. package/esm/__version.js +1 -1
  3. package/esm/_staging/drills/drillingUtils.d.ts +9 -0
  4. package/esm/_staging/drills/drillingUtils.js +19 -1
  5. package/esm/index.d.ts +2 -2
  6. package/esm/index.js +1 -1
  7. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.js +9 -2
  8. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadMeasureParameterDependencies.d.ts +12 -0
  9. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadMeasureParameterDependencies.js +98 -0
  10. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/resolveDashboardConfig.js +1 -0
  11. package/esm/model/commandHandlers/drill/common/mergeFilters.d.ts +3 -3
  12. package/esm/model/commandHandlers/drill/common/mergeFilters.js +26 -1
  13. package/esm/model/commandHandlers/drill/common/sourceDrillFilters.d.ts +2 -1
  14. package/esm/model/commandHandlers/drill/common/sourceDrillFilters.js +25 -5
  15. package/esm/model/commandHandlers/drill/drillToDashboardHandler.js +17 -16
  16. package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.js +7 -4
  17. package/esm/model/commandHandlers/filterContext/measureValueFilter/removeMeasureValueFilterHandler.js +7 -0
  18. package/esm/model/react/useWidgetFilters.js +4 -1
  19. package/esm/model/store/catalog/catalogReducers.d.ts +5 -1
  20. package/esm/model/store/catalog/catalogReducers.js +4 -0
  21. package/esm/model/store/catalog/catalogSelectors.d.ts +15 -2
  22. package/esm/model/store/catalog/catalogSelectors.js +13 -0
  23. package/esm/model/store/catalog/catalogState.d.ts +20 -1
  24. package/esm/model/store/catalog/catalogState.js +1 -0
  25. package/esm/model/store/catalog/index.d.ts +1 -0
  26. package/esm/model/store/tabs/index.d.ts +6 -0
  27. package/esm/model/store/tabs/layout/layoutReducers.d.ts +4 -0
  28. package/esm/model/store/tabs/layout/layoutReducers.js +25 -0
  29. package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +19 -6
  30. package/esm/model/store/tabs/parameters/parametersSelectors.js +69 -16
  31. package/esm/presentation/filterBar/parameterFilter/DashboardParameterFilter.js +3 -2
  32. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +8 -0
  33. package/esm/presentation/localization/bundles/en-US.localization-bundle.js +8 -0
  34. package/esm/presentation/widget/common/configuration/FilterConfiguration.js +4 -2
  35. package/esm/presentation/widget/common/configuration/useMeasureValueFilterCompatibility.d.ts +6 -2
  36. package/esm/presentation/widget/common/configuration/useMeasureValueFilterCompatibility.js +95 -22
  37. package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/useExcludedDrillDefinitionFilters.js +2 -2
  38. package/esm/presentation/widget/insight/configuration/DrillFilters/TargetDashboardFiltersContext.d.ts +2 -1
  39. package/esm/presentation/widget/insight/configuration/DrillFilters/TargetDashboardFiltersContext.js +3 -1
  40. package/esm/presentation/widget/insight/configuration/DrillFilters/drillFiltersConfigUtils.d.ts +4 -1
  41. package/esm/presentation/widget/insight/configuration/DrillFilters/drillFiltersConfigUtils.js +15 -1
  42. package/esm/presentation/widget/insight/configuration/DrillFilters/messages.d.ts +6 -0
  43. package/esm/presentation/widget/insight/configuration/DrillFilters/messages.js +6 -0
  44. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapDashboardFilterToOption.d.ts +6 -2
  45. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapDashboardFilterToOption.js +18 -3
  46. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapSourceInsightFilterToOption.d.ts +4 -2
  47. package/esm/presentation/widget/insight/configuration/DrillFilters/optionMappings/mapSourceInsightFilterToOption.js +10 -6
  48. package/esm/presentation/widget/insight/configuration/DrillFilters/types.d.ts +2 -1
  49. package/esm/presentation/widget/insight/configuration/DrillFilters/useDrillFiltersConfig.js +78 -6
  50. package/esm/presentation/widget/insight/configuration/DrillFilters/useFetchTargetDashboardFilters.d.ts +2 -1
  51. package/esm/presentation/widget/insight/configuration/DrillFilters/useFetchTargetDashboardFilters.js +4 -1
  52. package/esm/sdk-ui-dashboard.d.ts +53 -6
  53. package/package.json +20 -20
@@ -1,3 +1,3 @@
1
- export declare const LIB_VERSION = "11.36.0-alpha.1";
1
+ export declare const LIB_VERSION = "11.36.0-alpha.2";
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.36.0-alpha.1";
3
+ export const LIB_VERSION = "11.36.0-alpha.2";
4
4
  export const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
5
5
  export const LIB_NAME = "@gooddata/sdk-ui-dashboard";
@@ -40,3 +40,12 @@ export declare function isMatchingSourceInsightFilter(filter: IFilter, sourceFil
40
40
  export declare function isSourceInsightFilterObjRefEqual(left: SourceInsightFilterObjRef, right: SourceInsightFilterObjRef): boolean;
41
41
  export declare function sourceInsightFilterObjRef(filter: IFilter): SourceInsightFilterObjRef | undefined;
42
42
  export declare function sourceInsightFilterObjRefValue(sourceFilterObjRef: SourceInsightFilterObjRef): ObjRefInScope;
43
+ /**
44
+ * Resolves a measure-scoped ref from an insight filter to the underlying catalog measure ref.
45
+ *
46
+ * Source insight MVFs usually target a local measure identifier, while dashboard MVFs target
47
+ * the metric object ref. Use this when comparing or merging source MVFs with dashboard MVFs.
48
+ *
49
+ * @internal
50
+ */
51
+ export declare function resolveSourceMeasureRef(measureRef: ObjRefInScope | undefined, sourceInsightMeasures: IMeasure[]): ObjRef | undefined;
@@ -1,6 +1,6 @@
1
1
  // (C) 2020-2026 GoodData Corporation
2
2
  import { isEqual } from "lodash-es";
3
- import { areObjRefsEqual, drillDownReferenceHierarchyRef, filterMeasureRef, filterObjRef, isAttributeFilter, isCrossFiltering, isDateFilter, isDrillFromAttribute, isDrillFromMeasure, isDrillToLegacyDashboard, isIdentifierRef, isKeyDriveAnalysis, isLocalIdRef, isMeasureDescriptor, isMeasureValueFilter, isRankingFilter, measureFilters, measureLocalId, } from "@gooddata/sdk-model";
3
+ import { areObjRefsEqual, drillDownReferenceHierarchyRef, filterMeasureRef, filterObjRef, isAttributeFilter, isCrossFiltering, isDateFilter, isDrillFromAttribute, isDrillFromMeasure, isDrillToLegacyDashboard, isIdentifierRef, isKeyDriveAnalysis, isLocalIdRef, isMeasureDescriptor, isMeasureValueFilter, isRankingFilter, measureFilters, measureItem, measureLocalId, } from "@gooddata/sdk-model";
4
4
  import { getMappingHeaderLocalIdentifier, } from "@gooddata/sdk-ui";
5
5
  export function getDrillsBySourceLocalIdentifiers(widgetDrillDefinition, drillSourceLocalIdentifiers) {
6
6
  return widgetDrillDefinition.filter((d) => isDrillToLegacyDashboard(d) ||
@@ -185,3 +185,21 @@ export function sourceInsightFilterObjRefValue(sourceFilterObjRef) {
185
185
  }
186
186
  throw new Error("Invalid SourceInsightFilterObjRef");
187
187
  }
188
+ /**
189
+ * Resolves a measure-scoped ref from an insight filter to the underlying catalog measure ref.
190
+ *
191
+ * Source insight MVFs usually target a local measure identifier, while dashboard MVFs target
192
+ * the metric object ref. Use this when comparing or merging source MVFs with dashboard MVFs.
193
+ *
194
+ * @internal
195
+ */
196
+ export function resolveSourceMeasureRef(measureRef, sourceInsightMeasures) {
197
+ if (!measureRef) {
198
+ return undefined;
199
+ }
200
+ if (!isLocalIdRef(measureRef)) {
201
+ return measureRef;
202
+ }
203
+ const sourceMeasure = sourceInsightMeasures.find((measure) => measureLocalId(measure) === measureRef.localIdentifier);
204
+ return sourceMeasure ? measureItem(sourceMeasure) : undefined;
205
+ }
package/esm/index.d.ts CHANGED
@@ -138,8 +138,8 @@ export type { FilterContextState, WorkingDashboardAttributeFilter, WorkingDashbo
138
138
  export { selectFilterGroupsConfig } from "./model/store/tabs/filterGroups/filterGroupsSelectors.js";
139
139
  export { selectDateFilterConfigsOverrides, selectDateFilterConfigsOverridesByTab, selectDateFilterConfigsModeMap, selectEffectiveDateFiltersModeMap, selectDateFilterConfigsModeMapByTab, } from "./model/store/tabs/dateFilterConfigs/dateFilterConfigsSelectors.js";
140
140
  export { selectInsights, selectInsightRefs, selectInsightsMap, selectInsightByRef, selectInsightByWidgetRef, selectRawExportOverridesForInsightByRef, } from "./model/store/insights/insightsSelectors.js";
141
- export type { CatalogState, CatalogParametersStatus, ICatalogParametersState, } from "./model/store/catalog/catalogState.js";
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";
141
+ export type { CatalogState, CatalogParametersStatus, ICatalogParametersState, CatalogMeasureParametersStatus, ICatalogMeasureParametersState, } from "./model/store/catalog/catalogState.js";
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, selectCatalogMeasureParameters, selectCatalogMeasureParametersStatus, } 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
145
  export type { IAddParameterPayload, IRemoveParameterPayload, ISetParameterRuntimeValuePayload, } from "./model/store/tabs/parameters/parametersReducers.js";
package/esm/index.js CHANGED
@@ -103,7 +103,7 @@ export { DEFAULT_TAB_ID } from "./model/store/tabs/tabsState.js";
103
103
  export { selectFilterGroupsConfig } from "./model/store/tabs/filterGroups/filterGroupsSelectors.js";
104
104
  export { selectDateFilterConfigsOverrides, selectDateFilterConfigsOverridesByTab, selectDateFilterConfigsModeMap, selectEffectiveDateFiltersModeMap, selectDateFilterConfigsModeMapByTab, } from "./model/store/tabs/dateFilterConfigs/dateFilterConfigsSelectors.js";
105
105
  export { selectInsights, selectInsightRefs, selectInsightsMap, selectInsightByRef, selectInsightByWidgetRef, selectRawExportOverridesForInsightByRef, } from "./model/store/insights/insightsSelectors.js";
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";
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, selectCatalogMeasureParameters, selectCatalogMeasureParametersStatus, } from "./model/store/catalog/catalogSelectors.js";
107
107
  export { catalogActions } from "./model/store/catalog/index.js";
108
108
  export { selectDashboardParameterEntries, selectDashboardParameters, selectEffectiveParameterValuesForWidget, selectIsParametersChanged, selectParameterRuntimeOverrideByRef, } from "./model/store/tabs/parameters/parametersSelectors.js";
109
109
  export { drillActions } from "./model/store/drill/index.js";
@@ -33,6 +33,7 @@ import { loadDashboardParameters } from "./loadDashboardParameters.js";
33
33
  import { loadDashboardPermissions } from "./loadDashboardPermissions.js";
34
34
  import { loadDateHierarchyTemplates } from "./loadDateHierarchyTemplates.js";
35
35
  import { loadFilterViews } from "./loadFilterViews.js";
36
+ import { loadMeasureParameterDependencies } from "./loadMeasureParameterDependencies.js";
36
37
  import { loadUser } from "./loadUser.js";
37
38
  import { mergeDateFilterConfigWithOverrides } from "./mergeDateFilterConfigs.js";
38
39
  import { preloadAttributeFiltersData as preloadAttributeFiltersDataFromBackend } from "./preloadAttributeFiltersData.js";
@@ -180,8 +181,11 @@ function* loadExistingDashboard(ctx, cmd, dashboardRef) {
180
181
  // Note: activeTabLocalIdentifier is app state only, NOT persisted to/read from dashboard MD
181
182
  const resolvedActiveTabId = resolveActiveTabId(dashboardWithFilterView.tabs, cmd.payload.initialTabId, undefined);
182
183
  const dashboard = dashboardWithFilterView;
183
- const { tabsAttributeFilterConfigs, tabsDateFilterConfig, tabsDateFilterConfigSource } = yield call(getTabsFilterConfigs, dashboard, config, ctx, cmd);
184
- const workspaceParameters = yield call(loadWorkspaceParametersWithStatus, ctx, config.settings?.enableParameters ?? false);
184
+ const [{ tabsAttributeFilterConfigs, tabsDateFilterConfig, tabsDateFilterConfigSource }, workspaceParameters, measureParameterDependencies,] = yield all([
185
+ call(getTabsFilterConfigs, dashboard, config, ctx, cmd),
186
+ call(loadWorkspaceParametersWithStatus, ctx, config.settings?.enableParameters ?? false),
187
+ call(loadMeasureParameterDependencies, ctx, insights, config.settings?.enableParameters ?? false),
188
+ ]);
185
189
  const workspaceParametersList = Array.isArray(workspaceParameters) ? workspaceParameters : [];
186
190
  const initActions = yield call(actionsToInitializeExistingDashboard, ctx, dashboard, insights, config.settings, config.settings.enableImmediateAttributeFilterDisplayAsLabelMigration ?? false, undefined, undefined, tabsAttributeFilterConfigs, tabsDateFilterConfig, tabsDateFilterConfigSource, createDisplayFormMap([], []), cmd.payload.persistedDashboard, resolvedActiveTabId, workspaceParametersList);
187
191
  const catalogPayload = {
@@ -195,6 +199,7 @@ function* loadExistingDashboard(ctx, cmd, dashboardRef) {
195
199
  permissionsActions.setPermissions(permissions),
196
200
  catalogActions.setCatalogItems(catalogPayload),
197
201
  catalogActions.setCatalogParameters(makeCatalogParametersPayload(workspaceParameters)),
202
+ catalogActions.setCatalogMeasureParameters(measureParameterDependencies),
198
203
  ...initActions,
199
204
  // NOTE: Tab configs (dateFilterConfig, dateFilterConfigs, attributeFilterConfigs, filterContext)
200
205
  // are now initialized as part of the tabs state in initActions via setTabs action
@@ -229,6 +234,7 @@ function* initializeNewDashboard(ctx, cmd) {
229
234
  const workspaceParameters = yield call(loadWorkspaceParametersWithStatus, ctx, config.settings?.enableParameters ?? false);
230
235
  const workspaceParametersList = Array.isArray(workspaceParameters) ? workspaceParameters : [];
231
236
  const { initActions, dashboard, insights } = yield call(actionsToInitializeNewDashboard, ctx, config.settings, config.dateFilterConfig, catalog ? createDisplayFormMapFromCatalog(catalog) : createDisplayFormMap([], []), cmd.payload.initialTabId, workspaceParametersList);
237
+ const measureParameterDependencies = yield call(loadMeasureParameterDependencies, ctx, insights, config.settings?.enableParameters ?? false);
232
238
  const batch = batchActions([
233
239
  backendCapabilitiesActions.setBackendCapabilities(backend.capabilities),
234
240
  configActions.setConfig(config),
@@ -244,6 +250,7 @@ function* initializeNewDashboard(ctx, cmd) {
244
250
  dateHierarchyTemplates: dateHierarchyTemplates,
245
251
  }),
246
252
  catalogActions.setCatalogParameters(makeCatalogParametersPayload(workspaceParameters)),
253
+ catalogActions.setCatalogMeasureParameters(measureParameterDependencies),
247
254
  listedDashboardsActions.setListedDashboards(listedDashboards),
248
255
  accessibleDashboardsActions.setAccessibleDashboards(listedDashboards),
249
256
  executionResultsActions.clearAllExecutionResults(),
@@ -0,0 +1,12 @@
1
+ import { type IInsight } from "@gooddata/sdk-model";
2
+ import { type ICatalogMeasureParametersState } from "../../../store/catalog/catalogState.js";
3
+ import { type DashboardContext } from "../../../types/commonTypes.js";
4
+ /**
5
+ * Loads the dashboard-wide metric -> parameter dependency map from the workspace references service.
6
+ *
7
+ * @remarks
8
+ * Walks the dependency graph in `direction: "down"`, then collects parameter nodes reachable from
9
+ * each root metric, including transitive metric -> metric -> parameter chains. Disabled parameters
10
+ * return `uninitialized`; backend errors return `failed`.
11
+ */
12
+ export declare function loadMeasureParameterDependencies(ctx: DashboardContext, insights: IInsight[], enableParameters: boolean): Promise<ICatalogMeasureParametersState>;
@@ -0,0 +1,98 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { insightMeasures, isIdentifierRef, isMeasureDefinition, objRefToString, } from "@gooddata/sdk-model";
3
+ /**
4
+ * Loads the dashboard-wide metric -> parameter dependency map from the workspace references service.
5
+ *
6
+ * @remarks
7
+ * Walks the dependency graph in `direction: "down"`, then collects parameter nodes reachable from
8
+ * each root metric, including transitive metric -> metric -> parameter chains. Disabled parameters
9
+ * return `uninitialized`; backend errors return `failed`.
10
+ */
11
+ export async function loadMeasureParameterDependencies(ctx, insights, enableParameters) {
12
+ if (!enableParameters) {
13
+ return { status: "uninitialized", byMetric: {} };
14
+ }
15
+ const metricRefs = collectMetricRefs(insights);
16
+ if (metricRefs.length === 0) {
17
+ return { status: "loaded", byMetric: {} };
18
+ }
19
+ try {
20
+ const result = await ctx.backend
21
+ .workspace(ctx.workspace)
22
+ .references()
23
+ .getReferences(metricRefs, { direction: "down" });
24
+ const byMetric = buildReachableParameterMap(metricRefs, result.edges);
25
+ return { status: "loaded", byMetric };
26
+ }
27
+ catch {
28
+ return { status: "failed", byMetric: {} };
29
+ }
30
+ }
31
+ function collectMetricRefs(insights) {
32
+ const seen = new Set();
33
+ const refs = [];
34
+ for (const insight of insights) {
35
+ for (const measure of insightMeasures(insight)) {
36
+ const def = measure.measure.definition;
37
+ if (!isMeasureDefinition(def)) {
38
+ continue;
39
+ }
40
+ const item = def.measureDefinition.item;
41
+ if (!isIdentifierRef(item)) {
42
+ continue;
43
+ }
44
+ const key = objRefToString(item);
45
+ if (seen.has(key)) {
46
+ continue;
47
+ }
48
+ seen.add(key);
49
+ refs.push(item);
50
+ }
51
+ }
52
+ return refs;
53
+ }
54
+ function buildReachableParameterMap(roots, edges) {
55
+ const adjacency = buildAdjacency(edges);
56
+ const result = {};
57
+ for (const root of roots) {
58
+ const reachableParameters = reachableParameterRefs(root, adjacency);
59
+ result[objRefToString(root)] = reachableParameters;
60
+ }
61
+ return result;
62
+ }
63
+ function buildAdjacency(edges) {
64
+ const adjacency = new Map();
65
+ for (const edge of edges) {
66
+ const fromKey = objRefToString(edge.from);
67
+ const toKey = objRefToString(edge.to);
68
+ const next = adjacency.get(fromKey) ?? [];
69
+ next.push({ to: edge.to, key: toKey });
70
+ adjacency.set(fromKey, next);
71
+ }
72
+ return adjacency;
73
+ }
74
+ function reachableParameterRefs(start, adjacency) {
75
+ const parameters = [];
76
+ const parametersSeen = new Set();
77
+ const visited = new Set([objRefToString(start)]);
78
+ const queue = [start];
79
+ while (queue.length > 0) {
80
+ const node = queue.shift();
81
+ const neighbors = adjacency.get(objRefToString(node)) ?? [];
82
+ for (const neighbor of neighbors) {
83
+ if (visited.has(neighbor.key)) {
84
+ continue;
85
+ }
86
+ visited.add(neighbor.key);
87
+ if (neighbor.to.type === "parameter") {
88
+ if (!parametersSeen.has(neighbor.key)) {
89
+ parametersSeen.add(neighbor.key);
90
+ parameters.push(neighbor.to);
91
+ }
92
+ continue;
93
+ }
94
+ queue.push(neighbor.to);
95
+ }
96
+ }
97
+ return parameters;
98
+ }
@@ -135,6 +135,7 @@ export function* resolveDashboardConfig(ctx, cmd) {
135
135
  maxZoomLevel: config.maxZoomLevel === undefined
136
136
  ? settings.settings?.maxZoomLevel
137
137
  : config.maxZoomLevel,
138
+ isWhiteLabeled: config.isWhiteLabeled ?? settings.settings?.whiteLabeling?.enabled ?? false,
138
139
  };
139
140
  }
140
141
  const CONFIG_DEFAULTS = {
@@ -1,12 +1,12 @@
1
- import { type FilterContextItem, type IAttributeFilter, type IDateFilter } from "@gooddata/sdk-model";
2
- type SourceFilter = IAttributeFilter | IDateFilter;
1
+ import { type FilterContextItem, type IAttributeFilter, type IDateFilter, type IMeasureValueFilter } from "@gooddata/sdk-model";
2
+ export type SourceFilter = IAttributeFilter | IDateFilter | IMeasureValueFilter;
3
3
  /**
4
4
  * Merges dashboard filters with source filters by intersecting attribute element values
5
5
  * for filters that target the same attribute (matched by display form ref).
6
6
  *
7
7
  * - Matching attribute filters: element values are intersected (AND semantics).
8
+ * - Matching measure value filters: conditions get replaced.
8
9
  * - Unmatched filters from either side: passed through as-is.
9
10
  * - Date filters: passed through as-is (no intersection).
10
11
  */
11
12
  export declare function mergeDashboardAndSourceFilters(dashboardFilters: FilterContextItem[], sourceFilters: SourceFilter[]): Array<FilterContextItem | SourceFilter>;
12
- export {};
@@ -1,10 +1,11 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { areObjRefsEqual, filterAttributeElements, filterObjRef, isAttributeFilterWithSelection, isDashboardAttributeFilter, isNegativeAttributeFilter, } from "@gooddata/sdk-model";
2
+ import { areObjRefsEqual, filterAttributeElements, filterMeasureRef, filterObjRef, isAttributeFilterWithSelection, isDashboardAttributeFilter, isDashboardMeasureValueFilter, isMeasureValueFilter, isNegativeAttributeFilter, measureValueFilterConditions, } from "@gooddata/sdk-model";
3
3
  /**
4
4
  * Merges dashboard filters with source filters by intersecting attribute element values
5
5
  * for filters that target the same attribute (matched by display form ref).
6
6
  *
7
7
  * - Matching attribute filters: element values are intersected (AND semantics).
8
+ * - Matching measure value filters: conditions get replaced.
8
9
  * - Unmatched filters from either side: passed through as-is.
9
10
  * - Date filters: passed through as-is (no intersection).
10
11
  */
@@ -14,6 +15,22 @@ export function mergeDashboardAndSourceFilters(dashboardFilters, sourceFilters)
14
15
  }
15
16
  const usedSourceIndices = new Set();
16
17
  const mergedDashboardFilters = dashboardFilters.map((dashFilter) => {
18
+ if (isDashboardMeasureValueFilter(dashFilter)) {
19
+ const dashRef = dashFilter.dashboardMeasureValueFilter.measure;
20
+ const sourceIndex = sourceFilters.findIndex((sf, i) => {
21
+ if (usedSourceIndices.has(i) || !isMeasureValueFilter(sf)) {
22
+ return false;
23
+ }
24
+ const sourceRef = filterMeasureRef(sf);
25
+ return sourceRef ? areObjRefsEqual(dashRef, sourceRef) : false;
26
+ });
27
+ if (sourceIndex === -1) {
28
+ return dashFilter;
29
+ }
30
+ usedSourceIndices.add(sourceIndex);
31
+ const sourceFilter = sourceFilters[sourceIndex];
32
+ return intersectMeasureValueFilters(dashFilter, sourceFilter);
33
+ }
17
34
  if (!isDashboardAttributeFilter(dashFilter)) {
18
35
  return dashFilter;
19
36
  }
@@ -35,6 +52,14 @@ export function mergeDashboardAndSourceFilters(dashboardFilters, sourceFilters)
35
52
  const remainingSourceFilters = sourceFilters.filter((_, i) => !usedSourceIndices.has(i));
36
53
  return [...mergedDashboardFilters, ...remainingSourceFilters];
37
54
  }
55
+ function intersectMeasureValueFilters(dashFilter, sourceFilter) {
56
+ return {
57
+ dashboardMeasureValueFilter: {
58
+ ...dashFilter.dashboardMeasureValueFilter,
59
+ conditions: measureValueFilterConditions(sourceFilter),
60
+ },
61
+ };
62
+ }
38
63
  function intersectAttributeFilters(dashFilter, sourceFilter) {
39
64
  const dashElements = dashFilter.attributeFilter.attributeElements;
40
65
  const dashNegative = dashFilter.attributeFilter.negativeSelection;
@@ -1,6 +1,7 @@
1
1
  import { type IAttributeFilter, type IDateFilter, type IDrillToDashboard, type IDrillToInsight, type IFilter, type IInsight, type SourceInsightFilterObjRef } from "@gooddata/sdk-model";
2
+ import { type SourceFilter } from "./mergeFilters.js";
2
3
  type IDrillDefinitionWithIncludedSourceFilters = Pick<IDrillToDashboard | IDrillToInsight, "origin" | "includedSourceInsightFiltersObjRefs" | "includedSourceMeasureFiltersObjRefs">;
3
4
  export declare function getIncludedSourceInsightFilters(sourceInsight: IInsight | null, includedSourceInsightFiltersObjRefs: SourceInsightFilterObjRef[]): IFilter[];
4
5
  export declare function getIncludedSourceMeasureFilters(sourceInsight: IInsight | null, drillDefinition: IDrillDefinitionWithIncludedSourceFilters): Array<IAttributeFilter | IDateFilter>;
5
- export declare function getIncludedSourceFiltersForDashboard(sourceInsight: IInsight | null, drillDefinition: IDrillDefinitionWithIncludedSourceFilters): Array<IAttributeFilter | IDateFilter>;
6
+ export declare function getIncludedSourceFiltersForDashboard(sourceInsight: IInsight | null, drillDefinition: IDrillDefinitionWithIncludedSourceFilters): Array<SourceFilter>;
6
7
  export {};
@@ -1,6 +1,6 @@
1
1
  // (C) 2021-2026 GoodData Corporation
2
- import { insightFilters, insightMeasures, isAttributeFilter, isDateFilter, isMeasureValueFilter, isRankingFilter, } from "@gooddata/sdk-model";
3
- import { getSourceMeasureFiltersForDrillDefinition, isMatchingSourceInsightFilter, } from "../../../../_staging/drills/drillingUtils.js";
2
+ import { filterMeasureRef, insightFilters, insightMeasures, isAttributeFilter, isDateFilter, isMeasureValueFilter, isRankingFilter, } from "@gooddata/sdk-model";
3
+ import { getSourceMeasureFiltersForDrillDefinition, isMatchingSourceInsightFilter, resolveSourceMeasureRef, } from "../../../../_staging/drills/drillingUtils.js";
4
4
  export function getIncludedSourceInsightFilters(sourceInsight, includedSourceInsightFiltersObjRefs) {
5
5
  const sourceFilters = sourceInsight
6
6
  ? insightFilters(sourceInsight).filter((filter) => isAttributeFilter(filter) ||
@@ -18,13 +18,33 @@ export function getIncludedSourceMeasureFilters(sourceInsight, drillDefinition)
18
18
  return includedSourceFilters(sourceMeasureFilters, drillDefinition.includedSourceMeasureFiltersObjRefs ?? []);
19
19
  }
20
20
  export function getIncludedSourceFiltersForDashboard(sourceInsight, drillDefinition) {
21
+ const sourceInsightMeasures = sourceInsight ? insightMeasures(sourceInsight) : [];
21
22
  const sourceMeasureFilters = getIncludedSourceMeasureFilters(sourceInsight, drillDefinition);
22
- const sourceInsightFilters = getIncludedSourceInsightFilters(sourceInsight, drillDefinition.includedSourceInsightFiltersObjRefs ?? []).filter((filter) => {
23
- return isAttributeFilter(filter) || isDateFilter(filter);
24
- });
23
+ const sourceInsightFilters = getIncludedSourceInsightFilters(sourceInsight, drillDefinition.includedSourceInsightFiltersObjRefs ?? [])
24
+ .filter((filter) => {
25
+ return isAttributeFilter(filter) || isDateFilter(filter) || isMeasureValueFilter(filter);
26
+ })
27
+ .flatMap((filter) => normalizeSourceFilterForDashboard(filter, sourceInsightMeasures));
25
28
  // Keep the same precedence as drill-to-insight: measure filters win over source insight filters.
26
29
  return [...sourceMeasureFilters, ...sourceInsightFilters];
27
30
  }
31
+ function normalizeSourceFilterForDashboard(filter, sourceInsightMeasures) {
32
+ if (!isMeasureValueFilter(filter)) {
33
+ return [filter];
34
+ }
35
+ const measureRef = resolveSourceMeasureRef(filterMeasureRef(filter), sourceInsightMeasures);
36
+ if (!measureRef) {
37
+ return [];
38
+ }
39
+ return [
40
+ {
41
+ measureValueFilter: {
42
+ ...filter.measureValueFilter,
43
+ measure: measureRef,
44
+ },
45
+ },
46
+ ];
47
+ }
28
48
  function includedSourceFilters(sourceFilters, includedFilterObjRefs) {
29
49
  return sourceFilters.filter((sourceFilter) => {
30
50
  return includedFilterObjRefs.some((includedFilterObjRef) => isMatchingSourceInsightFilter(sourceFilter, includedFilterObjRef));
@@ -3,7 +3,7 @@ import { compact, isEmpty, isEqual } from "lodash-es";
3
3
  import { call, put, select } from "redux-saga/effects";
4
4
  import { invariant } from "ts-invariant";
5
5
  import { areObjRefsEqual, dashboardFilterLocalIdentifier, insightMeasures, isDashboardAttributeFilter, isDashboardMeasureValueFilter, isDateFilter, isSimpleMeasure, measureFilters, newAllTimeDashboardDateFilter, } from "@gooddata/sdk-model";
6
- import { dashboardAttributeFilterItemToAttributeFilter, dashboardDateFilterToDateFilterByWidget, } from "../../../converters/filterConverters.js";
6
+ import { dashboardAttributeFilterItemToAttributeFilter, dashboardDateFilterToDateFilterByWidget, dashboardMeasureValueFilterToMeasureValueFilter, } from "../../../converters/filterConverters.js";
7
7
  import { switchDashboardTab } from "../../commands/tabs.js";
8
8
  import { drillToDashboardRequested, drillToDashboardResolved, } from "../../events/drill.js";
9
9
  import { generateFilterLocalIdentifier } from "../../store/_infra/generators.js";
@@ -12,7 +12,7 @@ import { selectCatalogDateAttributes } from "../../store/catalog/catalogSelector
12
12
  import { selectEnableMultipleDateFilters } from "../../store/config/configSelectors.js";
13
13
  import { selectInsightByRef } from "../../store/insights/insightsSelectors.js";
14
14
  import { selectAttributeFilterConfigsDisplayAsLabelMap, selectAttributeFilterConfigsOverrides, } from "../../store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
15
- import { selectFilterContextAttributeFilterItems, selectFilterContextDateFilter, selectFilterContextDraggableFilterItems, } from "../../store/tabs/filterContext/filterContextSelectors.js";
15
+ import { selectFilterContextAttributeFilterItems, selectFilterContextDateFilter, selectFilterContextDraggableFilterItems, selectFilterContextMeasureValueFilters, } from "../../store/tabs/filterContext/filterContextSelectors.js";
16
16
  import { selectAnalyticalWidgetByRef } from "../../store/tabs/layout/layoutSelectors.js";
17
17
  import { convertIntersectionToAttributeFilters, removeIgnoredValuesFromDrillIntersection, } from "./common/intersectionUtils.js";
18
18
  import { mergeDashboardAndSourceFilters } from "./common/mergeFilters.js";
@@ -36,16 +36,17 @@ export function* drillToDashboardHandler(ctx, cmd) {
36
36
  const supportsMultipleDateFilters = yield select(selectSupportsMultipleDateFilters);
37
37
  const enableMultipleDateFilters = yield select(selectEnableMultipleDateFilters);
38
38
  const includeOtherDateFilters = supportsMultipleDateFilters && enableMultipleDateFilters;
39
- const allOtherFilters = yield select(selectAllOtherFilters);
39
+ const allDraggableFilters = yield select(selectAllDraggableFilters);
40
40
  const allAttributeFilters = yield select(selectAllAttributeFilters);
41
+ const allMeasureValueFilters = yield select(selectAllMeasureValueFilters);
42
+ const allNonDateFilters = [...allAttributeFilters, ...allMeasureValueFilters];
43
+ const dashboardFiltersToResolve = includeOtherDateFilters ? allDraggableFilters : allNonDateFilters;
41
44
  const widgetAwareFilters = isDrillingToSelf
42
45
  ? []
43
- : yield call(getWidgetAwareDashboardFilters, ctx, widget, includeOtherDateFilters);
46
+ : yield call(getWidgetAwareDashboardFilters, ctx, widget, dashboardFiltersToResolve);
44
47
  const candidateDashboardFilters = isDrillingToSelf
45
48
  ? // if drilling to self, just take all filters
46
- includeOtherDateFilters
47
- ? allOtherFilters
48
- : allAttributeFilters
49
+ dashboardFiltersToResolve
49
50
  : // if drilling to other, resolve widget filter ignores
50
51
  widgetAwareFilters;
51
52
  const dashboardFilters = removeIgnoredDashboardFilters(candidateDashboardFilters, ignoredDashboardFilterIds);
@@ -122,13 +123,19 @@ function selectDrillingDateFilter(state) {
122
123
  function selectAllAttributeFilters(state) {
123
124
  return selectFilterContextAttributeFilterItems(state);
124
125
  }
125
- function selectAllOtherFilters(state) {
126
+ function selectAllMeasureValueFilters(state) {
127
+ return selectFilterContextMeasureValueFilters(state);
128
+ }
129
+ function selectAllDraggableFilters(state) {
126
130
  return selectFilterContextDraggableFilterItems(state);
127
131
  }
128
132
  function convertFilterItemsToFilters(filter, widget) {
129
133
  if ("dateFilter" in filter) {
130
134
  return dashboardDateFilterToDateFilterByWidget(filter, widget);
131
135
  }
136
+ if (isDashboardMeasureValueFilter(filter)) {
137
+ return dashboardMeasureValueFilterToMeasureValueFilter(filter);
138
+ }
132
139
  return dashboardAttributeFilterItemToAttributeFilter(filter);
133
140
  }
134
141
  function removeIgnoredDashboardFilters(filters, ignoredDashboardFilterIds) {
@@ -140,15 +147,9 @@ function removeIgnoredDashboardFilters(filters, ignoredDashboardFilterIds) {
140
147
  return !localIdentifier || !ignoredDashboardFilterIds.has(localIdentifier);
141
148
  });
142
149
  }
143
- function* getWidgetAwareDashboardFilters(ctx, widget, includeOtherDateFilters) {
144
- const filtersIncludingDateFilters = yield select(selectFilterContextDraggableFilterItems);
145
- const attributeFilters = yield select(selectFilterContextAttributeFilterItems);
146
- const filterContextItems = includeOtherDateFilters ? filtersIncludingDateFilters : attributeFilters;
150
+ function* getWidgetAwareDashboardFilters(ctx, widget, filterContextItems) {
147
151
  const attributeFilterConfigs = yield select(selectAttributeFilterConfigsOverrides);
148
- // Drill-to-dashboard does not transfer measure value filters between dashboards in this iteration.
149
- // TODO INE: will be solved in https://gooddata.atlassian.net/browse/CQ-2285
150
- const drillTransferableItems = filterContextItems.filter((item) => !isDashboardMeasureValueFilter(item));
151
- const filtersPairs = drillTransferableItems.map((filter) => ({
152
+ const filtersPairs = filterContextItems.map((filter) => ({
152
153
  filter: convertFilterItemsToFilters(filter, widget),
153
154
  originalFilter: filter,
154
155
  }));
@@ -3,7 +3,7 @@ import { compact, partition, uniqBy } from "lodash-es";
3
3
  import { batchActions } from "redux-batched-actions";
4
4
  import { all, call, put, select } from "redux-saga/effects";
5
5
  import { NotSupported } from "@gooddata/sdk-backend-spi";
6
- import { areObjRefsEqual, attributeElementsIsEmpty, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemFilterElementsBy, dashboardAttributeFilterItemFilterElementsByDate, dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemValidateElementsBy, dashboardMeasureValueFilterLocalIdentifier, getAttributeElementsItems, isAllTimeDashboardDateFilter, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardMeasureValueFilter, isDashboardTextAttributeFilter, isSingleSelectionFilter, isUriRef, objRefToString, serializeObjRef, updateAttributeElementsItems, } from "@gooddata/sdk-model";
6
+ import { areObjRefsEqual, attributeElementsIsEmpty, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemFilterElementsBy, dashboardAttributeFilterItemFilterElementsByDate, dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemValidateElementsBy, dashboardFilterObjRef, dashboardMeasureValueFilterLocalIdentifier, getAttributeElementsItems, isAllTimeDashboardDateFilter, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardMeasureValueFilter, isDashboardTextAttributeFilter, isSingleSelectionFilter, isUriRef, objRefToString, serializeObjRef, updateAttributeElementsItems, } from "@gooddata/sdk-model";
7
7
  import { dashboardFilterToFilterContextItem } from "../../../_staging/dashboard/dashboardFilterContext.js";
8
8
  import { invalidArgumentsProvided } from "../../events/general.js";
9
9
  import { dispatchDashboardEvent } from "../../store/_infra/eventDispatcher.js";
@@ -455,13 +455,16 @@ function* getMeasureValueFiltersUpdateActions(measureValueFilters, resetOthers)
455
455
  const currentMeasureValueFilters = yield select(selectFilterContextMeasureValueFilters);
456
456
  const currentByLocalId = new Map(currentMeasureValueFilters.map((f) => [dashboardMeasureValueFilterLocalIdentifier(f), f]));
457
457
  for (const incoming of measureValueFilters) {
458
- const localIdentifier = dashboardMeasureValueFilterLocalIdentifier(incoming);
458
+ const incomingLocalIdentifier = dashboardMeasureValueFilterLocalIdentifier(incoming);
459
+ const currentFilter = currentByLocalId.get(incomingLocalIdentifier) ??
460
+ currentMeasureValueFilters.find((current) => areObjRefsEqual(dashboardFilterObjRef(current), dashboardFilterObjRef(incoming)));
459
461
  // Only update filters that already exist on the dashboard. Adding/removing MVFs is an
460
462
  // edit-mode operation and is not part of changeFilterContextSelection in view mode.
461
- if (!currentByLocalId.has(localIdentifier)) {
462
- console.warn(`changeFilterContextSelection: ignoring measure value filter with unknown localIdentifier "${localIdentifier}". The dashboard does not currently have a measure value filter with this id; adding new MVFs is not supported in view mode.`);
463
+ if (!currentFilter) {
464
+ console.warn(`changeFilterContextSelection: ignoring measure value filter with unknown localIdentifier "${incomingLocalIdentifier}". The dashboard does not currently have a measure value filter with this id or metric; adding new MVFs is not supported in view mode.`);
463
465
  continue;
464
466
  }
467
+ const localIdentifier = dashboardMeasureValueFilterLocalIdentifier(currentFilter);
465
468
  handledLocalIds.add(localIdentifier);
466
469
  updateActions.push(tabsActions.changeMeasureValueFilterCondition({
467
470
  localIdentifier,
@@ -1,5 +1,6 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { call, put, select } from "redux-saga/effects";
3
+ import { dashboardFilterObjRef } from "@gooddata/sdk-model";
3
4
  import { measureValueFilterRemoved } from "../../../events/filters.js";
4
5
  import { invalidArgumentsProvided } from "../../../events/general.js";
5
6
  import { dispatchDashboardEvent } from "../../../store/_infra/eventDispatcher.js";
@@ -12,8 +13,14 @@ export function* removeMeasureValueFilterHandler(ctx, cmd) {
12
13
  if (!affectedFilter) {
13
14
  throw invalidArgumentsProvided(ctx, cmd, `Filter with localIdentifier ${localIdentifier} not found.`);
14
15
  }
16
+ const removedMeasureRef = dashboardFilterObjRef(affectedFilter);
15
17
  yield put(tabsActions.removeMeasureValueFilter({ localIdentifier }));
16
18
  yield put(tabsActions.removeMeasureValueFilterConfig(localIdentifier));
19
+ if (removedMeasureRef) {
20
+ yield put(tabsActions.removeIgnoredMeasureValueFilter({
21
+ measureRefs: [removedMeasureRef],
22
+ }));
23
+ }
17
24
  yield dispatchDashboardEvent(measureValueFilterRemoved(ctx, affectedFilter, cmd.correlationId));
18
25
  yield call(dispatchFilterContextChanged, ctx, cmd);
19
26
  }
@@ -2,7 +2,7 @@
2
2
  import { useEffect, useMemo, useState } from "react";
3
3
  import stringify from "json-stable-stringify";
4
4
  import { isEqual } from "lodash-es";
5
- import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemLocalIdentifier, filterObjRef, isAllTimeDashboardDateFilter, isAllValuesDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardDateFilter, isDashboardDateFilterWithDimension, } from "@gooddata/sdk-model";
5
+ import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemLocalIdentifier, filterObjRef, isAllTimeDashboardDateFilter, isAllValuesDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMeasureValueFilter, } from "@gooddata/sdk-model";
6
6
  import { usePrevious } from "@gooddata/sdk-ui";
7
7
  import { safeSerializeObjRef } from "../../_staging/metadata/safeSerializeObjRef.js";
8
8
  import { queryWidgetFilters } from "../queries/widgets.js";
@@ -168,6 +168,9 @@ function useNonIgnoredFilters(widget) {
168
168
  else if (isDashboardDateFilterWithDimension(filter)) {
169
169
  return nonIgnoredFilterState.nonIgnoredFilterRefs.some((validRef) => areObjRefsEqual(validRef, filter.dateFilter.dataSet));
170
170
  }
171
+ else if (isDashboardMeasureValueFilter(filter)) {
172
+ return nonIgnoredFilterState.nonIgnoredFilterRefs.some((validRef) => areObjRefsEqual(validRef, filter.dashboardMeasureValueFilter.measure));
173
+ }
171
174
  else {
172
175
  // Common date filter: include only when widget does not ignore date filters
173
176
  return !widgetIgnoresDateFilter;
@@ -1,6 +1,6 @@
1
1
  import { type Action, type CaseReducer } from "@reduxjs/toolkit";
2
2
  import { type ICatalogAttribute, type ICatalogAttributeHierarchy, type ICatalogDateDataset, type ICatalogFact, type ICatalogMeasure, type IDateHierarchyTemplate } from "@gooddata/sdk-model";
3
- import { type CatalogState, type ICatalogParametersState } from "./catalogState.js";
3
+ import { type CatalogState, type ICatalogMeasureParametersState, type ICatalogParametersState } from "./catalogState.js";
4
4
  type CatalogReducer<A extends Action> = CaseReducer<CatalogState, A>;
5
5
  /**
6
6
  * @public
@@ -45,5 +45,9 @@ export declare const catalogReducers: {
45
45
  payload: ICatalogParametersState;
46
46
  type: string;
47
47
  }>;
48
+ setCatalogMeasureParameters: CatalogReducer<{
49
+ payload: ICatalogMeasureParametersState;
50
+ type: string;
51
+ }>;
48
52
  };
49
53
  export {};
@@ -32,6 +32,9 @@ const deleteAttributeHierarchy = (state, action) => {
32
32
  const setCatalogParameters = (state, action) => {
33
33
  state.parameters = action.payload;
34
34
  };
35
+ const setCatalogMeasureParameters = (state, action) => {
36
+ state.measureParameters = action.payload;
37
+ };
35
38
  export const catalogReducers = {
36
39
  setCatalogItems,
37
40
  setCatalogMeasuresAndFacts,
@@ -39,4 +42,5 @@ export const catalogReducers = {
39
42
  updateAttributeHierarchy,
40
43
  deleteAttributeHierarchy,
41
44
  setCatalogParameters,
45
+ setCatalogMeasureParameters,
42
46
  };
@@ -1,8 +1,8 @@
1
- import { type IAttributeDisplayFormMetadataObject, type ICatalogAttribute, type ICatalogAttributeHierarchy, type ICatalogDateAttribute, type ICatalogDateAttributeHierarchy, type ICatalogDateDataset, type ICatalogFact, type ICatalogMeasure, type IDateHierarchyTemplate, type IParameterMetadataObject, type ObjRef } from "@gooddata/sdk-model";
1
+ import { type IAttributeDisplayFormMetadataObject, type ICatalogAttribute, type ICatalogAttributeHierarchy, type ICatalogDateAttribute, type ICatalogDateAttributeHierarchy, type ICatalogDateDataset, type ICatalogFact, type ICatalogMeasure, type IDateHierarchyTemplate, type IParameterMetadataObject, type IdentifierRef, type ObjRef } from "@gooddata/sdk-model";
2
2
  import { type CatalogDateAttributeWithDataset } from "../../../_staging/catalog/dateAttributeWithDatasetMap.js";
3
3
  import { type ObjRefMap } from "../../../_staging/metadata/objRefMap.js";
4
4
  import { type DashboardSelector } from "../types.js";
5
- import { type CatalogParametersStatus } from "./catalogState.js";
5
+ import { type CatalogMeasureParametersStatus, type CatalogParametersStatus } from "./catalogState.js";
6
6
  /**
7
7
  * @public
8
8
  */
@@ -32,6 +32,19 @@ export declare const selectCatalogParametersStatus: DashboardSelector<CatalogPar
32
32
  * @alpha
33
33
  */
34
34
  export declare const selectCatalogParametersIsLoaded: DashboardSelector<boolean>;
35
+ /**
36
+ * Returns the dashboard-wide map from metric ref string to the parameter refs the metric depends on.
37
+ * The map is populated during dashboard initialization from the workspace references service.
38
+ *
39
+ * @alpha
40
+ */
41
+ export declare const selectCatalogMeasureParameters: DashboardSelector<Record<string, IdentifierRef[]>>;
42
+ /**
43
+ * Returns the load status of the dashboard-wide metric → parameter dependency map.
44
+ *
45
+ * @alpha
46
+ */
47
+ export declare const selectCatalogMeasureParametersStatus: DashboardSelector<CatalogMeasureParametersStatus>;
35
48
  /**
36
49
  * @alpha
37
50
  */
@@ -39,6 +39,19 @@ export const selectCatalogParametersStatus = createSelector(selectSelf, (state)
39
39
  * @alpha
40
40
  */
41
41
  export const selectCatalogParametersIsLoaded = createSelector(selectCatalogParametersStatus, (status) => status === "loaded");
42
+ /**
43
+ * Returns the dashboard-wide map from metric ref string to the parameter refs the metric depends on.
44
+ * The map is populated during dashboard initialization from the workspace references service.
45
+ *
46
+ * @alpha
47
+ */
48
+ export const selectCatalogMeasureParameters = createSelector(selectSelf, (state) => state.measureParameters.byMetric);
49
+ /**
50
+ * Returns the load status of the dashboard-wide metric → parameter dependency map.
51
+ *
52
+ * @alpha
53
+ */
54
+ export const selectCatalogMeasureParametersStatus = createSelector(selectSelf, (state) => state.measureParameters.status);
42
55
  /**
43
56
  * @alpha
44
57
  */