@gooddata/sdk-ui-dashboard 11.50.0-alpha.1 → 11.50.0-alpha.3

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 (48) hide show
  1. package/NOTICE +216 -203
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/_staging/dateFilterConfig/dateFilterConfigConverters.d.ts +1 -9
  5. package/esm/_staging/dateFilterConfig/dateFilterConfigConverters.d.ts.map +1 -1
  6. package/esm/_staging/dateFilterConfig/dateFilterConfigConverters.js +3 -88
  7. package/esm/_staging/dateFilterConfig/dateFilterOptionMapping.d.ts +1 -33
  8. package/esm/_staging/dateFilterConfig/dateFilterOptionMapping.d.ts.map +1 -1
  9. package/esm/_staging/dateFilterConfig/dateFilterOptionMapping.js +3 -260
  10. package/esm/_staging/dateFilterConfig/defaultConfig.d.ts +1 -11
  11. package/esm/_staging/dateFilterConfig/defaultConfig.d.ts.map +1 -1
  12. package/esm/_staging/dateFilterConfig/defaultConfig.js +3 -436
  13. package/esm/model/store/config/configSelectors.d.ts.map +1 -1
  14. package/esm/model/store/config/configSelectors.js +2 -9
  15. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts +4 -4
  16. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts.map +1 -1
  17. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.js +50 -359
  18. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.d.ts +38 -0
  19. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.d.ts.map +1 -0
  20. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.js +61 -0
  21. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.d.ts +35 -0
  22. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.d.ts.map +1 -0
  23. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.js +195 -0
  24. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.d.ts +55 -0
  25. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.d.ts.map +1 -0
  26. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.js +203 -0
  27. package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.d.ts +1 -9
  28. package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.d.ts.map +1 -1
  29. package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.js +3 -88
  30. package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.d.ts +1 -33
  31. package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.d.ts.map +1 -1
  32. package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.js +3 -260
  33. package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.d.ts +1 -11
  34. package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.d.ts.map +1 -1
  35. package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.js +3 -436
  36. package/esm/presentation/dashboardList/DashboardList.d.ts.map +1 -1
  37. package/esm/presentation/dashboardList/DashboardList.js +6 -0
  38. package/esm/presentation/filterBar/filterBar/DefaultFilterBarContainer.d.ts.map +1 -1
  39. package/esm/presentation/filterBar/filterBar/DefaultFilterBarContainer.js +11 -5
  40. package/esm/presentation/widget/common/InsightDropdown.d.ts.map +1 -1
  41. package/esm/presentation/widget/common/InsightDropdown.js +14 -0
  42. package/esm/presentation/widget/common/configuration/ConfigurationBubble.d.ts.map +1 -1
  43. package/esm/presentation/widget/common/configuration/ConfigurationBubble.js +2 -0
  44. package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/DashboardInsightMenuBubble.d.ts.map +1 -1
  45. package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/DashboardInsightMenuBubble.js +1 -1
  46. package/esm/tsdoc-metadata.json +1 -1
  47. package/package.json +21 -21
  48. package/styles/css/main.css +1 -1
@@ -1,96 +1,51 @@
1
1
  // (C) 2019-2026 GoodData Corporation
2
- import { useCallback, useMemo, useRef, useState } from "react";
3
- import { DEFAULT_CSV_DELIMITER, isExportDefinitionDashboardRequestPayload, isExportDefinitionVisualizationObjectRequestPayload, isInsightWidget, } from "@gooddata/sdk-model";
2
+ import { useCallback, useRef } from "react";
3
+ import { DEFAULT_CSV_DELIMITER, } from "@gooddata/sdk-model";
4
4
  import { getAutomationExportParametersByTab, setExportParametersByTab, } from "../../../../../_staging/automation/index.js";
5
5
  import { useAutomationsContext } from "../../../contexts/AutomationsContext.js";
6
6
  import { useScheduledEmailDialogContext } from "../../../contexts/ScheduledEmailDialogContext.js";
7
- import { shouldStoreExportParameters } from "../../../shared/automationFilters/automationParameters.js";
8
- import { getDefaultSelectedFiltersFromFiltersByTab } from "../../../shared/automationFilters/useAutomationFiltersSelect.js";
9
- import { getAppliedDashboardFilters, getAppliedWidgetFilters, getVisibleFiltersByFilters, getVisibleFiltersByFiltersByTab, } from "../../../shared/automationFilters/utils.js";
10
- import { convertCurrentUserToAutomationRecipient, convertCurrentUserToWorkspaceUser, convertExternalRecipientToAutomationRecipient, } from "../../../shared/utils/automationUtils.js";
11
- import { toModifiedISOStringToTimezone, toNormalizedFirstRunAndCron, toNormalizedStartDate, } from "../../utils/date.js";
12
- import { getUserTimezone } from "../../utils/timezone.js";
13
- import { newDashboardExportDefinitionMetadataObjectDefinition, newWidgetExportDefinitionMetadataObjectDefinition, } from "../utils/exportDefinitions.js";
7
+ import { toNormalizedStartDate } from "../../utils/date.js";
8
+ import { useScheduledEmailEffectiveFilters } from "./useScheduledEmailEffectiveFilters.js";
14
9
  import { useScheduledEmailExportSettings } from "./useScheduledEmailExportSettings.js";
