@gooddata/sdk-ui-dashboard 11.35.0-alpha.5 → 11.35.0-alpha.7
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.
- package/NOTICE +8 -8
- package/esm/__version.d.ts +1 -1
- package/esm/__version.js +1 -1
- package/esm/_staging/dashboard/dashboardFilterContext.js +18 -1
- package/esm/_staging/sharedHooks/useFiltersNamings.d.ts +1 -1
- package/esm/_staging/sharedHooks/useFiltersNamings.js +32 -5
- package/esm/index.d.ts +4 -5
- package/esm/index.js +2 -3
- package/esm/kdaDialog/dialog/hooks/useChangeAnalysis.js +21 -5
- package/esm/kdaDialog/internalTypes.d.ts +6 -1
- package/esm/kdaDialog/providers/Kda.js +4 -1
- package/esm/kdaDialog/providers/KdaState.js +1 -0
- package/esm/kdaDialog/types.d.ts +13 -2
- package/esm/model/commandHandlers/dashboard/common/parameterHydration.d.ts +11 -2
- package/esm/model/commandHandlers/dashboard/common/parameterHydration.js +21 -0
- package/esm/model/commandHandlers/dashboard/common/stateInitializers.js +44 -79
- package/esm/model/commandHandlers/dashboard/saveAsDashboardHandler.js +10 -5
- package/esm/model/commandHandlers/dashboard/saveDashboardHandler.js +11 -7
- package/esm/model/commandHandlers/drill/keyDriverAnalysisHandler.js +8 -3
- package/esm/model/store/_infra/generators.d.ts +1 -0
- package/esm/model/store/_infra/generators.js +4 -1
- package/esm/model/store/dashboardStore.d.ts +0 -2
- package/esm/model/store/dashboardStore.js +0 -2
- package/esm/model/store/filtering/dashboardFilterSelectors.d.ts +1 -1
- package/esm/model/store/filtering/dashboardFilterSelectors.js +8 -5
- package/esm/model/store/meta/metaSelectors.js +4 -3
- package/esm/model/store/tabs/filterContext/filterContextReducers.js +2 -2
- package/esm/model/store/tabs/index.d.ts +12 -0
- package/esm/model/store/tabs/index.js +2 -0
- package/esm/model/store/{parameters → tabs/parameters}/parametersReducers.d.ts +3 -7
- package/esm/model/store/tabs/parameters/parametersReducers.js +46 -0
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +72 -0
- package/esm/model/store/tabs/parameters/parametersSelectors.js +228 -0
- package/esm/model/store/{parameters → tabs/parameters}/parametersState.d.ts +11 -1
- package/esm/model/store/tabs/parameters/parametersState.js +20 -0
- package/esm/model/store/tabs/tabsState.d.ts +2 -0
- package/esm/model/store/types.d.ts +0 -6
- package/esm/model/utils/widgetFilters.d.ts +1 -1
- package/esm/model/utils/widgetFilters.js +1 -1
- package/esm/presentation/automationFilters/components/AutomationFiltersSelect.js +8 -2
- package/esm/presentation/automationFilters/components/AutomationMeasureValueFilter.d.ts +10 -0
- package/esm/presentation/automationFilters/components/AutomationMeasureValueFilter.js +66 -0
- package/esm/presentation/automationFilters/components/AutomationMeasureValueFilterContext.d.ts +25 -0
- package/esm/presentation/automationFilters/components/AutomationMeasureValueFilterContext.js +28 -0
- package/esm/presentation/automationFilters/useAutomationFilters.d.ts +4 -1
- package/esm/presentation/automationFilters/useAutomationFilters.js +35 -4
- package/esm/presentation/automationFilters/utils.d.ts +2 -1
- package/esm/presentation/automationFilters/utils.js +34 -5
- package/esm/presentation/dragAndDrop/draggableParameterFilter/DefaultParameterDraggingComponent.js +1 -1
- package/esm/presentation/dragAndDrop/useFilterDeleteDrop.js +2 -2
- package/esm/presentation/filterBar/filterBar/DefaultFilterBar.js +1 -1
- package/esm/presentation/filterBar/measureValueFilter/DefaultDashboardMeasureValueFilter.js +8 -42
- package/esm/presentation/filterBar/measureValueFilter/useDashboardMeasureValueFilterData.d.ts +86 -0
- package/esm/presentation/filterBar/measureValueFilter/useDashboardMeasureValueFilterData.js +105 -0
- package/esm/presentation/filterBar/parameterFilter/DashboardParameterFilter.js +3 -3
- package/esm/presentation/filterBar/parameterFilter/DashboardParameterPicker.js +3 -3
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/Insight/DashboardInsight.js +1 -1
- package/esm/sdk-ui-dashboard.d.ts +44 -32
- package/package.json +21 -21
- package/esm/model/store/parameters/index.d.ts +0 -12
- package/esm/model/store/parameters/index.js +0 -14
- package/esm/model/store/parameters/parametersReducers.js +0 -36
- package/esm/model/store/parameters/parametersSelectors.d.ts +0 -67
- package/esm/model/store/parameters/parametersSelectors.js +0 -122
- 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-
|
|
10
|
+
Date generated: 2026-5-12
|
|
11
11
|
|
|
12
|
-
Revision ID:
|
|
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.
|
|
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,
|
|
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.
|
|
5370
|
+
Package Title: baseline-browser-mapping (2.10.29)
|
|
5371
5371
|
|
|
5372
|
-
Package Locator: npm+baseline-browser-mapping$2.10.
|
|
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
|
-
|
|
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-
|
|
38280
|
+
Report Generated by FOSSA on 2026-5-12
|
package/esm/__version.d.ts
CHANGED
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.
|
|
3
|
+
export const LIB_VERSION = "11.35.0-alpha.7";
|
|
4
4
|
export const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
|
|
5
5
|
export const LIB_NAME = "@gooddata/sdk-ui-dashboard";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// (C) 2021-2026 GoodData Corporation
|
|
2
|
+
import { v4 as uuidv4 } from "uuid";
|
|
2
3
|
import { NotSupported } from "@gooddata/sdk-backend-spi";
|
|
3
|
-
import { dashboardAttributeFilterItemFilterElementsBy, dashboardFilterLocalIdentifier, filterAttributeElements, filterLocalIdentifier, filterObjRef, isAbsoluteDateFilter, isAllTimeDateFilter, isArbitraryAttributeFilter, isAttributeFilterWithSelection, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isMatchAttributeFilter, isNegativeAttributeFilter, isRelativeBoundedDateFilter, isRelativeDateFilter, isTempFilterContext, newAbsoluteDashboardDateFilter, newAllTimeDashboardDateFilter, newRelativeDashboardDateFilter, } from "@gooddata/sdk-model";
|
|
4
|
+
import { dashboardAttributeFilterItemFilterElementsBy, dashboardFilterLocalIdentifier, filterAttributeElements, filterLocalIdentifier, filterObjRef, isAbsoluteDateFilter, isAllTimeDateFilter, isArbitraryAttributeFilter, isAttributeFilterWithSelection, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isMatchAttributeFilter, isMeasureValueFilter, isNegativeAttributeFilter, isObjRef, isRelativeBoundedDateFilter, isRelativeDateFilter, isTempFilterContext, measureValueFilterConditions, measureValueFilterMeasure, newAbsoluteDashboardDateFilter, newAllTimeDashboardDateFilter, newRelativeDashboardDateFilter, } from "@gooddata/sdk-model";
|
|
4
5
|
import { createDefaultFilterContext } from "./defaultFilterContext.js";
|
|
5
6
|
/**
|
|
6
7
|
* Given a dashboard, this function will inspect its filter context and always return a valid instance of IFilterContextDefinition to use.
|
|
@@ -154,5 +155,21 @@ export function dashboardFilterToFilterContextItem(filter, keepDatasets) {
|
|
|
154
155
|
else if (isRelativeDateFilter(filter)) {
|
|
155
156
|
return newRelativeDashboardDateFilter(filter.relativeDateFilter.granularity, filter.relativeDateFilter.from, filter.relativeDateFilter.to, keepDatasets ? filter.relativeDateFilter.dataSet : undefined, filter.relativeDateFilter.localIdentifier, isRelativeBoundedDateFilter(filter) ? filter.relativeDateFilter.boundedFilter : undefined, filter.relativeDateFilter.emptyValueHandling);
|
|
156
157
|
}
|
|
158
|
+
else if (isMeasureValueFilter(filter)) {
|
|
159
|
+
const measure = measureValueFilterMeasure(filter);
|
|
160
|
+
// Dashboard MVF requires an ObjRef (catalog metric reference); LocalIdRef cannot
|
|
161
|
+
// survive the round-trip from execution to filter context.
|
|
162
|
+
if (!isObjRef(measure)) {
|
|
163
|
+
throw new NotSupported(`Unsupported filter type! Please provide valid dashboard filter. Filter: ${JSON.stringify(filter)}`);
|
|
164
|
+
}
|
|
165
|
+
const conditions = measureValueFilterConditions(filter);
|
|
166
|
+
return {
|
|
167
|
+
dashboardMeasureValueFilter: {
|
|
168
|
+
measure,
|
|
169
|
+
localIdentifier: filter.measureValueFilter.localIdentifier ?? uuidv4(),
|
|
170
|
+
...(conditions ? { conditions } : {}),
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
157
174
|
throw new NotSupported(`Unsupported filter type! Please provide valid dashboard filter. Filter: ${JSON.stringify(filter)}`);
|
|
158
175
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// (C) 2024-2026 GoodData Corporation
|
|
2
2
|
import { useIntl } from "react-intl";
|
|
3
3
|
import { v4 as uuidv4 } from "uuid";
|
|
4
|
-
import { dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemTitle, getAttributeElementsItems, isAllTimeDashboardDateFilter, isAllValuesDashboardAttributeFilter, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMatchAttributeFilter, serializeObjRef, } from "@gooddata/sdk-model";
|
|
5
|
-
import { DateFilterHelpers, getAttributeFilterSubtitle, getLocalizedIcuDateFormatPattern, getTextFilterStateText, } from "@gooddata/sdk-ui-filters";
|
|
4
|
+
import { areObjRefsEqual, dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemTitle, getAttributeElementsItems, isAllDashboardMeasureValueFilter, isAllTimeDashboardDateFilter, isAllValuesDashboardAttributeFilter, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMatchAttributeFilter, isDashboardMeasureValueFilter, objRefToString, serializeObjRef, } from "@gooddata/sdk-model";
|
|
5
|
+
import { DateFilterHelpers, getAttributeFilterSubtitle, getLocalizedIcuDateFormatPattern, getMeasureValueFilterConditionLabel, getTextFilterStateText, } from "@gooddata/sdk-ui-filters";
|
|
6
6
|
import { useDashboardSelector } from "../../model/react/DashboardStoreProvider.js";
|
|
7
|
-
import { selectAllCatalogAttributesMap } from "../../model/store/catalog/catalogSelectors.js";
|
|
8
|
-
import { selectLocale, selectSettings } from "../../model/store/config/configSelectors.js";
|
|
7
|
+
import { selectAllCatalogAttributesMap, selectCatalogMeasures, } from "../../model/store/catalog/catalogSelectors.js";
|
|
8
|
+
import { selectLocale, selectSeparators, selectSettings } from "../../model/store/config/configSelectors.js";
|
|
9
9
|
import { convertDateFilterConfigToDateFilterOptions } from "../dateFilterConfig/dateFilterConfigConverters.js";
|
|
10
10
|
import { matchDateFilterToDateFilterOptionWithPreference } from "../dateFilterConfig/dateFilterOptionMapping.js";
|
|
11
11
|
import { defaultDateFilterConfig } from "../dateFilterConfig/defaultConfig.js";
|
|
@@ -13,6 +13,10 @@ import { ensureAllTimeFilterForExport } from "../exportUtils/filterUtils.js";
|
|
|
13
13
|
import { useAttributeFilterDisplayFormFromMap } from "./useAttributeFilterDisplayFormFromMap.js";
|
|
14
14
|
import { useCommonDateFilterTitle } from "./useCommonDateFilterTitle.js";
|
|
15
15
|
import { useDateFiltersTitles } from "./useDateFiltersTitles.js";
|
|
16
|
+
const PERCENT_FORMAT_REGEX = /%/;
|
|
17
|
+
function isPercentageFormat(format) {
|
|
18
|
+
return !!format && PERCENT_FORMAT_REGEX.test(format);
|
|
19
|
+
}
|
|
16
20
|
/**
|
|
17
21
|
* Hook that gathers all dependencies needed for filter naming transformations.
|
|
18
22
|
* Reusable across different hooks that need to transform filters to namings.
|
|
@@ -29,6 +33,8 @@ function useFilterNamingDependencies(filtersForTitles) {
|
|
|
29
33
|
: settings.responsiveUiDateFormat;
|
|
30
34
|
const getAttributeFilterDisplayFormFromMap = useAttributeFilterDisplayFormFromMap();
|
|
31
35
|
const attrMap = useDashboardSelector(selectAllCatalogAttributesMap);
|
|
36
|
+
const measures = useDashboardSelector(selectCatalogMeasures);
|
|
37
|
+
const separators = useDashboardSelector(selectSeparators);
|
|
32
38
|
const dateFiltersForTitles = filtersForTitles.filter(isDashboardDateFilterWithDimension);
|
|
33
39
|
const commonDateFilterTitle = useCommonDateFilterTitle(intl);
|
|
34
40
|
const allDateFiltersTitlesObj = useDateFiltersTitles(dateFiltersForTitles, intl);
|
|
@@ -38,6 +44,8 @@ function useFilterNamingDependencies(filtersForTitles) {
|
|
|
38
44
|
dateFormat,
|
|
39
45
|
getAttributeFilterDisplayFormFromMap,
|
|
40
46
|
attrMap,
|
|
47
|
+
measures,
|
|
48
|
+
separators,
|
|
41
49
|
commonDateFilterTitle,
|
|
42
50
|
allDateFiltersTitlesObj,
|
|
43
51
|
};
|
|
@@ -47,7 +55,7 @@ function useFilterNamingDependencies(filtersForTitles) {
|
|
|
47
55
|
* Extracted to avoid code duplication between useFiltersNamings and useFiltersByTabNamings.
|
|
48
56
|
*/
|
|
49
57
|
function transformFiltersToNamings(filtersToDisplay, deps) {
|
|
50
|
-
const { intl, dateFormat, getAttributeFilterDisplayFormFromMap, attrMap, commonDateFilterTitle, allDateFiltersTitlesObj, } = deps;
|
|
58
|
+
const { intl, dateFormat, getAttributeFilterDisplayFormFromMap, attrMap, measures, separators, commonDateFilterTitle, allDateFiltersTitlesObj, } = deps;
|
|
51
59
|
// we want to show all time filter in the list of filters even if it is not stored
|
|
52
60
|
const extendedFiltersToDisplay = ensureAllTimeFilterForExport(filtersToDisplay);
|
|
53
61
|
return extendedFiltersToDisplay.map((filter) => {
|
|
@@ -127,6 +135,25 @@ function transformFiltersToNamings(filtersToDisplay, deps) {
|
|
|
127
135
|
subtitle,
|
|
128
136
|
};
|
|
129
137
|
}
|
|
138
|
+
else if (isDashboardMeasureValueFilter(filter)) {
|
|
139
|
+
const { measure, localIdentifier, title: customTitle, conditions, } = filter.dashboardMeasureValueFilter;
|
|
140
|
+
const catalogMetric = measures.find((m) => areObjRefsEqual(m.measure.ref, measure));
|
|
141
|
+
const defaultTitle = catalogMetric?.measure.title ?? objRefToString(measure);
|
|
142
|
+
const title = customTitle ?? defaultTitle;
|
|
143
|
+
const format = catalogMetric?.measure.format;
|
|
144
|
+
const usePercentage = isPercentageFormat(format);
|
|
145
|
+
const subtitle = getMeasureValueFilterConditionLabel(intl, conditions, {
|
|
146
|
+
usePercentage,
|
|
147
|
+
separators,
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
type: "measureValueFilter",
|
|
151
|
+
all: isAllDashboardMeasureValueFilter(filter),
|
|
152
|
+
id: localIdentifier,
|
|
153
|
+
title,
|
|
154
|
+
subtitle,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
130
157
|
else if (isDashboardMatchAttributeFilter(filter)) {
|
|
131
158
|
const { operator: matchOperator, literal, negativeSelection, displayForm, } = filter.matchAttributeFilter;
|
|
132
159
|
const filterDisplayForm = getAttributeFilterDisplayFormFromMap(displayForm);
|
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 {
|
|
146
|
-
export type {
|
|
147
|
-
export
|
|
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";
|
|
@@ -198,7 +197,7 @@ export { newDrillToSameDashboardHandler } from "./model/eventHandlers/drillToSam
|
|
|
198
197
|
export { type IHeadlessDashboardConfig, type IMonitoredAction, HeadlessDashboard, } from "./model/headlessDashboard/HeadlessDashboard.js";
|
|
199
198
|
export { isTemporaryIdentity, getWidgetTitle } from "./model/utils/dashboardItemUtils.js";
|
|
200
199
|
export { existBlacklistHierarchyPredicate } from "./model/utils/attributeHierarchyUtils.js";
|
|
201
|
-
export {
|
|
200
|
+
export { getAttributeFilters, removeIgnoredWidgetFilters } from "./model/utils/widgetFilters.js";
|
|
202
201
|
export { getAuthor } from "./model/utils/author.js";
|
|
203
202
|
export type { ICustomComponentBase, IDraggingComponentProps, IDropTargetComponentProps, IAttributeFilterDraggingComponentProps, IDateFilterDraggingComponentProps, IInsightDraggingComponentProps, IKpiDraggingComponentProps, IRichTextDraggingComponentProps, IVisualizationSwitcherDraggingComponentProps, IDashboardLayoutDraggingComponentProps, ICustomDraggingComponentProps, AttributeFilterDraggingComponent, DateFilterDraggingComponent, InsightDraggingComponent, KpiDraggingComponent, RichTextDraggingComponent, VisualizationSwitcherDraggingComponent, DashboardLayoutDraggingComponent, CustomDraggingComponent, AttributeFilterDraggableComponent, DateFilterDraggableComponent, InsightDraggableComponent, KpiDraggableComponent, RichTextDraggableComponent, VisualizationSwitcherDraggableComponent, DashboardLayoutDraggableComponent, CustomDraggableComponent, DraggableComponent, DropTarget, ICreatePanelItemComponentProps, CustomCreatePanelItemComponent, CreatableByDragComponent, CreatablePlaceholderComponent, CustomWidgetConfigPanelComponent, IWidgetConfigPanelProps, ConfigurableWidget, AttributeFilterComponentSet, DateFilterComponentSet, InsightWidgetComponentSet, RichTextWidgetComponentSet, VisualizationSwitcherWidgetComponentSet, DashboardLayoutWidgetComponentSet, CustomWidgetComponentSet, InsightComponentSetProvider, } from "./presentation/componentDefinition/types.js";
|
|
204
203
|
export { renderModeAware } from "./presentation/componentDefinition/renderModeAware.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 {
|
|
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";
|
|
@@ -141,7 +140,7 @@ export { newDrillToSameDashboardHandler } from "./model/eventHandlers/drillToSam
|
|
|
141
140
|
export { HeadlessDashboard, } from "./model/headlessDashboard/HeadlessDashboard.js";
|
|
142
141
|
export { isTemporaryIdentity, getWidgetTitle } from "./model/utils/dashboardItemUtils.js";
|
|
143
142
|
export { existBlacklistHierarchyPredicate } from "./model/utils/attributeHierarchyUtils.js";
|
|
144
|
-
export {
|
|
143
|
+
export { getAttributeFilters, removeIgnoredWidgetFilters } from "./model/utils/widgetFilters.js";
|
|
145
144
|
export { getAuthor } from "./model/utils/author.js";
|
|
146
145
|
export { renderModeAware } from "./presentation/componentDefinition/renderModeAware.js";
|
|
147
146
|
export { Dashboard } from "./presentation/dashboard/Dashboard.js";
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { useEffect, useMemo } from "react";
|
|
3
3
|
import stringify from "json-stable-stringify";
|
|
4
4
|
import { ClientFormatterFacade } from "@gooddata/number-formatter";
|
|
5
|
-
import { isAllValuesDashboardAttributeFilter, newAttribute, } from "@gooddata/sdk-model";
|
|
5
|
+
import { isAllDashboardMeasureValueFilter, isAllValuesDashboardAttributeFilter, newAttribute, } from "@gooddata/sdk-model";
|
|
6
6
|
import { useBackendStrict, useCancelablePromise, useWorkspaceStrict } from "@gooddata/sdk-ui";
|
|
7
|
-
import { dashboardAttributeFilterItemToAttributeFilter } from "../../../converters/filterConverters.js";
|
|
7
|
+
import { dashboardAttributeFilterItemToAttributeFilter, dashboardMeasureValueFilterToMeasureValueFilter, } from "../../../converters/filterConverters.js";
|
|
8
8
|
import { useAttribute } from "../../hooks/useAttribute.js";
|
|
9
9
|
import { useDateAttribute } from "../../hooks/useDateAttribute.js";
|
|
10
10
|
import { useRelevantFilters } from "../../hooks/useRelevantFilters.js";
|
|
@@ -18,14 +18,15 @@ export function useChangeAnalysis() {
|
|
|
18
18
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
19
19
|
}, [state.selectedUpdated]);
|
|
20
20
|
const filters = useRelevantFilters();
|
|
21
|
+
const measureValueFilters = state.measureValueFilters;
|
|
21
22
|
const loading = state.relevantStatus === "loading" || state.relevantStatus === "pending";
|
|
22
|
-
const results = useChangeAnalysisResults(definition, attributes, filters, loading);
|
|
23
|
+
const results = useChangeAnalysisResults(definition, attributes, filters, measureValueFilters, loading);
|
|
23
24
|
const list = useKdaStateWithList(results, definition);
|
|
24
25
|
useEffect(() => {
|
|
25
26
|
setState(list);
|
|
26
27
|
}, [list, setState]);
|
|
27
28
|
}
|
|
28
|
-
function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
|
|
29
|
+
function useChangeAnalysisResults(definition, attrs, attrFilters, measureValueFilters, loading) {
|
|
29
30
|
const backend = useBackendStrict();
|
|
30
31
|
const workspace = useWorkspaceStrict();
|
|
31
32
|
const from = definition?.range[0].date;
|
|
@@ -38,6 +39,13 @@ function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
|
|
|
38
39
|
.map((f) => stringify(f))
|
|
39
40
|
.join();
|
|
40
41
|
}, [attrFilters]);
|
|
42
|
+
// Use the same fingerprint approach for MVF so cancelable-promise recomputes only when conditions actually change.
|
|
43
|
+
const measureValueFiltersFingerprint = useMemo(() => {
|
|
44
|
+
return measureValueFilters
|
|
45
|
+
.filter((f) => !isAllDashboardMeasureValueFilter(f))
|
|
46
|
+
.map((f) => stringify(f))
|
|
47
|
+
.join();
|
|
48
|
+
}, [measureValueFilters]);
|
|
41
49
|
const dateAttribute = dateAttributeFinder(definition?.dateAttribute);
|
|
42
50
|
const shouldComputeChangeAnalysis = !!definition && !!dateAttribute && !loading;
|
|
43
51
|
const { includeTags, excludeTags } = useTags();
|
|
@@ -51,9 +59,16 @@ function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
|
|
|
51
59
|
return attr ? newAttribute(ref) : null;
|
|
52
60
|
})
|
|
53
61
|
.filter(Boolean);
|
|
54
|
-
const
|
|
62
|
+
const attributeExecutionFilters = attrFilters
|
|
55
63
|
.filter((f) => !isAllValuesDashboardAttributeFilter(f))
|
|
56
64
|
.map(dashboardAttributeFilterItemToAttributeFilter);
|
|
65
|
+
const measureValueExecutionFilters = measureValueFilters
|
|
66
|
+
.filter((f) => !isAllDashboardMeasureValueFilter(f))
|
|
67
|
+
.map(dashboardMeasureValueFilterToMeasureValueFilter);
|
|
68
|
+
const filters = [
|
|
69
|
+
...attributeExecutionFilters,
|
|
70
|
+
...measureValueExecutionFilters,
|
|
71
|
+
];
|
|
57
72
|
return backend
|
|
58
73
|
.workspace(workspace)
|
|
59
74
|
.keyDriverAnalysis()
|
|
@@ -83,6 +98,7 @@ function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
|
|
|
83
98
|
loading,
|
|
84
99
|
dateAttribute,
|
|
85
100
|
attributeFiltersFingerprint,
|
|
101
|
+
measureValueFiltersFingerprint,
|
|
86
102
|
includeTags,
|
|
87
103
|
excludeTags,
|
|
88
104
|
]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DashboardAttributeFilterItem, type ICatalogDateAttribute, type ISeparators, type ObjRef } from "@gooddata/sdk-model";
|
|
1
|
+
import { type DashboardAttributeFilterItem, type ICatalogDateAttribute, type IDashboardMeasureValueFilter, type ISeparators, type ObjRef } from "@gooddata/sdk-model";
|
|
2
2
|
import { type IUiListboxInteractiveItem } from "@gooddata/sdk-ui-kit";
|
|
3
3
|
import { type DeepReadonly, type IKdaDataPoint, type IKdaDefinition, type KdaPeriodType } from "./types.js";
|
|
4
4
|
export interface IKdaDateOptions {
|
|
@@ -48,6 +48,11 @@ export interface IKdaState {
|
|
|
48
48
|
selectedStatus: KdaAsyncStatus;
|
|
49
49
|
selectedError: Error | undefined;
|
|
50
50
|
attributeFilters: DashboardAttributeFilterItem[];
|
|
51
|
+
/**
|
|
52
|
+
* Dashboard measure value filters propagated to the change analysis computation.
|
|
53
|
+
* Not editable in the dialog UI — these flow through from the dashboard filter context.
|
|
54
|
+
*/
|
|
55
|
+
measureValueFilters: IDashboardMeasureValueFilter[];
|
|
51
56
|
items: IUiListboxInteractiveItem<IKdaItem>[];
|
|
52
57
|
itemsStatus: KdaAsyncStatus;
|
|
53
58
|
itemsError: Error | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2025-2026 GoodData Corporation
|
|
3
3
|
import { useMemo } from "react";
|
|
4
|
-
import { isAllValuesDashboardAttributeFilter } from "@gooddata/sdk-model";
|
|
4
|
+
import { isAllDashboardMeasureValueFilter, isAllValuesDashboardAttributeFilter, } from "@gooddata/sdk-model";
|
|
5
5
|
import { KdaStateProvider } from "./KdaState.js";
|
|
6
6
|
export function KdaProvider({ children, definition, separators, includeTags, excludeTags }) {
|
|
7
7
|
const state = useMemo(() => {
|
|
@@ -15,6 +15,9 @@ export function KdaProvider({ children, definition, separators, includeTags, exc
|
|
|
15
15
|
definitionStatus: "success",
|
|
16
16
|
isMinimized: true,
|
|
17
17
|
attributeFilters: (definition.filters?.slice() ?? []).filter((f) => !isAllValuesDashboardAttributeFilter(f)),
|
|
18
|
+
// MVF flows through from the dashboard filter context; noop "All" MVFs are dropped
|
|
19
|
+
// so the backend only receives meaningful conditions.
|
|
20
|
+
measureValueFilters: (definition.measureValueFilters?.slice() ?? []).filter((f) => !isAllDashboardMeasureValueFilter(f)),
|
|
18
21
|
};
|
|
19
22
|
}, [definition, separators, includeTags, excludeTags]);
|
|
20
23
|
return _jsx(KdaStateProvider, { value: state, children: children });
|
package/esm/kdaDialog/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DashboardAttributeFilterItem, type IAttributeDescriptorBody, type IMeasure, type ObjRef } from "@gooddata/sdk-model";
|
|
1
|
+
import { type DashboardAttributeFilterItem, type IAttributeDescriptorBody, type IDashboardMeasureValueFilter, type IMeasure, type ObjRef } from "@gooddata/sdk-model";
|
|
2
2
|
import { type OverlayController } from "@gooddata/sdk-ui-kit";
|
|
3
3
|
/**
|
|
4
4
|
* @internal
|
|
@@ -60,9 +60,20 @@ export interface IKdaDefinition {
|
|
|
60
60
|
*/
|
|
61
61
|
metrics?: IMeasure[];
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
63
|
+
* Attribute filters to apply.
|
|
64
|
+
*
|
|
65
|
+
* Attribute filters drive both the KDA "segment-by attribute" UI in the dialog and the
|
|
66
|
+
* scope of the change analysis computation.
|
|
64
67
|
*/
|
|
65
68
|
filters?: DashboardAttributeFilterItem[];
|
|
69
|
+
/**
|
|
70
|
+
* Measure value filters to apply to the change analysis computation.
|
|
71
|
+
*
|
|
72
|
+
* They are not editable in the dialog UI (KDA segments by attribute, not by metric value),
|
|
73
|
+
* but the dashboard MVFs are propagated to the backend so the computation respects the
|
|
74
|
+
* same metric-driven scope as the rest of the dashboard.
|
|
75
|
+
*/
|
|
76
|
+
measureValueFilters?: IDashboardMeasureValueFilter[];
|
|
66
77
|
/**
|
|
67
78
|
* Date attribute
|
|
68
79
|
*/
|
|
@@ -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 {
|
|
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 =
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
dateFilterConfig:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
dateFilterConfigs:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
attributeFilterConfigs:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
measureValueFilterConfigs:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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) {
|