@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.
- package/NOTICE +92923 -17333
- package/esm/__version.d.ts +1 -1
- package/esm/__version.js +1 -1
- package/esm/_staging/automation/index.d.ts +6 -0
- package/esm/_staging/automation/index.d.ts.map +1 -1
- package/esm/_staging/automation/index.js +7 -0
- package/esm/_staging/dashboard/flexibleLayout/builder/utils.d.ts +45 -0
- package/esm/_staging/dashboard/flexibleLayout/builder/utils.d.ts.map +1 -0
- package/esm/_staging/dashboard/flexibleLayout/builder/utils.js +54 -0
- package/esm/_staging/dateFilterConfig/fixtures.d.ts +10 -0
- package/esm/_staging/dateFilterConfig/fixtures.d.ts.map +1 -0
- package/esm/_staging/dateFilterConfig/fixtures.js +60 -0
- package/esm/_staging/layout/coordinates.mock.d.ts +17 -0
- package/esm/_staging/layout/coordinates.mock.d.ts.map +1 -0
- package/esm/_staging/layout/coordinates.mock.js +103 -0
- package/esm/index.d.ts +2 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/model/DashboardTester.d.ts +150 -0
- package/esm/model/DashboardTester.d.ts.map +1 -0
- package/esm/model/DashboardTester.js +208 -0
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.js +27 -1
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.d.ts +9 -0
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.d.ts.map +1 -0
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.js +27 -0
- package/esm/model/commandHandlers/timezone/changeDashboardTimezoneOverrideHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/timezone/changeDashboardTimezoneOverrideHandler.js +2 -11
- package/esm/model/commands/timezone.d.ts +10 -2
- package/esm/model/commands/timezone.d.ts.map +1 -1
- package/esm/model/commands/timezone.js +5 -2
- package/esm/model/fixtures/CatalogAvailability.fixtures.d.ts +14 -0
- package/esm/model/fixtures/CatalogAvailability.fixtures.d.ts.map +1 -0
- package/esm/model/fixtures/CatalogAvailability.fixtures.js +57 -0
- package/esm/model/fixtures/ComplexDashboard.fixtures.d.ts +56 -0
- package/esm/model/fixtures/ComplexDashboard.fixtures.d.ts.map +1 -0
- package/esm/model/fixtures/ComplexDashboard.fixtures.js +71 -0
- package/esm/model/fixtures/Dashboard.fixtures.d.ts +10 -0
- package/esm/model/fixtures/Dashboard.fixtures.d.ts.map +1 -0
- package/esm/model/fixtures/Dashboard.fixtures.js +13 -0
- package/esm/model/fixtures/Insights.fixtures.d.ts +6 -0
- package/esm/model/fixtures/Insights.fixtures.d.ts.map +1 -0
- package/esm/model/fixtures/Insights.fixtures.js +11 -0
- package/esm/model/fixtures/Layout.fixtures.d.ts +14 -0
- package/esm/model/fixtures/Layout.fixtures.d.ts.map +1 -0
- package/esm/model/fixtures/Layout.fixtures.js +115 -0
- package/esm/model/fixtures/SimpleDashboard.fixtures.d.ts +46 -0
- package/esm/model/fixtures/SimpleDashboard.fixtures.d.ts.map +1 -0
- package/esm/model/fixtures/SimpleDashboard.fixtures.js +315 -0
- package/esm/model/fixtures/SimpleDashboardNoDrills.fixtures.d.ts +28 -0
- package/esm/model/fixtures/SimpleDashboardNoDrills.fixtures.d.ts.map +1 -0
- package/esm/model/fixtures/SimpleDashboardNoDrills.fixtures.js +40 -0
- package/esm/plugins/customizationApis/fixtures/TestingDashboardCustomizationLogger.d.ts +16 -0
- package/esm/plugins/customizationApis/fixtures/TestingDashboardCustomizationLogger.d.ts.map +1 -0
- package/esm/plugins/customizationApis/fixtures/TestingDashboardCustomizationLogger.js +30 -0
- package/esm/plugins/customizationApis/utils.d.ts +3 -0
- package/esm/plugins/customizationApis/utils.d.ts.map +1 -0
- package/esm/plugins/customizationApis/utils.js +17 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogDestination.d.ts +6 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogDestination.d.ts.map +1 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogDestination.js +13 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogRecipients.d.ts +7 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogRecipients.d.ts.map +1 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogRecipients.js +12 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.d.ts.map +1 -1
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.js +25 -13
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/FormField.d.ts +8 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/FormField.d.ts.map +1 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/FormField.js +8 -0
- package/esm/presentation/automations/alerting/state/fixtures.d.ts +13 -0
- package/esm/presentation/automations/alerting/state/fixtures.d.ts.map +1 -0
- package/esm/presentation/automations/alerting/state/fixtures.js +37 -0
- package/esm/presentation/automations/alerting/types.d.ts +42 -2
- package/esm/presentation/automations/alerting/types.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.js +24 -5
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.d.ts +1 -5
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.js +2 -2
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts +0 -4
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogDestination.d.ts +6 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogDestination.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogDestination.js +10 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogRecipients.d.ts +6 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogRecipients.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/ScheduledEmailDialogRecipients.js +8 -0
- package/esm/presentation/automations/scheduledEmail/state/fixtures.d.ts +18 -0
- package/esm/presentation/automations/scheduledEmail/state/fixtures.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/state/fixtures.js +105 -0
- package/esm/presentation/automations/scheduledEmail/types.d.ts +52 -3
- package/esm/presentation/automations/scheduledEmail/types.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/parameterFixtures.d.ts +5 -0
- package/esm/presentation/automations/shared/automationFilters/parameterFixtures.d.ts.map +1 -0
- package/esm/presentation/automations/shared/automationFilters/parameterFixtures.js +22 -0
- package/esm/presentation/automations/shared/slots/types.d.ts +67 -1
- package/esm/presentation/automations/shared/slots/types.d.ts.map +1 -1
- package/esm/presentation/automations/shared/test/fixtures.d.ts +9 -0
- package/esm/presentation/automations/shared/test/fixtures.d.ts.map +1 -0
- package/esm/presentation/automations/shared/test/fixtures.js +101 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayout.d.ts +17 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayout.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayout.js +18 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutItemRenderer.d.ts +12 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutItemRenderer.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutItemRenderer.js +26 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutMocks.d.ts +20 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutMocks.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutMocks.js +95 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutRowRenderer.d.ts +14 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutRowRenderer.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutRowRenderer.js +9 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorder.d.ts +9 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorder.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorder.js +17 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorderMarker.d.ts +6 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorderMarker.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionBorderMarker.js +10 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeader.d.ts +9 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeader.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeader.js +14 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeaderRenderer.d.ts +8 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeaderRenderer.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionHeaderRenderer.js +49 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionRenderer.d.ts +7 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionRenderer.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutSectionRenderer.js +33 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutTypes.d.ts +62 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutTypes.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutTypes.js +2 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidget.d.ts +11 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidget.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidget.js +4 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidgetRenderer.d.ts +8 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidgetRenderer.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/DashboardEditLayoutWidgetRenderer.js +28 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/LayoutTypes.d.ts +26 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/LayoutTypes.d.ts.map +1 -0
- package/esm/presentation/flexibleLayout/useInKD/DashboardEditLayout/LayoutTypes.js +21 -0
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/EditAlert.d.ts.map +1 -1
- package/esm/presentation/widget/insight/configuration/InsightAlertConfig/EditAlert.js +1 -1
- package/esm/sdk-ui-dashboard.d.ts +172 -5
- 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;
|
|
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) {
|
package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.d.ts
ADDED
|
@@ -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"}
|
package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/loadAutomationTimezone.js
ADDED
|
@@ -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;
|
|
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;
|
|
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"}
|