10
+ import { useScheduledEmailFilters } from "./useScheduledEmailFilters.js";
11
+ import { useScheduledEmailFormState } from "./useScheduledEmailFormState.js";
15
12
  import { useScheduledEmailFormValidity } from "./useScheduledEmailFormValidity.js";
16
13
  export function useEditScheduledEmail({ scheduledExportToEdit, notificationChannels, insight, widget, users, editedAutomationFilters, dashboardFilters, editedAutomationFiltersByTab, maxAutomationsRecipients, setEditedAutomationFilters, setEditedAutomationFiltersByTab, availableFiltersAsVisibleFilters, storeFilters, setStoreFilters, filtersForNewAutomation, externalRecipientOverride, defaultPdfPageSize, filtersDataByTab, availableFiltersAsVisibleFiltersByTab, }) {
17
- const { settings, timezone, currentUser, features: { enableAutomationEvaluationMode }, } = useAutomationsContext();
18
- const { dashboardId, dashboardTitle, hiddenFilters: dashboardHiddenFilters, commonDateFilterId, widgetLocalIdToTabIdMap: widgetTabMap, exportParametersByTab: effectiveExportParametersByTab, } = useScheduledEmailDialogContext();
19
- const [isCronValid, setIsCronValid] = useState(true);
20
- const [isTitleValid, setIsTitleValid] = useState(true);
21
- const [isSubjectValid, setIsSubjectValid] = useState(true);
22
- const [isOnMessageValid, setIsOnMessageValid] = useState(true);
23
- const isWidget = !!widget && !!insight;
14
+ const { settings, features: { enableAutomationEvaluationMode }, } = useAutomationsContext();
15
+ const { dashboardId, dashboardTitle, widgetLocalIdToTabIdMap: widgetTabMap, } = useScheduledEmailDialogContext();
24
16
  // Dashboard
25
17
  const resolvedDefaultCsvDelimiter = settings?.exportCsvCustomDelimiter ?? DEFAULT_CSV_DELIMITER;
26
18
  const areDashboardFiltersChanged = !!dashboardFilters;
27
- const defaultUser = convertCurrentUserToWorkspaceUser(users ?? [], currentUser);
28
- const defaultRecipient = externalRecipientOverride
29
- ? convertExternalRecipientToAutomationRecipient(externalRecipientOverride)
30
- : convertCurrentUserToAutomationRecipient(users ?? [], currentUser);
31
- const firstChannel = notificationChannels[0]?.id;
32
19
  // Determine target tab ID if widget is present
33
20
  const targetTabId = widget?.localIdentifier ? widgetTabMap[widget.localIdentifier] : undefined;
34
- const effectiveWidgetFilters = getAppliedWidgetFilters(editedAutomationFilters ?? [], dashboardHiddenFilters, widget, insight, commonDateFilterId, false);
35
- const effectiveWidgetFiltersWithInsight = getAppliedWidgetFilters(editedAutomationFilters ?? [], dashboardHiddenFilters, widget, insight, commonDateFilterId, true);
36
- const effectiveVisibleWidgetFilters = getVisibleFiltersByFilters(editedAutomationFilters, availableFiltersAsVisibleFilters, true);
37
- const effectiveDashboardFilters = getAppliedDashboardFilters(editedAutomationFilters ?? [], dashboardHiddenFilters, isWidget ? true : storeFilters);
38
- // Process filters per tab if provided (for dashboard automations with tabs enabled)
39
- const effectiveDashboardFiltersByTab = useMemo(() => {
40
- if (!editedAutomationFiltersByTab || !storeFilters) {
41
- return undefined;
42
- }
43
- // Apply the same processing as effectiveDashboardFilters to each tab's filters
44
- return Object.entries(editedAutomationFiltersByTab).reduce((acc, [tabId, filters]) => {
45
- const tabHiddenFilters = filtersDataByTab?.find((tab) => tab.tabId === tabId)?.hiddenFilters ?? [];
46
- const appliedFilters = getAppliedDashboardFilters(filters ?? [], tabHiddenFilters, storeFilters);
47
- // Only add if we got filters back (storeFilters is true)
48
- if (appliedFilters) {
49
- acc[tabId] = appliedFilters;
50
- }
51
- return acc;
52
- }, {});
53
- }, [editedAutomationFiltersByTab, filtersDataByTab, storeFilters]);
54
- const effectiveVisibleDashboardFilters = getVisibleFiltersByFilters(editedAutomationFilters ?? [], availableFiltersAsVisibleFilters, storeFilters);
55
- const effectiveVisibleDashboardFiltersByTab = getVisibleFiltersByFiltersByTab(editedAutomationFiltersByTab, availableFiltersAsVisibleFiltersByTab, storeFilters);
56
- // Mirrors the filters seed above, for parameters.
57
- const parametersByTabForNewAutomation = shouldStoreExportParameters(isWidget, storeFilters) &&
58
- Object.keys(effectiveExportParametersByTab).length > 0
59
- ? effectiveExportParametersByTab
60
- : undefined;
61
- const [editedAutomation, setEditedAutomation] = useState(scheduledExportToEdit ??
62
- newAutomationMetadataObjectDefinition(isWidget
63
- ? {
64
- timezone,
65
- dashboardId: dashboardId,
66
- notificationChannel: firstChannel,
67
- insight,
68
- widget,
69
- recipient: defaultRecipient,
70
- widgetFilters: effectiveWidgetFilters,
71
- widgetFiltersWithInsight: effectiveWidgetFiltersWithInsight,
72
- dashboardFilters: effectiveDashboardFilters,
73
- visibleFiltersMetadata: effectiveVisibleWidgetFilters,
74
- defaultPdfPageSize,
75
- evaluationMode: "PER_RECIPIENT",
76
- targetTabId,
77
- parametersByTab: parametersByTabForNewAutomation,
78
- }
79
- : {
80
- timezone,
81
- dashboardId: dashboardId,
82
- notificationChannel: firstChannel,
83
- title: dashboardTitle,
84
- recipient: defaultRecipient,
85
- dashboardFilters: effectiveDashboardFilters,
86
- filtersByTab: effectiveDashboardFiltersByTab,
87
- visibleFiltersMetadata: effectiveVisibleDashboardFilters,
88
- visibleFiltersByTab: effectiveVisibleDashboardFiltersByTab,
89
- defaultPdfPageSize,
90
- evaluationMode: "PER_RECIPIENT",
91
- parametersByTab: parametersByTabForNewAutomation,
92
- }));
93
- const [originalAutomation] = useState(editedAutomation);
21
+ const { effectiveWidgetFilters, effectiveWidgetFiltersWithInsight, effectiveVisibleWidgetFilters, effectiveDashboardFilters, effectiveDashboardFiltersByTab, effectiveVisibleDashboardFilters, effectiveVisibleDashboardFiltersByTab, parametersByTabForNewAutomation, } = useScheduledEmailEffectiveFilters({
22
+ widget,
23
+ insight,
24
+ editedAutomationFilters,
25
+ editedAutomationFiltersByTab,
26
+ availableFiltersAsVisibleFilters,
27
+ availableFiltersAsVisibleFiltersByTab,
28
+ filtersDataByTab,
29
+ storeFilters,
30
+ });
31
+ const { editedAutomation, setEditedAutomation, originalAutomation, defaultRecipient, defaultUser, onTitleChange, onRecurrenceChange, onEvaluationModeChange, onDestinationChange, onRecipientsChange, onSubjectChange, onMessageChange, isCronValid, isTitleValid, isSubjectValid, isOnMessageValid, } = useScheduledEmailFormState({
32
+ scheduledExportToEdit,
33
+ widget,
34
+ insight,
35
+ notificationChannels,
36
+ users,
37
+ externalRecipientOverride,
38
+ effectiveWidgetFilters,
39
+ effectiveWidgetFiltersWithInsight,
40
+ effectiveVisibleWidgetFilters,
41
+ effectiveDashboardFilters,
42
+ effectiveDashboardFiltersByTab,
43
+ effectiveVisibleDashboardFilters,
44
+ effectiveVisibleDashboardFiltersByTab,
45
+ parametersByTabForNewAutomation,
46
+ defaultPdfPageSize,
47
+ targetTabId,
48
+ });
94
49
  // Holds the wire outside the automation so it survives a rebuild from zero export definitions —
95
50
  // with no definitions `setExportParametersByTab` has nowhere to store it.
96
51
  // Seeded from the stored wire.
@@ -101,224 +56,7 @@ export function useEditScheduledEmail({ scheduledExportToEdit, notificationChann
101
56
  const setParametersWire = useCallback((wire) => {
102
57
  latestParametersWireRef.current = wire;
103
58
  setEditedAutomation((automation) => setExportParametersByTab(automation, wire));
104
- }, []);
105
- const onTitleChange = (value, isValid) => {
106
- setIsTitleValid(isValid);
107
- setEditedAutomation((s) => ({ ...s, title: value }));
108
- };
109
- const onRecurrenceChange = (cronExpression, startDate, isValid) => {
110
- setIsCronValid(isValid);
111
- setEditedAutomation((s) => ({
112
- ...s,
113
- schedule: {
114
- ...s.schedule,
115
- cron: cronExpression,
116
- firstRun: toModifiedISOStringToTimezone(startDate ?? new Date(), timezone).iso,
117
- },
118
- }));
119
- };
120
- const onEvaluationModeChange = (isShared) => {
121
- setEditedAutomation((s) => ({
122
- ...s,
123
- evaluationMode: isShared ? "SHARED" : "PER_RECIPIENT",
124
- }));
125
- };
126
- const onDestinationChange = (notificationChannelId) => {
127
- setEditedAutomation((s) => ({
128
- ...s,
129
- notificationChannel: notificationChannelId,
130
- }));
131
- };
132
- const onRecipientsChange = (updatedRecipients) => {
133
- setEditedAutomation((s) => ({
134
- ...s,
135
- recipients: updatedRecipients,
136
- }));
137
- };
138
- const onSubjectChange = (value, isValid) => {
139
- setIsSubjectValid(isValid);
140
- setEditedAutomation((s) => ({
141
- ...s,
142
- details: {
143
- ...s.details,
144
- subject: value,
145
- },
146
- }));
147
- };
148
- const onMessageChange = (value, isValid) => {
149
- setIsOnMessageValid(isValid);
150
- setEditedAutomation((s) => ({
151
- ...s,
152
- details: {
153
- ...s.details,
154
- message: value,
155
- },
156
- }));
157
- };
158
- const onFiltersChange = useCallback((filters, storeFiltersParam) => {
159
- setEditedAutomationFilters(filters);
160
- const shouldStoreFilters = storeFiltersParam ?? storeFilters;
161
- if (isWidget) {
162
- if (!isInsightWidget(widget)) {
163
- return;
164
- }
165
- setEditedAutomation((s) => {
166
- const appliedDashboardFilters = getAppliedDashboardFilters(filters, dashboardHiddenFilters, true);
167
- const appliedWidgetFiltersWithInsight = getAppliedWidgetFilters(filters, dashboardHiddenFilters, widget, insight, commonDateFilterId, true);
168
- const appliedWidgetFiltersWithoutInsight = getAppliedWidgetFilters(filters, dashboardHiddenFilters, widget, insight, commonDateFilterId, false);
169
- const visibleFilters = getVisibleFiltersByFilters(filters, availableFiltersAsVisibleFilters, true);
170
- return {
171
- ...s,
172
- exportDefinitions: s.exportDefinitions?.map((exportDefinition) => {
173
- if (isExportDefinitionVisualizationObjectRequestPayload(exportDefinition.requestPayload)) {
174
- const format = exportDefinition.requestPayload.format;
175
- const shouldUseWidgetFiltersWithInsight = format === "CSV";
176
- const shouldUseWidgetFiltersWithoutInsight = format === "CSV_RAW";
177
- const appliedFilters = shouldUseWidgetFiltersWithInsight
178
- ? appliedWidgetFiltersWithInsight
179
- : shouldUseWidgetFiltersWithoutInsight
180
- ? appliedWidgetFiltersWithoutInsight
181
- : appliedDashboardFilters;
182
- return {
183
- ...exportDefinition,
184
- requestPayload: {
185
- ...exportDefinition.requestPayload,
186
- content: {
187
- ...exportDefinition.requestPayload.content,
188
- filters: appliedFilters,
189
- },
190
- },
191
- };
192
- }
193
- else {
194
- return exportDefinition;
195
- }
196
- }),
197
- metadata: {
198
- ...s.metadata,
199
- visibleFilters,
200
- },
201
- };
202
- });
203
- }
204
- else {
205
- setEditedAutomation((s) => {
206
- const appliedFilters = getAppliedDashboardFilters(filters, dashboardHiddenFilters, shouldStoreFilters);
207
- const visibleFilters = getVisibleFiltersByFilters(filters, availableFiltersAsVisibleFilters, shouldStoreFilters);
208
- return {
209
- ...s,
210
- exportDefinitions: s.exportDefinitions?.map((exportDefinition) => {
211
- if (isExportDefinitionDashboardRequestPayload(exportDefinition.requestPayload)) {
212
- return {
213
- ...exportDefinition,
214
- requestPayload: {
215
- ...exportDefinition.requestPayload,
216
- content: {
217
- ...exportDefinition.requestPayload.content,
218
- filters: appliedFilters,
219
- },
220
- },
221
- };
222
- }
223
- else {
224
- return exportDefinition;
225
- }
226
- }),
227
- metadata: {
228
- ...s.metadata,
229
- visibleFilters,
230
- },
231
- };
232
- });
233
- }
234
- }, [
235
- setEditedAutomationFilters,
236
- setEditedAutomation,
237
- dashboardHiddenFilters,
238
- availableFiltersAsVisibleFilters,
239
- storeFilters,
240
- widget,
241
- insight,
242
- isWidget,
243
- commonDateFilterId,
244
- ]);
245
- // Callback for per-tab filter changes - updates state AND syncs to export definitions
246
- const onFiltersByTabChange = useCallback((newFiltersByTab, storeFiltersParam) => {
247
- // Update the editedFiltersByTab state
248
- setEditedAutomationFiltersByTab?.(newFiltersByTab);
249
- const shouldStoreFilters = storeFiltersParam ?? storeFilters;
250
- const newEffectiveFiltersByTab = shouldStoreFilters
251
- ? Object.entries(newFiltersByTab).reduce((acc, [tabId, filters]) => {
252
- const tabHiddenFilters = filtersDataByTab?.find((tab) => tab.tabId === tabId)?.hiddenFilters ?? [];
253
- const appliedFilters = getAppliedDashboardFilters(filters ?? [], tabHiddenFilters, true);
254
- if (appliedFilters) {
255
- acc[tabId] = appliedFilters;
256
- }
257
- return acc;
258
- }, {})
259
- : undefined;
260
- const newVisibleFiltersByTab = getVisibleFiltersByFiltersByTab(newFiltersByTab, availableFiltersAsVisibleFiltersByTab, shouldStoreFilters);
261
- // Sync to export definitions AND metadata
262
- setEditedAutomation((s) => ({
263
- ...s,
264
- exportDefinitions: s.exportDefinitions?.map((exportDefinition) => {
265
- if (isExportDefinitionDashboardRequestPayload(exportDefinition.requestPayload)) {
266
- return {
267
- ...exportDefinition,
268
- requestPayload: {
269
- ...exportDefinition.requestPayload,
270
- content: {
271
- ...exportDefinition.requestPayload.content,
272
- filtersByTab: newEffectiveFiltersByTab,
273
- },
274
- },
275
- };
276
- }
277
- return exportDefinition;
278
- }),
279
- metadata: {
280
- ...s.metadata,
281
- visibleFiltersByTab: newVisibleFiltersByTab,
282
- },
283
- }));
284
- }, [
285
- setEditedAutomationFiltersByTab,
286
- storeFilters,
287
- setEditedAutomation,
288
- availableFiltersAsVisibleFiltersByTab,
289
- filtersDataByTab,
290
- ]);
291
- const onApplyCurrentFilters = useCallback(() => {
292
- // Widget schedules should never use per-tab filters, only dashboard schedules can have tabs
293
- const filtersByTabForNewAutomation = widget
294
- ? undefined
295
- : getDefaultSelectedFiltersFromFiltersByTab(filtersDataByTab);
296
- if (filtersByTabForNewAutomation) {
297
- onFiltersByTabChange(filtersByTabForNewAutomation);
298
- }
299
- else {
300
- onFiltersChange(filtersForNewAutomation ?? [], widget ? true : storeFilters);
301
- }
302
- }, [
303
- filtersForNewAutomation,
304
- storeFilters,
305
- onFiltersChange,
306
- onFiltersByTabChange,
307
- widget,
308
- filtersDataByTab,
309
- ]);
310
- const onStoreFiltersChange = useCallback((value, filters, filtersByTabParam) => {
311
- setStoreFilters(value);
312
- // If filtersByTab is provided, use onFiltersByTabChange, otherwise use onFiltersChange
313
- if (filtersByTabParam) {
314
- // Trigger filtersByTab change which handles the sync
315
- onFiltersByTabChange(filtersByTabParam, value);
316
- }
317
- if (filters) {
318
- // Use regular filters change
319
- onFiltersChange(filters, value);
320
- }
321
- }, [onFiltersChange, onFiltersByTabChange, setStoreFilters]);
59
+ }, [setEditedAutomation]);
322
60
  const { selectedAttachments, isDashboardExportSelected, isCsvExportSelected, isXlsxExportSelected, xlsxSettings, pdfSettings, csvSettings, csvRawSettings, slidesTemplateIds, onDashboardAttachmentsChange, onWidgetAttachmentsChange, onXlsxSettingsChange, onPdfSettingsChange, onCsvSettingsChange, onCsvRawSettingsChange, onSlidesTemplateIdChange, } = useScheduledEmailExportSettings({
323
61
  editedAutomation,
324
62
  setEditedAutomation,
@@ -335,6 +73,19 @@ export function useEditScheduledEmail({ scheduledExportToEdit, notificationChann
335
73
  resolvedDefaultCsvDelimiter,
336
74
  latestParametersWireRef,
337
75
  });
76
+ const { onFiltersChange, onFiltersByTabChange, onApplyCurrentFilters, onStoreFiltersChange } = useScheduledEmailFilters({
77
+ setEditedAutomation,
78
+ widget,
79
+ insight,
80
+ setEditedAutomationFilters,
81
+ setEditedAutomationFiltersByTab,
82
+ availableFiltersAsVisibleFilters,
83
+ availableFiltersAsVisibleFiltersByTab,
84
+ filtersDataByTab,
85
+ storeFilters,
86
+ setStoreFilters,
87
+ filtersForNewAutomation,
88
+ });
338
89
  const startDate = toNormalizedStartDate(editedAutomation.schedule?.firstRun, editedAutomation.schedule?.timezone);
339
90
  const { isSubmitDisabled, validationErrorMessage, isParentValid, allowExternalRecipients, allowOnlyLoggedUserRecipients, } = useScheduledEmailFormValidity({
340
91
  editedAutomation,
@@ -393,63 +144,3 @@ export function useEditScheduledEmail({ scheduledExportToEdit, notificationChann
393
144
  enableAutomationEvaluationMode,
394
145
  };
395
146
  }
396
- function newAutomationMetadataObjectDefinition({ timezone, dashboardId, notificationChannel, title, insight, widget, recipient, dashboardFilters, filtersByTab, widgetFilters, widgetFiltersWithInsight, visibleFiltersMetadata, visibleFiltersByTab, defaultPdfPageSize, evaluationMode, targetTabId, parametersByTab, }) {
397
- const { firstRun, cron } = toNormalizedFirstRunAndCron(timezone);
398
- const exportDefinition = widget && insight
399
- ? newWidgetExportDefinitionMetadataObjectDefinition({
400
- insight,
401
- widget,
402
- dashboardId,
403
- format: "PNG",
404
- widgetFilters,
405
- widgetFiltersWithInsight,
406
- dashboardFilters,
407
- defaultPdfPageSize,
408
- })
409
- : newDashboardExportDefinitionMetadataObjectDefinition({
410
- dashboardId,
411
- dashboardTitle: title ?? "",
412
- dashboardFilters,
413
- filtersByTab,
414
- format: "PDF",
415
- });
416
- let metadataObj = visibleFiltersMetadata || visibleFiltersByTab
417
- ? {
418
- metadata: {
419
- ...(visibleFiltersMetadata ? { visibleFilters: visibleFiltersMetadata } : {}),
420
- ...(visibleFiltersByTab ? { visibleFiltersByTab } : {}),
421
- },
422
- }
423
- : {};
424
- if (targetTabId) {
425
- metadataObj = {
426
- ...metadataObj,
427
- metadata: {
428
- ...metadataObj.metadata,
429
- targetTabIdentifier: targetTabId,
430
- },
431
- };
432
- }
433
- const automation = {
434
- type: "automation",
435
- title: undefined,
436
- description: undefined,
437
- tags: [],
438
- schedule: {
439
- timezone: timezone ?? getUserTimezone().identifier,
440
- firstRun,
441
- cron,
442
- },
443
- details: {
444
- message: "",
445
- subject: "",
446
- },
447
- exportDefinitions: [{ ...exportDefinition }],
448
- recipients: [recipient],
449
- evaluationMode,
450
- notificationChannel,
451
- dashboard: dashboardId ? { id: dashboardId } : undefined,
452
- ...metadataObj,
453
- };
454
- return parametersByTab ? setExportParametersByTab(automation, parametersByTab) : automation;
455
- }
@@ -0,0 +1,38 @@
1
+ import { type FilterContextItem, type IAutomationVisibleFilter, type IDashboardExportParameter, type IFilter, type IInsight, type IWidget } from "@gooddata/sdk-model";
2
+ import type { IAutomationFiltersTab } from "../../../../../model/store/filtering/types.js";
3
+ export interface IUseScheduledEmailEffectiveFiltersProps {
4
+ widget?: IWidget;
5
+ insight?: IInsight;
6
+ editedAutomationFilters?: FilterContextItem[];
7
+ editedAutomationFiltersByTab?: Record<string, FilterContextItem[]>;
8
+ availableFiltersAsVisibleFilters?: IAutomationVisibleFilter[] | undefined;
9
+ availableFiltersAsVisibleFiltersByTab?: Record<string, IAutomationVisibleFilter[]>;
10
+ filtersDataByTab?: IAutomationFiltersTab[] | undefined;
11
+ storeFilters?: boolean;
12
+ }
13
+ /**
14
+ * Derives the effective-filters cluster consumed early by `useScheduledEmailFormState` (draft init) and
15
+ * `useScheduledEmailExportSettings`, and later still by the `useScheduledEmailFilters` handlers.
16
+ *
17
+ * Filters slice A of 2. Reads `hiddenFilters`/`commonDateFilterId`/`exportParametersByTab` from
18
+ * {@link useScheduledEmailDialogContext} internally, as does `useScheduledEmailFilters` — the parent
19
+ * (`useEditScheduledEmail`) no longer reads them itself. `isWidget` is re-derived internally
20
+ * (`!!widget && !!insight`) — `useScheduledEmailFilters` keeps its own copy, a harmless identical
21
+ * re-derivation (mirrors the sibling hooks).
22
+ *
23
+ * `useScheduledEmailFilters` (slice B) owns the four filters handlers, which run after `formState` (they
24
+ * need `setEditedAutomation`); this derivation cluster runs before it, hence the split.
25
+ *
26
+ * @internal
27
+ */
28
+ export declare function useScheduledEmailEffectiveFilters({ widget, insight, editedAutomationFilters, editedAutomationFiltersByTab, availableFiltersAsVisibleFilters, availableFiltersAsVisibleFiltersByTab, filtersDataByTab, storeFilters }: IUseScheduledEmailEffectiveFiltersProps): {
29
+ effectiveWidgetFilters: IFilter[];
30
+ effectiveWidgetFiltersWithInsight: IFilter[];
31
+ effectiveVisibleWidgetFilters: IAutomationVisibleFilter[] | undefined;
32
+ effectiveDashboardFilters: FilterContextItem[] | undefined;
33
+ effectiveDashboardFiltersByTab: Record<string, FilterContextItem[]> | undefined;
34
+ effectiveVisibleDashboardFilters: IAutomationVisibleFilter[] | undefined;
35
+ effectiveVisibleDashboardFiltersByTab: Record<string, IAutomationVisibleFilter[]> | undefined;
36
+ parametersByTabForNewAutomation: Record<string, IDashboardExportParameter[]> | undefined;
37
+ };
38
+ //# sourceMappingURL=useScheduledEmailEffectiveFilters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScheduledEmailEffectiveFilters.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,OAAO,EACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AAU3F,MAAM,WAAW,uCAAuC;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,uBAAuB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC9C,4BAA4B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACnE,gCAAgC,CAAC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IAC1E,qCAAqC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC;IACnF,gBAAgB,CAAC,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iCAAiC,CAAC,EAC9C,MAAM,EACN,OAAO,EACP,uBAAuB,EACvB,4BAA4B,EAC5B,gCAAgC,EAChC,qCAAqC,EACrC,gBAAgB,EAChB,YAAY,EACf,EAAE,uCAAuC,GAAG;IACzC,sBAAsB,EAAE,OAAO,EAAE,CAAC;IAClC,iCAAiC,EAAE,OAAO,EAAE,CAAC;IAC7C,6BAA6B,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IACtE,yBAAyB,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IAC3D,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,GAAG,SAAS,CAAC;IAChF,gCAAgC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IACzE,qCAAqC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,GAAG,SAAS,CAAC;IAC9F,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,EAAE,CAAC,GAAG,SAAS,CAAC;CAC5F,CA4FA"}
@@ -0,0 +1,61 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useMemo } from "react";
3
+ import { useScheduledEmailDialogContext } from "../../../contexts/ScheduledEmailDialogContext.js";
4
+ import { shouldStoreExportParameters } from "../../../shared/automationFilters/automationParameters.js";
5
+ import { getAppliedDashboardFilters, getAppliedWidgetFilters, getVisibleFiltersByFilters, getVisibleFiltersByFiltersByTab, } from "../../../shared/automationFilters/utils.js";
6
+ /**
7
+ * Derives the effective-filters cluster consumed early by `useScheduledEmailFormState` (draft init) and
8
+ * `useScheduledEmailExportSettings`, and later still by the `useScheduledEmailFilters` handlers.
9
+ *
10
+ * Filters slice A of 2. Reads `hiddenFilters`/`commonDateFilterId`/`exportParametersByTab` from
11
+ * {@link useScheduledEmailDialogContext} internally, as does `useScheduledEmailFilters` — the parent
12
+ * (`useEditScheduledEmail`) no longer reads them itself. `isWidget` is re-derived internally
13
+ * (`!!widget && !!insight`) — `useScheduledEmailFilters` keeps its own copy, a harmless identical
14
+ * re-derivation (mirrors the sibling hooks).
15
+ *
16
+ * `useScheduledEmailFilters` (slice B) owns the four filters handlers, which run after `formState` (they
17
+ * need `setEditedAutomation`); this derivation cluster runs before it, hence the split.
18
+ *
19
+ * @internal
20
+ */
21
+ export function useScheduledEmailEffectiveFilters({ widget, insight, editedAutomationFilters, editedAutomationFiltersByTab, availableFiltersAsVisibleFilters, availableFiltersAsVisibleFiltersByTab, filtersDataByTab, storeFilters, }) {
22
+ const { hiddenFilters: dashboardHiddenFilters, commonDateFilterId, exportParametersByTab: effectiveExportParametersByTab, } = useScheduledEmailDialogContext();
23
+ const isWidget = !!widget && !!insight;
24
+ const effectiveWidgetFilters = getAppliedWidgetFilters(editedAutomationFilters ?? [], dashboardHiddenFilters, widget, insight, commonDateFilterId, false);
25
+ const effectiveWidgetFiltersWithInsight = getAppliedWidgetFilters(editedAutomationFilters ?? [], dashboardHiddenFilters, widget, insight, commonDateFilterId, true);
26
+ const effectiveVisibleWidgetFilters = getVisibleFiltersByFilters(editedAutomationFilters, availableFiltersAsVisibleFilters, true);
27
+ const effectiveDashboardFilters = getAppliedDashboardFilters(editedAutomationFilters ?? [], dashboardHiddenFilters, isWidget ? true : storeFilters);
28
+ // Process filters per tab if provided (for dashboard automations with tabs enabled)
29
+ const effectiveDashboardFiltersByTab = useMemo(() => {
30
+ if (!editedAutomationFiltersByTab || !storeFilters) {
31
+ return undefined;
32
+ }
33
+ // Apply the same processing as effectiveDashboardFilters to each tab's filters
34
+ return Object.entries(editedAutomationFiltersByTab).reduce((acc, [tabId, filters]) => {
35
+ const tabHiddenFilters = filtersDataByTab?.find((tab) => tab.tabId === tabId)?.hiddenFilters ?? [];
36
+ const appliedFilters = getAppliedDashboardFilters(filters ?? [], tabHiddenFilters, storeFilters);
37
+ // Only add if we got filters back (storeFilters is true)
38
+ if (appliedFilters) {
39
+ acc[tabId] = appliedFilters;
40
+ }
41
+ return acc;
42
+ }, {});
43
+ }, [editedAutomationFiltersByTab, filtersDataByTab, storeFilters]);
44
+ const effectiveVisibleDashboardFilters = getVisibleFiltersByFilters(editedAutomationFilters ?? [], availableFiltersAsVisibleFilters, storeFilters);
45
+ const effectiveVisibleDashboardFiltersByTab = getVisibleFiltersByFiltersByTab(editedAutomationFiltersByTab, availableFiltersAsVisibleFiltersByTab, storeFilters);
46
+ // Mirrors the filters seed above, for parameters.
47
+ const parametersByTabForNewAutomation = shouldStoreExportParameters(isWidget, storeFilters) &&
48
+ Object.keys(effectiveExportParametersByTab).length > 0
49
+ ? effectiveExportParametersByTab
50
+ : undefined;
51
+ return {
52
+ effectiveWidgetFilters,
53
+ effectiveWidgetFiltersWithInsight,
54
+ effectiveVisibleWidgetFilters,
55
+ effectiveDashboardFilters,
56
+ effectiveDashboardFiltersByTab,
57
+ effectiveVisibleDashboardFilters,
58
+ effectiveVisibleDashboardFiltersByTab,
59
+ parametersByTabForNewAutomation,
60
+ };
61
+ }
@@ -0,0 +1,35 @@
1
+ import { type Dispatch, type SetStateAction } from "react";
2
+ import { type FilterContextItem, type IAutomationMetadataObjectDefinition, type IAutomationVisibleFilter, type IInsight, type IWidget } from "@gooddata/sdk-model";
3
+ import type { IAutomationFiltersTab } from "../../../../../model/store/filtering/types.js";
4
+ export interface IUseScheduledEmailFiltersProps {
5
+ setEditedAutomation: Dispatch<SetStateAction<IAutomationMetadataObjectDefinition>>;
6
+ widget?: IWidget;
7
+ insight?: IInsight;
8
+ setEditedAutomationFilters: (filters: FilterContextItem[]) => void;
9
+ setEditedAutomationFiltersByTab?: (filters: Record<string, FilterContextItem[]>) => void;
10
+ availableFiltersAsVisibleFilters?: IAutomationVisibleFilter[] | undefined;
11
+ availableFiltersAsVisibleFiltersByTab?: Record<string, IAutomationVisibleFilter[]>;
12
+ filtersDataByTab?: IAutomationFiltersTab[] | undefined;
13
+ storeFilters?: boolean;
14
+ setStoreFilters: (storeFilters: boolean) => void;
15
+ filtersForNewAutomation: FilterContextItem[];
16
+ }
17
+ /**
18
+ * Owns the four scheduled-email filters handlers: they update the edited filters state and sync the
19
+ * result into the draft's export definitions and `metadata.visibleFilters`/`visibleFiltersByTab`.
20
+ *
21
+ * Filters slice B of 2. Runs after `useScheduledEmailFormState` because the handlers need
22
+ * `setEditedAutomation`; the derivation cluster in {@link useScheduledEmailEffectiveFilters} (slice A)
23
+ * has to run before it, which is why the two are separate hooks. Reads
24
+ * `hiddenFilters`/`commonDateFilterId` from {@link useScheduledEmailDialogContext} internally, same as
25
+ * slice A and as the parent (`useEditScheduledEmail`) did before.
26
+ *
27
+ * @internal
28
+ */
29
+ export declare function useScheduledEmailFilters({ setEditedAutomation, widget, insight, setEditedAutomationFilters, setEditedAutomationFiltersByTab, availableFiltersAsVisibleFilters, availableFiltersAsVisibleFiltersByTab, filtersDataByTab, storeFilters, setStoreFilters, filtersForNewAutomation }: IUseScheduledEmailFiltersProps): {
30
+ onFiltersChange: (filters: FilterContextItem[], storeFiltersParam?: boolean | undefined) => void;
31
+ onFiltersByTabChange: (newFiltersByTab: Record<string, FilterContextItem[]>, storeFiltersParam?: boolean | undefined) => void;
32
+ onApplyCurrentFilters: () => void;
33
+ onStoreFiltersChange: (value: boolean, filters?: FilterContextItem[] | undefined, filtersByTabParam?: Record<string, FilterContextItem[]> | undefined) => void;
34
+ };
35
+ //# sourceMappingURL=useScheduledEmailFilters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScheduledEmailFilters.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.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,+CAA+C,CAAC;AAU3F,MAAM,WAAW,8BAA8B;IAC3C,mBAAmB,EAAE,QAAQ,CAAC,cAAc,CAAC,mCAAmC,CAAC,CAAC,CAAC;IACnF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,0BAA0B,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,IAAI,CAAC;IACnE,+BAA+B,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,KAAK,IAAI,CAAC;IACzF,gCAAgC,CAAC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IAC1E,qCAAqC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC;IACnF,gBAAgB,CAAC,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,uBAAuB,EAAE,iBAAiB,EAAE,CAAC;CAChD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,EACrC,mBAAmB,EACnB,MAAM,EACN,OAAO,EACP,0BAA0B,EAC1B,+BAA+B,EAC/B,gCAAgC,EAChC,qCAAqC,EACrC,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,uBAAuB,EAC1B,EAAE,8BAA8B;;;;;EAqPhC"}