@gooddata/sdk-ui-dashboard 11.65.0-alpha.8 → 11.65.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +3 -91
- package/esm/__version.d.ts +1 -1
- package/esm/__version.js +1 -1
- package/esm/index.d.ts +3 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeDisplayFormHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeDisplayFormHandler.js +8 -7
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.js +19 -28
- package/esm/model/commandHandlers/filterContext/attributeFilter/removeAttributeFiltersHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/removeAttributeFiltersHandler.js +4 -5
- package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.js +14 -15
- package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.d.ts +4 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.js +11 -2
- package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.js +23 -45
- package/esm/model/commandHandlers/filterContext/common.d.ts +6 -5
- package/esm/model/commandHandlers/filterContext/common.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/common.js +12 -18
- package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.js +30 -36
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.js +11 -17
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.js +7 -10
- package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.d.ts +15 -0
- package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.js +88 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.d.ts +11 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.js +335 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.d.ts +52 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.js +60 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.d.ts +69 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.js +2 -0
- package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts +2 -1
- package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.js +41 -10
- package/esm/model/commands/parameters.d.ts +11 -1
- package/esm/model/commands/parameters.d.ts.map +1 -1
- package/esm/model/commands/parameters.js +2 -1
- package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.d.ts +75 -5
- package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.js +35 -60
- package/esm/model/store/tabs/dateFilterConfigs/dateFilterConfigsReducers.js +1 -1
- package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts +139 -31
- package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/filterContext/filterContextReducers.js +314 -529
- package/esm/model/store/tabs/filterContext/filterSync.d.ts +35 -13
- package/esm/model/store/tabs/filterContext/filterSync.d.ts.map +1 -1
- package/esm/model/store/tabs/filterContext/filterSync.js +79 -58
- package/esm/model/store/tabs/index.d.ts +10 -12
- package/esm/model/store/tabs/index.d.ts.map +1 -1
- package/esm/model/store/tabs/layout/layoutReducers.d.ts +1 -0
- package/esm/model/store/tabs/layout/layoutReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/measureValueFilterConfigs/measureValueFilterConfigsReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersReducers.d.ts +0 -5
- package/esm/model/store/tabs/parameters/parametersReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersReducers.js +8 -7
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +7 -0
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersSelectors.js +16 -0
- package/esm/model/store/tabs/tabsReducers.d.ts +8 -4
- package/esm/model/store/tabs/tabsReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/tabsReducers.js +15 -18
- package/esm/model/store/tabs/tabsState.d.ts +0 -10
- package/esm/model/store/tabs/tabsState.d.ts.map +1 -1
- package/esm/model/store/tabs/tabsState.js +0 -20
- package/esm/model/utils/attributeFilterMatching.d.ts +10 -0
- package/esm/model/utils/attributeFilterMatching.d.ts.map +1 -1
- package/esm/model/utils/attributeFilterMatching.js +14 -3
- package/esm/model/utils/attributeFilterSelectionTypeCompatibility.d.ts +8 -0
- package/esm/model/utils/attributeFilterSelectionTypeCompatibility.d.ts.map +1 -1
- package/esm/model/utils/attributeFilterSelectionTypeCompatibility.js +14 -4
- package/esm/presentation/dashboard/components/DashboardInner.js +1 -1
- package/esm/presentation/dashboard/components/DashboardInteractionComposing.d.ts +2 -1
- package/esm/presentation/dashboard/components/DashboardInteractionComposing.d.ts.map +1 -1
- package/esm/presentation/dashboard/components/DashboardInteractionComposing.js +9 -4
- package/esm/presentation/dashboard/types.d.ts +5 -0
- package/esm/presentation/dashboard/types.d.ts.map +1 -1
- package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.d.ts.map +1 -1
- package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.js +4 -1
- package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +4 -0
- package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/en-US.localization-bundle.js +4 -0
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/index.d.ts.map +1 -1
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/index.js +10 -1
- package/esm/sdk-ui-dashboard.d.ts +262 -43
- package/package.json +21 -21
- package/styles/css/dashboard.css +10 -2
- package/styles/css/dashboard.css.map +1 -1
- package/styles/css/main.css +10 -2
- package/styles/css/main.css.map +1 -1
- package/styles/scss/dashboard.scss +11 -2
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
// (C) 2021-2026 GoodData Corporation
|
|
2
2
|
import { invariant } from "ts-invariant";
|
|
3
|
-
import { areObjRefsEqual, attributeElementsIsEmpty, dashboardAttributeFilterItemLocalIdentifier, dashboardFilterLocalIdentifier,
|
|
3
|
+
import { areObjRefsEqual, attributeElementsIsEmpty, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemLocalIdentifier, dashboardFilterLocalIdentifier, isAttributeElementsByRef, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMatchAttributeFilter, isDashboardMeasureValueFilter, isIdentifierRef, newAllTimeDashboardDateFilter, } from "@gooddata/sdk-model";
|
|
4
|
+
import { isDisplayFormMetadataReferencedBy } from "../../../utils/attributeFilterMatching.js";
|
|
4
5
|
import { generateFilterLocalIdentifier, generateMeasureValueFilterLocalIdentifier, } from "../../_infra/generators.js";
|
|
5
|
-
import { getActiveTab, getTabOrActive
|
|
6
|
-
import { filterContextInitialState } from "./filterContextState.js";
|
|
6
|
+
import { getActiveTab, getTabOrActive } from "../tabsState.js";
|
|
7
|
+
import { filterContextInitialState, } from "./filterContextState.js";
|
|
7
8
|
import { applyFilterContext, initializeFilterContext } from "./filterContextUtils.js";
|
|
8
|
-
import {
|
|
9
|
+
import { findOriginalFilter, preserveFilterDependencies } from "./filterSync.js";
|
|
10
|
+
/**
|
|
11
|
+
* Filter context of the tab addressed by `tabLocalIdentifier`, or of the active tab when omitted.
|
|
12
|
+
* Initializes an empty filter context on a tab that has none.
|
|
13
|
+
*/
|
|
14
|
+
function getTabFilterContext(state, tabLocalIdentifier) {
|
|
15
|
+
const tab = getTabOrActive(state, tabLocalIdentifier);
|
|
16
|
+
if (!tab) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
if (!tab.filterContext) {
|
|
20
|
+
tab.filterContext = { ...filterContextInitialState };
|
|
21
|
+
}
|
|
22
|
+
return { tab, filterContext: tab.filterContext };
|
|
23
|
+
}
|
|
24
|
+
function getEditableFilterContext(state, tabLocalIdentifier) {
|
|
25
|
+
const target = getTabFilterContext(state, tabLocalIdentifier);
|
|
26
|
+
if (!target) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const definition = target.filterContext.filterContextDefinition;
|
|
30
|
+
invariant(definition, "Attempt to edit uninitialized filter context");
|
|
31
|
+
return { ...target, definition };
|
|
32
|
+
}
|
|
9
33
|
const setFilterContext = (state, action) => {
|
|
10
34
|
const activeTab = getActiveTab(state);
|
|
11
35
|
if (!activeTab) {
|
|
@@ -46,42 +70,34 @@ const updateFilterContextIdentityForTab = (state, action) => {
|
|
|
46
70
|
}
|
|
47
71
|
tab.filterContext.filterContextIdentity = filterContextIdentity;
|
|
48
72
|
};
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
73
|
const removeAttributeFilterDisplayForms = (state, action) => {
|
|
53
|
-
const
|
|
54
|
-
|
|
74
|
+
const { displayForm, tabLocalIdentifier } = action.payload;
|
|
75
|
+
const target = getTabFilterContext(state, tabLocalIdentifier);
|
|
76
|
+
if (!target) {
|
|
55
77
|
return;
|
|
56
78
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
const { filterContext } = target;
|
|
80
|
+
invariant(filterContext.attributeFilterDisplayForms, "attempting to work with uninitialized state");
|
|
81
|
+
// A cross-filtering virtual filter shares its display form with the dashboard filter it duplicates.
|
|
82
|
+
const usedDisplayForms = (filterContext.filterContextDefinition?.filters ?? [])
|
|
83
|
+
.filter(isDashboardAttributeFilterItem)
|
|
84
|
+
.map(dashboardAttributeFilterItemDisplayForm);
|
|
85
|
+
filterContext.attributeFilterDisplayForms = filterContext.attributeFilterDisplayForms.filter((df) => !isDisplayFormMetadataReferencedBy(df, displayForm) ||
|
|
86
|
+
usedDisplayForms.some((used) => isDisplayFormMetadataReferencedBy(df, used)));
|
|
65
87
|
};
|
|
66
88
|
const addAttributeFilterDisplayForm = (state, action) => {
|
|
67
89
|
// Handle both old and new payload formats for backward compatibility
|
|
68
90
|
const displayForm = "displayForm" in action.payload ? action.payload.displayForm : action.payload;
|
|
69
91
|
const tabLocalIdentifier = "tabLocalIdentifier" in action.payload ? action.payload.tabLocalIdentifier : undefined;
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
92
|
+
const target = getTabFilterContext(state, tabLocalIdentifier);
|
|
93
|
+
if (!target) {
|
|
72
94
|
return;
|
|
73
95
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
invariant(targetTab.filterContext.attributeFilterDisplayForms, "attempting to work with uninitialized state");
|
|
96
|
+
const { filterContext } = target;
|
|
97
|
+
invariant(filterContext.attributeFilterDisplayForms, "attempting to work with uninitialized state");
|
|
78
98
|
// if there is already a display form with the same ref, replace it
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
targetTab.filterContext.attributeFilterDisplayForms =
|
|
82
|
-
targetTab.filterContext.attributeFilterDisplayForms.filter((df) => !areObjRefsEqual(df, displayForm));
|
|
83
|
-
}
|
|
84
|
-
targetTab.filterContext.attributeFilterDisplayForms.push(displayForm);
|
|
99
|
+
filterContext.attributeFilterDisplayForms = filterContext.attributeFilterDisplayForms.filter((df) => !isDisplayFormMetadataReferencedBy(df, displayForm.ref));
|
|
100
|
+
filterContext.attributeFilterDisplayForms.push(displayForm);
|
|
85
101
|
};
|
|
86
102
|
//
|
|
87
103
|
//
|
|
@@ -92,88 +108,19 @@ const setPreloadedAttributesWithReferences = (state, action) => {
|
|
|
92
108
|
state.attributesWithReferences = action.payload;
|
|
93
109
|
};
|
|
94
110
|
const upsertDateFilter = (state, action) => {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
const source = tabs[0];
|
|
98
|
-
if (!source) {
|
|
111
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
112
|
+
if (!tab) {
|
|
99
113
|
return;
|
|
100
114
|
}
|
|
101
|
-
upsertDateFilterOnTab(
|
|
102
|
-
for (const tab of tabs.slice(1)) {
|
|
103
|
-
const payload = action.payload.restoreTargetOriginal
|
|
104
|
-
? restoredDateFilterPayload(tab, action.payload)
|
|
105
|
-
: action.payload;
|
|
106
|
-
if (!payload) {
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
upsertDateFilterOnTab(tab, payload, false);
|
|
110
|
-
}
|
|
115
|
+
upsertDateFilterOnTab(tab, action.payload);
|
|
111
116
|
};
|
|
112
|
-
|
|
113
|
-
* Saved date filter for a non-source tab during reset.
|
|
114
|
-
* A common date filter with no saved original is all time, which is stored as the filter's absence.
|
|
115
|
-
* A dimension date filter with no counterpart, or no saved original, is left unchanged.
|
|
116
|
-
*/
|
|
117
|
-
function restoredDateFilterPayload(tab, payload) {
|
|
118
|
-
const applied = findAppliedDateFilter(tab, payload.dataSet);
|
|
119
|
-
if (!applied && payload.dataSet) {
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
const original = findOriginalFilter(tab, applied ?? {
|
|
123
|
-
dateFilter: { type: "relative", granularity: "GDC.time.date" },
|
|
124
|
-
});
|
|
125
|
-
if (isDashboardDateFilter(original)) {
|
|
126
|
-
return toUpsertDateFilterPayload(original, payload);
|
|
127
|
-
}
|
|
128
|
-
if (!payload.dataSet) {
|
|
129
|
-
return { type: "allTime" };
|
|
130
|
-
}
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
function findAppliedDateFilter(tab, dataSet) {
|
|
134
|
-
const filters = tab.filterContext?.filterContextDefinition?.filters;
|
|
135
|
-
if (!filters) {
|
|
136
|
-
return undefined;
|
|
137
|
-
}
|
|
138
|
-
if (dataSet) {
|
|
139
|
-
return filters.find((item) => isDashboardDateFilter(item) && areObjRefsEqual(item.dateFilter.dataSet, dataSet));
|
|
140
|
-
}
|
|
141
|
-
return filters.find(isDashboardCommonDateFilter);
|
|
142
|
-
}
|
|
143
|
-
function toUpsertDateFilterPayload(filter, source) {
|
|
144
|
-
const { dataSet, localIdentifier, emptyValueHandling, boundedFilter, type, granularity, from, to } = filter.dateFilter;
|
|
145
|
-
const shared = {
|
|
146
|
-
...(dataSet ? { dataSet } : {}),
|
|
147
|
-
...(localIdentifier ? { localIdentifier } : {}),
|
|
148
|
-
...(emptyValueHandling ? { emptyValueHandling } : {}),
|
|
149
|
-
...(source.isWorkingSelectionChange ? { isWorkingSelectionChange: true } : {}),
|
|
150
|
-
...(source.tabLocalIdentifier ? { tabLocalIdentifier: source.tabLocalIdentifier } : {}),
|
|
151
|
-
};
|
|
152
|
-
if (isAllTimeDashboardDateFilter(filter)) {
|
|
153
|
-
return { type: "allTime", ...shared };
|
|
154
|
-
}
|
|
155
|
-
return {
|
|
156
|
-
type,
|
|
157
|
-
granularity,
|
|
158
|
-
from,
|
|
159
|
-
to,
|
|
160
|
-
...(boundedFilter ? { boundedFilter } : {}),
|
|
161
|
-
...shared,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
117
|
+
function upsertDateFilterOnTab(targetTab, payload) {
|
|
165
118
|
if (!targetTab.filterContext) {
|
|
166
|
-
if (!isSource) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
119
|
targetTab.filterContext = { ...filterContextInitialState };
|
|
170
120
|
}
|
|
171
121
|
const filterContextDefinition = payload.isWorkingSelectionChange
|
|
172
122
|
? targetTab.filterContext.workingFilterContextDefinition
|
|
173
123
|
: targetTab.filterContext.filterContextDefinition;
|
|
174
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
124
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
178
125
|
const dateDataSet = payload.dataSet;
|
|
179
126
|
let existingFilterIndex = -1;
|
|
@@ -183,9 +130,6 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
183
130
|
else {
|
|
184
131
|
existingFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardCommonDateFilter(item));
|
|
185
132
|
}
|
|
186
|
-
if (!isSource && existingFilterIndex < 0 && dateDataSet) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
133
|
if (payload.isWorkingSelectionChange && payload.type === "allTime") {
|
|
190
134
|
// we need to allways set working filter to distinguish between "not changed" and "all time" filter
|
|
191
135
|
if (existingFilterIndex >= 0) {
|
|
@@ -207,15 +151,9 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
207
151
|
}
|
|
208
152
|
}
|
|
209
153
|
else {
|
|
210
|
-
const existing = filterContextDefinition.filters[existingFilterIndex];
|
|
211
|
-
const preservedLocalIdentifier = isSource
|
|
212
|
-
? payload.localIdentifier
|
|
213
|
-
: isDashboardDateFilter(existing)
|
|
214
|
-
? existing.dateFilter.localIdentifier
|
|
215
|
-
: undefined;
|
|
216
154
|
if (payload.emptyValueHandling) {
|
|
217
155
|
// Preserve all-time common DF when it carries additional config (e.g. emptyValueHandling).
|
|
218
|
-
filterContextDefinition.filters[existingFilterIndex] = newAllTimeDashboardDateFilter(undefined,
|
|
156
|
+
filterContextDefinition.filters[existingFilterIndex] = newAllTimeDashboardDateFilter(undefined, payload.localIdentifier, payload.emptyValueHandling);
|
|
219
157
|
}
|
|
220
158
|
else {
|
|
221
159
|
// if allTime common DF remove the date filter altogether
|
|
@@ -236,7 +174,7 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
236
174
|
dateFilter.dateFilter.granularity = granularity;
|
|
237
175
|
dateFilter.dateFilter.from = from;
|
|
238
176
|
dateFilter.dateFilter.to = to;
|
|
239
|
-
if (localIdentifier
|
|
177
|
+
if (localIdentifier) {
|
|
240
178
|
dateFilter.dateFilter.localIdentifier = localIdentifier;
|
|
241
179
|
}
|
|
242
180
|
if (boundedFilter) {
|
|
@@ -253,7 +191,7 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
253
191
|
}
|
|
254
192
|
}
|
|
255
193
|
}
|
|
256
|
-
else
|
|
194
|
+
else {
|
|
257
195
|
const { type, granularity, from, to, dataSet, localIdentifier, boundedFilter, emptyValueHandling } = payload;
|
|
258
196
|
filterContextDefinition.filters.unshift({
|
|
259
197
|
dateFilter: {
|
|
@@ -270,69 +208,22 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
270
208
|
}
|
|
271
209
|
}
|
|
272
210
|
const updateAttributeFilterSelection = (state, action) => {
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
const source = tabs[0];
|
|
276
|
-
if (!source) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
const sourceFilter = findAppliedFilterByLocalId(source, action.payload.filterLocalId);
|
|
280
|
-
updateAttributeFilterSelectionOnTab(source, action.payload, action.payload.filterLocalId, true);
|
|
281
|
-
if (tabs.length === 1 ||
|
|
282
|
-
!sourceFilter ||
|
|
283
|
-
!isDashboardAttributeFilter(sourceFilter) ||
|
|
284
|
-
isCrossFilteringVirtualFilter(source, action.payload.filterLocalId, crossFilteringLocalIdsByTab)) {
|
|
211
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
212
|
+
if (!tab) {
|
|
285
213
|
return;
|
|
286
214
|
}
|
|
287
|
-
|
|
288
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences, {
|
|
289
|
-
allowListToText: false,
|
|
290
|
-
crossFilteringLocalIdsByTab,
|
|
291
|
-
});
|
|
292
|
-
if (!match || !isDashboardAttributeFilter(match)) {
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
const targetLocalId = match.attributeFilter.localIdentifier;
|
|
296
|
-
if (!targetLocalId) {
|
|
297
|
-
continue;
|
|
298
|
-
}
|
|
299
|
-
const original = action.payload.restoreTargetOriginal ? findOriginalFilter(tab, match) : undefined;
|
|
300
|
-
if (action.payload.restoreTargetOriginal && !isDashboardAttributeFilter(original)) {
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
updateAttributeFilterSelectionOnTab(tab, {
|
|
304
|
-
...action.payload,
|
|
305
|
-
filterLocalId: targetLocalId,
|
|
306
|
-
...(isDashboardAttributeFilter(original)
|
|
307
|
-
? {
|
|
308
|
-
elements: original.attributeFilter.attributeElements,
|
|
309
|
-
negativeSelection: original.attributeFilter.negativeSelection,
|
|
310
|
-
}
|
|
311
|
-
: {}),
|
|
312
|
-
enableImmediateAttributeFilterDisplayAsLabelMigration: false,
|
|
313
|
-
isResultOfMigration: false,
|
|
314
|
-
}, targetLocalId, false);
|
|
315
|
-
}
|
|
215
|
+
updateAttributeFilterSelectionOnTab(tab, action.payload);
|
|
316
216
|
};
|
|
317
|
-
function updateAttributeFilterSelectionOnTab(targetTab, payload
|
|
217
|
+
function updateAttributeFilterSelectionOnTab(targetTab, payload) {
|
|
318
218
|
if (!targetTab.filterContext) {
|
|
319
|
-
if (!isSource) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
219
|
targetTab.filterContext = { ...filterContextInitialState };
|
|
323
220
|
}
|
|
324
|
-
const { elements, negativeSelection, isWorkingSelectionChange, enableImmediateAttributeFilterDisplayAsLabelMigration, isResultOfMigration, isSelectionInvalid, } = payload;
|
|
221
|
+
const { filterLocalId, elements, negativeSelection, isWorkingSelectionChange, enableImmediateAttributeFilterDisplayAsLabelMigration, isResultOfMigration, isSelectionInvalid, } = payload;
|
|
325
222
|
const filterContextDefinition = isWorkingSelectionChange
|
|
326
223
|
? targetTab.filterContext.workingFilterContextDefinition
|
|
327
224
|
: targetTab.filterContext.filterContextDefinition;
|
|
328
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
225
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
332
226
|
const existingFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
333
|
-
if (!isSource && existingFilterIndex < 0) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
227
|
invariant(existingFilterIndex >= 0 || isWorkingSelectionChange, "Attempt to update non-existing filter");
|
|
337
228
|
if (isWorkingSelectionChange && existingFilterIndex >= 0) {
|
|
338
229
|
filterContextDefinition.filters[existingFilterIndex] = {
|
|
@@ -393,60 +284,23 @@ function findAppliedFilterByLocalId(tab, localIdentifier) {
|
|
|
393
284
|
return tab.filterContext?.filterContextDefinition?.filters.find((item) => dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
394
285
|
}
|
|
395
286
|
const replaceAttributeFilterItem = (state, action) => {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
const source = tabs[0];
|
|
399
|
-
if (!source) {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
const sourceFilter = findAppliedFilterByLocalId(source, action.payload.filterLocalId);
|
|
403
|
-
replaceAttributeFilterItemOnTab(source, action.payload, action.payload.filter, true);
|
|
404
|
-
if (tabs.length === 1 ||
|
|
405
|
-
!sourceFilter ||
|
|
406
|
-
!isDashboardAttributeFilterItem(sourceFilter) ||
|
|
407
|
-
isCrossFilteringVirtualFilter(source, action.payload.filterLocalId, crossFilteringLocalIdsByTab)) {
|
|
287
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
288
|
+
if (!tab) {
|
|
408
289
|
return;
|
|
409
290
|
}
|
|
410
|
-
|
|
411
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences, {
|
|
412
|
-
allowListToText: true,
|
|
413
|
-
crossFilteringLocalIdsByTab,
|
|
414
|
-
});
|
|
415
|
-
if (!match || !isDashboardAttributeFilterItem(match)) {
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
const targetLocalId = dashboardAttributeFilterItemLocalIdentifier(match);
|
|
419
|
-
if (!targetLocalId) {
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
const original = action.payload.restoreTargetOriginal ? findOriginalFilter(tab, match) : undefined;
|
|
423
|
-
if (action.payload.restoreTargetOriginal && !isDashboardAttributeFilterItem(original)) {
|
|
424
|
-
continue;
|
|
425
|
-
}
|
|
426
|
-
const replacement = isDashboardAttributeFilterItem(original) ? original : action.payload.filter;
|
|
427
|
-
replaceAttributeFilterItemOnTab(tab, { ...action.payload, filterLocalId: targetLocalId }, retargetAttributeFilterItem(replacement, targetLocalId), false);
|
|
428
|
-
}
|
|
291
|
+
replaceAttributeFilterItemOnTab(tab, action.payload);
|
|
429
292
|
};
|
|
430
|
-
function replaceAttributeFilterItemOnTab(targetTab, payload
|
|
293
|
+
function replaceAttributeFilterItemOnTab(targetTab, payload) {
|
|
431
294
|
if (!targetTab.filterContext) {
|
|
432
|
-
if (!isSource) {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
295
|
targetTab.filterContext = { ...filterContextInitialState };
|
|
436
296
|
}
|
|
437
|
-
const { filterLocalId, isWorkingSelectionChange, isSelectionInvalid } = payload;
|
|
297
|
+
const { filterLocalId, filter, isWorkingSelectionChange, isSelectionInvalid } = payload;
|
|
438
298
|
const filterContextDefinition = isWorkingSelectionChange
|
|
439
299
|
? targetTab.filterContext.workingFilterContextDefinition
|
|
440
300
|
: targetTab.filterContext.filterContextDefinition;
|
|
441
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
301
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
445
302
|
const existingFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilterItem(item) &&
|
|
446
303
|
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
447
|
-
if (!isSource && existingFilterIndex < 0) {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
304
|
// Preserve parent filter relationships from the existing filter when replacing.
|
|
451
305
|
// The replacement filter typically only carries selection data, not dependency configuration.
|
|
452
306
|
const replacementFilter = existingFilterIndex >= 0
|
|
@@ -480,17 +334,14 @@ function replaceAttributeFilterItemOnTab(targetTab, payload, filter, isSource) {
|
|
|
480
334
|
}
|
|
481
335
|
}
|
|
482
336
|
const addAttributeFilter = (state, action) => {
|
|
483
|
-
const
|
|
484
|
-
if (!
|
|
337
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
338
|
+
if (!target) {
|
|
485
339
|
return;
|
|
486
340
|
}
|
|
487
|
-
if (!activeTab.filterContext) {
|
|
488
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
489
|
-
}
|
|
490
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
491
341
|
const { displayForm, index, initialIsNegativeSelection, initialSelection, parentFilters, selectionMode, localIdentifier, title, } = action.payload;
|
|
342
|
+
const { definition } = target;
|
|
492
343
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
493
|
-
const isDateFilterPresent =
|
|
344
|
+
const isDateFilterPresent = definition.filters.findIndex(isDashboardDateFilter) >= 0;
|
|
494
345
|
const hasSelection = initialSelection && !attributeElementsIsEmpty(initialSelection);
|
|
495
346
|
const isNegative = selectionMode !== "single" && (initialIsNegativeSelection || !hasSelection);
|
|
496
347
|
// If DateFilter is present we have to move index by 1 because index of filter is calculated just for AttributeFilers array
|
|
@@ -500,117 +351,152 @@ const addAttributeFilter = (state, action) => {
|
|
|
500
351
|
attributeElements: initialSelection ?? { uris: [] },
|
|
501
352
|
displayForm,
|
|
502
353
|
negativeSelection: isNegative,
|
|
503
|
-
localIdentifier: localIdentifier
|
|
504
|
-
generateFilterLocalIdentifier(displayForm, Math.max(0, attributeFilterIndex)),
|
|
354
|
+
localIdentifier: resolveAttributeFilterLocalIdentifier(definition, displayForm, attributeFilterIndex, localIdentifier),
|
|
505
355
|
filterElementsBy: parentFilters ? [...parentFilters] : undefined,
|
|
506
356
|
...(selectionMode === undefined ? {} : { selectionMode }),
|
|
507
357
|
title,
|
|
508
358
|
},
|
|
509
359
|
};
|
|
510
360
|
if (index === -1) {
|
|
511
|
-
|
|
361
|
+
definition.filters.push(filter);
|
|
512
362
|
}
|
|
513
363
|
else {
|
|
514
|
-
|
|
364
|
+
definition.filters.splice(attributeFilterIndex, 0, filter);
|
|
515
365
|
}
|
|
516
366
|
};
|
|
517
367
|
const addTextAttributeFilter = (state, action) => {
|
|
518
|
-
const
|
|
519
|
-
if (!
|
|
368
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
369
|
+
if (!target) {
|
|
520
370
|
return;
|
|
521
371
|
}
|
|
522
|
-
if (!activeTab.filterContext) {
|
|
523
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
524
|
-
}
|
|
525
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
526
372
|
const { filter, index } = action.payload;
|
|
373
|
+
const { definition } = target;
|
|
527
374
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
528
|
-
const isDateFilterPresent =
|
|
375
|
+
const isDateFilterPresent = definition.filters.findIndex(isDashboardDateFilter) >= 0;
|
|
529
376
|
const attributeFilterIndex = isDateFilterPresent ? index + 1 : index;
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
377
|
+
const filterWithLocalIdentifier = withAttributeFilterLocalIdentifier(filter, resolveAttributeFilterLocalIdentifier(definition, dashboardAttributeFilterItemDisplayForm(filter), attributeFilterIndex, dashboardAttributeFilterItemLocalIdentifier(filter)));
|
|
378
|
+
if (!filterWithLocalIdentifier) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
if (index === -1) {
|
|
382
|
+
definition.filters.push(filterWithLocalIdentifier);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
definition.filters.splice(attributeFilterIndex, 0, filterWithLocalIdentifier);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
function withAttributeFilterLocalIdentifier(filter, localIdentifier) {
|
|
389
|
+
if (isDashboardArbitraryAttributeFilter(filter)) {
|
|
390
|
+
return {
|
|
533
391
|
arbitraryAttributeFilter: {
|
|
534
392
|
...filter.arbitraryAttributeFilter,
|
|
535
|
-
localIdentifier
|
|
536
|
-
|
|
393
|
+
localIdentifier,
|
|
394
|
+
},
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
if (isDashboardMatchAttributeFilter(filter)) {
|
|
398
|
+
return {
|
|
399
|
+
matchAttributeFilter: {
|
|
400
|
+
...filter.matchAttributeFilter,
|
|
401
|
+
localIdentifier,
|
|
537
402
|
},
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Keeps `preferred` unless another filter on the tab already uses it, otherwise generates
|
|
409
|
+
* the first free identifier. A filter mirrored from another tab can collide with a local one.
|
|
410
|
+
*/
|
|
411
|
+
function resolveAttributeFilterLocalIdentifier(definition, displayForm, index, preferred) {
|
|
412
|
+
return resolveFilterLocalIdentifier(definition, (candidateIndex) => generateFilterLocalIdentifier(displayForm, candidateIndex), index, preferred);
|
|
413
|
+
}
|
|
414
|
+
function resolveFilterLocalIdentifier(definition, generate, index, preferred) {
|
|
415
|
+
const used = new Set();
|
|
416
|
+
for (const item of definition.filters) {
|
|
417
|
+
const localIdentifier = dashboardFilterLocalIdentifier(item);
|
|
418
|
+
if (localIdentifier) {
|
|
419
|
+
used.add(localIdentifier);
|
|
538
420
|
}
|
|
539
|
-
: isDashboardMatchAttributeFilter(filter)
|
|
540
|
-
? {
|
|
541
|
-
matchAttributeFilter: {
|
|
542
|
-
...filter.matchAttributeFilter,
|
|
543
|
-
localIdentifier: filter.matchAttributeFilter.localIdentifier ??
|
|
544
|
-
generateFilterLocalIdentifier(filter.matchAttributeFilter.displayForm, generatedLocalIdentifierIndex),
|
|
545
|
-
},
|
|
546
|
-
}
|
|
547
|
-
: filter;
|
|
548
|
-
if (index === -1) {
|
|
549
|
-
activeTab.filterContext.filterContextDefinition.filters.push(filterWithLocalIdentifier);
|
|
550
421
|
}
|
|
551
|
-
|
|
552
|
-
|
|
422
|
+
if (preferred && !used.has(preferred)) {
|
|
423
|
+
return preferred;
|
|
553
424
|
}
|
|
554
|
-
|
|
425
|
+
let candidateIndex = Math.max(0, index);
|
|
426
|
+
let localIdentifier = generate(candidateIndex);
|
|
427
|
+
while (used.has(localIdentifier)) {
|
|
428
|
+
candidateIndex += 1;
|
|
429
|
+
localIdentifier = generate(candidateIndex);
|
|
430
|
+
}
|
|
431
|
+
return localIdentifier;
|
|
432
|
+
}
|
|
555
433
|
const removeAttributeFilter = (state, action) => {
|
|
556
|
-
const
|
|
557
|
-
if (!
|
|
434
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
435
|
+
if (!target) {
|
|
558
436
|
return;
|
|
559
437
|
}
|
|
560
|
-
if (!activeTab.filterContext) {
|
|
561
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
562
|
-
}
|
|
563
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
564
438
|
const { filterLocalId } = action.payload;
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
439
|
+
const { filterContext, definition } = target;
|
|
440
|
+
filterContext.filterContextDefinition = {
|
|
441
|
+
...definition,
|
|
442
|
+
filters: definition.filters.filter((item) => isDashboardDateFilter(item) ||
|
|
443
|
+
!isDashboardAttributeFilterItem(item) ||
|
|
444
|
+
dashboardAttributeFilterItemLocalIdentifier(item) !== filterLocalId),
|
|
571
445
|
};
|
|
446
|
+
removeAttributeFilterParentReferences(filterContext.filterContextDefinition, filterLocalId);
|
|
572
447
|
};
|
|
448
|
+
/**
|
|
449
|
+
* Drops parent references to a removed filter, including children that exist only on this tab.
|
|
450
|
+
*/
|
|
451
|
+
function removeAttributeFilterParentReferences(definition, removedLocalId) {
|
|
452
|
+
for (const item of definition.filters) {
|
|
453
|
+
if (isDashboardAttributeFilter(item) && item.attributeFilter.filterElementsBy) {
|
|
454
|
+
const remaining = item.attributeFilter.filterElementsBy.filter((parent) => parent.filterLocalIdentifier !== removedLocalId);
|
|
455
|
+
if (remaining.length !== item.attributeFilter.filterElementsBy.length) {
|
|
456
|
+
item.attributeFilter.filterElementsBy = remaining;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
else if (isDashboardArbitraryAttributeFilter(item) &&
|
|
460
|
+
item.arbitraryAttributeFilter.filterElementsBy) {
|
|
461
|
+
const remaining = item.arbitraryAttributeFilter.filterElementsBy.filter((parent) => parent.filterLocalIdentifier !== removedLocalId);
|
|
462
|
+
if (remaining.length !== item.arbitraryAttributeFilter.filterElementsBy.length) {
|
|
463
|
+
item.arbitraryAttributeFilter.filterElementsBy = remaining;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
573
468
|
const moveAttributeFilter = (state, action) => {
|
|
574
|
-
const
|
|
575
|
-
if (!
|
|
469
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
470
|
+
if (!target) {
|
|
576
471
|
return;
|
|
577
472
|
}
|
|
578
|
-
if (!activeTab.filterContext) {
|
|
579
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
580
|
-
}
|
|
581
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
582
473
|
const { filterLocalId, index } = action.payload;
|
|
583
|
-
const
|
|
474
|
+
const filters = target.definition.filters;
|
|
475
|
+
const currentFilterIndex = filters.findIndex((item) => isDashboardAttributeFilterItem(item) &&
|
|
584
476
|
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
585
477
|
invariant(currentFilterIndex >= 0, "Attempt to move non-existing filter");
|
|
586
|
-
const filter =
|
|
587
|
-
|
|
478
|
+
const filter = filters[currentFilterIndex];
|
|
479
|
+
filters.splice(currentFilterIndex, 1);
|
|
588
480
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
589
|
-
const isDateFilterPresent =
|
|
481
|
+
const isDateFilterPresent = filters.findIndex(isDashboardDateFilter) >= 0;
|
|
590
482
|
if (index === -1) {
|
|
591
|
-
|
|
483
|
+
filters.push(filter);
|
|
592
484
|
}
|
|
593
485
|
else {
|
|
594
486
|
// If DateFilter is present we have to move index by 1 because index of filter is calculated just for AttributeFilers array
|
|
595
487
|
const attributeFilterIndex = isDateFilterPresent ? index + 1 : index;
|
|
596
|
-
|
|
488
|
+
filters.splice(attributeFilterIndex, 0, filter);
|
|
597
489
|
}
|
|
598
490
|
};
|
|
599
491
|
const setAttributeFilterParents = (state, action) => {
|
|
600
|
-
const
|
|
601
|
-
if (!
|
|
492
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
493
|
+
if (!target) {
|
|
602
494
|
return;
|
|
603
495
|
}
|
|
604
|
-
if (!activeTab.filterContext) {
|
|
605
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
606
|
-
}
|
|
607
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
608
496
|
const { filterLocalId, parentFilters } = action.payload;
|
|
609
|
-
const
|
|
610
|
-
|
|
611
|
-
invariant(currentFilterIndex >= 0, "Attempt to set parent of a non-existing filter");
|
|
497
|
+
const filter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
498
|
+
invariant(filter, "Attempt to set parent of a non-existing filter");
|
|
612
499
|
// silently ignore when targeting match filter, will have no effect
|
|
613
|
-
const filter = activeTab.filterContext.filterContextDefinition.filters[currentFilterIndex];
|
|
614
500
|
if (isDashboardAttributeFilter(filter)) {
|
|
615
501
|
filter.attributeFilter.filterElementsBy = [...parentFilters];
|
|
616
502
|
}
|
|
@@ -619,19 +505,13 @@ const setAttributeFilterParents = (state, action) => {
|
|
|
619
505
|
}
|
|
620
506
|
};
|
|
621
507
|
const setAttributeFilterDependentDateFilters = (state, action) => {
|
|
622
|
-
const
|
|
623
|
-
if (!
|
|
508
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
509
|
+
if (!target) {
|
|
624
510
|
return;
|
|
625
511
|
}
|
|
626
|
-
if (!activeTab.filterContext) {
|
|
627
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
628
|
-
}
|
|
629
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
630
512
|
const { filterLocalId, dependentDateFilters } = action.payload;
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
invariant(currentFilterIndex >= 0, "Attempt to set dependent date filter of a non-existing filter");
|
|
634
|
-
const filter = activeTab.filterContext.filterContextDefinition.filters[currentFilterIndex];
|
|
513
|
+
const filter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
514
|
+
invariant(filter, "Attempt to set dependent date filter of a non-existing filter");
|
|
635
515
|
if (isDashboardAttributeFilter(filter)) {
|
|
636
516
|
filter.attributeFilter.filterElementsByDate = [...dependentDateFilters];
|
|
637
517
|
}
|
|
@@ -640,64 +520,43 @@ const setAttributeFilterDependentDateFilters = (state, action) => {
|
|
|
640
520
|
}
|
|
641
521
|
// Match filters do not support filterElementsByDate
|
|
642
522
|
};
|
|
523
|
+
function findAttributeFilterItem(definition, localIdentifier) {
|
|
524
|
+
return definition.filters.find((item) => isDashboardAttributeFilterItem(item) &&
|
|
525
|
+
dashboardAttributeFilterItemLocalIdentifier(item) === localIdentifier);
|
|
526
|
+
}
|
|
643
527
|
const clearAttributeFiltersSelection = (state, action) => {
|
|
644
|
-
const { tabLocalIdentifier,
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
if (!source) {
|
|
528
|
+
const { tabLocalIdentifier, filterLocalIds, restoreOriginal } = action.payload;
|
|
529
|
+
const tab = getTabOrActive(state, tabLocalIdentifier);
|
|
530
|
+
if (!tab) {
|
|
648
531
|
return;
|
|
649
532
|
}
|
|
650
|
-
if (!
|
|
651
|
-
|
|
533
|
+
if (!tab.filterContext) {
|
|
534
|
+
tab.filterContext = { ...filterContextInitialState };
|
|
652
535
|
}
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
});
|
|
660
|
-
for (const tab of tabs.slice(1)) {
|
|
661
|
-
for (const { filterLocalId, filter } of sourceFilters) {
|
|
662
|
-
if (!filter ||
|
|
663
|
-
!isDashboardAttributeFilter(filter) ||
|
|
664
|
-
isCrossFilteringVirtualFilter(source, filterLocalId, crossFilteringLocalIdsByTab)) {
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
const match = findCounterpartFilter(source, filter, tab, state.attributesWithReferences, {
|
|
668
|
-
allowListToText: false,
|
|
669
|
-
crossFilteringLocalIdsByTab,
|
|
670
|
-
});
|
|
671
|
-
if (!match || !isDashboardAttributeFilter(match) || !match.attributeFilter.localIdentifier) {
|
|
672
|
-
continue;
|
|
673
|
-
}
|
|
674
|
-
const targetLocalId = match.attributeFilter.localIdentifier;
|
|
675
|
-
if (action.payload.restoreTargetOriginal) {
|
|
676
|
-
const original = findOriginalFilter(tab, match);
|
|
677
|
-
if (!isDashboardAttributeFilter(original)) {
|
|
678
|
-
continue;
|
|
679
|
-
}
|
|
680
|
-
updateAttributeFilterSelectionOnTab(tab, {
|
|
681
|
-
filterLocalId: targetLocalId,
|
|
682
|
-
elements: original.attributeFilter.attributeElements,
|
|
683
|
-
negativeSelection: original.attributeFilter.negativeSelection,
|
|
684
|
-
}, targetLocalId, false);
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
clearAttributeFilterSelectionOnTab(tab, targetLocalId, false);
|
|
536
|
+
for (const filterLocalId of filterLocalIds) {
|
|
537
|
+
if (restoreOriginal) {
|
|
538
|
+
restoreAttributeFilterSelectionOnTab(tab, filterLocalId);
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
clearAttributeFilterSelectionOnTab(tab, filterLocalId);
|
|
688
542
|
}
|
|
689
543
|
}
|
|
690
544
|
};
|
|
691
|
-
function
|
|
692
|
-
const
|
|
693
|
-
|
|
545
|
+
function restoreAttributeFilterSelectionOnTab(tab, filterLocalId) {
|
|
546
|
+
const filter = findAppliedFilterByLocalId(tab, filterLocalId);
|
|
547
|
+
const original = filter ? findOriginalFilter(tab, filter) : undefined;
|
|
548
|
+
if (!isDashboardAttributeFilter(original)) {
|
|
694
549
|
return;
|
|
695
550
|
}
|
|
551
|
+
updateAttributeFilterSelectionOnTab(tab, {
|
|
552
|
+
filterLocalId,
|
|
553
|
+
elements: original.attributeFilter.attributeElements,
|
|
554
|
+
negativeSelection: original.attributeFilter.negativeSelection,
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
function clearAttributeFilterSelectionOnTab(tab, filterLocalId) {
|
|
696
558
|
invariant(tab.filterContext?.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
697
559
|
const currentFilterIndex = tab.filterContext.filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
698
|
-
if (!isSource && currentFilterIndex < 0) {
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
560
|
invariant(currentFilterIndex >= 0, "Attempt to clear selection of a non-existing filter");
|
|
702
561
|
const currentFilter = tab.filterContext.filterContextDefinition.filters[currentFilterIndex];
|
|
703
562
|
currentFilter.attributeFilter.negativeSelection =
|
|
@@ -710,17 +569,15 @@ function clearAttributeFilterSelectionOnTab(tab, filterLocalId, isSource) {
|
|
|
710
569
|
* Changes the display form for the filter given by its local identifier.
|
|
711
570
|
*/
|
|
712
571
|
const changeAttributeDisplayForm = (state, action) => {
|
|
713
|
-
const
|
|
714
|
-
if (!
|
|
572
|
+
const target = getTabFilterContext(state, action.payload.tabLocalIdentifier);
|
|
573
|
+
if (!target) {
|
|
715
574
|
return;
|
|
716
575
|
}
|
|
717
|
-
if (!targetTab.filterContext) {
|
|
718
|
-
targetTab.filterContext = { ...filterContextInitialState };
|
|
719
|
-
}
|
|
720
576
|
const { filterLocalId, displayForm, isWorkingSelectionChange, enableImmediateAttributeFilterDisplayAsLabelMigration, isResultOfMigration, } = action.payload;
|
|
577
|
+
const { filterContext } = target;
|
|
721
578
|
const filterContextDefinition = isWorkingSelectionChange
|
|
722
|
-
?
|
|
723
|
-
:
|
|
579
|
+
? filterContext.workingFilterContextDefinition
|
|
580
|
+
: filterContext.filterContextDefinition;
|
|
724
581
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
725
582
|
const currentFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
726
583
|
invariant(currentFilterIndex >= 0 || isWorkingSelectionChange, "Attempt to set parent of a non-existing filter");
|
|
@@ -738,7 +595,7 @@ const changeAttributeDisplayForm = (state, action) => {
|
|
|
738
595
|
currentFilter.attributeFilter.displayForm = { ...displayForm };
|
|
739
596
|
// update original filters to not show "reset filters" button, that will revert filter to wrong state
|
|
740
597
|
if (enableImmediateAttributeFilterDisplayAsLabelMigration && isResultOfMigration) {
|
|
741
|
-
const originalFilter =
|
|
598
|
+
const originalFilter = filterContext.originalFilterContextDefinition?.filters.find((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
742
599
|
if (isDashboardAttributeFilter(originalFilter)) {
|
|
743
600
|
originalFilter.attributeFilter.displayForm = { ...displayForm };
|
|
744
601
|
}
|
|
@@ -751,21 +608,12 @@ const changeAttributeDisplayForm = (state, action) => {
|
|
|
751
608
|
*/
|
|
752
609
|
const changeTextFilterDisplayForm = (state, action) => {
|
|
753
610
|
const targetTab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
754
|
-
|
|
755
|
-
return;
|
|
756
|
-
}
|
|
757
|
-
const { filterLocalId, displayForm } = action.payload;
|
|
758
|
-
const filterContextDefinition = targetTab.filterContext.filterContextDefinition;
|
|
611
|
+
const filterContextDefinition = targetTab?.filterContext?.filterContextDefinition;
|
|
759
612
|
if (!filterContextDefinition?.filters) {
|
|
760
613
|
return;
|
|
761
614
|
}
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
765
|
-
if (currentFilterIndex < 0) {
|
|
766
|
-
return;
|
|
767
|
-
}
|
|
768
|
-
const filter = filterContextDefinition.filters[currentFilterIndex];
|
|
615
|
+
const { filterLocalId, displayForm } = action.payload;
|
|
616
|
+
const filter = findAttributeFilterItem(filterContextDefinition, filterLocalId);
|
|
769
617
|
if (isDashboardArbitraryAttributeFilter(filter)) {
|
|
770
618
|
filter.arbitraryAttributeFilter.displayForm = { ...displayForm };
|
|
771
619
|
}
|
|
@@ -777,17 +625,12 @@ const changeTextFilterDisplayForm = (state, action) => {
|
|
|
777
625
|
* Changes the title for the filter given by its local identifier.
|
|
778
626
|
*/
|
|
779
627
|
const changeAttributeTitle = (state, action) => {
|
|
780
|
-
const
|
|
781
|
-
if (!
|
|
628
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
629
|
+
if (!target) {
|
|
782
630
|
return;
|
|
783
631
|
}
|
|
784
|
-
if (!activeTab.filterContext) {
|
|
785
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
786
|
-
}
|
|
787
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
788
632
|
const { filterLocalId, title } = action.payload;
|
|
789
|
-
const findFilter =
|
|
790
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
633
|
+
const findFilter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
791
634
|
invariant(findFilter, "Attempt to change title of a non-existing filter");
|
|
792
635
|
if (isDashboardAttributeFilter(findFilter)) {
|
|
793
636
|
findFilter.attributeFilter.title = title;
|
|
@@ -803,17 +646,12 @@ const changeAttributeTitle = (state, action) => {
|
|
|
803
646
|
* Changes the selection mode for the filter given by its local identifier.
|
|
804
647
|
*/
|
|
805
648
|
const changeSelectionMode = (state, action) => {
|
|
806
|
-
const
|
|
807
|
-
if (!
|
|
649
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
650
|
+
if (!target) {
|
|
808
651
|
return;
|
|
809
652
|
}
|
|
810
|
-
if (!activeTab.filterContext) {
|
|
811
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
812
|
-
}
|
|
813
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
814
653
|
const { filterLocalId, selectionMode } = action.payload;
|
|
815
|
-
const findFilter =
|
|
816
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
654
|
+
const findFilter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
817
655
|
invariant(findFilter, "Attempt to change selection mode of a non-existing filter");
|
|
818
656
|
// Text filters (arbitrary, match) do not have selectionMode; no-op for them
|
|
819
657
|
if (isDashboardAttributeFilter(findFilter)) {
|
|
@@ -821,15 +659,12 @@ const changeSelectionMode = (state, action) => {
|
|
|
821
659
|
}
|
|
822
660
|
};
|
|
823
661
|
const addDateFilter = (state, action) => {
|
|
824
|
-
const
|
|
825
|
-
if (!
|
|
662
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
663
|
+
if (!target) {
|
|
826
664
|
return;
|
|
827
665
|
}
|
|
828
|
-
if (!activeTab.filterContext) {
|
|
829
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
830
|
-
}
|
|
831
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
832
666
|
const { index, dateDataset } = action.payload;
|
|
667
|
+
const { definition } = target;
|
|
833
668
|
const filter = {
|
|
834
669
|
dateFilter: {
|
|
835
670
|
dataSet: dateDataset,
|
|
@@ -838,73 +673,58 @@ const addDateFilter = (state, action) => {
|
|
|
838
673
|
},
|
|
839
674
|
};
|
|
840
675
|
// Only draggable filters are indexed, if DateFilter is present should be always first item
|
|
841
|
-
const isCommonDateFilterPresent =
|
|
676
|
+
const isCommonDateFilterPresent = definition.filters.findIndex(isDashboardCommonDateFilter) >= 0;
|
|
842
677
|
if (index === -1) {
|
|
843
|
-
|
|
678
|
+
definition.filters.push(filter);
|
|
844
679
|
}
|
|
845
680
|
else {
|
|
846
681
|
// If CommonDateFilter is present we have to move index by 1 because index of filter is calculated just for AttributeFilers array
|
|
847
682
|
const newFilterIndex = isCommonDateFilterPresent ? index + 1 : index;
|
|
848
|
-
|
|
683
|
+
definition.filters.splice(newFilterIndex, 0, filter);
|
|
849
684
|
}
|
|
850
685
|
};
|
|
851
|
-
//
|
|
852
|
-
//
|
|
853
|
-
//
|
|
854
686
|
const addMeasureValueFilter = (state, action) => {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
const activeTab = getTabsToMutate(state)[0];
|
|
858
|
-
if (!activeTab) {
|
|
687
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
688
|
+
if (!target) {
|
|
859
689
|
return;
|
|
860
690
|
}
|
|
861
|
-
if (!activeTab.filterContext) {
|
|
862
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
863
|
-
}
|
|
864
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
865
691
|
const { index, measure, localIdentifier, title } = action.payload;
|
|
692
|
+
const { definition } = target;
|
|
866
693
|
const filter = {
|
|
867
694
|
dashboardMeasureValueFilter: {
|
|
868
695
|
measure,
|
|
869
|
-
localIdentifier:
|
|
696
|
+
localIdentifier: resolveFilterLocalIdentifier(definition, (candidateIndex) => generateMeasureValueFilterLocalIdentifier(measure, candidateIndex), index, localIdentifier),
|
|
870
697
|
title,
|
|
871
698
|
},
|
|
872
699
|
};
|
|
873
|
-
const isCommonDateFilterPresent =
|
|
700
|
+
const isCommonDateFilterPresent = definition.filters.findIndex(isDashboardCommonDateFilter) >= 0;
|
|
874
701
|
if (index === -1) {
|
|
875
|
-
|
|
702
|
+
definition.filters.push(filter);
|
|
876
703
|
}
|
|
877
704
|
else {
|
|
878
705
|
const newFilterIndex = isCommonDateFilterPresent ? index + 1 : index;
|
|
879
|
-
|
|
706
|
+
definition.filters.splice(newFilterIndex, 0, filter);
|
|
880
707
|
}
|
|
881
708
|
};
|
|
882
709
|
const removeMeasureValueFilter = (state, action) => {
|
|
883
|
-
const
|
|
884
|
-
if (!
|
|
710
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
711
|
+
if (!target) {
|
|
885
712
|
return;
|
|
886
713
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
...activeTab.filterContext.filterContextDefinition,
|
|
893
|
-
filters: activeTab.filterContext.filterContextDefinition.filters.filter((item) => !(isDashboardMeasureValueFilter(item) &&
|
|
894
|
-
dashboardFilterLocalIdentifier(item) === action.payload.localIdentifier)),
|
|
714
|
+
const { localIdentifier } = action.payload;
|
|
715
|
+
target.filterContext.filterContextDefinition = {
|
|
716
|
+
...target.definition,
|
|
717
|
+
filters: target.definition.filters.filter((item) => !(isDashboardMeasureValueFilter(item) &&
|
|
718
|
+
dashboardFilterLocalIdentifier(item) === localIdentifier)),
|
|
895
719
|
};
|
|
896
720
|
};
|
|
897
721
|
const moveMeasureValueFilter = (state, action) => {
|
|
898
|
-
const
|
|
899
|
-
if (!
|
|
722
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
723
|
+
if (!target) {
|
|
900
724
|
return;
|
|
901
725
|
}
|
|
902
|
-
if (!activeTab.filterContext) {
|
|
903
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
904
|
-
}
|
|
905
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
906
726
|
const { localIdentifier, index } = action.payload;
|
|
907
|
-
const filters =
|
|
727
|
+
const filters = target.definition.filters;
|
|
908
728
|
const currentFilterIndex = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
909
729
|
invariant(currentFilterIndex >= 0, "Attempt to move non-existing measure value filter");
|
|
910
730
|
const filter = filters[currentFilterIndex];
|
|
@@ -919,61 +739,91 @@ const moveMeasureValueFilter = (state, action) => {
|
|
|
919
739
|
}
|
|
920
740
|
};
|
|
921
741
|
const removeDateFilter = (state, action) => {
|
|
922
|
-
const
|
|
923
|
-
if (!
|
|
742
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
743
|
+
if (!target) {
|
|
924
744
|
return;
|
|
925
745
|
}
|
|
926
|
-
if (!activeTab.filterContext) {
|
|
927
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
928
|
-
}
|
|
929
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
930
746
|
const { dataSet } = action.payload;
|
|
931
|
-
const
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
747
|
+
const { filterContext, definition } = target;
|
|
748
|
+
const removed = definition.filters.find((item) => isDashboardDateFilterWithDimension(item) && areObjRefsEqual(item.dateFilter.dataSet, dataSet));
|
|
749
|
+
const removedLocalIdentifier = isDashboardDateFilter(removed)
|
|
750
|
+
? removed.dateFilter.localIdentifier
|
|
751
|
+
: undefined;
|
|
752
|
+
filterContext.filterContextDefinition = {
|
|
753
|
+
...definition,
|
|
754
|
+
filters: definition.filters.filter((item) => !isDashboardDateFilter(item) || !areObjRefsEqual(item.dateFilter.dataSet, dataSet)),
|
|
935
755
|
};
|
|
756
|
+
removeDimensionDateFilterDependencies(filterContext.filterContextDefinition, dataSet, removedLocalIdentifier);
|
|
936
757
|
};
|
|
758
|
+
/**
|
|
759
|
+
* Drops attribute-filter dependencies that point at the removed dimension date filter, including
|
|
760
|
+
* filters that exist only on this tab. Matches both the filter local identifier and the legacy
|
|
761
|
+
* dataset-identifier form.
|
|
762
|
+
*/
|
|
763
|
+
function removeDimensionDateFilterDependencies(definition, dataSet, removedLocalIdentifier) {
|
|
764
|
+
const datasetIdentifier = isIdentifierRef(dataSet) ? dataSet.identifier : undefined;
|
|
765
|
+
for (const item of definition.filters) {
|
|
766
|
+
if (isDashboardAttributeFilter(item)) {
|
|
767
|
+
const next = withoutRemovedDateDependency(item.attributeFilter.filterElementsByDate, removedLocalIdentifier, datasetIdentifier);
|
|
768
|
+
if (next !== item.attributeFilter.filterElementsByDate) {
|
|
769
|
+
item.attributeFilter.filterElementsByDate = next;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
else if (isDashboardArbitraryAttributeFilter(item)) {
|
|
773
|
+
const next = withoutRemovedDateDependency(item.arbitraryAttributeFilter.filterElementsByDate, removedLocalIdentifier, datasetIdentifier);
|
|
774
|
+
if (next !== item.arbitraryAttributeFilter.filterElementsByDate) {
|
|
775
|
+
item.arbitraryAttributeFilter.filterElementsByDate = next;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
function withoutRemovedDateDependency(dependencies, removedLocalIdentifier, datasetIdentifier) {
|
|
781
|
+
if (!dependencies?.length) {
|
|
782
|
+
return dependencies;
|
|
783
|
+
}
|
|
784
|
+
const remaining = dependencies.filter((dependency) => {
|
|
785
|
+
if (dependency.isCommonDate) {
|
|
786
|
+
return true;
|
|
787
|
+
}
|
|
788
|
+
const matchesLocalIdentifier = removedLocalIdentifier !== undefined &&
|
|
789
|
+
dependency.filterLocalIdentifier === removedLocalIdentifier;
|
|
790
|
+
const matchesDatasetIdentifier = datasetIdentifier !== undefined && dependency.filterLocalIdentifier === datasetIdentifier;
|
|
791
|
+
return !matchesLocalIdentifier && !matchesDatasetIdentifier;
|
|
792
|
+
});
|
|
793
|
+
return remaining.length === dependencies.length ? dependencies : remaining;
|
|
794
|
+
}
|
|
937
795
|
const moveDateFilter = (state, action) => {
|
|
938
|
-
const
|
|
939
|
-
if (!
|
|
796
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
797
|
+
if (!target) {
|
|
940
798
|
return;
|
|
941
799
|
}
|
|
942
|
-
if (!activeTab.filterContext) {
|
|
943
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
944
|
-
}
|
|
945
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
946
800
|
const { dataSet, index } = action.payload;
|
|
947
|
-
const
|
|
801
|
+
const filters = target.definition.filters;
|
|
802
|
+
const currentFilterIndex = filters.findIndex((item) => isDashboardDateFilter(item) && areObjRefsEqual(item.dateFilter.dataSet, dataSet));
|
|
948
803
|
invariant(currentFilterIndex >= 0, "Attempt to move non-existing filter");
|
|
949
|
-
const filter =
|
|
950
|
-
|
|
804
|
+
const filter = filters[currentFilterIndex];
|
|
805
|
+
filters.splice(currentFilterIndex, 1);
|
|
951
806
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
952
|
-
const isCommonDateFilterPresent =
|
|
807
|
+
const isCommonDateFilterPresent = filters.findIndex(isDashboardCommonDateFilter) >= 0;
|
|
953
808
|
if (index === -1) {
|
|
954
|
-
|
|
809
|
+
filters.push(filter);
|
|
955
810
|
}
|
|
956
811
|
else {
|
|
957
812
|
// If DateFilter is present we have to move index by 1 because index of filter is calculated just for DraggableFilters array
|
|
958
813
|
const dateFilterIndex = isCommonDateFilterPresent ? index + 1 : index;
|
|
959
|
-
|
|
814
|
+
filters.splice(dateFilterIndex, 0, filter);
|
|
960
815
|
}
|
|
961
816
|
};
|
|
962
817
|
/**
|
|
963
818
|
* Changes the element limiting items for the filter given by its local identifier.
|
|
964
819
|
*/
|
|
965
820
|
const changeLimitingItems = (state, action) => {
|
|
966
|
-
const
|
|
967
|
-
if (!
|
|
821
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
822
|
+
if (!target) {
|
|
968
823
|
return;
|
|
969
824
|
}
|
|
970
|
-
if (!activeTab.filterContext) {
|
|
971
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
972
|
-
}
|
|
973
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
974
825
|
const { filterLocalId, limitingItems } = action.payload;
|
|
975
|
-
const findFilter =
|
|
976
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
826
|
+
const findFilter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
977
827
|
invariant(findFilter, "Attempt to change limiting items of a non-existing filter");
|
|
978
828
|
if (isDashboardAttributeFilter(findFilter)) {
|
|
979
829
|
findFilter.attributeFilter.validateElementsBy = limitingItems;
|
|
@@ -1012,8 +862,9 @@ export function clearFilterContextWorkingValues(tab) {
|
|
|
1012
862
|
tab.filterContext.workingFilterContextDefinition = { filters: [] };
|
|
1013
863
|
}
|
|
1014
864
|
const resetWorkingFilterSelection = (state) => {
|
|
1015
|
-
|
|
1016
|
-
|
|
865
|
+
const activeTab = getActiveTab(state);
|
|
866
|
+
if (activeTab) {
|
|
867
|
+
clearFilterContextWorkingValues(activeTab);
|
|
1017
868
|
}
|
|
1018
869
|
};
|
|
1019
870
|
//
|
|
@@ -1030,59 +881,24 @@ const setDefaultFilterOverrides = (state, action) => {
|
|
|
1030
881
|
activeTab.filterContext.defaultFilterOverrides = action.payload;
|
|
1031
882
|
};
|
|
1032
883
|
const changeMeasureValueFilterCondition = (state, action) => {
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
const source = tabs[0];
|
|
1036
|
-
if (!source) {
|
|
1037
|
-
return;
|
|
1038
|
-
}
|
|
1039
|
-
const sourceFilter = findAppliedFilterByLocalId(source, localIdentifier);
|
|
1040
|
-
changeMeasureValueFilterConditionOnTab(source, action.payload, localIdentifier, true);
|
|
1041
|
-
if (!sourceFilter || !isDashboardMeasureValueFilter(sourceFilter)) {
|
|
884
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
885
|
+
if (!tab) {
|
|
1042
886
|
return;
|
|
1043
887
|
}
|
|
1044
|
-
|
|
1045
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences);
|
|
1046
|
-
const targetLocalId = match ? dashboardFilterLocalIdentifier(match) : undefined;
|
|
1047
|
-
if (!targetLocalId || !match) {
|
|
1048
|
-
continue;
|
|
1049
|
-
}
|
|
1050
|
-
if (action.payload.restoreTargetOriginal) {
|
|
1051
|
-
const original = findOriginalFilter(tab, match);
|
|
1052
|
-
if (!isDashboardMeasureValueFilter(original)) {
|
|
1053
|
-
continue;
|
|
1054
|
-
}
|
|
1055
|
-
changeMeasureValueFilterConditionOnTab(tab, {
|
|
1056
|
-
...action.payload,
|
|
1057
|
-
localIdentifier: targetLocalId,
|
|
1058
|
-
conditions: original.dashboardMeasureValueFilter.conditions,
|
|
1059
|
-
}, targetLocalId, false);
|
|
1060
|
-
continue;
|
|
1061
|
-
}
|
|
1062
|
-
changeMeasureValueFilterConditionOnTab(tab, action.payload, targetLocalId, false);
|
|
1063
|
-
}
|
|
888
|
+
changeMeasureValueFilterConditionOnTab(tab, action.payload);
|
|
1064
889
|
};
|
|
1065
|
-
function changeMeasureValueFilterConditionOnTab(tab, payload
|
|
890
|
+
function changeMeasureValueFilterConditionOnTab(tab, payload) {
|
|
1066
891
|
if (!tab.filterContext) {
|
|
1067
|
-
if (!isSource) {
|
|
1068
|
-
return;
|
|
1069
|
-
}
|
|
1070
892
|
tab.filterContext = { ...filterContextInitialState };
|
|
1071
893
|
}
|
|
1072
|
-
const { conditions, isWorkingSelectionChange } = payload;
|
|
894
|
+
const { localIdentifier, conditions, isWorkingSelectionChange } = payload;
|
|
1073
895
|
const filterContextDefinition = isWorkingSelectionChange
|
|
1074
896
|
? tab.filterContext?.workingFilterContextDefinition
|
|
1075
897
|
: tab.filterContext?.filterContextDefinition;
|
|
1076
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
1077
|
-
return;
|
|
1078
|
-
}
|
|
1079
898
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
1080
899
|
const filters = filterContextDefinition.filters;
|
|
1081
900
|
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
1082
901
|
const hasConditions = !!conditions && conditions.length > 0;
|
|
1083
|
-
if (!isSource && index < 0) {
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
902
|
invariant(index >= 0 || isWorkingSelectionChange, `Attempt to change condition of measure value filter ${localIdentifier} that does not exist`);
|
|
1087
903
|
if (isWorkingSelectionChange && index < 0) {
|
|
1088
904
|
const workingFilter = {
|
|
@@ -1103,48 +919,17 @@ function changeMeasureValueFilterConditionOnTab(tab, payload, localIdentifier, i
|
|
|
1103
919
|
};
|
|
1104
920
|
}
|
|
1105
921
|
const setMeasureValueFilterDimensionality = (state, action) => {
|
|
1106
|
-
const
|
|
1107
|
-
|
|
1108
|
-
const source = tabs[0];
|
|
1109
|
-
if (!source) {
|
|
1110
|
-
return;
|
|
1111
|
-
}
|
|
1112
|
-
const sourceFilter = findAppliedFilterByLocalId(source, localIdentifier);
|
|
1113
|
-
setMeasureValueFilterDimensionalityOnTab(source, action.payload, localIdentifier, true);
|
|
1114
|
-
if (!sourceFilter || !isDashboardMeasureValueFilter(sourceFilter)) {
|
|
922
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
923
|
+
if (!tab) {
|
|
1115
924
|
return;
|
|
1116
925
|
}
|
|
1117
|
-
|
|
1118
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences);
|
|
1119
|
-
const targetLocalId = match ? dashboardFilterLocalIdentifier(match) : undefined;
|
|
1120
|
-
if (!targetLocalId || !match) {
|
|
1121
|
-
continue;
|
|
1122
|
-
}
|
|
1123
|
-
if (restoreTargetOriginal) {
|
|
1124
|
-
const original = findOriginalFilter(tab, match);
|
|
1125
|
-
if (!isDashboardMeasureValueFilter(original)) {
|
|
1126
|
-
continue;
|
|
1127
|
-
}
|
|
1128
|
-
setMeasureValueFilterDimensionalityOnTab(tab, {
|
|
1129
|
-
...action.payload,
|
|
1130
|
-
localIdentifier: targetLocalId,
|
|
1131
|
-
dimensionality: original.dashboardMeasureValueFilter.dimensionality,
|
|
1132
|
-
}, targetLocalId, false);
|
|
1133
|
-
continue;
|
|
1134
|
-
}
|
|
1135
|
-
setMeasureValueFilterDimensionalityOnTab(tab, action.payload, targetLocalId, false);
|
|
1136
|
-
}
|
|
926
|
+
setMeasureValueFilterDimensionalityOnTab(tab, action.payload);
|
|
1137
927
|
};
|
|
1138
|
-
function setMeasureValueFilterDimensionalityOnTab(tab, payload
|
|
928
|
+
function setMeasureValueFilterDimensionalityOnTab(tab, payload) {
|
|
929
|
+
const { localIdentifier } = payload;
|
|
1139
930
|
const filters = tab.filterContext?.filterContextDefinition?.filters;
|
|
1140
|
-
if (!isSource && !filters) {
|
|
1141
|
-
return;
|
|
1142
|
-
}
|
|
1143
931
|
invariant(filters, "Attempt to edit uninitialized filter context");
|
|
1144
932
|
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
1145
|
-
if (!isSource && index < 0) {
|
|
1146
|
-
return;
|
|
1147
|
-
}
|
|
1148
933
|
invariant(index >= 0, `Attempt to change dimensionality of measure value filter ${localIdentifier} that does not exist`);
|
|
1149
934
|
const filter = filters[index];
|
|
1150
935
|
const dimensionality = payload.dimensionality && payload.dimensionality.length > 0 ? payload.dimensionality : undefined;
|
|
@@ -1156,20 +941,20 @@ function setMeasureValueFilterDimensionalityOnTab(tab, payload, localIdentifier,
|
|
|
1156
941
|
};
|
|
1157
942
|
}
|
|
1158
943
|
const changeMeasureValueFilterTitle = (state, action) => {
|
|
1159
|
-
const
|
|
1160
|
-
|
|
944
|
+
const { filterLocalId, title, tabLocalIdentifier } = action.payload;
|
|
945
|
+
const targetTab = getTabOrActive(state, tabLocalIdentifier);
|
|
946
|
+
if (!targetTab) {
|
|
1161
947
|
return;
|
|
1162
948
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) &&
|
|
1166
|
-
|
|
1167
|
-
invariant(index >= 0, `Attempt to change title of measure value filter ${action.payload.filterLocalId} that does not exist`);
|
|
949
|
+
const filters = targetTab.filterContext?.filterContextDefinition?.filters;
|
|
950
|
+
invariant(filters, "Attempt to edit uninitialized filter context");
|
|
951
|
+
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === filterLocalId);
|
|
952
|
+
invariant(index >= 0, `Attempt to change title of measure value filter ${filterLocalId} that does not exist`);
|
|
1168
953
|
const filter = filters[index];
|
|
1169
954
|
filters[index] = {
|
|
1170
955
|
dashboardMeasureValueFilter: {
|
|
1171
956
|
...filter.dashboardMeasureValueFilter,
|
|
1172
|
-
title
|
|
957
|
+
title,
|
|
1173
958
|
},
|
|
1174
959
|
};
|
|
1175
960
|
};
|