@gooddata/sdk-ui-dashboard 11.52.0-alpha.1 → 11.52.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 (163) hide show
  1. package/NOTICE +86 -14
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/index.d.ts +1 -5
  5. package/esm/index.d.ts.map +1 -1
  6. package/esm/index.js +0 -3
  7. package/esm/model/commandHandlers/index.d.ts.map +1 -1
  8. package/esm/model/commandHandlers/index.js +0 -2
  9. package/esm/model/commands/base.d.ts +1 -1
  10. package/esm/model/commands/base.d.ts.map +1 -1
  11. package/esm/model/commands/index.d.ts +1 -2
  12. package/esm/model/commands/index.d.ts.map +1 -1
  13. package/esm/model/store/dashboardStore.d.ts +0 -2
  14. package/esm/model/store/dashboardStore.d.ts.map +1 -1
  15. package/esm/model/store/dashboardStore.js +0 -2
  16. package/esm/model/store/types.d.ts +0 -3
  17. package/esm/model/store/types.d.ts.map +1 -1
  18. package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.d.ts.map +1 -1
  19. package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.js +2 -2
  20. package/esm/presentation/automations/alerting/DefaultAlertingDialog/hooks/useAlertFormState.d.ts +3 -4
  21. package/esm/presentation/automations/alerting/DefaultAlertingDialog/hooks/useAlertFormState.d.ts.map +1 -1
  22. package/esm/presentation/automations/alerting/DefaultAlertingDialog/hooks/useAlertFormState.js +14 -16
  23. package/esm/presentation/automations/alerting/DefaultAlertingDialog/hooks/useEditAlert.d.ts +1 -3
  24. package/esm/presentation/automations/alerting/DefaultAlertingDialog/hooks/useEditAlert.d.ts.map +1 -1
  25. package/esm/presentation/automations/alerting/DefaultAlertingDialog/hooks/useEditAlert.js +1 -4
  26. package/esm/presentation/automations/alerting/types.d.ts +1 -13
  27. package/esm/presentation/automations/alerting/types.d.ts.map +1 -1
  28. package/esm/presentation/automations/connectors/AlertingConnector.d.ts +4 -5
  29. package/esm/presentation/automations/connectors/AlertingConnector.d.ts.map +1 -1
  30. package/esm/presentation/automations/connectors/AlertingConnector.js +8 -17
  31. package/esm/presentation/automations/connectors/AlertingConnector.test.js +0 -16
  32. package/esm/presentation/automations/connectors/ScheduledEmailConnector.d.ts +4 -4
  33. package/esm/presentation/automations/connectors/ScheduledEmailConnector.d.ts.map +1 -1
  34. package/esm/presentation/automations/connectors/ScheduledEmailConnector.js +8 -18
  35. package/esm/presentation/automations/connectors/ScheduledEmailConnector.test.js +0 -20
  36. package/esm/presentation/automations/connectors/hooks/useBuildAlertingDialogContext.d.ts +1 -4
  37. package/esm/presentation/automations/connectors/hooks/useBuildAlertingDialogContext.d.ts.map +1 -1
  38. package/esm/presentation/automations/connectors/hooks/useBuildAlertingDialogContext.js +5 -10
  39. package/esm/presentation/automations/connectors/hooks/useBuildAlertingDialogContext.test.js +13 -10
  40. package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.d.ts.map +1 -1
  41. package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.js +35 -3
  42. package/esm/presentation/automations/connectors/hooks/useBuildAutomationsContext.test.js +76 -27
  43. package/esm/presentation/automations/connectors/hooks/useBuildScheduledEmailDialogContext.d.ts +1 -4
  44. package/esm/presentation/automations/connectors/hooks/useBuildScheduledEmailDialogContext.d.ts.map +1 -1
  45. package/esm/presentation/automations/connectors/hooks/useBuildScheduledEmailDialogContext.js +1 -14
  46. package/esm/presentation/automations/connectors/hooks/useBuildScheduledEmailDialogContext.test.js +1 -11
  47. package/esm/presentation/automations/contexts/AlertingDialogContext.d.ts +11 -14
  48. package/esm/presentation/automations/contexts/AlertingDialogContext.d.ts.map +1 -1
  49. package/esm/presentation/automations/contexts/AlertingDialogContext.js +3 -3
  50. package/esm/presentation/automations/contexts/AutomationsContext.d.ts +31 -1
  51. package/esm/presentation/automations/contexts/AutomationsContext.d.ts.map +1 -1
  52. package/esm/presentation/automations/contexts/ScheduledEmailDialogContext.d.ts +5 -18
  53. package/esm/presentation/automations/contexts/ScheduledEmailDialogContext.d.ts.map +1 -1
  54. package/esm/presentation/automations/contexts/ScheduledEmailDialogContext.js +3 -5
  55. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.d.ts.map +1 -1
  56. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.js +5 -5
  57. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.d.ts +3 -12
  58. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.d.ts.map +1 -1
  59. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.js +21 -21
  60. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts +6 -3
  61. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts.map +1 -1
  62. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.js +14 -27
  63. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/useWorkspaceUsersSearch.d.ts +13 -0
  64. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/useWorkspaceUsersSearch.d.ts.map +1 -0
  65. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/useWorkspaceUsersSearch.js +44 -0
  66. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts +1 -3
  67. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.d.ts.map +1 -1
  68. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useEditScheduledEmail.js +1 -4
  69. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.d.ts.map +1 -1
  70. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailEffectiveFilters.js +3 -12
  71. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.d.ts.map +1 -1
  72. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFilters.js +2 -1
  73. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.d.ts +8 -9
  74. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.d.ts.map +1 -1
  75. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/hooks/useScheduledEmailFormState.js +12 -11
  76. package/esm/presentation/automations/scheduledEmail/types.d.ts +1 -13
  77. package/esm/presentation/automations/scheduledEmail/types.d.ts.map +1 -1
  78. package/esm/presentation/automations/scheduledEmail/utils/users.d.ts +1 -2
  79. package/esm/presentation/automations/scheduledEmail/utils/users.d.ts.map +1 -1
  80. package/esm/presentation/automations/scheduledEmail/utils/users.js +1 -10
  81. package/esm/presentation/automations/shared/automationFilters/components/AutomationDateFilter.test.js +9 -0
  82. package/esm/presentation/automations/shared/automationFilters/hooks/useAutomationVisibleFilters.d.ts.map +1 -1
  83. package/esm/presentation/automations/shared/automationFilters/hooks/useAutomationVisibleFilters.js +7 -2
  84. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.d.ts.map +1 -1
  85. package/esm/presentation/automations/shared/automationFilters/hooks/useValidateExistingAutomationFilters.js +2 -14
  86. package/esm/presentation/automations/shared/automationFilters/useAutomationAlertParameters.d.ts +12 -3
  87. package/esm/presentation/automations/shared/automationFilters/useAutomationAlertParameters.d.ts.map +1 -1
  88. package/esm/presentation/automations/shared/automationFilters/useAutomationAlertParameters.js +3 -11
  89. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.d.ts +7 -1
  90. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.d.ts.map +1 -1
  91. package/esm/presentation/automations/shared/automationFilters/useAutomationExportParameters.js +9 -25
  92. package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.d.ts.map +1 -1
  93. package/esm/presentation/automations/shared/automationFilters/useAutomationFiltersSelect.js +4 -7
  94. package/esm/presentation/automations/shared/hooks/useDateFiltersTitles.d.ts.map +1 -1
  95. package/esm/presentation/automations/shared/hooks/useDateFiltersTitles.js +6 -3
  96. package/esm/presentation/automations/shared/hooks/useFiltersNamings.d.ts.map +1 -1
  97. package/esm/presentation/automations/shared/hooks/useFiltersNamings.js +23 -10
  98. package/esm/presentation/automations/shared/utils/automationUtils.d.ts +1 -3
  99. package/esm/presentation/automations/shared/utils/automationUtils.d.ts.map +1 -1
  100. package/esm/presentation/automations/shared/utils/automationUtils.js +0 -17
  101. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.d.ts.map +1 -1
  102. package/esm/presentation/drill/DrillConfigPanel/DrillToUrl/CustomUrlEditor.js +5 -4
  103. package/esm/presentation/drill/utils/dashboardPredicate.d.ts +0 -15
  104. package/esm/presentation/drill/utils/dashboardPredicate.d.ts.map +1 -1
  105. package/esm/presentation/drill/utils/dashboardPredicate.js +1 -16
  106. package/esm/presentation/presentationComponents/DashboardItems/DashboardItem.d.ts +4 -0
  107. package/esm/presentation/presentationComponents/DashboardItems/DashboardItem.d.ts.map +1 -1
  108. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/CreateAlert.d.ts +2 -3
  109. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/CreateAlert.d.ts.map +1 -1
  110. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/CreateAlert.js +2 -2
  111. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/EditAlert.d.ts +2 -3
  112. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/EditAlert.d.ts.map +1 -1
  113. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/EditAlert.js +2 -2
  114. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useEditAlert.d.ts +1 -1
  115. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useEditAlert.d.ts.map +1 -1
  116. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/hooks/useEditAlert.js +4 -6
  117. package/esm/presentation/widget/visualizationSwitcher/EditModeDashboardVisualizationSwitcher.d.ts.map +1 -1
  118. package/esm/presentation/widget/visualizationSwitcher/EditModeDashboardVisualizationSwitcher.js +1 -1
  119. package/esm/presentation/widget/visualizationSwitcher/ViewModeDashboardVisualizationSwitcher.d.ts.map +1 -1
  120. package/esm/presentation/widget/visualizationSwitcher/ViewModeDashboardVisualizationSwitcher.js +3 -1
  121. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/DefaultDashboardVisualizationSwitcherWidget.d.ts.map +1 -1
  122. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/DefaultDashboardVisualizationSwitcherWidget.js +1 -1
  123. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/EditableDashboardVisualizationSwitcherWidget.d.ts.map +1 -1
  124. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/EditableDashboardVisualizationSwitcherWidget.js +1 -1
  125. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/ExportableDashboardVisualizationSwitcherWidget.d.ts.map +1 -1
  126. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/ExportableDashboardVisualizationSwitcherWidget.js +1 -1
  127. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/VisualizationSwitcherNavigationHeader.d.ts +2 -1
  128. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/VisualizationSwitcherNavigationHeader.d.ts.map +1 -1
  129. package/esm/presentation/widget/widget/VisualizationSwitcherWidget/VisualizationSwitcherNavigationHeader.js +4 -4
  130. package/esm/sdk-ui-dashboard.d.ts +47 -115
  131. package/package.json +21 -21
  132. package/styles/css/main.css +2 -0
  133. package/styles/css/main.css.map +1 -1
  134. package/styles/css/visualizationSwitcherHeader.css +1 -0
  135. package/styles/css/visualizationSwitcherHeader.css.map +1 -1
  136. package/styles/css/visualizationSwitcherWidget.css +1 -0
  137. package/styles/css/visualizationSwitcherWidget.css.map +1 -1
  138. package/styles/scss/visualizationSwitcherHeader.scss +2 -0
  139. package/styles/scss/visualizationSwitcherWidget.scss +2 -0
  140. package/esm/model/commandHandlers/users/loadAllUsersHandler.d.ts +0 -5
  141. package/esm/model/commandHandlers/users/loadAllUsersHandler.d.ts.map +0 -1
  142. package/esm/model/commandHandlers/users/loadAllUsersHandler.js +0 -19
  143. package/esm/model/commandHandlers/users/loadWorkspaceUsers.d.ts +0 -4
  144. package/esm/model/commandHandlers/users/loadWorkspaceUsers.d.ts.map +0 -1
  145. package/esm/model/commandHandlers/users/loadWorkspaceUsers.js +0 -3
  146. package/esm/model/commands/users.d.ts +0 -19
  147. package/esm/model/commands/users.d.ts.map +0 -1
  148. package/esm/model/commands/users.js +0 -15
  149. package/esm/model/react/useWorkspaceUsers.d.ts +0 -9
  150. package/esm/model/react/useWorkspaceUsers.d.ts.map +0 -1
  151. package/esm/model/react/useWorkspaceUsers.js +0 -27
  152. package/esm/model/store/users/index.d.ts +0 -9
  153. package/esm/model/store/users/index.d.ts.map +0 -1
  154. package/esm/model/store/users/index.js +0 -12
  155. package/esm/model/store/users/usersReducers.d.ts +0 -21
  156. package/esm/model/store/users/usersReducers.d.ts.map +0 -1
  157. package/esm/model/store/users/usersReducers.js +0 -15
  158. package/esm/model/store/users/usersSelectors.d.ts +0 -22
  159. package/esm/model/store/users/usersSelectors.d.ts.map +0 -1
  160. package/esm/model/store/users/usersSelectors.js +0 -27
  161. package/esm/model/store/users/usersState.d.ts +0 -12
  162. package/esm/model/store/users/usersState.d.ts.map +0 -1
  163. package/esm/model/store/users/usersState.js +0 -2
