@gooddata/sdk-ui-dashboard 11.54.0-alpha.3 → 11.54.0-alpha.5

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 (142) hide show
  1. package/NOTICE +92923 -17333
  2. package/esm/__version.d.ts +1 -1
  3. package/esm/__version.js +1 -1
  4. package/esm/_staging/automation/index.d.ts +6 -0
  5. package/esm/_staging/automation/index.d.ts.map +1 -1
  6. package/esm/_staging/automation/index.js +7 -0
  7. package/esm/_staging/dashboard/flexibleLayout/builder/utils.d.ts +45 -0
  8. package/esm/_staging/dashboard/flexibleLayout/builder/utils.d.ts.map +1 -0
  9. package/esm/_staging/dashboard/flexibleLayout/builder/utils.js +54 -0
  10. package/esm/_staging/dateFilterConfig/fixtures.d.ts +10 -0
  11. package/esm/_staging/dateFilterConfig/fixtures.d.ts.map +1 -0
  12. package/esm/_staging/dateFilterConfig/fixtures.js +60 -0
  13. package/esm/_staging/layout/coordinates.mock.d.ts +17 -0
  14. package/esm/_staging/layout/coordinates.mock.d.ts.map +1 -0
  15. package/esm/_staging/layout/coordinates.mock.js +103 -0
  16. package/esm/index.d.ts +2 -2
  17. package/esm/index.d.ts.map +1 -1
  18. package/esm/model/DashboardTester.d.ts +150 -0
  19. package/esm/model/DashboardTester.d.ts.map +1 -0
  20. package/esm/model/DashboardTester.js +208 -0
  21. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.d.ts.map +1 -1
  22. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.js +27 -1
  23. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.d.ts +9 -0
  24. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.d.ts.map +1 -0
  25. package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.js +27 -0
  26. package/esm/model/commandHandlers/timezone/changeDashboardTimezoneOverrideHandler.d.ts.map +1 -1
  27. package/esm/model/commandHandlers/timezone/changeDashboardTimezoneOverrideHandler.js +2 -11
  28. package/esm/model/commands/timezone.d.ts +10 -2
  29. package/esm/model/commands/timezone.d.ts.map +1 -1
  30. package/esm/model/commands/timezone.js +5 -2
  31. package/esm/model/fixtures/CatalogAvailability.fixtures.d.ts +14 -0
  32. package/esm/model/fixtures/CatalogAvailability.fixtures.d.ts.map +1 -0
  33. package/esm/model/fixtures/CatalogAvailability.fixtures.js +57 -0
  34. package/esm/model/fixtures/ComplexDashboard.fixtures.d.ts +56 -0
  35. package/esm/model/fixtures/ComplexDashboard.fixtures.d.ts.map +1 -0
  36. package/esm/model/fixtures/ComplexDashboard.fixtures.js +71 -0
  37. package/esm/model/fixtures/Dashboard.fixtures.d.ts +10 -0
  38. package/esm/model/fixtures/Dashboard.fixtures.d.ts.map +1 -0
  39. package/esm/model/fixtures/Dashboard.fixtures.js +13 -0
  40. package/esm/model/fixtures/Insights.fixtures.d.ts +6 -0
  41. package/esm/model/fixtures/Insights.fixtures.d.ts.map +1 -0
  42. package/esm/model/fixtures/Insights.fixtures.js +11 -0
  43. package/esm/model/fixtures/Layout.fixtures.d.ts +14 -0
  44. package/esm/model/fixtures/Layout.fixtures.d.ts.map +1 -0
  45. package/esm/model/fixtures/Layout.fixtures.js +115 -0
  46. package/esm/model/fixtures/SimpleDashboard.fixtures.d.ts +46 -0
  47. package/esm/model/fixtures/SimpleDashboard.fixtures.d.ts.map +1 -0
  48. package/esm/model/fixtures/SimpleDashboard.fixtures.js +315 -0
  49. package/esm/model/fixtures/SimpleDashboardNoDrills.fixtures.d.ts +28 -0
  50. package/esm/model/fixtures/SimpleDashboardNoDrills.fixtures.d.ts.map +1 -0
  51. package/esm/model/fixtures/SimpleDashboardNoDrills.fixtures.js +40 -0
  52. package/esm/plugins/customizationApis/fixtures/TestingDashboardCustomizationLogger.d.ts +16 -0
  53. package/esm/plugins/customizationApis/fixtures/TestingDashboardCustomizationLogger.d.ts.map +1 -0
  54. package/esm/plugins/customizationApis/fixtures/TestingDashboardCustomizationLogger.js +30 -0
  55. package/esm/plugins/customizationApis/utils.d.ts +3 -0
  56. package/esm/plugins/customizationApis/utils.d.ts.map +1 -0
  57. package/esm/plugins/customizationApis/utils.js +17 -0
  58. package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogDestination.d.ts +6 -0
  59. package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogDestination.d.ts.map +1 -0
  60. package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogDestination.js +13 -0
  61. package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogRecipients.d.ts +7 -0
  62. package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogRecipients.d.ts.map +1 -0
  63. package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogRecipients.js +12 -0
  64. package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.d.ts.map +1 -1
  65. package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.js +25 -13
  66. package/esm/presentation/automations/alerting/DefaultAlertingDialog/FormField.d.ts +8 -0
  67. package/esm/presentation/automations/alerting/DefaultAlertingDialog/FormField.d.ts.map +1 -0
  68. package/esm/presentation/automations/alerting/DefaultAlertingDialog/FormField.js +8 -0
  69. package/esm/presentation/automations/alerting/state/fixtures.d.ts +13 -0
  70. package/esm/presentation/automations/alerting/state/fixtures.d.ts.map +1 -0
  71. package/esm/presentation/automations/alerting/state/fixtures.js +37 -0
  72. package/esm/presentation/automations/alerting/types.d.ts +42 -2
  73. package/esm/presentation/automations/alerting/types.d.ts.map +1 -1
  74. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.d.ts.map +1 -1
  75. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.js +24 -5
  76. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.d.ts +1 -5
  77. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.d.ts.map +1 -1
  78. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.js +2 -2
  79. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts +0 -4
  80. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts.map +1 -1
  81. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogDestination.d.ts +6 -0
  82. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogDestination.d.ts.map +1 -0
  83. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogDestination.js +10 -0
  84. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogRecipients.d.ts +6 -0
  85. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogRecipients.d.ts.map +1 -0
  86. package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogRecipients.js +8 -0
  87. package/esm/presentation/automations/scheduledEmail/state/fixtures.d.ts +18 -0
  88. package/esm/presentation/automations/scheduledEmail/state/fixtures.d.ts.map +1 -0
  89. package/esm/presentation/automations/scheduledEmail/state/fixtures.js +105 -0
  90. package/esm/presentation/automations/scheduledEmail/types.d.ts +52 -3
  91. package/esm/presentation/automations/scheduledEmail/types.d.ts.map +1 -1
  92. package/esm/presentation/automations/shared/automationFilters/parameterFixtures.d.ts +5 -0
  93. package/esm/presentation/automations/shared/automationFilters/parameterFixtures.d.ts.map +1 -0
  94. package/esm/presentation/automations/shared/automationFilters/parameterFixtures.js +22 -0
  95. package/esm/presentation/automations/shared/slots/types.d.ts +67 -1
  96. package/esm/presentation/automations/shared/slots/types.d.ts.map +1 -1
  97. package/esm/presentation/automations/shared/test/fixtures.d.ts +9 -0
  98. package/esm/presentation/automations/shared/test/fixtures.d.ts.map +1 -0
  99. package/esm/presentation/automations/shared/test/fixtures.js +101 -0
  100. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayout.d.ts +17 -0
  101. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayout.d.ts.map +1 -0
  102. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayout.js +18 -0
  103. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutItemRenderer.d.ts +12 -0
  104. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutItemRenderer.d.ts.map +1 -0
  105. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutItemRenderer.js +26 -0
  106. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutMocks.d.ts +20 -0
  107. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutMocks.d.ts.map +1 -0
  108. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutMocks.js +95 -0
  109. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutRowRenderer.d.ts +14 -0
  110. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutRowRenderer.d.ts.map +1 -0
  111. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutRowRenderer.js +9 -0
  112. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorder.d.ts +9 -0
  113. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorder.d.ts.map +1 -0
  114. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorder.js +17 -0
  115. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorderMarker.d.ts +6 -0
  116. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorderMarker.d.ts.map +1 -0
  117. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorderMarker.js +10 -0
  118. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeader.d.ts +9 -0
  119. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeader.d.ts.map +1 -0
  120. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeader.js +14 -0
  121. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeaderRenderer.d.ts +8 -0
  122. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeaderRenderer.d.ts.map +1 -0
  123. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeaderRenderer.js +49 -0
  124. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionRenderer.d.ts +7 -0
  125. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionRenderer.d.ts.map +1 -0
  126. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionRenderer.js +33 -0
  127. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutTypes.d.ts +62 -0
  128. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutTypes.d.ts.map +1 -0
  129. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutTypes.js +2 -0
  130. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidget.d.ts +11 -0
  131. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidget.d.ts.map +1 -0
  132. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidget.js +4 -0
  133. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidgetRenderer.d.ts +8 -0
  134. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidgetRenderer.d.ts.map +1 -0
  135. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidgetRenderer.js +28 -0
  136. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/LayoutTypes.d.ts +26 -0
  137. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/LayoutTypes.d.ts.map +1 -0
  138. package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/LayoutTypes.js +21 -0
  139. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/EditAlert.d.ts.map +1 -1
  140. package/esm/presentation/widget/insight/configuration/InsightAlertConfig/EditAlert.js +1 -1
  141. package/esm/sdk-ui-dashboard.d.ts +172 -5
  142. package/package.json +21 -21
