@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.
- package/NOTICE +216 -203
- package/esm/__version.d.ts +1 -1
- package/esm/__version.js +1 -1
- package/esm/_staging/dateFilterConfig/dateFilterConfigConverters.d.ts +1 -9
- package/esm/_staging/dateFilterConfig/dateFilterConfigConverters.d.ts.map +1 -1
- package/esm/_staging/dateFilterConfig/dateFilterConfigConverters.js +3 -88
- package/esm/_staging/dateFilterConfig/dateFilterOptionMapping.d.ts +1 -33
- package/esm/_staging/dateFilterConfig/dateFilterOptionMapping.d.ts.map +1 -1
- package/esm/_staging/dateFilterConfig/dateFilterOptionMapping.js +3 -260
- package/esm/_staging/dateFilterConfig/defaultConfig.d.ts +1 -11
- package/esm/_staging/dateFilterConfig/defaultConfig.d.ts.map +1 -1
- package/esm/_staging/dateFilterConfig/defaultConfig.js +3 -436
- package/esm/model/store/config/configSelectors.d.ts.map +1 -1
- package/esm/model/store/config/configSelectors.js +2 -9
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts +4 -4
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.js +50 -359
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.d.ts +38 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.js +61 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.d.ts +35 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.js +195 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.d.ts +55 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.js +203 -0
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.d.ts +1 -9
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.d.ts.map +1 -1
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterConfigConverters.js +3 -88
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.d.ts +1 -33
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.d.ts.map +1 -1
- package/esm/presentation/automations/shared/dateFilterConfig/dateFilterOptionMapping.js +3 -260
- package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.d.ts +1 -11
- package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.d.ts.map +1 -1
- package/esm/presentation/automations/shared/dateFilterConfig/defaultConfig.js +3 -436
- package/esm/presentation/dashboardList/DashboardList.d.ts.map +1 -1
- package/esm/presentation/dashboardList/DashboardList.js +6 -0
- package/esm/presentation/filterBar/filterBar/DefaultFilterBarContainer.d.ts.map +1 -1
- package/esm/presentation/filterBar/filterBar/DefaultFilterBarContainer.js +11 -5
- package/esm/presentation/widget/common/InsightDropdown.d.ts.map +1 -1
- package/esm/presentation/widget/common/InsightDropdown.js +14 -0
- package/esm/presentation/widget/common/configuration/ConfigurationBubble.d.ts.map +1 -1
- package/esm/presentation/widget/common/configuration/ConfigurationBubble.js +2 -0
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/DashboardInsightMenuBubble.d.ts.map +1 -1
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/DashboardInsightMenuBubble.js +1 -1
- package/esm/tsdoc-metadata.json +1 -1
- package/package.json +21 -21
- package/styles/css/main.css +1 -1
|
@@ -1,96 +1,51 @@
|
|
|
1
1
|
// (C) 2019-2026 GoodData Corporation
|
|
2
|
-
import { useCallback,
|
|
3
|
-
import { DEFAULT_CSV_DELIMITER,
|
|
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 {
|
|
8
|
-
import {
|
|
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,
|
|
18
|
-
const { dashboardId, dashboardTitle,
|
|
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
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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"}
|