@gooddata/sdk-ui-dashboard 11.58.0-alpha.3 → 11.58.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/esm/__version.d.ts +1 -1
  2. package/esm/__version.js +1 -1
  3. package/esm/index.d.ts +2 -2
  4. package/esm/index.d.ts.map +1 -1
  5. package/esm/index.js +2 -2
  6. package/esm/internal.d.ts +1 -0
  7. package/esm/internal.d.ts.map +1 -1
  8. package/esm/internal.js +1 -0
  9. package/esm/model/commandHandlers/common/validateDrillToCustomUrlParams.d.ts.map +1 -1
  10. package/esm/model/commandHandlers/common/validateDrillToCustomUrlParams.js +6 -1
  11. package/esm/model/commandHandlers/common/validateDrills.d.ts.map +1 -1
  12. package/esm/model/commandHandlers/common/validateDrills.js +12 -3
  13. package/esm/model/commandHandlers/dashboard/dashboardDrillReferences.d.ts +4 -0
  14. package/esm/model/commandHandlers/dashboard/dashboardDrillReferences.d.ts.map +1 -0
  15. package/esm/model/commandHandlers/dashboard/dashboardDrillReferences.js +53 -0
  16. package/esm/model/commandHandlers/dashboard/saveAsDashboardHandler.d.ts.map +1 -1
  17. package/esm/model/commandHandlers/dashboard/saveAsDashboardHandler.js +4 -1
  18. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.d.ts.map +1 -1
  19. package/esm/model/commandHandlers/dashboard/saveDashboardHandler.js +30 -6
  20. package/esm/model/commandHandlers/drill/drillToAttributeUrlHandler.d.ts.map +1 -1
  21. package/esm/model/commandHandlers/drill/drillToAttributeUrlHandler.js +2 -0
  22. package/esm/model/commandHandlers/drill/drillToCustomUrlHandler.d.ts.map +1 -1
  23. package/esm/model/commandHandlers/drill/drillToCustomUrlHandler.js +2 -0
  24. package/esm/model/commandHandlers/drill/drillToDashboardHandler.d.ts.map +1 -1
  25. package/esm/model/commandHandlers/drill/drillToDashboardHandler.js +2 -0
  26. package/esm/model/commandHandlers/drill/drillToInsightHandler.d.ts.map +1 -1
  27. package/esm/model/commandHandlers/drill/drillToInsightHandler.js +3 -1
  28. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.d.ts.map +1 -1
  29. package/esm/model/commandHandlers/drill/resolveDrillToCustomUrl.js +30 -29
  30. package/esm/model/commandHandlers/drill/validateDrillAccess.d.ts +6 -0
  31. package/esm/model/commandHandlers/drill/validateDrillAccess.d.ts.map +1 -0
  32. package/esm/model/commandHandlers/drill/validateDrillAccess.js +10 -0
  33. package/esm/model/store/catalog/catalogSelectors.d.ts +26 -1
  34. package/esm/model/store/catalog/catalogSelectors.d.ts.map +1 -1
  35. package/esm/model/store/catalog/catalogSelectors.js +13 -2
  36. package/esm/model/store/filtering/dashboardFilterSelectors.d.ts +8 -2
  37. package/esm/model/store/filtering/dashboardFilterSelectors.d.ts.map +1 -1
  38. package/esm/model/store/filtering/dashboardFilterSelectors.js +41 -25
  39. package/esm/model/store/filtering/types.d.ts +5 -0
  40. package/esm/model/store/filtering/types.d.ts.map +1 -1
  41. package/esm/model/store/tabs/layout/layoutSelectors.d.ts.map +1 -1
  42. package/esm/model/store/tabs/layout/layoutSelectors.js +2 -1
  43. package/esm/model/store/ui/index.d.ts +1 -0
  44. package/esm/model/store/ui/index.d.ts.map +1 -1
  45. package/esm/model/store/ui/uiReducers.d.ts +5 -1
  46. package/esm/model/store/ui/uiReducers.d.ts.map +1 -1
  47. package/esm/model/store/ui/uiReducers.js +8 -4
  48. package/esm/model/store/ui/uiSelectors.d.ts +5 -1
  49. package/esm/model/store/ui/uiSelectors.d.ts.map +1 -1
  50. package/esm/model/store/ui/uiSelectors.js +4 -0
  51. package/esm/model/store/ui/uiState.d.ts +2 -1
  52. package/esm/model/store/ui/uiState.d.ts.map +1 -1
  53. package/esm/model/store/ui/uiState.js +1 -0
  54. package/esm/model/store/widgetDrills/drillRestrictionSelectors.d.ts +23 -0
  55. package/esm/model/store/widgetDrills/drillRestrictionSelectors.d.ts.map +1 -0
  56. package/esm/model/store/widgetDrills/drillRestrictionSelectors.js +5 -0
  57. package/esm/model/store/widgetDrills/drillRestrictionUtils.d.ts +5 -0
  58. package/esm/model/store/widgetDrills/drillRestrictionUtils.d.ts.map +1 -0
  59. package/esm/model/store/widgetDrills/drillRestrictionUtils.js +27 -0
  60. package/esm/model/store/widgetDrills/widgetDrillSelectors.d.ts.map +1 -1
  61. package/esm/model/store/widgetDrills/widgetDrillSelectors.js +9 -5
  62. package/esm/presentation/automations/alerting/state/AlertingDialogStateProvider.js +1 -0
  63. package/esm/presentation/automations/alerting/state/useAlertDraftFilterWrites.d.ts +4 -2
  64. package/esm/presentation/automations/alerting/state/useAlertDraftFilterWrites.d.ts.map +1 -1
  65. package/esm/presentation/automations/alerting/state/useAlertDraftFilterWrites.js +12 -3
  66. package/esm/presentation/automations/alerting/utils/items.js +8 -14
  67. package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.d.ts.map +1 -1
  68. package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.js +8 -2
  69. package/esm/presentation/automations/contexts/AutomationsContext.d.ts +4 -2
  70. package/esm/presentation/automations/contexts/AutomationsContext.d.ts.map +1 -1
  71. package/esm/presentation/automations/scheduledEmail/hooks/useExportTimezones.js +1 -1
  72. package/esm/presentation/automations/scheduledEmail/state/ScheduledEmailDialogStateProvider.js +1 -0
  73. package/esm/presentation/automations/scheduledEmail/state/useScheduledEmailDraftFilterWrites.d.ts +4 -2
  74. package/esm/presentation/automations/scheduledEmail/state/useScheduledEmailDraftFilterWrites.d.ts.map +1 -1
  75. package/esm/presentation/automations/scheduledEmail/state/useScheduledEmailDraftFilterWrites.js +25 -6
  76. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.d.ts.map +1 -1
  77. package/esm/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.js +16 -11
  78. package/esm/presentation/automations/shared/automationFilters/components/AutomationRestrictedFilters.d.ts +9 -0
  79. package/esm/presentation/automations/shared/automationFilters/components/AutomationRestrictedFilters.d.ts.map +1 -0
  80. package/esm/presentation/automations/shared/automationFilters/components/AutomationRestrictedFilters.js +22 -0
  81. package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.d.ts +2 -2
  82. package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.d.ts.map +1 -1
  83. package/esm/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.js +17 -5
  84. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.d.ts +8 -0
  85. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.d.ts.map +1 -1
  86. package/esm/presentation/automations/shared/automationFilters/useAutomationFilters.js +54 -10
  87. package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.d.ts.map +1 -1
  88. package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.js +3 -2
  89. package/esm/presentation/automations/shared/filters/conversions.d.ts +10 -2
  90. package/esm/presentation/automations/shared/filters/conversions.d.ts.map +1 -1
  91. package/esm/presentation/automations/shared/filters/conversions.js +15 -6
  92. package/esm/presentation/dashboardSettingsDialog/DefaultDashboardSettingsDialog.d.ts.map +1 -1
  93. package/esm/presentation/dashboardSettingsDialog/DefaultDashboardSettingsDialog.js +3 -4
  94. package/esm/presentation/dashboardSettingsDialog/TimezoneOption.d.ts.map +1 -1
  95. package/esm/presentation/dashboardSettingsDialog/TimezoneOption.js +20 -7
  96. package/esm/presentation/dialogs/ExportCsvDialog.d.ts.map +1 -1
  97. package/esm/presentation/dialogs/ExportCsvDialog.js +2 -1
  98. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditorParametersSections/IdentifierParametersSection.js +1 -1
  99. package/esm/presentation/drill/DrillSelect/DrillSelectDropdown.d.ts +2 -1
  100. package/esm/presentation/drill/DrillSelect/DrillSelectDropdown.d.ts.map +1 -1
  101. package/esm/presentation/drill/DrillSelect/DrillSelectDropdown.js +19 -1
  102. package/esm/presentation/drill/DrillSelect/WithDrillSelect.d.ts.map +1 -1
  103. package/esm/presentation/drill/DrillSelect/WithDrillSelect.js +12 -4
  104. package/esm/presentation/drill/DrillSelect/types.d.ts +1 -0
  105. package/esm/presentation/drill/DrillSelect/types.d.ts.map +1 -1
  106. package/esm/presentation/drill/hooks/useDrillSelectDropdownMenuItems.d.ts.map +1 -1
  107. package/esm/presentation/drill/hooks/useDrillSelectDropdownMenuItems.js +4 -2
  108. package/esm/presentation/insightNotSavedDialog/InsightNotSavedDialog.d.ts.map +1 -1
  109. package/esm/presentation/insightNotSavedDialog/InsightNotSavedDialog.js +4 -5
  110. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +21 -1
  111. package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  112. package/esm/presentation/localization/bundles/en-US.localization-bundle.js +25 -5
  113. package/esm/sdk-ui-dashboard.d.ts +20 -19
  114. package/package.json +21 -21
  115. package/styles/css/dashboard.css +1 -7
  116. package/styles/css/dashboard.css.map +1 -1
  117. package/styles/css/dashboardSettingsDialog.css +4 -0
  118. package/styles/css/dashboardSettingsDialog.css.map +1 -1
  119. package/styles/css/export.css +0 -6
  120. package/styles/css/export.css.map +1 -1
  121. package/styles/css/main.css +5 -13
  122. package/styles/css/main.css.map +1 -1
  123. package/styles/css/notifications_channels_dialog.css +1 -7
  124. package/styles/css/notifications_channels_dialog.css.map +1 -1
  125. package/styles/scss/dashboardSettingsDialog.scss +5 -0
  126. package/styles/scss/export.scss +0 -9
  127. package/styles/scss/notifications_channels_dialog.scss +1 -10
  128. package/esm/model/types/drillTypes.d.ts +0 -13
  129. package/esm/model/types/drillTypes.d.ts.map +0 -1
  130. package/esm/model/types/drillTypes.js +0 -14