@@ -9,11 +9,6 @@ const fixtures = vi.hoisted(() => {
9
9
  let managementDialogProps;
10
10
  let dialogProps;
11
11
  let automationsError;
12
- const useWorkspaceUsers = vi.fn(() => ({
13
- users: [],
14
- status: "success",
15
- usersError: new Error("users failed to load"),
16
- }));
17
12
  const seState = {
18
13
  isScheduleEmailingDialogOpen: false,
19
14
  isScheduleEmailingManagementDialogOpen: true,
@@ -22,7 +17,6 @@ const fixtures = vi.hoisted(() => {
22
17
  buildAutomationUrl,
23
18
  navigate,
24
19
  onScheduleEmailingManagementEdit,
25
- useWorkspaceUsers,
26
20
  seState,
27
21
  get managementDialogProps() {
28
22
  return managementDialogProps;
@@ -83,9 +77,6 @@ vi.mock("../../../model/react/useDasboardScheduledEmails/useDashboardScheduledEm
83
77
  insight: { insight: { identifier: "insight-1", title: "Insight" } },
84
78
  }),
85
79
  }));
86
- vi.mock("../../../model/react/useWorkspaceUsers.js", () => ({
87
- useWorkspaceUsers: fixtures.useWorkspaceUsers,
88
- }));
89
80
  vi.mock("../../../model/store/config/configSelectors.js", () => ({
90
81
  selectExternalRecipient: () => "recipient@example.com",
91
82
  selectIsEmbedded: () => false,
@@ -163,7 +154,6 @@ describe("ScheduledEmailConnector", () => {
163
154
  fixtures.managementDialogProps = undefined;
164
155
  fixtures.dialogProps = undefined;
165
156
  fixtures.automationsError = undefined;
166
- fixtures.useWorkspaceUsers.mockClear();
167
157
  fixtures.seState.isScheduleEmailingDialogOpen = false;
168
158
  fixtures.seState.isScheduleEmailingManagementDialogOpen = true;
169
159
  });
@@ -200,16 +190,6 @@ describe("ScheduledEmailConnector", () => {
200
190
  dashboard: undefined,
201
191
  });
202
192
  });
203
- it("does not load workspace users when only the management dialog is open", () => {
204
- render(_jsx(ScheduledEmailConnector, {}));
205
- expect(fixtures.useWorkspaceUsers).not.toHaveBeenCalled();
206
- });
207
- it("loads workspace users when the create/edit dialog is open", () => {
208
- fixtures.seState.isScheduleEmailingDialogOpen = true;
209
- fixtures.seState.isScheduleEmailingManagementDialogOpen = false;
210
- render(_jsx(ScheduledEmailConnector, {}));
211
- expect(fixtures.useWorkspaceUsers).toHaveBeenCalled();
212
- });
213
193
  it("does not supply the deprecated data props to the create/edit dialog", () => {
214
194
  fixtures.seState.isScheduleEmailingDialogOpen = true;
215
195
  fixtures.seState.isScheduleEmailingManagementDialogOpen = false;
@@ -1,13 +1,10 @@
1
- import { type IAutomationMetadataObject, type IInsight, type INotificationChannelIdentifier, type INotificationChannelMetadataObject, type IWidget, type IWorkspaceUser } from "@gooddata/sdk-model";
2
- import type { GoodDataSdkError } from "@gooddata/sdk-ui";
1
+ import { type IAutomationMetadataObject, type IInsight, type INotificationChannelIdentifier, type INotificationChannelMetadataObject, type IWidget } from "@gooddata/sdk-model";
3
2
  import type { IAlertingDialogContextValue } from "../../contexts/AlertingDialogContext.js";
4
3
  export interface IUseBuildAlertingDialogContextOpts {
5
4
  mode: "create" | "edit";
6
5
  widget?: IWidget;
7
6
  insight?: IInsight;
8
7
  alertToEdit?: IAutomationMetadataObject;
9
- users: IWorkspaceUser[];
10
- usersError?: GoodDataSdkError;
11
8
  notificationChannels: INotificationChannelIdentifier[] | INotificationChannelMetadataObject[];
12
9
  isLoading: boolean;
13
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useBuildAlertingDialogContext.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/connectors/hooks/useBuildAlertingDialogContext.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,KAAK,yBAAyB,EAC9B,KAAK,QAAQ,EACb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EACZ,KAAK,cAAc,EAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAiBzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;AAI3F,MAAM,WAAW,kCAAkC;IAC/C,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,oBAAoB,EAAE,8BAA8B,EAAE,GAAG,kCAAkC,EAAE,CAAC;IAC9F,SAAS,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,6BAA6B,CACzC,IAAI,EAAE,kCAAkC,GACzC,2BAA2B,CAsG7B"}
1
+ {"version":3,"file":"useBuildAlertingDialogContext.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/connectors/hooks/useBuildAlertingDialogContext.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,KAAK,yBAAyB,EAC9B,KAAK,QAAQ,EACb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EAEf,MAAM,qBAAqB,CAAC;AAmB7B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;AAI3F,MAAM,WAAW,kCAAkC;IAC/C,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,oBAAoB,EAAE,8BAA8B,EAAE,GAAG,kCAAkC,EAAE,CAAC;IAC9F,SAAS,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,6BAA6B,CACzC,IAAI,EAAE,kCAAkC,GACzC,2BAA2B,CAoG7B"}
@@ -6,20 +6,19 @@ import { useDashboardSelector } from "../../../../model/react/DashboardStoreProv
6
6
  import { selectExecutionResultEntities } from "../../../../model/store/executionResults/executionResultsSelectors.js";
7
7
  import { selectAutomationCommonDateFilterId, selectAutomationDefaultSelectedFilters, selectDashboardHiddenFilters, } from "../../../../model/store/filtering/dashboardFilterSelectors.js";
8
8
  import { selectDashboardId, selectEvaluationFrequency } from "../../../../model/store/meta/metaSelectors.js";
9
- import { selectWidgetLocalIdToTabIdMap } from "../../../../model/store/tabs/layout/layoutSelectors.js";
10
- import { selectEffectiveParameterValuesForWidget } from "../../../../model/store/tabs/parameters/parametersSelectors.js";
9
+ import { selectEffectiveDashboardParametersForWidget, selectEffectiveParameterValuesForWidget, } from "../../../../model/store/tabs/parameters/parametersSelectors.js";
11
10
  import { getWidgetTitle } from "../../../../model/utils/dashboardItemUtils.js";
12
11
  import { useCommandAsPromise, useDeleteAutomation } from "./useCommandAsPromise.js";
13
12
  export function useBuildAlertingDialogContext(opts) {
14
- const { mode, widget, insight, alertToEdit, users, usersError, notificationChannels, isLoading } = opts;
13
+ const { mode, widget, insight, alertToEdit, notificationChannels, isLoading } = opts;
15
14
  const dashboardFilters = useDashboardSelector(selectAutomationDefaultSelectedFilters);
16
15
  const hiddenFilters = useDashboardSelector(selectDashboardHiddenFilters);
17
16
  const dashboardId = useDashboardSelector(selectDashboardId);
18
- const widgetLocalIdToTabIdMap = useDashboardSelector(selectWidgetLocalIdToTabIdMap);
19
17
  const executionResultEntities = useDashboardSelector(selectExecutionResultEntities);
20
18
  const commonDateFilterId = useDashboardSelector(selectAutomationCommonDateFilterId);
21
19
  const dashboardEvaluationFrequency = useDashboardSelector(selectEvaluationFrequency);
22
20
  const parameterValues = useDashboardSelector(selectEffectiveParameterValuesForWidget(widget?.ref));
21
+ const dashboardParameters = useDashboardSelector(selectEffectiveDashboardParametersForWidget(widget?.ref));
23
22
  const widgetTitle = useMemo(() => {
24
23
  if (widget) {
25
24
  return getWidgetTitle(widget);
@@ -61,17 +60,15 @@ export function useBuildAlertingDialogContext(opts) {
61
60
  dashboardId,
62
61
  dashboardFilters,
63
62
  hiddenFilters,
64
- widgetLocalIdToTabIdMap,
65
63
  executionResultByRef,
66
64
  parameterValues,
65
+ dashboardParameters,
67
66
  commonDateFilterId,
68
67
  dashboardEvaluationFrequency,
69
68
  createAlert,
70
69
  saveAlert,
71
70
  deleteAlert,
72
71
  alertToEdit,
73
- users,
74
- usersError,
75
72
  notificationChannels,
76
73
  isLoading,
77
74
  }), [
@@ -82,17 +79,15 @@ export function useBuildAlertingDialogContext(opts) {
82
79
  dashboardId,
83
80
  dashboardFilters,
84
81
  hiddenFilters,
85
- widgetLocalIdToTabIdMap,
86
82
  executionResultByRef,
87
83
  parameterValues,
84
+ dashboardParameters,
88
85
  commonDateFilterId,
89
86
  dashboardEvaluationFrequency,
90
87
  createAlert,
91
88
  saveAlert,
92
89
  deleteAlert,
93
90
  alertToEdit,
94
- users,
95
- usersError,
96
91
  notificationChannels,
97
92
  isLoading,
98
93
  ]);
@@ -39,11 +39,13 @@ vi.mock("../../../../model/store/meta/metaSelectors.js", () => ({
39
39
  selectDashboardId: () => "dashboard-1",
40
40
  selectEvaluationFrequency: () => undefined,
41
41
  }));
42
- vi.mock("../../../../model/store/tabs/layout/layoutSelectors.js", () => ({
43
- selectWidgetLocalIdToTabIdMap: () => ({}),
42
+ const parameterSentinels = vi.hoisted(() => ({
43
+ parameterValues: [],
44
+ dashboardParameters: [],
44
45
  }));
45
46
  vi.mock("../../../../model/store/tabs/parameters/parametersSelectors.js", () => ({
46
- selectEffectiveParameterValuesForWidget: () => () => [],
47
+ selectEffectiveParameterValuesForWidget: () => () => parameterSentinels.parameterValues,
48
+ selectEffectiveDashboardParametersForWidget: () => () => parameterSentinels.dashboardParameters,
47
49
  }));
48
50
  vi.mock("../../../../model/utils/dashboardItemUtils.js", () => ({
49
51
  getWidgetTitle: () => "widget title",
@@ -54,7 +56,6 @@ describe("useBuildAlertingDialogContext", () => {
54
56
  const ref = idRef("widget-1");
55
57
  const { result, rerender } = renderHook(() => useBuildAlertingDialogContext({
56
58
  mode: "create",
57
- users: [],
58
59
  notificationChannels: [],
59
60
  isLoading: false,
60
61
  }));
@@ -70,23 +71,25 @@ describe("useBuildAlertingDialogContext", () => {
70
71
  });
71
72
  it("passes the create/edit inputs through to the context unchanged", () => {
72
73
  const alertToEdit = { id: "alert-1", title: "My alert" };
73
- const users = [
74
- { ref: idRef("user-1"), uri: "/users/user-1", login: "user-1", email: "user-1@example.com" },
75
- ];
76
74
  const notificationChannels = [
77
75
  { id: "channel-1", type: "notificationChannel" },
78
76
  ];
79
77
  const { result } = renderHook(() => useBuildAlertingDialogContext({
80
78
  mode: "edit",
81
79
  alertToEdit,
82
- users,
83
- usersError: undefined,
84
80
  notificationChannels,
85
81
  isLoading: true,
86
82
  }));
87
83
  expect(result.current.alertToEdit).toBe(alertToEdit);
88
- expect(result.current.users).toBe(users);
89
84
  expect(result.current.notificationChannels).toBe(notificationChannels);
90
85
  expect(result.current.isLoading).toBe(true);
91
86
  });
87
+ it("forwards the widget's effective dashboard parameters onto the alerting dialog context", () => {
88
+ const { result } = renderHook(() => useBuildAlertingDialogContext({
89
+ mode: "create",
90
+ notificationChannels: [],
91
+ isLoading: false,
92
+ }));
93
+ expect(result.current.dashboardParameters).toBe(parameterSentinels.dashboardParameters);
94
+ });
92
95
  });
@@ -1 +1 @@
1
- {"version":3,"file":"useBuildAutomationsContext.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/connectors/hooks/useBuildAutomationsContext.ts"],"names":[],"mappings":"AA0EA,OAAO,KAAK,EACR,wBAAwB,EAE3B,MAAM,sCAAsC,CAAC;AAI9C,wBAAgB,0BAA0B,IAAI,wBAAwB,CA+LrE"}
1
+ {"version":3,"file":"useBuildAutomationsContext.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/connectors/hooks/useBuildAutomationsContext.ts"],"names":[],"mappings":"AAmFA,OAAO,KAAK,EACR,wBAAwB,EAG3B,MAAM,sCAAsC,CAAC;AAI9C,wBAAgB,0BAA0B,IAAI,wBAAwB,CAmOrE"}
@@ -1,8 +1,8 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { useCallback, useMemo } from "react";
3
3
  import { useDashboardSelector } from "../../../../model/react/DashboardStoreProvider.js";
4
- import { selectAllCatalogAttributesMap, selectAllCatalogDisplayFormsMap, selectCatalogAttributes, selectCatalogDateDatasets, selectCatalogMeasures, } from "../../../../model/store/catalog/catalogSelectors.js";
5
- import { selectEnableAlertOncePerInterval, selectEnableAnomalyDetectionAlert, selectEnableAutomationEvaluationMode, selectEnableSlideshowExports, selectExternalRecipient, selectIsWhiteLabeled, selectLocale, selectSeparators, selectSettings, selectTimezone, selectWeekStart, } from "../../../../model/store/config/configSelectors.js";
4
+ import { selectAllCatalogAttributesMap, selectAllCatalogDisplayFormsMap, selectCatalogAttributes, selectCatalogDateDatasets, selectCatalogMeasures, selectCatalogParameters, selectCatalogParametersIsLoaded, } from "../../../../model/store/catalog/catalogSelectors.js";
5
+ import { selectEnableAlertOncePerInterval, selectEnableAnomalyDetectionAlert, selectEnableAutomationEvaluationMode, selectEnableParameters, selectEnableSlideshowExports, selectEnableStringParameters, selectExternalRecipient, selectIsWhiteLabeled, selectLocale, selectSeparators, selectSettings, selectTimezone, selectWeekStart, } from "../../../../model/store/config/configSelectors.js";
6
6
  import { selectEntitlementMinimumRecurrenceMinutes, selectMaxAutomationRecipients, } from "../../../../model/store/entitlements/entitlementsSelectors.js";
7
7
  import { selectAutomationAvailableDashboardFilters, selectAutomationCommonDateFilterId, selectAutomationDefaultSelectedFilters, selectAutomationFiltersByTab, selectDashboardFiltersWithoutCrossFiltering, selectDashboardHiddenFilters, selectDashboardLockedFilters, } from "../../../../model/store/filtering/dashboardFilterSelectors.js";
8
8
  import { selectPersistedDashboardFilterContextDateFilterConfig } from "../../../../model/store/meta/metaSelectors.js";
@@ -11,8 +11,10 @@ import { selectAttributeFilterConfigsOverrides, selectAttributeFilterConfigsOver
11
11
  import { selectDateFilterConfigOverridesByTab, selectEffectiveDateFilterAvailableGranularities, selectEffectiveDateFilterGranularitiesPerTab, selectEffectiveDateFilterOptions, selectEffectiveDateFilterOptionsPerTab, } from "../../../../model/store/tabs/dateFilterConfig/dateFilterConfigSelectors.js";
12
12
  import { selectDateFilterConfigsOverrides, selectDateFilterConfigsOverridesByTab, } from "../../../../model/store/tabs/dateFilterConfigs/dateFilterConfigsSelectors.js";
13
13
  import { selectAttributeFilterDisplayFormsMap } from "../../../../model/store/tabs/filterContext/filterContextSelectors.js";
14
- import { selectWidgetsMap } from "../../../../model/store/tabs/layout/layoutSelectors.js";
14
+ import { selectWidgetLocalIdToTabIdMap, selectWidgetsMap, } from "../../../../model/store/tabs/layout/layoutSelectors.js";
15
15
  import { selectMeasureValueFilterConfigsOverrides, selectMeasureValueFilterConfigsOverridesByTab, } from "../../../../model/store/tabs/measureValueFilterConfigs/measureValueFilterConfigsSelectors.js";
16
+ import { selectSmartPersistedTabsParameters } from "../../../../model/store/tabs/parameters/parametersSelectors.js";
17
+ import { selectTabs } from "../../../../model/store/tabs/tabsSelectors.js";
16
18
  import { selectExecutionTimestamp, selectScheduleEmailDialogReturnFocusTo, } from "../../../../model/store/ui/uiSelectors.js";
17
19
  import { selectCurrentUser } from "../../../../model/store/user/userSelectors.js";
18
20
  const DEFAULT_MIN_RECURRENCE_MINUTES = "60";
@@ -66,6 +68,13 @@ export function useBuildAutomationsContext() {
66
68
  const isExecutionTimestampMode = !!executionTimestamp;
67
69
  const scheduleEmailDialogReturnFocusTo = useDashboardSelector(selectScheduleEmailDialogReturnFocusTo);
68
70
  const widgetsMap = useDashboardSelector(selectWidgetsMap);
71
+ const parametersEnabled = useDashboardSelector(selectEnableParameters);
72
+ const stringParametersEnabled = useDashboardSelector(selectEnableStringParameters);
73
+ const parameterCatalog = useDashboardSelector(selectCatalogParameters);
74
+ const parameterCatalogIsLoaded = useDashboardSelector(selectCatalogParametersIsLoaded);
75
+ const dashboardParametersByTab = useDashboardSelector(selectSmartPersistedTabsParameters);
76
+ const tabs = useDashboardSelector(selectTabs);
77
+ const widgetLocalIdToTabIdMap = useDashboardSelector(selectWidgetLocalIdToTabIdMap);
69
78
  const getCatalogAttributeByRef = useCallback((ref) => allCatalogAttributesMap.get(ref), [allCatalogAttributesMap]);
70
79
  const getAttributeFilterDisplayForm = useCallback((displayForm) => attrFilterDisplayFormsMap.get(displayForm) ?? catalogDisplayFormsMap.get(displayForm), [attrFilterDisplayFormsMap, catalogDisplayFormsMap]);
71
80
  const widgetExistsByRef = useCallback((ref) => !!ref && widgetsMap.get(ref) !== undefined, [widgetsMap]);
@@ -75,6 +84,23 @@ export function useBuildAutomationsContext() {
75
84
  getGranularitiesForTab: (tabId) => granularitiesPerTab[tabId] ?? [],
76
85
  getOptionsForTab: (tabId) => optionsPerTab[tabId],
77
86
  }), [availableGranularities, dateFilterOptions, granularitiesPerTab, optionsPerTab]);
87
+ // Memoized deliberately: `.map()` allocates, and an unstable `tabIds` would land in the
88
+ // dependency array of the context useMemo below and change the whole context identity on
89
+ // every render.
90
+ const tabIds = useMemo(() => (tabs ?? []).map((tab) => tab.localIdentifier), [tabs]);
91
+ const parameters = useMemo(() => ({
92
+ enabled: parametersEnabled,
93
+ stringParametersEnabled,
94
+ catalog: parameterCatalog,
95
+ catalogIsLoaded: parameterCatalogIsLoaded,
96
+ dashboardParametersByTab,
97
+ }), [
98
+ parametersEnabled,
99
+ stringParametersEnabled,
100
+ parameterCatalog,
101
+ parameterCatalogIsLoaded,
102
+ dashboardParametersByTab,
103
+ ]);
78
104
  const features = useMemo(() => ({
79
105
  canCreateAutomation,
80
106
  enableAlertOncePerInterval,
@@ -127,6 +153,9 @@ export function useBuildAutomationsContext() {
127
153
  isSecondaryTitleVisible: true,
128
154
  externalRecipient,
129
155
  features,
156
+ parameters,
157
+ tabIds,
158
+ widgetLocalIdToTabIdMap,
130
159
  getCatalogAttributeByRef,
131
160
  getAttributeFilterDisplayForm,
132
161
  widgetExistsByRef,
@@ -165,6 +194,9 @@ export function useBuildAutomationsContext() {
165
194
  isWhiteLabeled,
166
195
  externalRecipient,
167
196
  features,
197
+ parameters,
198
+ tabIds,
199
+ widgetLocalIdToTabIdMap,
168
200
  getCatalogAttributeByRef,
169
201
  getAttributeFilterDisplayForm,
170
202
  widgetExistsByRef,
@@ -26,33 +26,51 @@ const selectors = vi.hoisted(() => {
26
26
  },
27
27
  },
28
28
  };
29
+ // Every mocked selector must return one of these. A mock that allocates per call
30
+ // (`() => []`) would make the context value change identity on every render, which the
31
+ // referential-stability test below exists to catch. In production every one of these
32
+ // selectors is a createSelector and returns a stable reference.
29
33
  return {
30
34
  availableGranularities,
31
35
  dateFilterOptions,
32
36
  granularitiesPerTab,
33
37
  optionsPerTab,
38
+ emptyArray: [],
39
+ emptyRecord: {},
40
+ emptyMap: new Map(),
41
+ separators: { decimal: ".", thousand: "," },
42
+ currentUser: { login: "test@example.com", ref: { identifier: "test" } },
43
+ widgetsMap: { get: () => undefined },
44
+ parameterCatalog: [],
45
+ dashboardParametersByTab: {},
46
+ tabs: [{ localIdentifier: "tab1" }],
47
+ widgetTabMap: { "widget-1": "tab1" },
34
48
  };
35
49
  });
36
50
  vi.mock("../../../../model/react/DashboardStoreProvider.js", () => ({
37
51
  useDashboardSelector: vi.fn((selector) => selector()),
38
52
  }));
39
53
  vi.mock("../../../../model/store/catalog/catalogSelectors.js", () => ({
40
- selectAllCatalogAttributesMap: () => new Map(),
41
- selectAllCatalogDisplayFormsMap: () => new Map(),
42
- selectCatalogAttributes: () => [],
43
- selectCatalogDateDatasets: () => [],
44
- selectCatalogMeasures: () => [],
54
+ selectAllCatalogAttributesMap: () => selectors.emptyMap,
55
+ selectAllCatalogDisplayFormsMap: () => selectors.emptyMap,
56
+ selectCatalogAttributes: () => selectors.emptyArray,
57
+ selectCatalogDateDatasets: () => selectors.emptyArray,
58
+ selectCatalogMeasures: () => selectors.emptyArray,
59
+ selectCatalogParameters: () => selectors.parameterCatalog,
60
+ selectCatalogParametersIsLoaded: () => true,
45
61
  }));
46
62
  vi.mock("../../../../model/store/config/configSelectors.js", () => ({
47
63
  selectDateFormat: () => "MM/dd/yyyy",
48
64
  selectEnableAlertOncePerInterval: () => false,
49
65
  selectEnableAnomalyDetectionAlert: () => false,
50
66
  selectEnableAutomationEvaluationMode: () => false,
67
+ selectEnableParameters: () => true,
51
68
  selectEnableSlideshowExports: () => false,
69
+ selectEnableStringParameters: () => true,
52
70
  selectExternalRecipient: () => undefined,
53
71
  selectIsWhiteLabeled: () => false,
54
72
  selectLocale: () => "en-US",
55
- selectSeparators: () => ({ decimal: ".", thousand: "," }),
73
+ selectSeparators: () => selectors.separators,
56
74
  selectSettings: () => undefined,
57
75
  selectTimezone: () => undefined,
58
76
  selectWeekStart: () => "Sunday",
@@ -61,7 +79,10 @@ vi.mock("../../../../model/store/drill/drillSelectors.js", () => ({
61
79
  selectIsCrossFiltering: () => false,
62
80
  }));
63
81
  vi.mock("../../../../model/store/tabs/tabsSelectors.js", () => ({
64
- selectTabs: () => [],
82
+ selectTabs: () => selectors.tabs,
83
+ }));
84
+ vi.mock("../../../../model/store/tabs/parameters/parametersSelectors.js", () => ({
85
+ selectSmartPersistedTabsParameters: () => selectors.dashboardParametersByTab,
65
86
  }));
66
87
  vi.mock("../../../../model/store/permissions/permissionsSelectors.js", () => ({
67
88
  selectCanCreateAutomation: () => true,
@@ -69,29 +90,29 @@ vi.mock("../../../../model/store/permissions/permissionsSelectors.js", () => ({
69
90
  selectCanUseAiAssistant: () => false,
70
91
  }));
71
92
  vi.mock("../../../../model/store/user/userSelectors.js", () => ({
72
- selectCurrentUser: () => ({ login: "test@example.com", ref: { identifier: "test" } }),
93
+ selectCurrentUser: () => selectors.currentUser,
73
94
  }));
74
95
  vi.mock("../../../../model/store/filtering/dashboardFilterSelectors.js", () => ({
75
- selectAutomationAvailableDashboardFilters: () => [],
96
+ selectAutomationAvailableDashboardFilters: () => selectors.emptyArray,
76
97
  selectAutomationCommonDateFilterId: () => undefined,
77
- selectAutomationDefaultSelectedFilters: () => [],
78
- selectAutomationFiltersByTab: () => [],
79
- selectDashboardFiltersWithoutCrossFiltering: () => [],
80
- selectDashboardHiddenFilters: () => [],
81
- selectDashboardLockedFilters: () => [],
98
+ selectAutomationDefaultSelectedFilters: () => selectors.emptyArray,
99
+ selectAutomationFiltersByTab: () => selectors.emptyArray,
100
+ selectDashboardFiltersWithoutCrossFiltering: () => selectors.emptyArray,
101
+ selectDashboardHiddenFilters: () => selectors.emptyArray,
102
+ selectDashboardLockedFilters: () => selectors.emptyArray,
82
103
  }));
83
104
  vi.mock("../../../../model/store/meta/metaSelectors.js", () => ({
84
105
  selectPersistedDashboardFilterContextDateFilterConfig: () => undefined,
85
106
  }));
86
107
  vi.mock("../../../../model/store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js", () => ({
87
- selectAttributeFilterConfigsOverrides: () => [],
88
- selectAttributeFilterConfigsOverridesByTab: () => ({}),
89
- selectAttributeFilterConfigsSelectionTypeMap: () => new Map(),
90
- selectAttributeFilterConfigsSelectionTypeMapByTab: () => ({}),
91
- selectEffectiveAttributeFiltersModeMap: () => new Map(),
108
+ selectAttributeFilterConfigsOverrides: () => selectors.emptyArray,
109
+ selectAttributeFilterConfigsOverridesByTab: () => selectors.emptyRecord,
110
+ selectAttributeFilterConfigsSelectionTypeMap: () => selectors.emptyMap,
111
+ selectAttributeFilterConfigsSelectionTypeMapByTab: () => selectors.emptyRecord,
112
+ selectEffectiveAttributeFiltersModeMap: () => selectors.emptyMap,
92
113
  }));
93
114
  vi.mock("../../../../model/store/tabs/dateFilterConfig/dateFilterConfigSelectors.js", () => ({
94
- selectDateFilterConfigOverridesByTab: () => ({}),
115
+ selectDateFilterConfigOverridesByTab: () => selectors.emptyRecord,
95
116
  selectEffectiveDateFilterAvailableGranularities: () => selectors.availableGranularities,
96
117
  selectEffectiveDateFilterGranularitiesPerTab: () => selectors.granularitiesPerTab,
97
118
  selectEffectiveDateFilterMode: () => "active",
@@ -99,12 +120,12 @@ vi.mock("../../../../model/store/tabs/dateFilterConfig/dateFilterConfigSelectors
99
120
  selectEffectiveDateFilterOptionsPerTab: () => selectors.optionsPerTab,
100
121
  }));
101
122
  vi.mock("../../../../model/store/tabs/dateFilterConfigs/dateFilterConfigsSelectors.js", () => ({
102
- selectDateFilterConfigsOverrides: () => [],
103
- selectDateFilterConfigsOverridesByTab: () => ({}),
104
- selectEffectiveDateFiltersModeMap: () => new Map(),
123
+ selectDateFilterConfigsOverrides: () => selectors.emptyArray,
124
+ selectDateFilterConfigsOverridesByTab: () => selectors.emptyRecord,
125
+ selectEffectiveDateFiltersModeMap: () => selectors.emptyMap,
105
126
  }));
106
127
  vi.mock("../../../../model/store/tabs/filterContext/filterContextSelectors.js", () => ({
107
- selectAttributeFilterDisplayFormsMap: () => new Map(),
128
+ selectAttributeFilterDisplayFormsMap: () => selectors.emptyMap,
108
129
  }));
109
130
  vi.mock("../../../../model/store/entitlements/entitlementsSelectors.js", () => ({
110
131
  selectMaxAutomationRecipients: () => 10,
@@ -115,11 +136,12 @@ vi.mock("../../../../model/store/ui/uiSelectors.js", () => ({
115
136
  selectScheduleEmailDialogReturnFocusTo: () => undefined,
116
137
  }));
117
138
  vi.mock("../../../../model/store/tabs/measureValueFilterConfigs/measureValueFilterConfigsSelectors.js", () => ({
118
- selectMeasureValueFilterConfigsOverrides: () => [],
119
- selectMeasureValueFilterConfigsOverridesByTab: () => ({}),
139
+ selectMeasureValueFilterConfigsOverrides: () => selectors.emptyArray,
140
+ selectMeasureValueFilterConfigsOverridesByTab: () => selectors.emptyRecord,
120
141
  }));
121
142
  vi.mock("../../../../model/store/tabs/layout/layoutSelectors.js", () => ({
122
- selectWidgetsMap: () => ({ get: () => undefined }),
143
+ selectWidgetsMap: () => selectors.widgetsMap,
144
+ selectWidgetLocalIdToTabIdMap: () => selectors.widgetTabMap,
123
145
  }));
124
146
  import { useBuildAutomationsContext } from "./useBuildAutomationsContext.js";
125
147
  describe("useBuildAutomationsContext", () => {
@@ -134,3 +156,30 @@ describe("useBuildAutomationsContext", () => {
134
156
  expect(result.current.features.canCreateAutomation).toBe(true);
135
157
  });
136
158
  });
159
+ describe("useBuildAutomationsContext — parameter data", () => {
160
+ it("exposes the dashboard-global parameter data the shared automationFilters hooks need", () => {
161
+ const { result } = renderHook(() => useBuildAutomationsContext());
162
+ expect(result.current.parameters).toEqual({
163
+ enabled: true,
164
+ stringParametersEnabled: true,
165
+ catalog: selectors.parameterCatalog,
166
+ catalogIsLoaded: true,
167
+ dashboardParametersByTab: selectors.dashboardParametersByTab,
168
+ });
169
+ expect(result.current.tabIds).toEqual(["tab1"]);
170
+ expect(result.current.widgetLocalIdToTabIdMap).toBe(selectors.widgetTabMap);
171
+ });
172
+ });
173
+ describe("useBuildAutomationsContext — referential stability", () => {
174
+ it("returns a referentially identical context value when re-rendered with unchanged store state", () => {
175
+ const { result, rerender } = renderHook(() => useBuildAutomationsContext());
176
+ const first = result.current;
177
+ rerender();
178
+ // The whole context value, not just its members: an unmemoized `tabIds` or `parameters`
179
+ // would land in the top-level useMemo's dependency array and change this identity on
180
+ // every render, re-rendering every consumer in both dialog trees.
181
+ expect(result.current).toBe(first);
182
+ expect(result.current.tabIds).toBe(first.tabIds);
183
+ expect(result.current.parameters).toBe(first.parameters);
184
+ });
185
+ });
@@ -1,12 +1,9 @@
1
- import { type FilterContextItem, type IAutomationMetadataObject, type IInsight, type INotificationChannelIdentifier, type INotificationChannelMetadataObject, type IWidget, type IWorkspaceUser } from "@gooddata/sdk-model";
2
- import type { GoodDataSdkError } from "@gooddata/sdk-ui";
1
+ import { type FilterContextItem, type IAutomationMetadataObject, type IInsight, type INotificationChannelIdentifier, type INotificationChannelMetadataObject, type IWidget } from "@gooddata/sdk-model";
3
2
  import type { IScheduledEmailDialogContextValue } from "../../contexts/ScheduledEmailDialogContext.js";
4
3
  export interface IUseBuildScheduledEmailDialogContextOpts {
5
4
  widget?: IWidget;
6
5
  insight?: IInsight;
7
6
  scheduledExportToEdit?: IAutomationMetadataObject;
8
- users: IWorkspaceUser[];
9
- usersError?: GoodDataSdkError;
10
7
  notificationChannels: INotificationChannelIdentifier[] | INotificationChannelMetadataObject[];
11
8
  isLoading: boolean;
12
9
  dashboardFilters?: FilterContextItem[];
@@ -1 +1 @@
1
- {"version":3,"file":"useBuildScheduledEmailDialogContext.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/connectors/hooks/useBuildScheduledEmailDialogContext.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,QAAQ,EACb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EACZ,KAAK,cAAc,EAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAuBzD,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAIvG,MAAM,WAAW,wCAAwC;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,qBAAqB,CAAC,EAAE,yBAAyB,CAAC;IAClD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,oBAAoB,EAAE,8BAA8B,EAAE,GAAG,kCAAkC,EAAE,CAAC;IAC9F,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC1C;AAED,wBAAgB,mCAAmC,CAC/C,IAAI,EAAE,wCAAwC,GAC/C,iCAAiC,CA2GnC"}
1
+ {"version":3,"file":"useBuildScheduledEmailDialogContext.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/connectors/hooks/useBuildScheduledEmailDialogContext.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,QAAQ,EACb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EAEf,MAAM,qBAAqB,CAAC;AAqB7B,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAIvG,MAAM,WAAW,wCAAwC;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,qBAAqB,CAAC,EAAE,yBAAyB,CAAC;IAClD,oBAAoB,EAAE,8BAA8B,EAAE,GAAG,kCAAkC,EAAE,CAAC;IAC9F,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC1C;AAED,wBAAgB,mCAAmC,CAC/C,IAAI,EAAE,wCAAwC,GAC/C,iCAAiC,CAwFnC"}
@@ -11,24 +11,19 @@ import { selectDashboardId, selectDashboardTitle } from "../../../../model/store
11
11
  import { selectEffectiveAttributeFiltersModeMap } from "../../../../model/store/tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
12
12
  import { selectEffectiveDateFilterMode } from "../../../../model/store/tabs/dateFilterConfig/dateFilterConfigSelectors.js";
13
13
  import { selectEffectiveDateFiltersModeMap } from "../../../../model/store/tabs/dateFilterConfigs/dateFilterConfigsSelectors.js";
14
- import { selectWidgetLocalIdToTabIdMap } from "../../../../model/store/tabs/layout/layoutSelectors.js";
15
14
  import { selectExportEffectiveParameters } from "../../../../model/store/tabs/parameters/parametersSelectors.js";
16
- import { selectTabs } from "../../../../model/store/tabs/tabsSelectors.js";
17
15
  import { getWidgetTitle } from "../../../../model/utils/dashboardItemUtils.js";
18
16
  import { useCommandAsPromise, useDeleteAutomation } from "./useCommandAsPromise.js";
19
17
  export function useBuildScheduledEmailDialogContext(opts) {
20
- const { widget, insight, scheduledExportToEdit, users, usersError, notificationChannels, isLoading, dashboardFilters, } = opts;
18
+ const { widget, insight, scheduledExportToEdit, notificationChannels, isLoading, dashboardFilters } = opts;
21
19
  const hiddenFilters = useDashboardSelector(selectDashboardHiddenFilters);
22
20
  const dashboardId = useDashboardSelector(selectDashboardId);
23
21
  const dashboardTitle = useDashboardSelector(selectDashboardTitle);
24
- const widgetLocalIdToTabIdMap = useDashboardSelector(selectWidgetLocalIdToTabIdMap);
25
22
  const commonDateFilterId = useDashboardSelector(selectAutomationCommonDateFilterId);
26
23
  const exportParametersByTab = useDashboardSelector(selectExportEffectiveParameters(widget ? [objRefToString(widget.ref)] : undefined));
27
24
  const exportTemplates = useExportTemplates();
28
25
  const dateFormat = useDashboardSelector(selectDateFormat);
29
26
  const isCrossFiltering = useDashboardSelector(selectIsCrossFiltering);
30
- const tabs = useDashboardSelector(selectTabs);
31
- const hasMultipleTabs = (tabs?.length ?? 0) > 1;
32
27
  const commonDateFilterMode = useDashboardSelector(selectEffectiveDateFilterMode);
33
28
  const dateFiltersModeMap = useDashboardSelector(selectEffectiveDateFiltersModeMap);
34
29
  const attributeFiltersModeMap = useDashboardSelector(selectEffectiveAttributeFiltersModeMap);
@@ -57,13 +52,11 @@ export function useBuildScheduledEmailDialogContext(opts) {
57
52
  dashboardTitle,
58
53
  dashboardFilters,
59
54
  hiddenFilters,
60
- widgetLocalIdToTabIdMap,
61
55
  commonDateFilterId,
62
56
  exportParametersByTab,
63
57
  exportTemplates,
64
58
  dateFormat,
65
59
  isCrossFiltering,
66
- hasMultipleTabs,
67
60
  commonDateFilterMode,
68
61
  dateFiltersModeMap,
69
62
  attributeFiltersModeMap,
@@ -71,8 +64,6 @@ export function useBuildScheduledEmailDialogContext(opts) {
71
64
  saveScheduledEmail,
72
65
  deleteScheduledEmail,
73
66
  scheduledExportToEdit,
74
- users,
75
- usersError,
76
67
  notificationChannels,
77
68
  isLoading,
78
69
  }), [
@@ -83,13 +74,11 @@ export function useBuildScheduledEmailDialogContext(opts) {
83
74
  dashboardTitle,
84
75
  dashboardFilters,
85
76
  hiddenFilters,
86
- widgetLocalIdToTabIdMap,
87
77
  commonDateFilterId,
88
78
  exportParametersByTab,
89
79
  exportTemplates,
90
80
  dateFormat,
91
81
  isCrossFiltering,
92
- hasMultipleTabs,
93
82
  commonDateFilterMode,
94
83
  dateFiltersModeMap,
95
84
  attributeFiltersModeMap,
@@ -97,8 +86,6 @@ export function useBuildScheduledEmailDialogContext(opts) {
97
86
  saveScheduledEmail,
98
87
  deleteScheduledEmail,
99
88
  scheduledExportToEdit,
100
- users,
101
- usersError,
102
89
  notificationChannels,
103
90
  isLoading,
104
91
  ]);
@@ -43,9 +43,6 @@ vi.mock("../../../../model/store/config/configSelectors.js", () => ({
43
43
  vi.mock("../../../../model/store/drill/drillSelectors.js", () => ({
44
44
  selectIsCrossFiltering: () => false,
45
45
  }));
46
- vi.mock("../../../../model/store/tabs/layout/layoutSelectors.js", () => ({
47
- selectWidgetLocalIdToTabIdMap: () => ({ widgetId: "tab-1" }),
48
- }));
49
46
  vi.mock("../../../../model/store/tabs/dateFilterConfig/dateFilterConfigSelectors.js", () => ({
50
47
  selectEffectiveDateFilterMode: () => "active",
51
48
  }));
@@ -79,10 +76,9 @@ import { useBuildScheduledEmailDialogContext, } from "./useBuildScheduledEmailDi
79
76
  // ---------------------------------------------------------------------------
80
77
  // Tests
81
78
  // ---------------------------------------------------------------------------
82
- // The builder's create/edit inputs (users, notificationChannels, isLoading) are required options;
79
+ // The builder's create/edit inputs (notificationChannels, isLoading) are required options;
83
80
  // tests that don't care about them use this minimal, valid base and override what they need.
84
81
  const BASE_OPTS = {
85
- users: [],
86
82
  notificationChannels: [],
87
83
  isLoading: false,
88
84
  };
@@ -94,23 +90,17 @@ describe("useBuildScheduledEmailDialogContext", () => {
94
90
  });
95
91
  it("passes the create/edit inputs through and carries the effective dashboard filters", () => {
96
92
  const scheduledExportToEdit = { id: "schedule-1", title: "Weekly" };
97
- const users = [
98
- { ref: idRef("user-1"), uri: "/users/user-1", login: "user-1", email: "user-1@example.com" },
99
- ];
100
93
  const notificationChannels = [
101
94
  { id: "channel-1", type: "notificationChannel" },
102
95
  ];
103
96
  const dashboardFilters = [];
104
97
  const { result } = renderHook(() => useBuildScheduledEmailDialogContext({
105
98
  scheduledExportToEdit,
106
- users,
107
- usersError: undefined,
108
99
  notificationChannels,
109
100
  isLoading: true,
110
101
  dashboardFilters,
111
102
  }));
112
103
  expect(result.current.scheduledExportToEdit).toBe(scheduledExportToEdit);
113
- expect(result.current.users).toBe(users);
114
104
  expect(result.current.notificationChannels).toBe(notificationChannels);
115
105
  expect(result.current.isLoading).toBe(true);
116
106
  // the connector computes `saved ?? getAppliedDashboardFilters(...)` and passes the result in;