@gooddata/sdk-ui-dashboard 11.43.0-alpha.0 → 11.43.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +130 -130
- 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/index.js +1 -1
- package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.d.ts.map +1 -1
- package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.js +10 -5
- package/esm/model/commandHandlers/filterContext/dateFilter/removeDateFiltersHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/dateFilter/removeDateFiltersHandler.js +22 -4
- package/esm/model/commandHandlers/scheduledEmail/createScheduledEmailHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/scheduledEmail/createScheduledEmailHandler.js +3 -1
- package/esm/model/commandHandlers/scheduledEmail/csvRawExecutionDefinition.d.ts +2 -2
- package/esm/model/commandHandlers/scheduledEmail/csvRawExecutionDefinition.d.ts.map +1 -1
- package/esm/model/commandHandlers/scheduledEmail/csvRawExecutionDefinition.js +36 -3
- package/esm/model/commandHandlers/scheduledEmail/saveScheduledEmailHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/scheduledEmail/saveScheduledEmailHandler.js +3 -1
- package/esm/model/store/executionResults/executionResultsSelectors.d.ts +4 -0
- package/esm/model/store/executionResults/executionResultsSelectors.d.ts.map +1 -1
- package/esm/model/store/executionResults/executionResultsSelectors.js +4 -1
- package/esm/model/store/filtering/dashboardFilterSelectors.d.ts +1 -30
- package/esm/model/store/filtering/dashboardFilterSelectors.d.ts.map +1 -1
- package/esm/model/store/filtering/dashboardFilterSelectors.js +3 -0
- package/esm/model/store/filtering/types.d.ts +33 -0
- package/esm/model/store/filtering/types.d.ts.map +1 -0
- package/esm/model/store/filtering/types.js +2 -0
- package/esm/model/store/tabs/dateFilterConfig/dateFilterConfigSelectors.d.ts +14 -0
- package/esm/model/store/tabs/dateFilterConfig/dateFilterConfigSelectors.d.ts.map +1 -1
- package/esm/model/store/tabs/dateFilterConfig/dateFilterConfigSelectors.js +35 -0
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +12 -0
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersSelectors.js +37 -12
- package/esm/presentation/automations/_staging/alerting/DefaultAlertingDialog/DefaultAlertingDialog.d.ts.map +1 -1
- package/esm/presentation/automations/_staging/alerting/DefaultAlertingDialog/DefaultAlertingDialog.js +10 -5
- package/esm/presentation/automations/_staging/alerting/DefaultAlertingManagementDialog/components/PauseAlertRunner.js +1 -1
- package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.d.ts +3 -0
- package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.d.ts.map +1 -0
- package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.js +110 -0
- package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.test.d.ts +2 -0
- package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.test.d.ts.map +1 -0
- package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.test.js +99 -0
- package/esm/presentation/automations/connectors/hooks/useWidgetAutomationFilters.d.ts +4 -0
- package/esm/presentation/automations/connectors/hooks/useWidgetAutomationFilters.d.ts.map +1 -0
- package/esm/presentation/automations/connectors/hooks/useWidgetAutomationFilters.js +46 -0
- package/esm/presentation/automations/contexts/AutomationsContext.d.ts +42 -2
- package/esm/presentation/automations/contexts/AutomationsContext.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.js +8 -2
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/hooks/useWidgetAutomationFilters.d.ts +2 -3
- package/esm/presentation/automations/scheduledEmail/hooks/useWidgetAutomationFilters.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/hooks/useWidgetAutomationFilters.js +4 -45
- package/esm/presentation/automations/shared/automationFilters/components/AutomationDateFilter.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/components/AutomationDateFilter.js +9 -16
- package/esm/presentation/automations/shared/automationFilters/components/AutomationDateFilter.test.d.ts +2 -0
- package/esm/presentation/automations/shared/automationFilters/components/AutomationDateFilter.test.d.ts.map +1 -0
- package/esm/presentation/automations/shared/automationFilters/components/AutomationDateFilter.test.js +131 -0
- package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts +1 -1
- package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useAutomationVisibleFilters.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useAutomationVisibleFilters.js +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.d.ts +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.js +4 -6
- package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForNewAutomation.d.ts +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForNewAutomation.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForNewAutomation.js +3 -4
- package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.js +4 -10
- package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.d.ts +1 -1
- package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.js +3 -28
- package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.d.ts +2 -2
- package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.js +2 -5
- package/esm/presentation/automations/shared/automationFilters/utils.d.ts +1 -1
- package/esm/presentation/automations/shared/automationFilters/utils.d.ts.map +1 -1
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.d.ts +10 -0
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.d.ts.map +1 -0
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.js +89 -0
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.d.ts +34 -0
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.d.ts.map +1 -0
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.js +261 -0
- package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.d.ts +12 -0
- package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.d.ts.map +1 -0
- package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.js +437 -0
- package/esm/presentation/automations/shared/exportUtils/filterUtils.d.ts +3 -0
- package/esm/presentation/automations/shared/exportUtils/filterUtils.d.ts.map +1 -0
- package/esm/presentation/automations/shared/exportUtils/filterUtils.js +14 -0
- package/esm/presentation/automations/shared/hooks/useAttributeFilterDisplayFormFromMap.d.ts +3 -0
- package/esm/presentation/automations/shared/hooks/useAttributeFilterDisplayFormFromMap.d.ts.map +1 -0
- package/esm/presentation/automations/shared/hooks/useAttributeFilterDisplayFormFromMap.js +7 -0
- package/esm/presentation/automations/shared/hooks/useCommonDateFilterTitle.d.ts +3 -0
- package/esm/presentation/automations/shared/hooks/useCommonDateFilterTitle.d.ts.map +1 -0
- package/esm/presentation/automations/shared/hooks/useCommonDateFilterTitle.js +6 -0
- package/esm/presentation/automations/shared/hooks/useDateFiltersTitles.d.ts +4 -0
- package/esm/presentation/automations/shared/hooks/useDateFiltersTitles.d.ts.map +1 -0
- package/esm/presentation/automations/shared/hooks/useDateFiltersTitles.js +19 -0
- package/esm/presentation/automations/shared/hooks/useFiltersNamings.d.ts +13 -0
- package/esm/presentation/automations/shared/hooks/useFiltersNamings.d.ts.map +1 -0
- package/esm/presentation/automations/shared/hooks/useFiltersNamings.js +196 -0
- package/esm/presentation/automations/shared/utils/automationUtils.d.ts +24 -0
- package/esm/presentation/automations/shared/utils/automationUtils.d.ts.map +1 -0
- package/esm/presentation/automations/shared/utils/automationUtils.js +135 -0
- package/esm/presentation/automations/shared/utils/filterContextUtils.d.ts +4 -0
- package/esm/presentation/automations/shared/utils/filterContextUtils.d.ts.map +1 -0
- package/esm/presentation/automations/shared/utils/filterContextUtils.js +67 -0
- package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.d.ts.map +1 -1
- package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.js +11 -13
- package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFilterConfigurationState.d.ts.map +1 -1
- package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFilterConfigurationState.js +34 -16
- package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFiltersConfiguration.d.ts.map +1 -1
- package/esm/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFiltersConfiguration.js +23 -8
- package/esm/presentation/filterBar/attributeFilter/useDependentDateFilters.d.ts.map +1 -1
- package/esm/presentation/filterBar/attributeFilter/useDependentDateFilters.js +17 -6
- package/esm/presentation/topBar/menuButton/DefaultMenuButton.d.ts.map +1 -1
- package/esm/presentation/topBar/menuButton/DefaultMenuButton.js +11 -20
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/Insight/DashboardInsight.d.ts.map +1 -1
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/Insight/DashboardInsight.js +3 -4
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/DrillDialogExportDropdown.d.ts.map +1 -1
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/DrillDialogExportDropdown.js +1 -1
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/DrillDialogInsight.d.ts.map +1 -1
- package/esm/presentation/widget/insight/ViewModeDashboardInsight/InsightDrillDialog/DrillDialogInsight.js +11 -2
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useCreateAlert.d.ts.map +1 -0
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useInsightWidgetAlerting.d.ts.map +1 -1
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useInsightWidgetAlerting.js +2 -2
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useSaveAlertToBackend.d.ts.map +1 -0
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useUpdateAlert.d.ts.map +1 -0
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useWidgetAutomationFilters.d.ts +4 -0
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useWidgetAutomationFilters.d.ts.map +1 -0
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useWidgetAutomationFilters.js +46 -0
- package/esm/presentation/widget/insight/configuration/InsightAlertsNew.d.ts.map +1 -1
- package/esm/presentation/widget/insight/configuration/InsightAlertsNew.js +1 -1
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/DashboardInsightMenuItemButton.d.ts.map +1 -1
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/DashboardInsightMenuItemButton.js +2 -2
- package/esm/presentation/widget/insightMenu/types.js +1 -1
- package/esm/presentation/widget/widget/warningPartialResult/InsightWidgetWarningPartialResult.d.ts.map +1 -1
- package/esm/presentation/widget/widget/warningPartialResult/InsightWidgetWarningPartialResult.js +1 -1
- package/esm/sdk-ui-dashboard.d.ts +11 -2
- package/esm/tsdoc-metadata.json +1 -1
- package/package.json +20 -20
- package/esm/presentation/automations/_staging/alerting/DefaultAlertingDialog/hooks/useCreateAlert.d.ts.map +0 -1
- package/esm/presentation/automations/_staging/alerting/DefaultAlertingDialog/hooks/useSaveAlertToBackend.d.ts.map +0 -1
- package/esm/presentation/automations/_staging/alerting/DefaultAlertingDialog/hooks/useUpdateAlert.d.ts.map +0 -1
- /package/esm/presentation/{automations/_staging/alerting/DefaultAlertingDialog → widget/insight/configuration/InsightAlertConfig}/hooks/useCreateAlert.d.ts +0 -0
- /package/esm/presentation/{automations/_staging/alerting/DefaultAlertingDialog → widget/insight/configuration/InsightAlertConfig}/hooks/useCreateAlert.js +0 -0
- /package/esm/presentation/{automations/_staging/alerting/DefaultAlertingDialog → widget/insight/configuration/InsightAlertConfig}/hooks/useSaveAlertToBackend.d.ts +0 -0
- /package/esm/presentation/{automations/_staging/alerting/DefaultAlertingDialog → widget/insight/configuration/InsightAlertConfig}/hooks/useSaveAlertToBackend.js +0 -0
- /package/esm/presentation/{automations/_staging/alerting/DefaultAlertingDialog → widget/insight/configuration/InsightAlertConfig}/hooks/useUpdateAlert.d.ts +0 -0
- /package/esm/presentation/{automations/_staging/alerting/DefaultAlertingDialog → widget/insight/configuration/InsightAlertConfig}/hooks/useUpdateAlert.js +0 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// (C) 2024-2026 GoodData Corporation
|
|
2
|
+
import { useIntl } from "react-intl";
|
|
3
|
+
import { areObjRefsEqual, dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemTitle, getAttributeElementsItems, isAllTimeDashboardDateFilter, isAllValuesDashboardAttributeFilter, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMatchAttributeFilter, isDashboardMeasureValueFilter, objRefToString, serializeObjRef, } from "@gooddata/sdk-model";
|
|
4
|
+
import { DateFilterHelpers, getAttributeFilterSubtitle, getLocalizedIcuDateFormatPattern, getMeasureValueFilterConditionLabel, getTextFilterStateText, } from "@gooddata/sdk-ui-filters";
|
|
5
|
+
import { useAutomationsContext } from "../../contexts/AutomationsContext.js";
|
|
6
|
+
import { convertDateFilterConfigToDateFilterOptions } from "../dateFilterConfig/dateFilterConfigConverters.js";
|
|
7
|
+
import { matchDateFilterToDateFilterOptionWithPreference } from "../dateFilterConfig/dateFilterOptionMapping.js";
|
|
8
|
+
import { defaultDateFilterConfig } from "../dateFilterConfig/defaultConfig.js";
|
|
9
|
+
import { ensureAllTimeFilterForExport } from "../exportUtils/filterUtils.js";
|
|
10
|
+
import { useAttributeFilterDisplayFormFromMap } from "./useAttributeFilterDisplayFormFromMap.js";
|
|
11
|
+
import { useCommonDateFilterTitle } from "./useCommonDateFilterTitle.js";
|
|
12
|
+
import { useDateFiltersTitles } from "./useDateFiltersTitles.js";
|
|
13
|
+
const PERCENT_FORMAT_REGEX = /%/;
|
|
14
|
+
function isPercentageFormat(format) {
|
|
15
|
+
return !!format && PERCENT_FORMAT_REGEX.test(format);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook that gathers all dependencies needed for filter naming transformations.
|
|
19
|
+
* Reusable across different hooks that need to transform filters to namings.
|
|
20
|
+
*
|
|
21
|
+
* @param filtersForTitles - Array of filters (date filters will be extracted for titles)
|
|
22
|
+
* @returns Object containing all dependencies needed for filter naming transformations
|
|
23
|
+
*/
|
|
24
|
+
function useFilterNamingDependencies(filtersForTitles) {
|
|
25
|
+
const intl = useIntl();
|
|
26
|
+
const { locale, settings, catalogMeasures: measures, separators, getCatalogAttributeByRef, } = useAutomationsContext();
|
|
27
|
+
const dateFormat = settings?.formatLocale
|
|
28
|
+
? getLocalizedIcuDateFormatPattern(settings.formatLocale)
|
|
29
|
+
: settings?.responsiveUiDateFormat;
|
|
30
|
+
const getAttributeFilterDisplayFormFromMap = useAttributeFilterDisplayFormFromMap();
|
|
31
|
+
const dateFiltersForTitles = filtersForTitles.filter(isDashboardDateFilterWithDimension);
|
|
32
|
+
const commonDateFilterTitle = useCommonDateFilterTitle(intl);
|
|
33
|
+
const allDateFiltersTitlesObj = useDateFiltersTitles(dateFiltersForTitles, intl);
|
|
34
|
+
return {
|
|
35
|
+
intl,
|
|
36
|
+
locale,
|
|
37
|
+
dateFormat,
|
|
38
|
+
getAttributeFilterDisplayFormFromMap,
|
|
39
|
+
getCatalogAttributeByRef,
|
|
40
|
+
measures,
|
|
41
|
+
separators,
|
|
42
|
+
commonDateFilterTitle,
|
|
43
|
+
allDateFiltersTitlesObj,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Pure function that transforms filters into filter namings.
|
|
48
|
+
* Extracted to avoid code duplication between useFiltersNamings and useFiltersByTabNamings.
|
|
49
|
+
*/
|
|
50
|
+
function transformFiltersToNamings(filtersToDisplay, deps) {
|
|
51
|
+
const { intl, dateFormat, getAttributeFilterDisplayFormFromMap, getCatalogAttributeByRef, measures, separators, commonDateFilterTitle, allDateFiltersTitlesObj, } = deps;
|
|
52
|
+
// we want to show all time filter in the list of filters even if it is not stored
|
|
53
|
+
const extendedFiltersToDisplay = ensureAllTimeFilterForExport(filtersToDisplay);
|
|
54
|
+
return extendedFiltersToDisplay.map((filter) => {
|
|
55
|
+
if (isDashboardAttributeFilter(filter)) {
|
|
56
|
+
const displayForm = getAttributeFilterDisplayFormFromMap(filter.attributeFilter.displayForm);
|
|
57
|
+
if (!displayForm) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const attribute = getCatalogAttributeByRef(displayForm.attribute);
|
|
61
|
+
if (!attribute) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const valuesAsAttributeElements = getAttributeElementsItems(filter.attributeFilter.attributeElements)?.map((element) => ({
|
|
65
|
+
title: element,
|
|
66
|
+
uri: element,
|
|
67
|
+
}));
|
|
68
|
+
const subtitle = getAttributeFilterSubtitle(filter.attributeFilter.negativeSelection, valuesAsAttributeElements, intl);
|
|
69
|
+
return {
|
|
70
|
+
type: "attributeFilter",
|
|
71
|
+
all: isAllValuesDashboardAttributeFilter(filter),
|
|
72
|
+
id: filter.attributeFilter.localIdentifier,
|
|
73
|
+
title: filter.attributeFilter.title ?? attribute.attribute.title,
|
|
74
|
+
subtitle,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
else if (isDashboardDateFilter(filter)) {
|
|
78
|
+
/**
|
|
79
|
+
* Shenanigans inspired by core date filter and dashboard date filter implementation
|
|
80
|
+
* to get the date filter option for its subtitle.
|
|
81
|
+
*/
|
|
82
|
+
const dateFilterOptionInfo = matchDateFilterToDateFilterOptionWithPreference(filter, convertDateFilterConfigToDateFilterOptions(defaultDateFilterConfig), undefined);
|
|
83
|
+
const dateFilterOption = DateFilterHelpers.applyExcludeCurrentPeriod(dateFilterOptionInfo.dateFilterOption, dateFilterOptionInfo.excludeCurrentPeriod);
|
|
84
|
+
const subtitle = DateFilterHelpers.getDateFilterTitleUsingTranslator(dateFilterOption, intl, "full", dateFormat);
|
|
85
|
+
const a = filter;
|
|
86
|
+
if (isDashboardDateFilterWithDimension(a)) {
|
|
87
|
+
const key = serializeObjRef(a.dateFilter.dataSet);
|
|
88
|
+
return {
|
|
89
|
+
type: "dateFilter",
|
|
90
|
+
all: isAllTimeDashboardDateFilter(a),
|
|
91
|
+
id: a.dateFilter.localIdentifier ?? `dateFilter:${key}`,
|
|
92
|
+
title: allDateFiltersTitlesObj[key],
|
|
93
|
+
subtitle,
|
|
94
|
+
dataSet: a.dateFilter.dataSet,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const b = filter;
|
|
98
|
+
if (isDashboardCommonDateFilter(b)) {
|
|
99
|
+
return {
|
|
100
|
+
type: "dateFilter",
|
|
101
|
+
common: true,
|
|
102
|
+
all: isAllTimeDashboardDateFilter(b),
|
|
103
|
+
id: b.dateFilter.localIdentifier ?? "dateFilter:common",
|
|
104
|
+
title: commonDateFilterTitle || intl.formatMessage({ id: "dateFilterDropdown.title" }),
|
|
105
|
+
subtitle,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
else if (isDashboardArbitraryAttributeFilter(filter)) {
|
|
111
|
+
const { values, negativeSelection, displayForm } = filter.arbitraryAttributeFilter;
|
|
112
|
+
const filterDisplayForm = getAttributeFilterDisplayFormFromMap(displayForm);
|
|
113
|
+
if (!filterDisplayForm) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
const attribute = getCatalogAttributeByRef(filterDisplayForm.attribute);
|
|
117
|
+
if (!attribute) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
const operator = values.length === 0 && negativeSelection ? "all" : negativeSelection ? "isNot" : "is";
|
|
121
|
+
const subtitle = getTextFilterStateText(operator, values, "", intl);
|
|
122
|
+
const title = dashboardAttributeFilterItemTitle(filter) ?? attribute.attribute.title;
|
|
123
|
+
return {
|
|
124
|
+
type: "attributeFilter",
|
|
125
|
+
all: values.length === 0 && negativeSelection,
|
|
126
|
+
id: dashboardAttributeFilterItemLocalIdentifier(filter),
|
|
127
|
+
title,
|
|
128
|
+
subtitle,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
else if (isDashboardMeasureValueFilter(filter)) {
|
|
132
|
+
const { measure, localIdentifier, title: customTitle, conditions, } = filter.dashboardMeasureValueFilter;
|
|
133
|
+
const catalogMetric = measures.find((m) => areObjRefsEqual(m.measure.ref, measure));
|
|
134
|
+
const defaultTitle = catalogMetric?.measure.title ?? objRefToString(measure);
|
|
135
|
+
const title = customTitle ?? defaultTitle;
|
|
136
|
+
const format = catalogMetric?.measure.format;
|
|
137
|
+
const usePercentage = isPercentageFormat(format);
|
|
138
|
+
const subtitle = getMeasureValueFilterConditionLabel(intl, conditions, {
|
|
139
|
+
usePercentage,
|
|
140
|
+
separators,
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
type: "measureValueFilter",
|
|
144
|
+
all: !conditions || conditions.length === 0,
|
|
145
|
+
id: localIdentifier,
|
|
146
|
+
title,
|
|
147
|
+
subtitle,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
else if (isDashboardMatchAttributeFilter(filter)) {
|
|
151
|
+
const { operator: matchOperator, literal, negativeSelection, displayForm, } = filter.matchAttributeFilter;
|
|
152
|
+
const filterDisplayForm = getAttributeFilterDisplayFormFromMap(displayForm);
|
|
153
|
+
if (!filterDisplayForm) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
const attribute = getCatalogAttributeByRef(filterDisplayForm.attribute);
|
|
157
|
+
if (!attribute) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
const isNegative = negativeSelection ?? false;
|
|
161
|
+
const operatorMap = {
|
|
162
|
+
contains: isNegative ? "doesNotContain" : "contains",
|
|
163
|
+
startsWith: isNegative ? "doesNotStartWith" : "startsWith",
|
|
164
|
+
endsWith: isNegative ? "doesNotEndWith" : "endsWith",
|
|
165
|
+
};
|
|
166
|
+
const operator = operatorMap[matchOperator] ?? "contains";
|
|
167
|
+
const subtitle = getTextFilterStateText(operator, [], literal, intl);
|
|
168
|
+
const title = dashboardAttributeFilterItemTitle(filter) ?? attribute.attribute.title;
|
|
169
|
+
return {
|
|
170
|
+
type: "attributeFilter",
|
|
171
|
+
all: false,
|
|
172
|
+
id: dashboardAttributeFilterItemLocalIdentifier(filter),
|
|
173
|
+
title,
|
|
174
|
+
subtitle,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
export function useFiltersNamings(filtersToDisplay) {
|
|
183
|
+
const deps = useFilterNamingDependencies(filtersToDisplay);
|
|
184
|
+
return transformFiltersToNamings(filtersToDisplay, deps);
|
|
185
|
+
}
|
|
186
|
+
export function useFiltersByTabNamings(tabFilters) {
|
|
187
|
+
// Collect all filters from all tabs for titles lookup
|
|
188
|
+
const allFilters = Object.values(tabFilters).flat();
|
|
189
|
+
const deps = useFilterNamingDependencies(allFilters);
|
|
190
|
+
// Process each tab's filters separately using the shared transformation function
|
|
191
|
+
const result = {};
|
|
192
|
+
Object.entries(tabFilters).forEach(([tabId, filters]) => {
|
|
193
|
+
result[tabId] = transformFiltersToNamings(filters, deps);
|
|
194
|
+
});
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type FilterContextItem, type IAutomationMetadataObject, type IAutomationMetadataObjectDefinition, type IAutomationRecipient, type IExportDefinitionMetadataObject, type IExportDefinitionMetadataObjectDefinition, type IFilter, type IUser, type IWorkspaceUser } from "@gooddata/sdk-model";
|
|
2
|
+
export declare const isDashboardAutomation: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => boolean;
|
|
3
|
+
export declare const isVisualisationAutomation: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => boolean;
|
|
4
|
+
export declare const isCsvVisualizationAutomation: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => boolean;
|
|
5
|
+
export declare const isCsvVisualizationExportDefinition: (exportDefinition: IExportDefinitionMetadataObject | IExportDefinitionMetadataObjectDefinition | undefined) => boolean;
|
|
6
|
+
export declare const isXlsxVisualizationAutomation: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => boolean;
|
|
7
|
+
export declare const isXlsxVisualizationExportDefinition: (exportDefinition: IExportDefinitionMetadataObject | IExportDefinitionMetadataObjectDefinition | undefined) => boolean;
|
|
8
|
+
export declare const getAutomationDashboardFilters: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => FilterContextItem[] | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Extracts dashboard filters structured by tab from automation metadata object.
|
|
11
|
+
* Returns filtersByTab from the first dashboard export definition.
|
|
12
|
+
*/
|
|
13
|
+
export declare const getAutomationDashboardFiltersByTab: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => Record<string, FilterContextItem[]> | undefined;
|
|
14
|
+
export declare const getAutomationVisualizationFilters: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => {
|
|
15
|
+
executionFilters: IFilter[] | undefined;
|
|
16
|
+
filterContextItems: FilterContextItem[] | undefined;
|
|
17
|
+
};
|
|
18
|
+
export declare const getAutomationAlertFilters: (automation: IAutomationMetadataObject | IAutomationMetadataObjectDefinition | undefined) => IFilter[] | undefined;
|
|
19
|
+
export declare const areAutomationsEqual: (originalAutomation: IAutomationMetadataObjectDefinition, updatedAutomation: IAutomationMetadataObjectDefinition) => boolean;
|
|
20
|
+
export declare const convertCurrentUserToAutomationRecipient: (users: IWorkspaceUser[], user: IUser) => IAutomationRecipient;
|
|
21
|
+
export declare const convertCurrentUserToWorkspaceUser: (users: IWorkspaceUser[], user: IUser) => IWorkspaceUser;
|
|
22
|
+
export declare const convertUserToAutomationRecipient: (user: IUser) => IAutomationRecipient;
|
|
23
|
+
export declare const convertExternalRecipientToAutomationRecipient: (externalRecipient: string) => IAutomationRecipient;
|
|
24
|
+
//# sourceMappingURL=automationUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automationUtils.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/utils/automationUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,mCAAmC,EACxC,KAAK,oBAAoB,EAEzB,KAAK,+BAA+B,EACpC,KAAK,yCAAyC,EAE9C,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,cAAc,EAKtB,MAAM,qBAAqB,CAAC;AAE7B,eAAO,MAAM,qBAAqB,sGAYjC,CAAC;AAEF,eAAO,MAAM,yBAAyB,sGAYrC,CAAC;AAEF,eAAO,MAAM,4BAA4B,sGAQxC,CAAC;AAEF,eAAO,MAAM,kCAAkC,wHAW9C,CAAC;AAEF,eAAO,MAAM,6BAA6B,sGAQzC,CAAC;AAEF,eAAO,MAAM,mCAAmC,wHAW/C,CAAC;AAEF,eAAO,MAAM,6BAA6B,8HAYzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kCAAkC,8IAY9C,CAAC;AAEF,eAAO,MAAM,iCAAiC;;;CAuB7C,CAAC;AAEF,eAAO,MAAM,yBAAyB,oHAQrC,CAAC;AAOF,eAAO,MAAM,mBAAmB,8HAqB/B,CAAC;AAEF,eAAO,MAAM,uCAAuC,gEAOnD,CAAC;AAEF,eAAO,MAAM,iCAAiC,0DAe7C,CAAC;AAEF,eAAO,MAAM,gCAAgC,uCAO5C,CAAC;AAEF,eAAO,MAAM,6CAA6C,qDASzD,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// (C) 2024-2026 GoodData Corporation
|
|
2
|
+
import { isEqual, omit, pick } from "lodash-es";
|
|
3
|
+
import { isExportDefinitionDashboardRequestPayload, isExportDefinitionVisualizationObjectRequestPayload, isFilter, isFilterContextItem, } from "@gooddata/sdk-model";
|
|
4
|
+
export const isDashboardAutomation = (automation) => {
|
|
5
|
+
if (!automation) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
return (automation.exportDefinitions?.some((exportDefinition) => {
|
|
9
|
+
return isExportDefinitionDashboardRequestPayload(exportDefinition.requestPayload);
|
|
10
|
+
}) ?? false);
|
|
11
|
+
};
|
|
12
|
+
export const isVisualisationAutomation = (automation) => {
|
|
13
|
+
if (!automation) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return (automation.exportDefinitions?.some((exportDefinition) => {
|
|
17
|
+
return isExportDefinitionVisualizationObjectRequestPayload(exportDefinition.requestPayload);
|
|
18
|
+
}) ?? false);
|
|
19
|
+
};
|
|
20
|
+
export const isCsvVisualizationAutomation = (automation) => {
|
|
21
|
+
if (!automation) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return automation.exportDefinitions?.some(isCsvVisualizationExportDefinition) ?? false;
|
|
25
|
+
};
|
|
26
|
+
export const isCsvVisualizationExportDefinition = (exportDefinition) => {
|
|
27
|
+
if (!exportDefinition) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return (isExportDefinitionVisualizationObjectRequestPayload(exportDefinition.requestPayload) &&
|
|
31
|
+
exportDefinition.requestPayload.format === "CSV");
|
|
32
|
+
};
|
|
33
|
+
export const isXlsxVisualizationAutomation = (automation) => {
|
|
34
|
+
if (!automation) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return automation.exportDefinitions?.some(isXlsxVisualizationExportDefinition) ?? false;
|
|
38
|
+
};
|
|
39
|
+
export const isXlsxVisualizationExportDefinition = (exportDefinition) => {
|
|
40
|
+
if (!exportDefinition) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return (isExportDefinitionVisualizationObjectRequestPayload(exportDefinition.requestPayload) &&
|
|
44
|
+
exportDefinition.requestPayload.format === "XLSX");
|
|
45
|
+
};
|
|
46
|
+
export const getAutomationDashboardFilters = (automation) => {
|
|
47
|
+
if (!automation) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return automation.exportDefinitions?.find((exportDefinition) => {
|
|
51
|
+
return isExportDefinitionDashboardRequestPayload(exportDefinition.requestPayload);
|
|
52
|
+
})?.requestPayload?.content.filters?.filter((f) => isFilterContextItem(f));
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Extracts dashboard filters structured by tab from automation metadata object.
|
|
56
|
+
* Returns filtersByTab from the first dashboard export definition.
|
|
57
|
+
*/
|
|
58
|
+
export const getAutomationDashboardFiltersByTab = (automation) => {
|
|
59
|
+
if (!automation) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
return automation.exportDefinitions?.find((exportDefinition) => {
|
|
63
|
+
return isExportDefinitionDashboardRequestPayload(exportDefinition.requestPayload);
|
|
64
|
+
})?.requestPayload?.content.filtersByTab;
|
|
65
|
+
};
|
|
66
|
+
export const getAutomationVisualizationFilters = (automation) => {
|
|
67
|
+
if (!automation) {
|
|
68
|
+
return { executionFilters: undefined, filterContextItems: undefined };
|
|
69
|
+
}
|
|
70
|
+
const executionFilters = automation.exportDefinitions?.find((exportDefinition) => {
|
|
71
|
+
return isExportDefinitionVisualizationObjectRequestPayload(exportDefinition.requestPayload);
|
|
72
|
+
})?.requestPayload?.content.filters?.filter((f) => isFilter(f));
|
|
73
|
+
const filterContextItems = automation.exportDefinitions?.find((exportDefinition) => {
|
|
74
|
+
return isExportDefinitionVisualizationObjectRequestPayload(exportDefinition.requestPayload);
|
|
75
|
+
})?.requestPayload?.content.filters?.filter((f) => isFilterContextItem(f));
|
|
76
|
+
return {
|
|
77
|
+
executionFilters: (executionFilters ?? []).length > 0 ? executionFilters : undefined,
|
|
78
|
+
filterContextItems: (filterContextItems ?? []).length > 0 ? filterContextItems : undefined,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
export const getAutomationAlertFilters = (automation) => {
|
|
82
|
+
if (!automation) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
return automation.alert?.execution?.filters?.filter(isFilter);
|
|
86
|
+
};
|
|
87
|
+
const sortByFormat = (a, b) => a.requestPayload.format.localeCompare(b.requestPayload.format);
|
|
88
|
+
export const areAutomationsEqual = (originalAutomation, updatedAutomation) => {
|
|
89
|
+
const automationWithoutExportDefinitions = omit(updatedAutomation, "exportDefinitions");
|
|
90
|
+
const origAutomationWithoutExportDefinitions = omit(originalAutomation, "exportDefinitions");
|
|
91
|
+
// We only want to compare requestPayload and title of exportDefinitions, rest may be omitted as it is just arbitrary
|
|
92
|
+
// metadata that is not relevant for the comparison and causes false positive results when comparing new and old def.
|
|
93
|
+
// Sorting is done just to avoid false positive result of different order of export definitions.
|
|
94
|
+
const automationExportDefinitions = updatedAutomation.exportDefinitions
|
|
95
|
+
?.map((exportDefinition) => pick(exportDefinition, ["requestPayload", "title"]))
|
|
96
|
+
.sort(sortByFormat);
|
|
97
|
+
const origAutomationExportDefinitions = originalAutomation.exportDefinitions
|
|
98
|
+
?.map((exportDefinition) => pick(exportDefinition, ["requestPayload", "title"]))
|
|
99
|
+
.sort(sortByFormat);
|
|
100
|
+
return (isEqual(automationWithoutExportDefinitions, origAutomationWithoutExportDefinitions) &&
|
|
101
|
+
isEqual(automationExportDefinitions, origAutomationExportDefinitions));
|
|
102
|
+
};
|
|
103
|
+
export const convertCurrentUserToAutomationRecipient = (users, user) => {
|
|
104
|
+
const foundUser = users.find((u) => u.login === user.login);
|
|
105
|
+
return convertUserToAutomationRecipient(foundUser ?? user);
|
|
106
|
+
};
|
|
107
|
+
export const convertCurrentUserToWorkspaceUser = (users, user) => {
|
|
108
|
+
const foundUser = users.find((u) => u.login === user.login);
|
|
109
|
+
return (foundUser ?? {
|
|
110
|
+
email: user.email ?? "",
|
|
111
|
+
fullName: user.fullName,
|
|
112
|
+
status: "ENABLED",
|
|
113
|
+
login: user.login,
|
|
114
|
+
lastName: user.lastName,
|
|
115
|
+
firstName: user.firstName,
|
|
116
|
+
uri: user.login,
|
|
117
|
+
ref: user.ref,
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
export const convertUserToAutomationRecipient = (user) => {
|
|
121
|
+
return {
|
|
122
|
+
id: user.login,
|
|
123
|
+
email: user.email,
|
|
124
|
+
name: user.fullName,
|
|
125
|
+
type: "user",
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
export const convertExternalRecipientToAutomationRecipient = (externalRecipient) => {
|
|
129
|
+
return {
|
|
130
|
+
id: externalRecipient,
|
|
131
|
+
email: externalRecipient,
|
|
132
|
+
name: externalRecipient,
|
|
133
|
+
type: "externalUser",
|
|
134
|
+
};
|
|
135
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type FilterContextItem } from "@gooddata/sdk-model";
|
|
2
|
+
import { type IDashboardFilter } from "../../../../types.js";
|
|
3
|
+
export declare function dashboardFilterToFilterContextItem(filter: IDashboardFilter, keepDatasets: boolean): FilterContextItem | undefined;
|
|
4
|
+
//# sourceMappingURL=filterContextUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filterContextUtils.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/utils/filterContextUtils.ts"],"names":[],"mappings":"AAKA,OAAO,EAEH,KAAK,iBAAiB,EAmBzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,wBAAgB,kCAAkC,CAC9C,MAAM,EAAE,gBAAgB,EACxB,YAAY,EAAE,OAAO,GACtB,iBAAiB,GAAG,SAAS,CA8E/B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// (C) 2021-2026 GoodData Corporation
|
|
2
|
+
// Derived from _staging/dashboard/dashboardFilterContext.ts
|
|
3
|
+
import { NotSupported } from "@gooddata/sdk-backend-spi";
|
|
4
|
+
import { filterAttributeElements, filterLocalIdentifier, filterObjRef, isAbsoluteDateFilter, isAllTimeDateFilter, isArbitraryAttributeFilter, isAttributeFilterWithSelection, isMatchAttributeFilter, isMeasureValueFilter, isNegativeAttributeFilter, isObjRef, isRelativeBoundedDateFilter, isRelativeDateFilter, measureValueFilterConditions, measureValueFilterMeasure, newAbsoluteDashboardDateFilter, newAllTimeDashboardDateFilter, newRelativeDashboardDateFilter, } from "@gooddata/sdk-model";
|
|
5
|
+
export function dashboardFilterToFilterContextItem(filter, keepDatasets) {
|
|
6
|
+
if (isAttributeFilterWithSelection(filter)) {
|
|
7
|
+
return {
|
|
8
|
+
attributeFilter: {
|
|
9
|
+
negativeSelection: isNegativeAttributeFilter(filter),
|
|
10
|
+
displayForm: filterObjRef(filter),
|
|
11
|
+
attributeElements: filterAttributeElements(filter),
|
|
12
|
+
selectionMode: "multi",
|
|
13
|
+
localIdentifier: filterLocalIdentifier(filter),
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
else if (isArbitraryAttributeFilter(filter)) {
|
|
18
|
+
return {
|
|
19
|
+
arbitraryAttributeFilter: {
|
|
20
|
+
displayForm: filterObjRef(filter),
|
|
21
|
+
values: filter.arbitraryAttributeFilter.values,
|
|
22
|
+
negativeSelection: filter.arbitraryAttributeFilter.negativeSelection ?? false,
|
|
23
|
+
localIdentifier: filterLocalIdentifier(filter),
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
else if (isMatchAttributeFilter(filter)) {
|
|
28
|
+
return {
|
|
29
|
+
matchAttributeFilter: {
|
|
30
|
+
displayForm: filterObjRef(filter),
|
|
31
|
+
operator: filter.matchAttributeFilter.operator,
|
|
32
|
+
literal: filter.matchAttributeFilter.literal,
|
|
33
|
+
caseSensitive: filter.matchAttributeFilter.caseSensitive,
|
|
34
|
+
negativeSelection: filter.matchAttributeFilter.negativeSelection,
|
|
35
|
+
localIdentifier: filterLocalIdentifier(filter),
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
else if (isAbsoluteDateFilter(filter)) {
|
|
40
|
+
return newAbsoluteDashboardDateFilter(filter.absoluteDateFilter.from, filter.absoluteDateFilter.to, keepDatasets ? filter.absoluteDateFilter.dataSet : undefined, filter.absoluteDateFilter.localIdentifier, filter.absoluteDateFilter.emptyValueHandling);
|
|
41
|
+
}
|
|
42
|
+
else if (isAllTimeDateFilter(filter)) {
|
|
43
|
+
return newAllTimeDashboardDateFilter(keepDatasets ? filter.relativeDateFilter.dataSet : undefined, filter.relativeDateFilter.localIdentifier, filter.relativeDateFilter.emptyValueHandling);
|
|
44
|
+
}
|
|
45
|
+
else if (isRelativeDateFilter(filter)) {
|
|
46
|
+
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);
|
|
47
|
+
}
|
|
48
|
+
else if (isMeasureValueFilter(filter)) {
|
|
49
|
+
const measure = measureValueFilterMeasure(filter);
|
|
50
|
+
// Dashboard MVFs always reference the measure by ObjRef. Insight MVFs use LocalIdRef
|
|
51
|
+
// (bucket localId) and have no honest representation in the dashboard filter context —
|
|
52
|
+
// they reach this converter only because automation execution filters mix dashboard and
|
|
53
|
+
// insight filters. Caller is responsible for dropping these undefined entries.
|
|
54
|
+
if (!isObjRef(measure)) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
const conditions = measureValueFilterConditions(filter);
|
|
58
|
+
return {
|
|
59
|
+
dashboardMeasureValueFilter: {
|
|
60
|
+
measure,
|
|
61
|
+
localIdentifier: filter.measureValueFilter.localIdentifier ?? `mvf:${JSON.stringify(measure)}`,
|
|
62
|
+
...(conditions ? { conditions } : {}),
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
throw new NotSupported(`Unsupported filter type! Please provide valid dashboard filter. Filter: ${JSON.stringify(filter)}`);
|
|
67
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomUrlEditor.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAoB,KAAK,SAAS,EAAW,MAAM,YAAY,CAAC;AAEvE,OAAO,EAKH,KAAK,MAAM,EAad,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"CustomUrlEditor.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAoB,KAAK,SAAS,EAAW,MAAM,YAAY,CAAC;AAEvE,OAAO,EAKH,KAAK,MAAM,EAad,MAAM,qBAAqB,CAAC;AA6B7B,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,gBAAgB,CAAC;AAG/E,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,uBAAuB,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5C,IAAI,EAAE,SAAS,CAAC;CACnB;AAsCD,wBAAgB,QAAQ,CAAC,EACrB,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,IAAI,EACJ,uBAAuB,EAC1B,EAAE,cAAc,kDAoBhB;AAwHD,UAAU,eAAe;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACjB;AAmLD,MAAM,WAAW,qBAAqB;IAClC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,qBAAqB,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACpD,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,sCAAsC,EAAE,MAAM,EAAE,CAAC;IACjD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,EAAE,OAAO,CAAC;IACjC,4BAA4B,EAAE,OAAO,CAAC;IACtC,uBAAuB,EAAE,OAAO,CAAC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;CACrB;AAmHD,wBAAgB,eAAe,CAAC,KAAK,EAAE,qBAAqB,2CAkB3D"}
|
|
@@ -9,13 +9,11 @@ import { filterObjRef, idRef, insightFilters as insightDefinitionFilters, isArbi
|
|
|
9
9
|
import { ConfirmDialogBase, FullScreenOverlay, Overlay, OverlayController, OverlayControllerProvider, SyntaxHighlightingInput, useMediaQuery, } from "@gooddata/sdk-ui-kit";
|
|
10
10
|
import { dashboardAttributeFilterItemToAttributeFilter } from "../../../../converters/filterConverters.js";
|
|
11
11
|
import { useDashboardSelector } from "../../../../model/react/DashboardStoreProvider.js";
|
|
12
|
-
import { useWidgetFilters } from "../../../../model/react/useWidgetFilters.js";
|
|
13
12
|
import { selectAllCatalogDisplayFormsMap, selectAllCatalogMeasuresMap, } from "../../../../model/store/catalog/catalogSelectors.js";
|
|
14
13
|
import { selectEnableMeasureValueFilterKD, selectIsWhiteLabeled, } from "../../../../model/store/config/configSelectors.js";
|
|
15
14
|
import { selectInsightByWidgetRef } from "../../../../model/store/insights/insightsSelectors.js";
|
|
16
15
|
import { selectAttributeFilterConfigsOverrides } from "../../../../model/store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
|
|
17
16
|
import { selectFilterContextAttributeFilterItems, selectFilterContextMeasureValueFilters, } from "../../../../model/store/tabs/filterContext/filterContextSelectors.js";
|
|
18
|
-
import { selectFilterableWidgetByRef } from "../../../../model/store/tabs/layout/layoutSelectors.js";
|
|
19
17
|
import { DASHBOARD_HEADER_OVERLAYS_Z_INDEX } from "../../../constants/zIndex.js";
|
|
20
18
|
import { useInvalidFilteringParametersIdentifiers } from "../../../widget/insight/configuration/DrillTargets/useInvalidFilteringParametersIdentifiers.js";
|
|
21
19
|
import { isDrillToCustomUrlConfig } from "../../types.js";
|
|
@@ -291,19 +289,19 @@ function useInsightMeasureValueFilters(widgetRef, enabled) {
|
|
|
291
289
|
}, [enabled, insight]);
|
|
292
290
|
}
|
|
293
291
|
function useSanitizedInsightFilters(widgetRef) {
|
|
294
|
-
const
|
|
295
|
-
const widgetFiltersResult = useWidgetFilters(widget);
|
|
292
|
+
const insight = useDashboardSelector(selectInsightByWidgetRef(widgetRef));
|
|
296
293
|
const sanitizeAttributeFilter = useSanitizeAttributeFilter();
|
|
297
294
|
return useMemo(() => {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
295
|
+
if (!insight) {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
// Date filters are currently not supported, so filter them out
|
|
299
|
+
return uniqBy(insightDefinitionFilters(insight)
|
|
300
|
+
.filter(isAttributeFilter)
|
|
301
|
+
.map(sanitizeAttributeFilter)
|
|
302
|
+
.filter(isAttributeFilter), // filter out undefined values (eg. filters with removed display forms)
|
|
303
|
+
(f) => serializeObjRef(filterObjRef(f)));
|
|
304
|
+
}, [insight, sanitizeAttributeFilter]);
|
|
307
305
|
}
|
|
308
306
|
function useSanitizedDashboardFilters() {
|
|
309
307
|
// Date filters are currently not supported, so select only attribute filters
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDependentDateFilterConfigurationState.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFilterConfigurationState.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,KAAK,+BAA+B,EACpC,KAAK,oBAAoB,
|
|
1
|
+
{"version":3,"file":"useDependentDateFilterConfigurationState.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFilterConfigurationState.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,KAAK,+BAA+B,EACpC,KAAK,oBAAoB,EAG5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,6BAA6B,EAAE,MAAM,kDAAkD,CAAC;AAEtG;;GAEG;AACH,wBAAgB,wCAAwC,CACpD,eAAe,EAAE,oBAAoB,EAAE,EACvC,gBAAgB,CAAC,EAAE,oBAAoB,EACvC,oBAAoB,CAAC,EAAE,+BAA+B,EAAE,mCAyE3D;AAED,wBAAgB,8CAA8C,CAC1D,gBAAgB,CAAC,EAAE,oBAAoB,GACxC,oBAAoB,CAWtB"}
|
|
@@ -8,12 +8,22 @@ import { isUriRef, } from "@gooddata/sdk-model";
|
|
|
8
8
|
export function useDependentDateFilterConfigurationState(neighborFilters, commonDateFilter, filterElementsByDate) {
|
|
9
9
|
const neighborDateFiltersWithDimensions = useMemo(() => {
|
|
10
10
|
return neighborFilters.map((neighborFilter) => {
|
|
11
|
-
const
|
|
12
|
-
invariant(!isUriRef(
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const neighborDataSet = neighborFilter.dateFilter.dataSet;
|
|
12
|
+
invariant(!isUriRef(neighborDataSet));
|
|
13
|
+
// Prefer the filter's own localIdentifier over the dataset identifier so that multiple date
|
|
14
|
+
// filters backed by the same dataset can be told apart. Falls back to the dataset identifier
|
|
15
|
+
// for date filters that don't carry a localIdentifier (e.g. older backend records).
|
|
16
|
+
const filterLocalIdentifier = neighborFilter.dateFilter.localIdentifier ?? neighborDataSet?.identifier;
|
|
17
|
+
const isSelected = filterElementsByDate?.some((by) =>
|
|
18
|
+
// Match against both the new (localIdentifier) and legacy (dataset identifier)
|
|
19
|
+
// formats: dashboards saved before this change store the dataset identifier in
|
|
20
|
+
// filterLocalIdentifier, so we must accept either form to stay backwards compatible.
|
|
21
|
+
(by.filterLocalIdentifier === filterLocalIdentifier ||
|
|
22
|
+
by.filterLocalIdentifier === neighborDataSet?.identifier) &&
|
|
23
|
+
!by.isCommonDate) || false;
|
|
24
|
+
invariant(filterLocalIdentifier, "Cannot initialize the attribute filter configuration panel, neighbor date filter has missing 'localIdentifier' property.");
|
|
15
25
|
return {
|
|
16
|
-
localIdentifier:
|
|
26
|
+
localIdentifier: filterLocalIdentifier,
|
|
17
27
|
isSelected,
|
|
18
28
|
dataSet: neighborFilter.dateFilter.dataSet,
|
|
19
29
|
from: neighborFilter.dateFilter.from,
|
|
@@ -28,19 +38,27 @@ export function useDependentDateFilterConfigurationState(neighborFilters, common
|
|
|
28
38
|
const commonDate = parseCommonDateFilter(commonDateFilter);
|
|
29
39
|
return (filterElementsByDate ?? [])
|
|
30
40
|
.filter((parent) => parent.isCommonDate)
|
|
31
|
-
.map((parent) =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
dataSet
|
|
41
|
+
.map((parent) => {
|
|
42
|
+
// Resolve the target dimension. New format: the explicit `dataSet` field carries it
|
|
43
|
+
// (filterLocalIdentifier references the common date filter itself). Legacy format: no
|
|
44
|
+
// `dataSet`, so the dimension identifier was stored directly in filterLocalIdentifier.
|
|
45
|
+
// The config item is keyed by the dimension so it matches the per-dimension picker items.
|
|
46
|
+
const dimension = parent.dataSet ?? {
|
|
35
47
|
identifier: parent.filterLocalIdentifier,
|
|
36
48
|
type: "dataSet",
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
};
|
|
50
|
+
invariant(!isUriRef(dimension));
|
|
51
|
+
return {
|
|
52
|
+
localIdentifier: dimension.identifier,
|
|
53
|
+
isSelected: true,
|
|
54
|
+
dataSet: dimension,
|
|
55
|
+
from: commonDate.from,
|
|
56
|
+
to: commonDate.to,
|
|
57
|
+
granularity: commonDate.granularity,
|
|
58
|
+
type: commonDate.type,
|
|
59
|
+
isCommonDate: true,
|
|
60
|
+
};
|
|
61
|
+
});
|
|
44
62
|
}, [filterElementsByDate, commonDateFilter]);
|
|
45
63
|
return [...neighborDateFiltersWithDimensions, ...commonDateFilters];
|
|
46
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDependentDateFiltersConfiguration.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFiltersConfiguration.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useDependentDateFiltersConfiguration.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/filterBar/attributeFilter/dashboardDropdownBody/configuration/hooks/useDependentDateFiltersConfiguration.ts"],"names":[],"mappings":"AAQA,OAAO,EACH,KAAK,yBAAyB,EAE9B,KAAK,oBAAoB,EAE5B,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,KAAK,6BAA6B,EAAE,MAAM,kDAAkD,CAAC;AAOtG,wBAAgB,oCAAoC,CAChD,mBAAmB,EAAE,oBAAoB,EAAE,EAC3C,aAAa,EAAE,yBAAyB,EACxC,gBAAgB,CAAC,EAAE,oBAAoB;;;;;;;EAqH1C"}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { useCallback, useMemo, useState } from "react";
|
|
3
3
|
import { isEqual } from "lodash-es";
|
|
4
4
|
import { invariant } from "ts-invariant";
|
|
5
|
-
import {
|
|
5
|
+
import { generateDateFilterLocalIdentifier } from "@gooddata/sdk-backend-base";
|
|
6
|
+
import { isUriRef, } from "@gooddata/sdk-model";
|
|
6
7
|
import { setAttributeFilterDependentDateFilters } from "../../../../../../model/commands/filters.js";
|
|
7
8
|
import { useDispatchDashboardCommand } from "../../../../../../model/react/useDispatchDashboardCommand.js";
|
|
8
9
|
import { useDependentCommonDateFilterConfigurationState, useDependentDateFilterConfigurationState, } from "./useDependentDateFilterConfigurationState.js";
|
|
@@ -15,9 +16,11 @@ export function useDependentDateFiltersConfiguration(neighborDateFilters, curren
|
|
|
15
16
|
const [dependentDateFilters, setDependentDateFilters] = useState(originalState);
|
|
16
17
|
const [dependentCommonDateFilter, setDependentCommonDateFilter] = useState(originalCommonDateFilterState);
|
|
17
18
|
const onDependentDateFiltersSelect = (item, isSelected, isCommonDate) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
invariant(!isUriRef(item.dataSet));
|
|
20
|
+
// Match on item.localIdentifier rather than item.dataSet?.identifier (the dataset identifier):
|
|
21
|
+
// state entries now store dateFilter.localIdentifier as their key, which matches item.localIdentifier
|
|
22
|
+
// since both come from the same useDependentDateFilterConfigurationState initializer.
|
|
23
|
+
const changedParentIndex = dependentDateFilters.findIndex((dependentDateFilter) => dependentDateFilter.localIdentifier === item.localIdentifier &&
|
|
21
24
|
dependentDateFilter.isCommonDate === isCommonDate);
|
|
22
25
|
if (changedParentIndex === -1) {
|
|
23
26
|
setDependentDateFilters([...dependentDateFilters, item]);
|
|
@@ -44,18 +47,30 @@ export function useDependentDateFiltersConfiguration(neighborDateFilters, curren
|
|
|
44
47
|
const onDependentDateFiltersChange = useCallback(() => {
|
|
45
48
|
// dispatch the command only if the configuration changed
|
|
46
49
|
if (onDependentDateFiltersConfigurationChanged) {
|
|
50
|
+
// Common date filter has no dimension of its own, so we reference it by its own
|
|
51
|
+
// localIdentifier (falling back to the canonical common-date id) and carry the chosen
|
|
52
|
+
// dimension in the separate `dataSet` field. Specific date filters are referenced by their
|
|
53
|
+
// localIdentifier and need no dataSet (it is derived from the referenced filter).
|
|
54
|
+
const commonDateLocalId = commonDateFilter?.dateFilter.localIdentifier ?? generateDateFilterLocalIdentifier(0);
|
|
47
55
|
const dateFilters = dependentDateFilters
|
|
48
56
|
.filter((filter) => filter.isSelected)
|
|
49
|
-
.map((filter) =>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
.map((filter) => filter.isCommonDate
|
|
58
|
+
? {
|
|
59
|
+
filterLocalIdentifier: commonDateLocalId,
|
|
60
|
+
isCommonDate: true,
|
|
61
|
+
dataSet: filter.dataSet,
|
|
62
|
+
}
|
|
63
|
+
: {
|
|
64
|
+
filterLocalIdentifier: filter.localIdentifier,
|
|
65
|
+
isCommonDate: false,
|
|
66
|
+
});
|
|
53
67
|
saveDependentDateFilterCommand(currentFilter.attributeFilter.localIdentifier, dateFilters);
|
|
54
68
|
}
|
|
55
69
|
}, [
|
|
56
70
|
dependentDateFilters,
|
|
57
71
|
onDependentDateFiltersConfigurationChanged,
|
|
58
72
|
currentFilter,
|
|
73
|
+
commonDateFilter,
|
|
59
74
|
saveDependentDateFilterCommand,
|
|
60
75
|
]);
|
|
61
76
|
return {
|