@@ -1,5 +1,5 @@
1
1
  import { type Dispatch, type SetStateAction } from "react";
2
- import { type FilterContextItem, type IAutomationMetadataObjectDefinition, type IAutomationVisibleFilter, type IInsight, type IWidget } from "@gooddata/sdk-model";
2
+ import { type FilterContextItem, type IAutomationMetadataObject, type IAutomationMetadataObjectDefinition, type IAutomationVisibleFilter, type IInsight, type IWidget } from "@gooddata/sdk-model";
3
3
  import type { IAutomationFiltersTab } from "../../../../model/store/filtering/types.js";
4
4
  /**
5
5
  * Props for {@link useScheduledEmailDraftFilterWrites}.
@@ -7,6 +7,8 @@ import type { IAutomationFiltersTab } from "../../../../model/store/filtering/ty
7
7
  */
8
8
  export interface IUseScheduledEmailDraftFilterWritesProps {
9
9
  setEditedAutomation: Dispatch<SetStateAction<IAutomationMetadataObjectDefinition>>;
10
+ /** The schedule as it was loaded; the source of the visible-filter entries only it can name. */
11
+ scheduledExportToEdit?: IAutomationMetadataObject;
10
12
  widget?: IWidget;
11
13
  insight?: IInsight;
12
14
  storeFilters: boolean;
@@ -20,7 +22,7 @@ export interface IUseScheduledEmailDraftFilterWritesProps {
20
22
  *
21
23
  * @internal
22
24
  */
23
- export declare function useScheduledEmailDraftFilterWrites({ setEditedAutomation, widget, insight, storeFilters, availableFiltersAsVisibleFilters, availableFiltersAsVisibleFiltersByTab, filtersByTab, }: IUseScheduledEmailDraftFilterWritesProps): {
25
+ export declare function useScheduledEmailDraftFilterWrites({ setEditedAutomation, scheduledExportToEdit, widget, insight, storeFilters, availableFiltersAsVisibleFilters, availableFiltersAsVisibleFiltersByTab, filtersByTab, }: IUseScheduledEmailDraftFilterWritesProps): {
24
26
  applyFiltersToDraft: (filters: FilterContextItem[], storeFiltersParam?: boolean) => void;
25
27
  applyFiltersByTabToDraft: (newFiltersByTab: Record<string, FilterContextItem[]>, storeFiltersParam?: boolean) => void;
26
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useScheduledEmailDraftFilterWrites.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/scheduledEmail/state/useScheduledEmailDraftFilterWrites.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAe,MAAM,OAAO,CAAC;AAExE,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,mCAAmC,EACxC,KAAK,wBAAwB,EAC7B,KAAK,QAAQ,EACb,KAAK,OAAO,EAIf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AASxF;;;GAGG;AACH,MAAM,WAAW,wCAAwC;IACrD,mBAAmB,EAAE,QAAQ,CAAC,cAAc,CAAC,mCAAmC,CAAC,CAAC,CAAC;IACnF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,gCAAgC,CAAC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IAC1E,qCAAqC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC;IACnF,YAAY,CAAC,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;CACtD;AAED;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAAC,EAC/C,mBAAmB,EACnB,MAAM,EACN,OAAO,EACP,YAAY,EACZ,gCAAgC,EAChC,qCAAqC,EACrC,YAAY,GACf,EAAE,wCAAwC,GAAG;IAC1C,mBAAmB,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,iBAAiB,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzF,wBAAwB,EAAE,CACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,EACpD,iBAAiB,CAAC,EAAE,OAAO,KAC1B,IAAI,CAAC;CACb,CA8LA"}
1
+ {"version":3,"file":"useScheduledEmailDraftFilterWrites.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/scheduledEmail/state/useScheduledEmailDraftFilterWrites.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAwB,MAAM,OAAO,CAAC;AAEjF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,mCAAmC,EACxC,KAAK,wBAAwB,EAC7B,KAAK,QAAQ,EACb,KAAK,OAAO,EAIf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAUxF;;;GAGG;AACH,MAAM,WAAW,wCAAwC;IACrD,mBAAmB,EAAE,QAAQ,CAAC,cAAc,CAAC,mCAAmC,CAAC,CAAC,CAAC;IACnF,gGAAgG;IAChG,qBAAqB,CAAC,EAAE,yBAAyB,CAAC;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,gCAAgC,CAAC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IAC1E,qCAAqC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC;IACnF,YAAY,CAAC,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;CACtD;AAED;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAAC,EAC/C,mBAAmB,EACnB,qBAAqB,EACrB,MAAM,EACN,OAAO,EACP,YAAY,EACZ,gCAAgC,EAChC,qCAAqC,EACrC,YAAY,GACf,EAAE,wCAAwC,GAAG;IAC1C,mBAAmB,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,iBAAiB,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzF,wBAAwB,EAAE,CACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,EACpD,iBAAiB,CAAC,EAAE,OAAO,KAC1B,IAAI,CAAC;CACb,CAyNA"}
@@ -1,6 +1,7 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { useCallback } from "react";
2
+ import { useCallback, useMemo } from "react";
3
3
  import { isExportDefinitionDashboardRequestPayload, isExportDefinitionVisualizationObjectRequestPayload, isInsightWidget, } from "@gooddata/sdk-model";
4
+ import { useAutomationsContext } from "../../contexts/AutomationsContext.js";
4
5
  import { useScheduledEmailDialogContext } from "../../contexts/ScheduledEmailDialogContext.js";
5
6
  import { getAppliedDashboardFilters, getAppliedWidgetFilters, getVisibleFiltersByFilters, getVisibleFiltersByFiltersByTab, } from "../../shared/filters/index.js";
6
7
  /**
@@ -9,8 +10,19 @@ import { getAppliedDashboardFilters, getAppliedWidgetFilters, getVisibleFiltersB
9
10
  *
10
11
  * @internal
11
12
  */
12
- export function useScheduledEmailDraftFilterWrites({ setEditedAutomation, widget, insight, storeFilters, availableFiltersAsVisibleFilters, availableFiltersAsVisibleFiltersByTab, filtersByTab, }) {
13
+ export function useScheduledEmailDraftFilterWrites({ setEditedAutomation, scheduledExportToEdit, widget, insight, storeFilters, availableFiltersAsVisibleFilters, availableFiltersAsVisibleFiltersByTab, filtersByTab, }) {
13
14
  const { hiddenFilters: dashboardHiddenFilters, commonDateFilterId } = useScheduledEmailDialogContext();
15
+ const { isFilterRestricted } = useAutomationsContext();
16
+ // Read from the loaded schedule, not from the draft: turning the store-filters checkbox off
17
+ // empties the draft's entries, and turning it back on must restore them.
18
+ const restrictedFallback = useMemo(() => ({
19
+ storedVisibleFilters: scheduledExportToEdit?.metadata?.visibleFilters,
20
+ isFilterRestricted,
21
+ }), [scheduledExportToEdit, isFilterRestricted]);
22
+ const restrictedFallbackByTab = useMemo(() => ({
23
+ storedVisibleFilters: scheduledExportToEdit?.metadata?.visibleFiltersByTab,
24
+ isFilterRestricted,
25
+ }), [scheduledExportToEdit, isFilterRestricted]);
14
26
  // Re-derived locally (not passed as a prop) so that the `if (isWidget)` branch below narrows
15
27
  // `widget`/`insight` via TS's aliased-condition control-flow analysis — this requires the boolean
16
28
  // to be declared from those exact variables in this same scope, same as in the parent.
@@ -25,7 +37,7 @@ export function useScheduledEmailDraftFilterWrites({ setEditedAutomation, widget
25
37
  const appliedDashboardFilters = getAppliedDashboardFilters(filters, dashboardHiddenFilters, true);
26
38
  const appliedWidgetFiltersWithInsight = getAppliedWidgetFilters(filters, dashboardHiddenFilters, widget, insight, commonDateFilterId, true);
27
39
  const appliedWidgetFiltersWithoutInsight = getAppliedWidgetFilters(filters, dashboardHiddenFilters, widget, insight, commonDateFilterId, false);
28
- const visibleFilters = getVisibleFiltersByFilters(filters, availableFiltersAsVisibleFilters, true);
40
+ const visibleFilters = getVisibleFiltersByFilters(filters, availableFiltersAsVisibleFilters, true, restrictedFallback);
29
41
  return {
30
42
  ...s,
31
43
  exportDefinitions: s.exportDefinitions?.map((exportDefinition) => {
@@ -63,7 +75,7 @@ export function useScheduledEmailDraftFilterWrites({ setEditedAutomation, widget
63
75
  else {
64
76
  setEditedAutomation((s) => {
65
77
  const appliedFilters = getAppliedDashboardFilters(filters, dashboardHiddenFilters, shouldStoreFilters);
66
- const visibleFilters = getVisibleFiltersByFilters(filters, availableFiltersAsVisibleFilters, shouldStoreFilters);
78
+ const visibleFilters = getVisibleFiltersByFilters(filters, availableFiltersAsVisibleFilters, shouldStoreFilters, restrictedFallback);
67
79
  return {
68
80
  ...s,
69
81
  exportDefinitions: s.exportDefinitions?.map((exportDefinition) => {
@@ -99,6 +111,7 @@ export function useScheduledEmailDraftFilterWrites({ setEditedAutomation, widget
99
111
  insight,
100
112
  isWidget,
101
113
  commonDateFilterId,
114
+ restrictedFallback,
102
115
  ]);
103
116
  // Callback for per-tab filter changes - updates state AND syncs to export definitions
104
117
  const applyFiltersByTabToDraft = useCallback((newFiltersByTab, storeFiltersParam) => {
@@ -113,7 +126,7 @@ export function useScheduledEmailDraftFilterWrites({ setEditedAutomation, widget
113
126
  return acc;
114
127
  }, {})
115
128
  : undefined;
116
- const newVisibleFiltersByTab = getVisibleFiltersByFiltersByTab(newFiltersByTab, availableFiltersAsVisibleFiltersByTab, shouldStoreFilters);
129
+ const newVisibleFiltersByTab = getVisibleFiltersByFiltersByTab(newFiltersByTab, availableFiltersAsVisibleFiltersByTab, shouldStoreFilters, restrictedFallbackByTab);
117
130
  // Sync to export definitions AND metadata
118
131
  setEditedAutomation((s) => ({
119
132
  ...s,
@@ -137,6 +150,12 @@ export function useScheduledEmailDraftFilterWrites({ setEditedAutomation, widget
137
150
  visibleFiltersByTab: newVisibleFiltersByTab,
138
151
  },
139
152
  }));
140
- }, [storeFilters, setEditedAutomation, availableFiltersAsVisibleFiltersByTab, filtersByTab]);
153
+ }, [
154
+ storeFilters,
155
+ setEditedAutomation,
156
+ availableFiltersAsVisibleFiltersByTab,
157
+ filtersByTab,
158
+ restrictedFallbackByTab,
159
+ ]);
141
160
  return { applyFiltersToDraft, applyFiltersByTabToDraft };
142
161
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AutomationFiltersSelect.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AutomationFiltersSelect.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationFiltersSelect.tsx"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ import { AutomationAttributeFilter } from "./AutomationAttributeFilter.js";
12
12
  import { AutomationDateFilter } from "./AutomationDateFilter.js";
13
13
  import { AutomationMeasureValueFilter } from "./AutomationMeasureValueFilter.js";
14
14
  import { AutomationParameter } from "./AutomationParameter.js";
15
+ import { AutomationRestrictedFilters } from "./AutomationRestrictedFilters.js";
15
16
  const COLLAPSED_FILTERS_COUNT = 2;
16
17
  function AutomationCheckboxOrNote({ isDashboardAutomation, storeFilters, handleStoreFiltersChange, handleKeyDown, automationFilterSelectTooltipId, parametersEnabled, }) {
17
18
  const intl = useIntl();
@@ -51,6 +52,7 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
51
52
  const { commonDateFilterId, lockedFilters, attributeConfigs, dateConfigs, filterAnnouncement, filterGroupRef, makeFilterGroupUnfocusable, setAddFilterButtonRefs, } = shouldRenderByTab && tabFiltersData.processedFiltersByTab ? tabFiltersData : flatFiltersData;
52
53
  const { focusAddFilterButton } = flatFiltersData;
53
54
  const filters = shouldRenderByTab ? [] : flatFiltersData.visibleFilters;
55
+ const restrictedFilterCount = shouldRenderByTab ? 0 : flatFiltersData.restrictedFilterCount;
54
56
  const visibleParameters = shouldRenderByTab ? [] : parameters;
55
57
  const attributes = shouldRenderByTab ? [] : flatFiltersData.attributes;
56
58
  const dateDatasets = shouldRenderByTab ? [] : flatFiltersData.dateDatasets;
@@ -69,7 +71,7 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
69
71
  : flatFiltersData.handleStoreFiltersChange;
70
72
  const intl = useIntl();
71
73
  const [isExpanded, setIsExpanded] = useState(showAllFilters);
72
- const chipCount = filters.length + visibleParameters.length;
74
+ const chipCount = filters.length + visibleParameters.length + (restrictedFilterCount > 0 ? 1 : 0);
73
75
  const isExpandable = !showAllFilters && chipCount > COLLAPSED_FILTERS_COUNT;
74
76
  const handleKeyDown = (e) => {
75
77
  if (isActionKey(e)) {
@@ -83,7 +85,9 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
83
85
  ref: parameter.ref,
84
86
  title: parameter.title,
85
87
  }));
86
- const isAddButtonDisabled = availableFilters?.length === selectedFilters?.length && availableParameters.length === 0;
88
+ // Counting availableFilters would overcount: it keeps the restricted filters, which the dropdown
89
+ // never offers, so the button would stay enabled over an empty dropdown.
90
+ const isAddButtonDisabled = !flatFiltersData.hasFiltersToAdd && availableParameters.length === 0;
87
91
  const tooltipTextValues = {
88
92
  add: intl.formatMessage({ id: "dialogs.automation.filters.add" }),
89
93
  addDisabled: intl.formatMessage({ id: "dialogs.automation.filters.addDisabled" }),
@@ -104,9 +108,6 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
104
108
  }),
105
109
  iconAriaHidden: true,
106
110
  } }), _jsx(Bubble, { className: "bubble-primary", alignPoints: [{ align: "bc tc" }], children: isExpanded ? (_jsx(FormattedMessage, { id: "dialogs.automation.filters.showLess" })) : (_jsx(FormattedMessage, { id: "dialogs.automation.filters.showAll" })) })] })) : (_jsx(FormattedMessage, { id: "dialogs.schedule.email.filters", values: { count: chipCount } })) })), _jsxs("div", { className: "gd-automation-filters", children: [showAllFilters ? (_jsxs(_Fragment, { children: [_jsx(AutomationCheckboxOrNote, { isDashboardAutomation: isDashboardAutomation, storeFilters: storeFilters, handleStoreFiltersChange: handleStoreFiltersChange, handleKeyDown: handleKeyDown, automationFilterSelectTooltipId: automationFilterSelectTooltipId, parametersEnabled: parametersEnabled }), _jsx(Divider, {})] })) : null, _jsxs("div", { className: `gd-automation-filters__wrapper${storeFilters || !isDashboardAutomation ? "" : " gd-automation-filters__wrapper--disabled"}`, children: [disableFilters ? _jsx("div", { className: "gd-automation-filters__overlay" }) : null, shouldRenderByTab && tabFiltersData.processedFiltersByTab ? (_jsx("div", { className: "gd-automation-filters__list gd-automation-filters__list--tabbed", role: "group", "aria-labelledby": AUTOMATION_FILTERS_GROUP_LABEL_ID, ref: filterGroupRef, onBlur: makeFilterGroupUnfocusable, children: tabFiltersData.processedFiltersByTab.map((tab, index) => {
107
- // Check if all filters for this tab are already selected
108
- const tabEditedFilters = editedFiltersByTab?.[tab.tabId] ?? [];
109
- const tabAvailableFilters = filtersByTab?.find((t) => t.tabId === tab.tabId)?.availableFilters ?? [];
110
111
  const tabParameters = parametersByTab?.[tab.tabId] ?? [];
111
112
  const tabAvailableParameters = availableParametersByTab?.[tab.tabId] ?? [];
112
113
  const tabParameterDropdownItems = tabAvailableParameters.map((parameter) => ({
@@ -114,12 +115,11 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
114
115
  ref: parameter.ref,
115
116
  title: parameter.title,
116
117
  }));
117
- const isTabAddButtonDisabled = tabEditedFilters.length >= tabAvailableFilters.length &&
118
- tabAvailableParameters.length === 0;
118
+ const isTabAddButtonDisabled = !tab.hasFiltersToAdd && tabAvailableParameters.length === 0;
119
119
  const tabTooltipText = isTabAddButtonDisabled
120
120
  ? tooltipTextValues.addDisabled
121
121
  : tooltipTextValues.add;
122
- return (_jsx(AutomationFiltersTabSection, { tabTitle: tab.tabTitle, tabId: tab.tabId, canAddItems: !isTabAddButtonDisabled, filters: tab.visibleFilters, attributeConfigs: tab.attributeConfigs, commonDateFilterId: commonDateFilterId, lockedFilters: tab.lockedFilters, onChange: (filter) => tabFiltersData.handleTabFilterChange(tab.tabId, filter), onDelete: (filter) => tabFiltersData.handleTabFilterDelete(tab.tabId, filter), parameters: tabParameters, onParameterChange: (ref, value) => {
122
+ return (_jsx(AutomationFiltersTabSection, { tabTitle: tab.tabTitle, tabId: tab.tabId, canAddItems: !isTabAddButtonDisabled, filters: tab.visibleFilters, restrictedFilterCount: tab.restrictedFilterCount, onRestrictedFiltersRemove: () => tabFiltersData.handleTabRestrictedFiltersRemove(tab.tabId), attributeConfigs: tab.attributeConfigs, commonDateFilterId: commonDateFilterId, lockedFilters: tab.lockedFilters, onChange: (filter) => tabFiltersData.handleTabFilterChange(tab.tabId, filter), onDelete: (filter) => tabFiltersData.handleTabFilterDelete(tab.tabId, filter), parameters: tabParameters, onParameterChange: (ref, value) => {
123
123
  announceParameterChanged(tabParameters, ref, value);
124
124
  onParameterChangeByTab?.(tab.tabId, ref, value);
125
125
  }, onParameterDelete: (ref) => {
@@ -148,6 +148,11 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
148
148
  ariaHaspopup: "dialog",
149
149
  } }) }) })), DropdownTitleComponent: () => (_jsx("div", { className: "gd-automation-filters__dropdown-header", children: _jsx(Typography, { tagName: "h3", id: AUTOMATION_FILTERS_DIALOG_TITLE_ID, children: _jsx(FormattedMessage, { id: "dialogs.automation.filters.title" }) }) })), renderNoData: () => (_jsx("div", { className: "gd-automation-filters__dropdown-no-filters", children: _jsx(FormattedMessage, { id: "dialogs.automation.filters.noFilters" }) })) }) }, tab.tabId));
150
150
  }) })) : (_jsxs("div", { className: "gd-automation-filters__list", role: "group", "aria-labelledby": AUTOMATION_FILTERS_GROUP_LABEL_ID, ref: filterGroupRef, onBlur: makeFilterGroupUnfocusable, children: [[
151
+ ...(restrictedFilterCount > 0
152
+ ? [
153
+ _jsx(AutomationRestrictedFilters, { count: restrictedFilterCount, onRemove: flatFiltersData.handleRemoveRestrictedFilters, isReadOnly: disableFilters }, "restricted-filters"),
154
+ ]
155
+ : []),
151
156
  ...filters.map((filter) => {
152
157
  const isCommonDateFilter = isDashboardCommonDateFilter(filter) ||
153
158
  (isDashboardDateFilter(filter) &&
@@ -211,17 +216,17 @@ function AutomationFilter({ filter, attributeConfigs, onChange, onDelete, isComm
211
216
  * Renders filters for a single tab with a tab title header.
212
217
  * Used when displaying filters grouped by tab for whole dashboard automations.
213
218
  */
214
- function AutomationFiltersTabSection({ tabId, tabTitle, filters, attributeConfigs, commonDateFilterId, lockedFilters, onChange, onDelete, parameters, onParameterChange, onParameterDelete, overlayPositionType, showDivider = false, addFilterButton, canAddItems, readonlyFilters, }) {
219
+ function AutomationFiltersTabSection({ tabId, tabTitle, filters, attributeConfigs, commonDateFilterId, lockedFilters, restrictedFilterCount, onRestrictedFiltersRemove, onChange, onDelete, parameters, onParameterChange, onParameterDelete, overlayPositionType, showDivider = false, addFilterButton, canAddItems, readonlyFilters, }) {
215
220
  const intl = useIntl();
216
221
  const tabSectionLabelId = useIdPrefixed(`automation-filters-tab-${tabId}`);
217
222
  // Display tab title or fallback to generic "Tab" label
218
223
  const displayTitle = tabTitle || intl.formatMessage({ id: "dialogs.automation.filters.tab.untitled" });
219
224
  const tabLabel = intl.formatMessage({ id: "dialogs.automation.filters.tab.label" });
220
- if (filters.length === 0 && parameters.length === 0 && !canAddItems) {
225
+ if (filters.length === 0 && parameters.length === 0 && restrictedFilterCount === 0 && !canAddItems) {
221
226
  return null;
222
227
  }
223
228
  const content = (_jsx("span", { className: "gd-automation-filters__tab-title s-automation-filters-tab-title", children: displayTitle }));
224
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "gd-automation-filters__tab-section s-automation-filters-tab-section", role: "group", "aria-labelledby": tabSectionLabelId, children: [_jsxs("div", { className: "gd-automation-filters__tab-header", children: [_jsx("span", { className: "gd-automation-filters__tab-label", children: tabLabel }), _jsx(UiTooltip, { content: content, triggerBy: ["hover", "focus"], optimalPlacement: true, anchor: _jsx("span", { className: "gd-automation-filters__tab-title s-automation-filters-tab-title", id: tabSectionLabelId, children: displayTitle }) })] }), _jsxs("div", { className: "gd-automation-filters__tab-filters", children: [filters.map((filter) => {
229
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "gd-automation-filters__tab-section s-automation-filters-tab-section", role: "group", "aria-labelledby": tabSectionLabelId, children: [_jsxs("div", { className: "gd-automation-filters__tab-header", children: [_jsx("span", { className: "gd-automation-filters__tab-label", children: tabLabel }), _jsx(UiTooltip, { content: content, triggerBy: ["hover", "focus"], optimalPlacement: true, anchor: _jsx("span", { className: "gd-automation-filters__tab-title s-automation-filters-tab-title", id: tabSectionLabelId, children: displayTitle }) })] }), _jsxs("div", { className: "gd-automation-filters__tab-filters", children: [restrictedFilterCount > 0 ? (_jsx(AutomationRestrictedFilters, { count: restrictedFilterCount, onRemove: onRestrictedFiltersRemove, isReadOnly: readonlyFilters })) : null, filters.map((filter) => {
225
230
  const isCommonDateFilter = isDashboardCommonDateFilter(filter) ||
226
231
  (isDashboardDateFilter(filter) &&
227
232
  commonDateFilterId === filter.dateFilter.localIdentifier);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Stands in for the automation filters the current user may not read, without naming them.
3
+ */
4
+ export declare function AutomationRestrictedFilters({ count, onRemove, isReadOnly, }: {
5
+ count: number;
6
+ onRemove: () => void;
7
+ isReadOnly?: boolean;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=AutomationRestrictedFilters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutomationRestrictedFilters.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationRestrictedFilters.tsx"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,EACxC,KAAK,EACL,QAAQ,EACR,UAAU,GACb,EAAE;IACC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,2CA8CA"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useIntl } from "react-intl";
3
+ import { UiChip, UiTooltip, useIdPrefixed } from "@gooddata/sdk-ui-kit";
4
+ const CHIP_ANCHOR_STYLES = { display: "flex", width: "100%", height: "100%", minWidth: 0 };
5
+ const DELETE_ANCHOR_STYLES = { height: "100%" };
6
+ /**
7
+ * Stands in for the automation filters the current user may not read, without naming them.
8
+ */
9
+ export function AutomationRestrictedFilters({ count, onRemove, isReadOnly, }) {
10
+ const intl = useIntl();
11
+ const tooltipId = useIdPrefixed("automation-restricted-filters-tooltip");
12
+ const label = intl.formatMessage({ id: "filterBar.restrictedFilters" }, { count });
13
+ const reason = intl.formatMessage({ id: "filterBar.restrictedFilters.reason" }, { count });
14
+ const deleteTooltip = intl.formatMessage({ id: "dialogs.automation.filters.restricted.deleteTooltip" }, { count });
15
+ return (_jsx(UiChip, { label: label,
16
+ // the entry has nothing to open; isLocked also renders the lock icon
17
+ isLocked: true, isExpandable: false, isDeletable: !isReadOnly, onDelete: onRemove, dataTestId: "automation-restricted-filters", accessibilityConfig: {
18
+ ariaLabel: `${label} ${reason}`,
19
+ deleteAriaLabel: deleteTooltip,
20
+ deleteAriaDescribedBy: tooltipId,
21
+ }, renderChipContent: (content) => (_jsx(UiTooltip, { id: tooltipId, arrowPlacement: "top-start", content: reason, triggerBy: ["hover", "focus"], anchor: content, anchorWrapperStyles: CHIP_ANCHOR_STYLES })), renderActionButton: (button) => (_jsx(UiTooltip, { arrowPlacement: "top-start", content: deleteTooltip, triggerBy: ["hover", "focus"], anchor: button, anchorWrapperStyles: DELETE_ANCHOR_STYLES })) }));
22
+ }
@@ -1,11 +1,11 @@
1
1
  import { type FilterContextItem, type IAutomationMetadataObject, type IAutomationVisibleFilter } from "@gooddata/sdk-model";
2
2
  import { type ExtendedDashboardWidget } from "../../../../../model/types/layoutTypes.js";
3
- export declare function useDefaultSelectedFiltersForExistingAutomation(automationToEdit?: IAutomationMetadataObject, availableVisibleFilters?: IAutomationVisibleFilter[], widget?: ExtendedDashboardWidget): (import("@gooddata/sdk-model").IDashboardArbitraryAttributeFilter | import("@gooddata/sdk-model").IDashboardAttributeFilter | import("@gooddata/sdk-model").IDashboardDateFilter | import("@gooddata/sdk-model").IDashboardMatchAttributeFilter | import("@gooddata/sdk-model").IDashboardMeasureValueFilter)[];
3
+ export declare function useDefaultSelectedFiltersForExistingAutomation(automationToEdit?: IAutomationMetadataObject, availableVisibleFilters?: IAutomationVisibleFilter[], widget?: ExtendedDashboardWidget): FilterContextItem[];
4
4
  /**
5
5
  * Reconstructs filters per tab from saved visibleFiltersByTab and filtersByTab.
6
6
  * Applies the same matching logic as getDefaultSelectedFiltersByVisibleFilters to each tab.
7
7
  *
8
8
  * @internal
9
9
  */
10
- export declare function getDefaultSelectedFiltersByTabForExistingAutomation(automationToEdit: IAutomationMetadataObject | undefined, availableDashboardFiltersByTab?: Record<string, FilterContextItem[]>, commonDateFilterId?: string): Record<string, FilterContextItem[]> | undefined;
10
+ export declare function getDefaultSelectedFiltersByTabForExistingAutomation(automationToEdit: IAutomationMetadataObject | undefined, availableDashboardFiltersByTab?: Record<string, FilterContextItem[]>, commonDateFilterId?: string, isFilterRestricted?: (filter: FilterContextItem) => boolean): Record<string, FilterContextItem[]> | undefined;
11
11
  //# sourceMappingURL=useDefaultSelectedFiltersForExistingAutomation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDefaultSelectedFiltersForExistingAutomation.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAShC,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAYzF,wBAAgB,8CAA8C,CAC1D,gBAAgB,CAAC,EAAE,yBAAyB,EAC5C,uBAAuB,CAAC,EAAE,wBAAwB,EAAE,EACpD,MAAM,CAAC,EAAE,uBAAuB,mTA2CnC;AAwED;;;;;GAKG;AACH,wBAAgB,mDAAmD,CAC/D,gBAAgB,EAAE,yBAAyB,GAAG,SAAS,EACvD,8BAA8B,GAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAM,EACxE,kBAAkB,CAAC,EAAE,MAAM,GAC5B,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,GAAG,SAAS,CAoCjD"}
1
+ {"version":3,"file":"useDefaultSelectedFiltersForExistingAutomation.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/hooks/useDefaultSelectedFiltersForExistingAutomation.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAShC,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AA6BzF,wBAAgB,8CAA8C,CAC1D,gBAAgB,CAAC,EAAE,yBAAyB,EAC5C,uBAAuB,CAAC,EAAE,wBAAwB,EAAE,EACpD,MAAM,CAAC,EAAE,uBAAuB,uBAkDnC;AAwED;;;;;GAKG;AACH,wBAAgB,mDAAmD,CAC/D,gBAAgB,EAAE,yBAAyB,GAAG,SAAS,EACvD,8BAA8B,GAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAM,EACxE,kBAAkB,CAAC,EAAE,MAAM,EAC3B,kBAAkB,GAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,OAAqB,GACzE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,GAAG,SAAS,CAyCjD"}
@@ -6,8 +6,17 @@ import { isDashboardFilter } from "../../../../../types.js";
6
6
  import { useAutomationsContext } from "../../../contexts/AutomationsContext.js";
7
7
  import { dashboardFilterToFilterContextItem } from "../../filters/index.js";
8
8
  import { getAutomationAlertFilters, getAutomationDashboardFilters, getAutomationDashboardFiltersByTab, getAutomationVisualizationFilters, } from "../../utils/automationUtils.js";
9
+ /**
10
+ * Keeps the restricted filters the automation stores but the reconstruction above cannot find: one the
11
+ * author had already hidden when it was saved never got a visible-filter entry to match on.
12
+ */
13
+ function withStoredRestrictedFilters(reconstructed, savedFilters, isFilterRestricted) {
14
+ const presentIds = new Set(reconstructed.map(dashboardFilterLocalIdentifier));
15
+ const missing = (savedFilters ?? []).filter((filter) => isFilterRestricted(filter) && !presentIds.has(dashboardFilterLocalIdentifier(filter)));
16
+ return missing.length > 0 ? [...reconstructed, ...missing] : reconstructed;
17
+ }
9
18
  export function useDefaultSelectedFiltersForExistingAutomation(automationToEdit, availableVisibleFilters, widget) {
10
- const { automationAvailableFilters: availableDashboardFilters, commonDateFilterId } = useAutomationsContext();
19
+ const { automationAvailableFilters: availableDashboardFilters, commonDateFilterId, isFilterRestricted, } = useAutomationsContext();
11
20
  const savedWidgetAlertFilters = getAutomationAlertFilters(automationToEdit);
12
21
  const { executionFilters: savedWidgetScheduleFilters, filterContextItems: savedWidgetScheduleFilterContextItems, } = getAutomationVisualizationFilters(automationToEdit);
13
22
  const savedDashboardScheduleFilters = getAutomationDashboardFilters(automationToEdit);
@@ -30,7 +39,7 @@ export function useDefaultSelectedFiltersForExistingAutomation(automationToEdit,
30
39
  ]);
31
40
  const availableWidgetFilters = removeIgnoredWidgetFilters(availableDashboardFilters, widget);
32
41
  const savedVisibleFilters = automationToEdit?.metadata?.visibleFilters ?? [];
33
- return getDefaultSelectedFiltersByVisibleFilters(savedVisibleFilters, availableWidgetFilters, savedFilterContextItems, commonDateFilterId);
42
+ return withStoredRestrictedFilters(getDefaultSelectedFiltersByVisibleFilters(savedVisibleFilters, availableWidgetFilters, savedFilterContextItems, commonDateFilterId), savedFilterContextItems, isFilterRestricted);
34
43
  }
35
44
  /**
36
45
  * Reconstructs default filters selection for the AutomationFiltersSelect component from existing widget automation.
@@ -87,7 +96,7 @@ function getDefaultSelectedFiltersByVisibleFilters(savedVisibleFilters, availabl
87
96
  *
88
97
  * @internal
89
98
  */
90
- export function getDefaultSelectedFiltersByTabForExistingAutomation(automationToEdit, availableDashboardFiltersByTab = {}, commonDateFilterId) {
99
+ export function getDefaultSelectedFiltersByTabForExistingAutomation(automationToEdit, availableDashboardFiltersByTab = {}, commonDateFilterId, isFilterRestricted = () => false) {
91
100
  if (!automationToEdit) {
92
101
  return undefined;
93
102
  }
@@ -98,10 +107,13 @@ export function getDefaultSelectedFiltersByTabForExistingAutomation(automationTo
98
107
  }
99
108
  // If we have visibleFiltersByTab, use it to properly reconstruct filters
100
109
  if (savedVisibleFiltersByTab) {
101
- return Object.entries(savedVisibleFiltersByTab).reduce((acc, [tabId, savedVisibleFilters]) => {
110
+ // A tab whose only stored filter was hidden has no visible-filter entries, so take the tab ids
111
+ // from both sides or that tab would be skipped entirely.
112
+ const tabIds = new Set([...Object.keys(savedVisibleFiltersByTab), ...Object.keys(savedFiltersByTab)]);
113
+ return [...tabIds].reduce((acc, tabId) => {
102
114
  const availableFiltersForTab = availableDashboardFiltersByTab[tabId] ?? [];
103
115
  const savedFiltersForTab = savedFiltersByTab[tabId] ?? [];
104
- const reconstructedFilters = getDefaultSelectedFiltersByVisibleFilters(savedVisibleFilters, availableFiltersForTab, savedFiltersForTab, commonDateFilterId);
116
+ const reconstructedFilters = withStoredRestrictedFilters(getDefaultSelectedFiltersByVisibleFilters(savedVisibleFiltersByTab[tabId] ?? [], availableFiltersForTab, savedFiltersForTab, commonDateFilterId), savedFiltersForTab, isFilterRestricted);
105
117
  if (reconstructedFilters.length > 0) {
106
118
  acc[tabId] = reconstructedFilters;
107
119
  }
@@ -11,6 +11,10 @@ export interface IProcessedAutomationFiltersTab {
11
11
  tabTitle: string;
12
12
  /** Visible filters after applying hidden filter logic */
13
13
  visibleFilters: FilterContextItem[];
14
+ /** How many of the tab's selected filters the user is forbidden to access */
15
+ restrictedFilterCount: number;
16
+ /** Whether the add-filter dropdown has anything left to offer */
17
+ hasFiltersToAdd: boolean;
14
18
  /** Locked filters for this tab */
15
19
  lockedFilters: FilterContextItem[];
16
20
  /** Catalog attributes available for Add filter dropdown */
@@ -39,6 +43,9 @@ export declare const useAutomationFilters: ({ availableFilters, selectedFilters,
39
43
  commonDateFilterId: string | undefined;
40
44
  lockedFilters: FilterContextItem[];
41
45
  visibleFilters: FilterContextItem[];
46
+ restrictedFilterCount: number;
47
+ hasFiltersToAdd: boolean;
48
+ handleRemoveRestrictedFilters: () => void;
42
49
  attributes: ICatalogAttribute[];
43
50
  dateDatasets: ICatalogDateDataset[];
44
51
  measures: ICatalogMeasure[];
@@ -76,6 +83,7 @@ export declare const useAutomationFiltersByTab: ({ filtersByTab, editedFiltersBy
76
83
  handleTabFilterChange: (tabId: string, updatedFilter: FilterContextItem | undefined) => void;
77
84
  handleTabFilterDelete: (tabId: string, filterToDelete: FilterContextItem) => void;
78
85
  handleTabFilterAdd: (tabId: string, displayForm: ObjRef, attributes: ICatalogAttribute[], dateDatasets: ICatalogDateDataset[]) => void;
86
+ handleTabRestrictedFiltersRemove: (tabId: string) => void;
79
87
  handleStoreFiltersChange: (value: boolean) => void;
80
88
  makeFilterGroupUnfocusable: () => void;
81
89
  setAddFilterButtonRefs: (element: HTMLButtonElement | HTMLDivElement | null, dropdownButtonRef?: MutableRefObject<HTMLElement>) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useAutomationFilters.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/automationFilters/useAutomationFilters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,gBAAgB,EAA0C,MAAM,OAAO,CAAC;AAItF,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,+BAA+B,EACpC,KAAK,8BAA8B,EAEnC,KAAK,MAAM,EACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAiFxF;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC3C,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,kCAAkC;IAClC,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,2DAA2D;IAC3D,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,8DAA8D;IAC9D,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,sFAAsF;IACtF,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,4DAA4D;IAC5D,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;IACxC,4CAA4C;IAC5C,gBAAgB,EAAE,+BAA+B,EAAE,CAAC;IACpD,uCAAuC;IACvC,WAAW,EAAE,8BAA8B,EAAE,CAAC;CACjD;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,sGAM9B;IACC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IACxD,oBAAoB,EAAE,CAClB,WAAW,EAAE,OAAO,EACpB,OAAO,EAAE,iBAAiB,EAAE,EAC5B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,KACjD,IAAI,CAAC;CACb;;;;;;;;;;;;;iCAuGgB,iBAAiB,GAAG,SAAS;iCAoB7B,iBAAiB;sCAkBT,MAAM,cAAc,iBAAiB,EAAE,gBAAgB,mBAAmB,EAAE;sCA8BrF,OAAO;sCASF,iBAAiB,GAAG,cAAc,GAAG,IAAI,sBAC9B,gBAAgB,CAAC,WAAW,CAAC;CA6B5D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,0GAMnC;IACC,YAAY,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;IAClD,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACzD,oBAAoB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,KAAK,IAAI,CAAC;IACnF,oBAAoB,EAAE,CAClB,WAAW,EAAE,OAAO,EACpB,OAAO,CAAC,EAAE,iBAAiB,EAAE,EAC7B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,KACjD,IAAI,CAAC;IACV,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;;;;;;;;mCAsFe,MAAM,iBAAiB,iBAAiB,GAAG,SAAS;mCAsBpD,MAAM,kBAAkB,iBAAiB;gCAkBtC,MAAM,eACA,MAAM,cACP,iBAAiB,EAAE,gBACjB,mBAAmB,EAAE;sCA8B/B,OAAO;;sCAgBF,iBAAiB,GAAG,cAAc,GAAG,IAAI,sBAC9B,gBAAgB,CAAC,WAAW,CAAC;CAuC5D,CAAC"}
1
+ {"version":3,"file":"useAutomationFilters.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/automationFilters/useAutomationFilters.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,21 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
2
  import { useCallback, useMemo, useRef, useState } from "react";
3
+ import { partition } from "lodash-es";
3
4
  import { useIntl } from "react-intl";
4
5
  import { useAutomationsContext } from "../../contexts/AutomationsContext.js";
5
6
  import { applyFilterChange, getCatalogAttributesByFilters, getCatalogDateDatasetsByFilters, getCatalogMeasuresByFilters, getFilterTitle, getNonHiddenFilters, getNonSelectedFilters, removeFilterFrom, resolveFilterToAdd, resolveTabFilterToAdd, } from "./utils.js";
6
7
  /**
7
- * Computes visible filters by removing hidden filters.
8
+ * Computes the filters the bar renders: restricted ones split off to be reported as a count, hidden
9
+ * ones removed from the rest. Restricted filters stay in the selection, so they are still saved.
10
+ *
11
+ * @remarks
12
+ * Restricted filters are taken out before the hidden check, so one the author hid after the automation
13
+ * stored it is still counted and removable rather than kept invisibly.
8
14
  */
9
15
  function computeVisibleFilters(selectedFilters, context) {
10
- return getNonHiddenFilters(selectedFilters, context.attributeConfigs, context.dateConfigs, context.isCommonDateFilterHidden, context.disableDateFilters);
16
+ const [restrictedFilters, readableFilters] = partition(selectedFilters, context.isFilterRestricted);
17
+ const visibleFilters = getNonHiddenFilters(readableFilters, context.attributeConfigs, context.dateConfigs, context.isCommonDateFilterHidden, context.disableDateFilters);
18
+ return { visibleFilters, restrictedFilters };
11
19
  }
12
20
  /**
13
21
  * Computes catalog attributes available for the Add filter dropdown.
@@ -32,7 +40,7 @@ function computeAddDropdownMeasures(nonSelectedFilters, context) {
32
40
  */
33
41
  export const useAutomationFilters = ({ availableFilters, selectedFilters, onFiltersChange, onStoreFiltersChange, disableDateFilters = false, }) => {
34
42
  const intl = useIntl();
35
- const { catalogAttributes: allAttributes, catalogDateDatasets: allDateDatasets, catalogMeasures: allMeasures, attributeFilterConfigs: attributeConfigs, dateFilterConfigs: dateConfigs, measureValueFilterConfigs: mvfConfigs, dateFilterContextConfig: dateFilterConfig, commonDateFilterId, lockedFilters, } = useAutomationsContext();
43
+ const { catalogAttributes: allAttributes, catalogDateDatasets: allDateDatasets, catalogMeasures: allMeasures, attributeFilterConfigs: attributeConfigs, dateFilterConfigs: dateConfigs, measureValueFilterConfigs: mvfConfigs, dateFilterContextConfig: dateFilterConfig, commonDateFilterId, lockedFilters, isFilterRestricted, } = useAutomationsContext();
36
44
  const [filterAnnouncement, setFilterAnnouncement] = useState("");
37
45
  const addFilterButtonRef = useRef(null);
38
46
  const filterGroupRef = useRef(null);
@@ -47,6 +55,7 @@ export const useAutomationFilters = ({ availableFilters, selectedFilters, onFilt
47
55
  mvfConfigs,
48
56
  isCommonDateFilterHidden,
49
57
  disableDateFilters,
58
+ isFilterRestricted,
50
59
  }), [
51
60
  allAttributes,
52
61
  allDateDatasets,
@@ -56,9 +65,12 @@ export const useAutomationFilters = ({ availableFilters, selectedFilters, onFilt
56
65
  mvfConfigs,
57
66
  isCommonDateFilterHidden,
58
67
  disableDateFilters,
68
+ isFilterRestricted,
59
69
  ]);
60
- const visibleFilters = useMemo(() => computeVisibleFilters(selectedFilters, processingContext), [selectedFilters, processingContext]);
61
- const nonSelectedFilters = useMemo(() => getNonSelectedFilters(availableFilters, selectedFilters), [availableFilters, selectedFilters]);
70
+ const { visibleFilters, restrictedFilters } = useMemo(() => computeVisibleFilters(selectedFilters, processingContext), [selectedFilters, processingContext]);
71
+ // Dropped once here, so no consumer has to remember to exclude a restricted filter.
72
+ const selectableFilters = useMemo(() => availableFilters.filter((filter) => !isFilterRestricted(filter)), [availableFilters, isFilterRestricted]);
73
+ const nonSelectedFilters = useMemo(() => getNonSelectedFilters(selectableFilters, selectedFilters), [selectableFilters, selectedFilters]);
62
74
  const attributes = useMemo(() => computeAddDropdownAttributes(nonSelectedFilters, processingContext), [nonSelectedFilters, processingContext]);
63
75
  const dateDatasets = useMemo(() => computeAddDropdownDateDatasets(nonSelectedFilters, processingContext), [nonSelectedFilters, processingContext]);
64
76
  const measures = useMemo(() => computeAddDropdownMeasures(nonSelectedFilters, processingContext), [nonSelectedFilters, processingContext]);
@@ -133,6 +145,20 @@ export const useAutomationFilters = ({ availableFilters, selectedFilters, onFilt
133
145
  intl,
134
146
  focusAddFilterButton,
135
147
  ]);
148
+ const handleRemoveRestrictedFilters = useCallback(() => {
149
+ const message = intl.formatMessage({ id: "automationFilters.announcement.restrictedFiltersRemoved" }, { count: restrictedFilters.length });
150
+ announceFiltersChanged(message);
151
+ onFiltersChange(selectedFilters.filter((filter) => !isFilterRestricted(filter)));
152
+ focusFilterGroup();
153
+ }, [
154
+ onFiltersChange,
155
+ focusFilterGroup,
156
+ announceFiltersChanged,
157
+ selectedFilters,
158
+ restrictedFilters,
159
+ isFilterRestricted,
160
+ intl,
161
+ ]);
136
162
  const handleStoreFiltersChange = useCallback((value) => {
137
163
  onStoreFiltersChange(value, selectedFilters, undefined);
138
164
  }, [onStoreFiltersChange, selectedFilters]);
@@ -147,6 +173,9 @@ export const useAutomationFilters = ({ availableFilters, selectedFilters, onFilt
147
173
  commonDateFilterId,
148
174
  lockedFilters,
149
175
  visibleFilters,
176
+ restrictedFilterCount: restrictedFilters.length,
177
+ hasFiltersToAdd: nonSelectedFilters.length > 0,
178
+ handleRemoveRestrictedFilters,
150
179
  attributes,
151
180
  dateDatasets,
152
181
  measures,
@@ -169,7 +198,7 @@ export const useAutomationFilters = ({ availableFilters, selectedFilters, onFilt
169
198
  * Returns processed filters and handlers for add/change/delete operations per tab.
170
199
  */
171
200
  export const useAutomationFiltersByTab = ({ filtersByTab, editedFiltersByTab, onFiltersByTabChange, onStoreFiltersChange, disableDateFilters = false, }) => {
172
- const { catalogAttributes: allAttributes, catalogDateDatasets: allDateDatasets, catalogMeasures: allMeasures, commonDateFilterId, attributeFilterConfigsByTab: attributeConfigsByTab, dateFilterConfigsByTab: dateConfigsByTab, dateFilterConfigOverridesByTab: dateFilterConfigByTab, measureValueFilterConfigsByTab: mvfConfigsByTab, } = useAutomationsContext();
201
+ const { catalogAttributes: allAttributes, catalogDateDatasets: allDateDatasets, catalogMeasures: allMeasures, commonDateFilterId, attributeFilterConfigsByTab: attributeConfigsByTab, dateFilterConfigsByTab: dateConfigsByTab, dateFilterConfigOverridesByTab: dateFilterConfigByTab, measureValueFilterConfigsByTab: mvfConfigsByTab, isFilterRestricted, } = useAutomationsContext();
173
202
  const [filterAnnouncement] = useState("");
174
203
  const addFilterButtonRef = useRef(null);
175
204
  const filterGroupRef = useRef(null);
@@ -195,14 +224,14 @@ export const useAutomationFiltersByTab = ({ filtersByTab, editedFiltersByTab, on
195
224
  mvfConfigs,
196
225
  isCommonDateFilterHidden,
197
226
  disableDateFilters,
227
+ isFilterRestricted,
198
228
  };
199
229
  // Use edited filters if available, otherwise default selected filters
200
230
  const selectedFilters = editedFiltersByTab?.[tabId] ?? tab.defaultSelectedFilters;
201
- const availableFilters = tab.availableFilters;
202
231
  // Apply visible filter logic (removes hidden filters based on config)
203
- const visibleFilters = computeVisibleFilters(selectedFilters, processingContext);
232
+ const { visibleFilters, restrictedFilters } = computeVisibleFilters(selectedFilters, processingContext);
204
233
  // Compute non-selected filters for Add dropdown
205
- const nonSelectedFilters = getNonSelectedFilters(availableFilters, selectedFilters);
234
+ const nonSelectedFilters = getNonSelectedFilters(tab.selectableFilters, selectedFilters);
206
235
  // Compute catalog items for Add dropdown
207
236
  const attributes = computeAddDropdownAttributes(nonSelectedFilters, processingContext);
208
237
  const dateDatasets = computeAddDropdownDateDatasets(nonSelectedFilters, processingContext);
@@ -211,6 +240,8 @@ export const useAutomationFiltersByTab = ({ filtersByTab, editedFiltersByTab, on
211
240
  tabId: tab.tabId,
212
241
  tabTitle: tab.tabTitle,
213
242
  visibleFilters,
243
+ restrictedFilterCount: restrictedFilters.length,
244
+ hasFiltersToAdd: nonSelectedFilters.length > 0,
214
245
  lockedFilters: tab.lockedFilters,
215
246
  attributes,
216
247
  dateDatasets,
@@ -231,6 +262,7 @@ export const useAutomationFiltersByTab = ({ filtersByTab, editedFiltersByTab, on
231
262
  dateFilterConfigByTab,
232
263
  mvfConfigsByTab,
233
264
  disableDateFilters,
265
+ isFilterRestricted,
234
266
  ]);
235
267
  // Handlers for per-tab filter operations (similar to original hook)
236
268
  const handleTabFilterChange = useCallback((tabId, updatedFilter) => {
@@ -267,7 +299,9 @@ export const useAutomationFiltersByTab = ({ filtersByTab, editedFiltersByTab, on
267
299
  if (!tabData) {
268
300
  return;
269
301
  }
270
- const availableFilter = resolveTabFilterToAdd(displayForm, tabData.availableFilters, attributes, dateDatasets);
302
+ // Resolves by ObjRef, which is coarser than the local identifier used elsewhere: one
303
+ // catalog attribute can back several filters, so a restricted one must not be a candidate.
304
+ const availableFilter = resolveTabFilterToAdd(displayForm, tabData.selectableFilters, attributes, dateDatasets);
271
305
  if (availableFilter) {
272
306
  onFiltersByTabChange({
273
307
  ...editedFiltersByTab,
@@ -275,6 +309,15 @@ export const useAutomationFiltersByTab = ({ filtersByTab, editedFiltersByTab, on
275
309
  });
276
310
  }
277
311
  }, [editedFiltersByTab, onFiltersByTabChange, filtersByTab]);
312
+ const handleTabRestrictedFiltersRemove = useCallback((tabId) => {
313
+ if (!editedFiltersByTab || !onFiltersByTabChange) {
314
+ return;
315
+ }
316
+ onFiltersByTabChange({
317
+ ...editedFiltersByTab,
318
+ [tabId]: (editedFiltersByTab[tabId] ?? []).filter((filter) => !isFilterRestricted(filter)),
319
+ });
320
+ }, [editedFiltersByTab, onFiltersByTabChange, isFilterRestricted]);
278
321
  const handleStoreFiltersChange = useCallback((value) => {
279
322
  onStoreFiltersChange(value, undefined, editedFiltersByTab);
280
323
  }, [editedFiltersByTab, onStoreFiltersChange]);
@@ -314,6 +357,7 @@ export const useAutomationFiltersByTab = ({ filtersByTab, editedFiltersByTab, on
314
357
  handleTabFilterChange,
315
358
  handleTabFilterDelete,
316
359
  handleTabFilterAdd,
360
+ handleTabRestrictedFiltersRemove,
317
361
  handleStoreFiltersChange,
318
362
  makeFilterGroupUnfocusable,
319
363
  setAddFilterButtonRefs,
@@ -1 +1 @@
1
- {"version":3,"file":"useAutomationFiltersSelect.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAEhC,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AActF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;AAErE;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IACxC,uBAAuB,EAAE,iBAAiB,EAAE,CAAC;IAC7C,0BAA0B,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IACnE,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,gBAAgB,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IAClD,gCAAgC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IACzE,uBAAuB,EAAE,iBAAiB,EAAE,CAAC;IAC7C;;;;;OAKG;IACH,YAAY,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;IAClD;;;;OAIG;IACH,4BAA4B,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC7D;;OAEG;IACH,+BAA+B,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAEvE,qCAAqC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,GAAG,SAAS,CAAC;CACjG;AAiFD;;GAEG;AACH,eAAO,MAAM,0BAA0B,kCAGpC;IACC;;OAEG;IACH,MAAM,CAAC,EAAE,uBAAuB,CAAC;IAEjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;CAChD,KAAG,2BA8GH,CAAC;AAEF,wBAAgB,yCAAyC,CAAC,YAAY,EAAE,qBAAqB,EAAE,GAAG,SAAS,kCAQ1G;AAED,wBAAgB,mCAAmC,CAAC,YAAY,EAAE,qBAAqB,EAAE,GAAG,SAAS,uCAQpG"}
1
+ {"version":3,"file":"useAutomationFiltersSelect.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAEhC,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AActF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;AAErE;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IACxC,uBAAuB,EAAE,iBAAiB,EAAE,CAAC;IAC7C,0BAA0B,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IACnE,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,gBAAgB,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IAClD,gCAAgC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IACzE,uBAAuB,EAAE,iBAAiB,EAAE,CAAC;IAC7C;;;;;OAKG;IACH,YAAY,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;IAClD;;;;OAIG;IACH,4BAA4B,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC7D;;OAEG;IACH,+BAA+B,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAEvE,qCAAqC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,GAAG,SAAS,CAAC;CACjG;AAiFD;;GAEG;AACH,eAAO,MAAM,0BAA0B,kCAGpC;IACC;;OAEG;IACH,MAAM,CAAC,EAAE,uBAAuB,CAAC;IAEjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;CAChD,KAAG,2BAiHH,CAAC;AAEF,wBAAgB,yCAAyC,CAAC,YAAY,EAAE,qBAAqB,EAAE,GAAG,SAAS,kCAQ1G;AAED,wBAAgB,mCAAmC,CAAC,YAAY,EAAE,qBAAqB,EAAE,GAAG,SAAS,uCAQpG"}
@@ -68,7 +68,7 @@ function checkAreParametersStored(automationToEdit) {
68
68
  * Hook to get data for AutomationFiltersSelect component.
69
69
  */
70
70
  export const useAutomationFiltersSelect = ({ widget, automationToEdit, }) => {
71
- const { availableFilters, automationFiltersByTab: allFiltersByTab, commonDateFilterId, parameters: { enabled: parametersEnabled }, } = useAutomationsContext();
71
+ const { availableFilters, automationFiltersByTab: allFiltersByTab, commonDateFilterId, isFilterRestricted, parameters: { enabled: parametersEnabled }, } = useAutomationsContext();
72
72
  const availableFiltersWithoutIgnoredWidgetFilters = useMemo(() => removeIgnoredWidgetFilters(availableFilters, widget), [availableFilters, widget]);
73
73
  const availableFiltersAsVisibleFilters = useAutomationVisibleFilters(availableFiltersWithoutIgnoredWidgetFilters);
74
74
  const filtersForNewAutomation = useDefaultSelectedFiltersForNewAutomation(widget);
@@ -99,7 +99,7 @@ export const useAutomationFiltersSelect = ({ widget, automationToEdit, }) => {
99
99
  if (!filtersByTab || !automationToEdit || isDashboardAutomationWithoutStoredFilters) {
100
100
  return undefined;
101
101
  }
102
- const filtersByTabForExistingAutomation = getDefaultSelectedFiltersByTabForExistingAutomation(automationToEdit, availableFiltersByTab, commonDateFilterId);
102
+ const filtersByTabForExistingAutomation = getDefaultSelectedFiltersByTabForExistingAutomation(automationToEdit, availableFiltersByTab, commonDateFilterId, isFilterRestricted);
103
103
  if (filtersByTabForExistingAutomation) {
104
104
  return filtersByTabForExistingAutomation;
105
105
  }
@@ -110,6 +110,7 @@ export const useAutomationFiltersSelect = ({ widget, automationToEdit, }) => {
110
110
  isDashboardAutomationWithoutStoredFilters,
111
111
  commonDateFilterId,
112
112
  availableFiltersByTab,
113
+ isFilterRestricted,
113
114
  ]);
114
115
  // State for edited filters per tab (only used when dashboard tabs are enabled)
115
116
  const [editedAutomationFiltersByTab, setEditedAutomationFiltersByTab] = useState(automationToEdit && !isDashboardAutomationWithoutStoredFilters