@@ -0,0 +1,150 @@
1
+ import { type PayloadAction } from "@reduxjs/toolkit";
2
+ import { type RecordedBackendConfig } from "@gooddata/sdk-backend-mockingbird";
3
+ import { type IBackendCapabilities } from "@gooddata/sdk-backend-spi";
4
+ import { type Identifier } from "@gooddata/sdk-model";
5
+ import { type IRenderingWorkerConfiguration } from "./commandHandlers/render/types.js";
6
+ import { type DashboardCommandType } from "./commands/base.js";
7
+ import { type InitializeDashboard } from "./commands/dashboard.js";
8
+ import { type DashboardEventType } from "./events/base.js";
9
+ import { type DashboardEvents } from "./events/index.js";
10
+ import { HeadlessDashboard } from "./headlessDashboard/HeadlessDashboard.js";
11
+ import { type IDashboardQueryService } from "./store/_infra/queryService.js";
12
+ import { type DashboardState } from "./store/types.js";
13
+ import { type DashboardContext, type DashboardModelCustomizationFns } from "./types/commonTypes.js";
14
+ type DashboardTesterConfig = {
15
+ queryServices?: IDashboardQueryService<any, any>[];
16
+ renderingWorkerConfig?: IRenderingWorkerConfiguration;
17
+ customizationFns?: DashboardModelCustomizationFns;
18
+ };
19
+ export declare class DashboardTester extends HeadlessDashboard {
20
+ protected constructor(ctx: DashboardContext, config?: DashboardTesterConfig);
21
+ /**
22
+ * Creates an instance of DashboardTester set up to run tests on top of a dashboard with the provided
23
+ * identifier. The dashboard will be loaded from recorded backend, from its reference workspace.
24
+ *
25
+ * You may additionally influence how the different query services behave (typically to stub/mock the service)
26
+ */
27
+ static forRecording(identifier: Identifier, testerConfig?: DashboardTesterConfig, backendConfig?: RecordedBackendConfig, customCapabilities?: Partial<IBackendCapabilities>): DashboardTester;
28
+ /**
29
+ * Creates an instance of DashboardTester set up to run tests on top of an empty, freshly initialized dashboard.
30
+ *
31
+ * You may additionally influence how the different query services behave (typically to stub/mock the service)
32
+ */
33
+ static forNewDashboard(testerConfig?: DashboardTesterConfig, backendConfig?: RecordedBackendConfig): DashboardTester;
34
+ /**
35
+ * Wait the specified time.
36
+ *
37
+ * @param timeout - timeout after which the wait will be resolved
38
+ * @returns promise
39
+ */
40
+ wait(timeout: number): Promise<void>;
41
+ /**
42
+ * Returns all actions that were dispatched since the tester was created or since it was last reset.
43
+ */
44
+ dispatchedActions(): ReadonlyArray<PayloadAction<any>>;
45
+ /**
46
+ * Wait for all of the listed actions to occur. The wait is bounded by a timeout that is 1s by default.
47
+ *
48
+ * This is useful when testing commands that emit multiple events and you need to verify that all of the
49
+ * events happened. This function does not care about the order in which the events occurred.
50
+ *
51
+ * @param actionTypes - action types to wait for
52
+ * @param timeout - timeout after which the wait fails
53
+ */
54
+ waitForAll(actionTypes: ReadonlyArray<DashboardEventType | DashboardCommandType | string>, timeout?: number): Promise<any>;
55
+ /**
56
+ * Returns all events that were emitted during execution. Events are a sub-type of actions - they are
57
+ * actions that are suitable for external consumption and describe what has happened in the dashboard.
58
+ *
59
+ * The events are accumulated during test run. You may reset them using `resetMonitors`
60
+ */
61
+ emittedEvents(): ReadonlyArray<DashboardEvents>;
62
+ /**
63
+ * Resets internal state of the tester's monitors. The captured actions will be cleared up as part
64
+ * of this.
65
+ */
66
+ resetMonitors(): void;
67
+ /**
68
+ * Returns dashboard state.
69
+ */
70
+ state(): DashboardState;
71
+ /**
72
+ * Returns digests of all events that were emitted during execution. Digest contains just the event
73
+ * type and the correlation id of the event. The payload is discarded.
74
+ *
75
+ * This is useful for snapshotting event sequence.
76
+ */
77
+ emittedEventsDigest(): ReadonlyArray<{
78
+ type: string;
79
+ correlationId?: string;
80
+ }>;
81
+ }
82
+ export interface IPreloadedTesterOptions {
83
+ /**
84
+ * Customize the load command.
85
+ *
86
+ * Default is plain command created by `initializeDashboard()`.
87
+ */
88
+ initCommand?: InitializeDashboard;
89
+ /**
90
+ * Customize recorded backend configuration.
91
+ *
92
+ * Default is no customization.
93
+ */
94
+ backendConfig?: RecordedBackendConfig;
95
+ /**
96
+ * Customize recorded backend capabilities
97
+ *
98
+ * Default is no customization
99
+ */
100
+ customCapabilities?: Partial<IBackendCapabilities>;
101
+ /**
102
+ * Customize implementations of query services to use for the component.
103
+ *
104
+ * Default is no customization, meaning default implementations will be used. Note that with default
105
+ * implementations you may encounter runtime errors as they want to use SPI methods that are not implemented
106
+ * on the recorded analytical backend.
107
+ */
108
+ queryServices?: IDashboardQueryService<any, any>[];
109
+ /**
110
+ * Customize dashboard model customization functions.
111
+ *
112
+ * Default is no customization.
113
+ */
114
+ customizationFns?: DashboardModelCustomizationFns;
115
+ }
116
+ /**
117
+ * This factory will return a function that can be integrated into vitest's `beforeAll` or `beforeEach` statements. That returned
118
+ * function will drive initialization of the dashboard tester and will tell vitest it's `done` or it will `fail`.
119
+ *
120
+ * When successfully loaded, the returned function will call the `onLoaded` callback
121
+ *
122
+ * An example usage:
123
+ *
124
+ * ```
125
+ * let Tester: DashboardTester;
126
+ *
127
+ * beforeEach(async ()=> {
128
+ * await preloadedTesterFactory2((tester) => {
129
+ * Tester = tester;
130
+ * }, SimpleDashboardIdentifier);
131
+ * });
132
+ *
133
+ * it("should do xyz", () => {
134
+ *
135
+ * })
136
+ * ```
137
+ *
138
+ * Obvious warning: beforeAll creates one instance for all tests and is therefore not safe when some tests do modifications of
139
+ * the dashboard. Use beforeEach in that case.
140
+ *
141
+ * Note: before sending the instance of dashboard tester, the function will ensure all the event monitors are reset so
142
+ * that the captured events related to load do not interfere with the test itself.
143
+ *
144
+ * @param onLoaded - function to call when the dashboard is successfully loaded
145
+ * @param identifier - identifier of the dashboard to load
146
+ * @param options - options influencing how the tester is created
147
+ */
148
+ export declare function preloadedTesterFactory(onLoaded: (tester: DashboardTester) => void | Promise<void>, identifier?: Identifier, options?: IPreloadedTesterOptions): Promise<void>;
149
+ export {};
150
+ //# sourceMappingURL=DashboardTester.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardTester.d.ts","sourceRoot":"","sources":["../../src/model/DashboardTester.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ // (C) 2021-2026 GoodData Corporation
2
+ import { ReferenceRecordings } from "@gooddata/reference-workspace";
3
+ import { defaultRecordedBackendCapabilities, objRefsToStringKey, recordedBackend, } from "@gooddata/sdk-backend-mockingbird";
4
+ import { idRef } from "@gooddata/sdk-model";
5
+ import { newRenderingWorker } from "./commandHandlers/render/renderingWorker.js";
6
+ import { initializeDashboard } from "./commands/dashboard.js";
7
+ import { isDashboardCommandStarted, isDashboardQueryCompleted, isDashboardQueryStarted, } from "./events/general.js";
8
+ import { HeadlessDashboard } from "./headlessDashboard/HeadlessDashboard.js";
9
+ export class DashboardTester extends HeadlessDashboard {
10
+ constructor(ctx, config) {
11
+ const headlessDahboardConfig = {
12
+ queryServices: config?.queryServices,
13
+ backgroundWorkers: [newRenderingWorker(config?.renderingWorkerConfig || {})],
14
+ customizationFns: config?.customizationFns,
15
+ };
16
+ super(ctx, headlessDahboardConfig);
17
+ }
18
+ /**
19
+ * Creates an instance of DashboardTester set up to run tests on top of a dashboard with the provided
20
+ * identifier. The dashboard will be loaded from recorded backend, from its reference workspace.
21
+ *
22
+ * You may additionally influence how the different query services behave (typically to stub/mock the service)
23
+ */
24
+ static forRecording(identifier, testerConfig, backendConfig, customCapabilities) {
25
+ const ctx = {
26
+ backend: recordedBackend(ReferenceRecordings.Recordings, {
27
+ ...backendConfig,
28
+ getCommonAttributesResponses: {
29
+ ...commonAttributeResponses,
30
+ ...(backendConfig?.getCommonAttributesResponses || {}),
31
+ },
32
+ }, {
33
+ ...defaultRecordedBackendCapabilities,
34
+ ...customCapabilities,
35
+ }),
36
+ workspace: "reference-workspace",
37
+ dashboardRef: idRef(identifier),
38
+ };
39
+ return new DashboardTester(ctx, testerConfig);
40
+ }
41
+ /**
42
+ * Creates an instance of DashboardTester set up to run tests on top of an empty, freshly initialized dashboard.
43
+ *
44
+ * You may additionally influence how the different query services behave (typically to stub/mock the service)
45
+ */
46
+ static forNewDashboard(testerConfig, backendConfig) {
47
+ const ctx = {
48
+ backend: recordedBackend(ReferenceRecordings.Recordings, {
49
+ ...backendConfig,
50
+ getCommonAttributesResponses: {
51
+ ...commonAttributeResponses,
52
+ ...(backendConfig?.getCommonAttributesResponses || {}),
53
+ },
54
+ }),
55
+ workspace: "reference-workspace",
56
+ };
57
+ return new DashboardTester(ctx, testerConfig);
58
+ }
59
+ /**
60
+ * Wait the specified time.
61
+ *
62
+ * @param timeout - timeout after which the wait will be resolved
63
+ * @returns promise
64
+ */
65
+ wait(timeout) {
66
+ return new Promise((resolve) => {
67
+ setTimeout(() => {
68
+ resolve();
69
+ }, timeout);
70
+ });
71
+ }
72
+ /**
73
+ * Returns all actions that were dispatched since the tester was created or since it was last reset.
74
+ */
75
+ dispatchedActions() {
76
+ return this.capturedActions.slice();
77
+ }
78
+ /**
79
+ * Wait for all of the listed actions to occur. The wait is bounded by a timeout that is 1s by default.
80
+ *
81
+ * This is useful when testing commands that emit multiple events and you need to verify that all of the
82
+ * events happened. This function does not care about the order in which the events occurred.
83
+ *
84
+ * @param actionTypes - action types to wait for
85
+ * @param timeout - timeout after which the wait fails
86
+ */
87
+ waitForAll(actionTypes, timeout = 1000) {
88
+ return Promise.race([
89
+ Promise.all(actionTypes.map((actionType) => this.getOrCreateMonitoredAction(actionType).promise)),
90
+ new Promise((_, reject) => {
91
+ setTimeout(() => {
92
+ reject(new Error(`Wait for all actions '${actionTypes.join(", ")}' timed out after ${timeout}ms`));
93
+ }, timeout);
94
+ }),
95
+ ]);
96
+ }
97
+ /**
98
+ * Returns all events that were emitted during execution. Events are a sub-type of actions - they are
99
+ * actions that are suitable for external consumption and describe what has happened in the dashboard.
100
+ *
101
+ * The events are accumulated during test run. You may reset them using `resetMonitors`
102
+ */
103
+ emittedEvents() {
104
+ return this.capturedEvents.slice();
105
+ }
106
+ /**
107
+ * Resets internal state of the tester's monitors. The captured actions will be cleared up as part
108
+ * of this.
109
+ */
110
+ resetMonitors() {
111
+ this.capturedActions = [];
112
+ this.capturedEvents = [];
113
+ this.monitoredActions = {};
114
+ }
115
+ /**
116
+ * Returns dashboard state.
117
+ */
118
+ state() {
119
+ return super.state();
120
+ }
121
+ /**
122
+ * Returns digests of all events that were emitted during execution. Digest contains just the event
123
+ * type and the correlation id of the event. The payload is discarded.
124
+ *
125
+ * This is useful for snapshotting event sequence.
126
+ */
127
+ emittedEventsDigest() {
128
+ return this.emittedEvents().map((evt) => {
129
+ if (isDashboardQueryStarted(evt) || isDashboardQueryCompleted(evt)) {
130
+ return {
131
+ type: evt.type,
132
+ correlationId: evt.correlationId,
133
+ queryType: evt.payload.query.type,
134
+ };
135
+ }
136
+ if (isDashboardCommandStarted(evt)) {
137
+ return {
138
+ type: evt.type,
139
+ correlationId: evt.correlationId,
140
+ commandType: evt.payload.command.type,
141
+ };
142
+ }
143
+ return {
144
+ type: evt.type,
145
+ correlationId: evt.correlationId,
146
+ };
147
+ });
148
+ }
149
+ }
150
+ /**
151
+ * This factory will return a function that can be integrated into vitest's `beforeAll` or `beforeEach` statements. That returned
152
+ * function will drive initialization of the dashboard tester and will tell vitest it's `done` or it will `fail`.
153
+ *
154
+ * When successfully loaded, the returned function will call the `onLoaded` callback
155
+ *
156
+ * An example usage:
157
+ *
158
+ * ```
159
+ * let Tester: DashboardTester;
160
+ *
161
+ * beforeEach(async ()=> {
162
+ * await preloadedTesterFactory2((tester) => {
163
+ * Tester = tester;
164
+ * }, SimpleDashboardIdentifier);
165
+ * });
166
+ *
167
+ * it("should do xyz", () => {
168
+ *
169
+ * })
170
+ * ```
171
+ *
172
+ * Obvious warning: beforeAll creates one instance for all tests and is therefore not safe when some tests do modifications of
173
+ * the dashboard. Use beforeEach in that case.
174
+ *
175
+ * Note: before sending the instance of dashboard tester, the function will ensure all the event monitors are reset so
176
+ * that the captured events related to load do not interfere with the test itself.
177
+ *
178
+ * @param onLoaded - function to call when the dashboard is successfully loaded
179
+ * @param identifier - identifier of the dashboard to load
180
+ * @param options - options influencing how the tester is created
181
+ */
182
+ export async function preloadedTesterFactory(onLoaded, identifier, options = {}) {
183
+ const { initCommand = initializeDashboard(), queryServices, backendConfig, customCapabilities, customizationFns, } = options;
184
+ const tester = identifier
185
+ ? DashboardTester.forRecording(identifier, { queryServices, customizationFns }, {
186
+ ...backendConfig,
187
+ }, {
188
+ ...customCapabilities,
189
+ })
190
+ : DashboardTester.forNewDashboard({ queryServices, customizationFns }, {
191
+ ...backendConfig,
192
+ });
193
+ tester.dispatch(initCommand);
194
+ await tester
195
+ .waitFor("GDC.DASH/EVT.INITIALIZED")
196
+ .then(() => Promise.resolve(onLoaded(tester)).then(() => tester.resetMonitors()))
197
+ .catch((err) => {
198
+ throw `DashboardTester failed to load dashboard: ${err.message}`;
199
+ });
200
+ }
201
+ const commonAttributeResponses = {
202
+ [objRefsToStringKey([idRef("obj_1054"), idRef("obj_1086")])]: [idRef("obj_1057")],
203
+ [objRefsToStringKey([idRef("obj_1054"), idRef("obj_1088")])]: [idRef("obj_1057")],
204
+ [objRefsToStringKey([idRef("obj_1054"), idRef("obj_1070")])]: [idRef("obj_1057")],
205
+ [objRefsToStringKey([idRef("obj_1070"), idRef("obj_1088")])]: [idRef("obj_1057")],
206
+ [objRefsToStringKey([idRef("obj_1086"), idRef("obj_1088")])]: [idRef("obj_1057")],
207
+ [objRefsToStringKey([idRef("obj_1070"), idRef("obj_1086")])]: [idRef("obj_1057")],
208
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/dashboard/initializeDashboardHandler/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAiC,KAAK,iBAAiB,EAAc,MAAM,2BAA2B,CAAC;AAC9G,OAAO,EACH,KAAK,UAAU,EAIf,KAAK,sBAAsB,EAW9B,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAqB1E,OAAO,EACH,KAAK,gBAAgB,EAGxB,MAAM,+BAA+B,CAAC;AA4bvC,wBAAiB,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB;;;yDAgB9E;AAkCD,wBAAiB,2BAA2B,CAAC,GAAG,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU;;;0EAKxF;AAED,wBAAiB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,sNAW3D;AAcD,wBAAiB,0BAA0B,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB,GAAG,YAAY,CA6BzG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/dashboard/initializeDashboardHandler/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAiC,KAAK,iBAAiB,EAAc,MAAM,2BAA2B,CAAC;AAC9G,OAAO,EACH,KAAK,UAAU,EAIf,KAAK,sBAAsB,EAW9B,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAsB1E,OAAO,EACH,KAAK,gBAAgB,EAGxB,MAAM,+BAA+B,CAAC;AAwcvC,wBAAiB,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB;;;yDAgB9E;AAkCD,wBAAiB,2BAA2B,CAAC,GAAG,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU;;;0EAKxF;AAED,wBAAiB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,sNAW3D;AAoCD,wBAAiB,0BAA0B,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,mBAAmB,GAAG,YAAY,CAoCzG"}
@@ -5,6 +5,7 @@ import { all, call, put, spawn } from "redux-saga/effects";
5
5
  import { walkLayout } from "@gooddata/sdk-backend-spi";
6
6
  import { areObjRefsEqual, isDrillToInsight, isInsightWidget, isVisualizationSwitcherWidget, serializeObjRef, } from "@gooddata/sdk-model";
7
7
  import { createDisplayFormMap, createDisplayFormMapFromCatalog, } from "../../../../_staging/catalog/displayFormMap.js";
8
+ import { changeDashboardTimezoneOverride } from "../../../commands/timezone.js";
8
9
  import { dashboardInitialized } from "../../../events/dashboard.js";
9
10
  import { getPrivateContext } from "../../../store/_infra/contexts.js";
10
11
  import { accessibleDashboardsActions } from "../../../store/accessibleDashboards/index.js";
@@ -25,8 +26,10 @@ import { tabsActions } from "../../../store/tabs/index.js";
25
26
  import { DEFAULT_TAB_ID } from "../../../store/tabs/tabsState.js";
26
27
  import { uiActions } from "../../../store/ui/index.js";
27
28
  import { userActions } from "../../../store/user/index.js";
29
+ import { changeDashboardTimezoneOverrideHandler } from "../../timezone/changeDashboardTimezoneOverrideHandler.js";
28
30
  import { applyDefaultFilterView } from "../common/filterViews.js";
29
31
  import { actionsToInitializeExistingDashboard, actionsToInitializeNewDashboard, } from "../common/stateInitializers.js";
32
+ import { loadAutomationTimezone } from "./loadAutomationTimezone.js";
30
33
  import { loadCatalog } from "./loadCatalog.js";
31
34
  import { loadDashboardList } from "./loadDashboardList.js";
32
35
  import { loadDashboardParameters } from "./loadDashboardParameters.js";
@@ -175,8 +178,9 @@ function* loadExistingDashboard(ctx, cmd, dashboardRef) {
175
178
  call(loadDateHierarchyTemplates, ctx),
176
179
  call(loadFilterViews, ctx),
177
180
  call(loadExportTimezone, ctx),
181
+ call(loadAutomationTimezone, ctx),
178
182
  ];
179
- const [dashboardWithReferences, { resolvedConfig: config, additionalData: { workspaceAutomationsCount, notificationChannelsCount }, }, permissions, entitlements, user, dashboardPermissions, dateHierarchyTemplates, filterViews, exportTimezone,] = yield all(calls);
183
+ const [dashboardWithReferences, { resolvedConfig: config, additionalData: { workspaceAutomationsCount, notificationChannelsCount }, }, permissions, entitlements, user, dashboardPermissions, dateHierarchyTemplates, filterViews, exportTimezone, automationTimezone,] = yield all(calls);
180
184
  const { dashboard: loadedDashboard, references: { insights }, } = dashboardWithReferences;
181
185
  const dashboardWithFilterView = applyDefaultFilterView(loadedDashboard, filterViews, config.exportId);
182
186
  // Resolve active tab: URL's initialTabId takes precedence, otherwise default to first tab
@@ -221,6 +225,8 @@ function* loadExistingDashboard(ctx, cmd, dashboardRef) {
221
225
  return {
222
226
  batch,
223
227
  event,
228
+ // an export render takes its timezone from the export itself
229
+ automationTimezone: exportTimezone ? undefined : automationTimezone,
224
230
  };
225
231
  }
226
232
  function* initializeNewDashboard(ctx, cmd) {
@@ -339,6 +345,20 @@ function* advancedLoader(ctx, cmd, dashboard) {
339
345
  call(requestDashboardsList, ctx),
340
346
  ]);
341
347
  }
348
+ /**
349
+ * Applies a deep-linked automation's timezone as the dashboard's timezone override. A rejection
350
+ * (feature disabled, invalid stored timezone) leaves the dashboard on its own timezone rather
351
+ * than failing the initialization.
352
+ */
353
+ function* restoreAutomationTimezone(ctx, timezoneId, correlationId) {
354
+ try {
355
+ const event = yield call(changeDashboardTimezoneOverrideHandler, ctx, changeDashboardTimezoneOverride(timezoneId, correlationId, true));
356
+ yield put(event);
357
+ }
358
+ catch (reason) {
359
+ console.error(`Restoring the timezone "${timezoneId}" of the deep-linked automation failed`, reason);
360
+ }
361
+ }
342
362
  export function* initializeDashboardHandler(ctx, cmd) {
343
363
  const { dashboardRef } = ctx;
344
364
  try {
@@ -351,6 +371,12 @@ export function* initializeDashboardHandler(ctx, cmd) {
351
371
  result = (yield call(initializeNewDashboard, ctx, cmd));
352
372
  }
353
373
  yield put(result.batch);
374
+ // before the loading success that lets the widgets render and execute, so the notification
375
+ // recipient never sees the dashboard's own timezone first. The view-mode override check is
376
+ // bypassed: the automation was evaluated in this timezone, whatever the dashboard says now.
377
+ if (result.automationTimezone) {
378
+ yield call(restoreAutomationTimezone, ctx, result.automationTimezone, cmd.correlationId);
379
+ }
354
380
  yield put(loadingActions.setLoadingSuccess());
355
381
  yield put(result.event);
356
382
  if (dashboardRef) {
@@ -0,0 +1,9 @@
1
+ import { type DashboardContext } from "../../../types/commonTypes.js";
2
+ /**
3
+ * Loads the timezone baked into the automation the dashboard is deep-linked to (the focus
4
+ * object's `automationId`, as used by the links in alert and scheduled-export notifications).
5
+ * Restoring it is what makes the dashboard match the numbers the recipient was mailed.
6
+ * Undefined means the dashboard's own (or workspace/organization) timezone applies.
7
+ */
8
+ export declare function loadAutomationTimezone(ctx: DashboardContext): Promise<string | undefined>;
9
+ //# sourceMappingURL=loadAutomationTimezone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadAutomationTimezone.d.ts","sourceRoot":"","sources":["../../../../../src/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAmB/F"}
@@ -0,0 +1,27 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { getAutomationTimezone } from "../../../../_staging/automation/index.js";
3
+ /**
4
+ * Loads the timezone baked into the automation the dashboard is deep-linked to (the focus
5
+ * object's `automationId`, as used by the links in alert and scheduled-export notifications).
6
+ * Restoring it is what makes the dashboard match the numbers the recipient was mailed.
7
+ * Undefined means the dashboard's own (or workspace/organization) timezone applies.
8
+ */
9
+ export async function loadAutomationTimezone(ctx) {
10
+ const { automationId } = ctx.config?.focusObject ?? {};
11
+ if (!automationId) {
12
+ return undefined;
13
+ }
14
+ try {
15
+ // the service getter itself throws on backends without automation support
16
+ const automation = await ctx.backend
17
+ .workspace(ctx.workspace)
18
+ .automations()
19
+ .getAutomation(automationId);
20
+ return getAutomationTimezone(automation);
21
+ }
22
+ catch (error) {
23
+ // a missing or inaccessible automation must not fail the dashboard load
24
+ console.error("Loading of the automation timezone failed", error);
25
+ return undefined;
26
+ }
27
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"changeDashboardTimezoneOverrideHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/timezone/changeDashboardTimezoneOverrideHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAAE,KAAK,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAEnF,OAAO,EACH,KAAK,iCAAiC,EAEzC,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAWnE,wBAAiB,sCAAsC,CACnD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,gCAAgC,GACtC,YAAY,CAAC,iCAAiC,CAAC,CAuCjD"}
1
+ {"version":3,"file":"changeDashboardTimezoneOverrideHandler.d.ts","sourceRoot":"","sources":["../../../../src/model/commandHandlers/timezone/changeDashboardTimezoneOverrideHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAAE,KAAK,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAEnF,OAAO,EACH,KAAK,iCAAiC,EAEzC,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,wBAAiB,sCAAsC,CACnD,GAAG,EAAE,gBAAgB,EACrB,GAAG,EAAE,gCAAgC,GACtC,YAAY,CAAC,iCAAiC,CAAC,CAuCjD"}
@@ -1,20 +1,11 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { put, select } from "redux-saga/effects";
3
- import { resolveTimezoneId } from "@gooddata/sdk-model";
3
+ import { isValidIanaTimezoneId, resolveTimezoneId } from "@gooddata/sdk-model";
4
4
  import { invalidArgumentsProvided } from "../../events/general.js";
5
5
  import { dashboardTimezoneOverrideChanged, } from "../../events/timezone.js";
6
6
  import { selectEnableTimezoneChange } from "../../store/config/configSelectors.js";
7
7
  import { selectDashboardTimezoneConfig, selectEffectiveDashboardTimezone, } from "../../store/meta/metaSelectors.js";
8
8
  import { uiActions } from "../../store/ui/index.js";
9
- function isValidIanaTimezoneId(timezoneId) {
10
- try {
11
- new Intl.DateTimeFormat(undefined, { timeZone: timezoneId });
12
- return true;
13
- }
14
- catch {
15
- return false;
16
- }
17
- }
18
9
  export function* changeDashboardTimezoneOverrideHandler(ctx, cmd) {
19
10
  // the gating protects paths that arrive from outside the UI (e.g. the embedding
20
11
  // setTimezone postMessage), which do not go through the menu-item visibility checks
@@ -23,7 +14,7 @@ export function* changeDashboardTimezoneOverrideHandler(ctx, cmd) {
23
14
  throw invalidArgumentsProvided(ctx, cmd, "Cannot change the timezone override: the dashboard timezone feature is disabled.");
24
15
  }
25
16
  const timezoneConfig = yield select(selectDashboardTimezoneConfig);
26
- if (timezoneConfig?.allowUserOverrideInViewMode !== true) {
17
+ if (!cmd.payload.bypassUserOverrideCheck && timezoneConfig?.allowUserOverrideInViewMode !== true) {
27
18
  throw invalidArgumentsProvided(ctx, cmd, "Cannot change the timezone override: the dashboard's timezone configuration does not allow user overrides in view mode.");
28
19
  }
29
20
  // the model layer is the single resolution point of the browser-detected sentinel for the
@@ -11,6 +11,12 @@ export interface IChangeDashboardTimezoneOverridePayload {
11
11
  * the dashboard/workspace configuration applies again.
12
12
  */
13
13
  readonly timezoneId: string | undefined;
14
+ /**
15
+ * Skips the check that the dashboard's timezone configuration allows user overrides in view
16
+ * mode, for restoring a timezone the platform already committed to (an export render, an
17
+ * automation deep link). The dashboard timezone feature flag is still honored.
18
+ */
19
+ readonly bypassUserOverrideCheck?: boolean;
14
20
  }
15
21
  /**
16
22
  * @alpha
@@ -29,14 +35,16 @@ export interface IChangeDashboardTimezoneOverride extends IDashboardCommand {
29
35
  *
30
36
  * The command is rejected when the ad-hoc override is not allowed: the dashboard timezone
31
37
  * feature is disabled or the dashboard's timezone configuration does not allow user overrides
32
- * in view mode.
38
+ * in view mode — the latter bypassable via `bypassUserOverrideCheck`.
33
39
  *
34
40
  * @param timezoneId - concrete IANA timezone id, the BROWSER_DETECTED sentinel (resolved to the
35
41
  * viewer's browser timezone by the handler), or undefined to clear the override
36
42
  * @param correlationId - specify correlation id to use for this command. this will be included in all
37
43
  * events that will be emitted during the command processing
44
+ * @param bypassUserOverrideCheck - see
45
+ * {@link IChangeDashboardTimezoneOverridePayload.bypassUserOverrideCheck}
38
46
  *
39
47
  * @alpha
40
48
  */
41
- export declare function changeDashboardTimezoneOverride(timezoneId: string | undefined, correlationId?: string): IChangeDashboardTimezoneOverride;
49
+ export declare function changeDashboardTimezoneOverride(timezoneId: string | undefined, correlationId?: string, bypassUserOverrideCheck?: boolean): IChangeDashboardTimezoneOverride;
42
50
  //# sourceMappingURL=timezone.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../../../src/model/commands/timezone.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,uCAAuC;IACpD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,gCAAiC,SAAQ,iBAAiB;IACvE,QAAQ,CAAC,IAAI,EAAE,uCAAuC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,uCAAuC,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,+BAA+B,CAC3C,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,aAAa,CAAC,EAAE,MAAM,GACvB,gCAAgC,CAQlC"}
1
+ {"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../../../src/model/commands/timezone.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,uCAAuC;IACpD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAExC;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,gCAAiC,SAAQ,iBAAiB;IACvE,QAAQ,CAAC,IAAI,EAAE,uCAAuC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,uCAAuC,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,+BAA+B,CAC3C,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,aAAa,CAAC,EAAE,MAAM,EACtB,uBAAuB,CAAC,EAAE,OAAO,GAClC,gCAAgC,CASlC"}
@@ -9,21 +9,24 @@
9
9
  *
10
10
  * The command is rejected when the ad-hoc override is not allowed: the dashboard timezone
11
11
  * feature is disabled or the dashboard's timezone configuration does not allow user overrides
12
- * in view mode.
12
+ * in view mode — the latter bypassable via `bypassUserOverrideCheck`.
13
13
  *
14
14
  * @param timezoneId - concrete IANA timezone id, the BROWSER_DETECTED sentinel (resolved to the
15
15
  * viewer's browser timezone by the handler), or undefined to clear the override
16
16
  * @param correlationId - specify correlation id to use for this command. this will be included in all
17
17
  * events that will be emitted during the command processing
18
+ * @param bypassUserOverrideCheck - see
19
+ * {@link IChangeDashboardTimezoneOverridePayload.bypassUserOverrideCheck}
18
20
  *
19
21
  * @alpha
20
22
  */
21
- export function changeDashboardTimezoneOverride(timezoneId, correlationId) {
23
+ export function changeDashboardTimezoneOverride(timezoneId, correlationId, bypassUserOverrideCheck) {
22
24
  return {
23
25
  type: "GDC.DASH/CMD.CHANGE_TIMEZONE_OVERRIDE",
24
26
  correlationId,
25
27
  payload: {
26
28
  timezoneId,
29
+ ...(bypassUserOverrideCheck ? { bypassUserOverrideCheck } : {}),
27
30
  },
28
31
  };
29
32
  }
@@ -0,0 +1,14 @@
1
+ import { type ICatalogDateDataset } from "@gooddata/sdk-model";
2
+ /**
3
+ * given all available datasets, this availability mock will pick 2 by name and associate relevance so that second one has more relevance
4
+ *
5
+ * Timeline date has greater relevance; see TimelineDateDatasetRef
6
+ * Activity date has lower relevance; see ActivityDateDatasetRef
7
+ */
8
+ export declare const MockAvailabilityWithDifferentRelevance: (datasets: ICatalogDateDataset[]) => ICatalogDateDataset[];
9
+ /**
10
+ * given all available datasets, this mock will pick 2 by name and ensure they have same relevance
11
+ */
12
+ export declare const MockAvailabilityWithSameRelevance: (datasets: ICatalogDateDataset[]) => ICatalogDateDataset[];
13
+ export declare const ActivityDateDatasetRef: import("@gooddata/sdk-model").IdentifierRef;
14
+ //# sourceMappingURL=CatalogAvailability.fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CatalogAvailability.fixtures.d.ts","sourceRoot":"","sources":["../../../src/model/fixtures/CatalogAvailability.fixtures.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAS,MAAM,qBAAqB,CAAC;AAuBtE;;;;;GAKG;AACH,eAAO,MAAM,sCAAsC,4DAclD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iCAAiC,4DAY7C,CAAC;AAEF,eAAO,MAAM,sBAAsB,6CAA4C,CAAC"}