@thoughtspot/visual-embed-sdk 1.37.0 → 1.37.1
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/cjs/package.json +2 -2
- package/cjs/src/auth.d.ts +9 -4
- package/cjs/src/auth.d.ts.map +1 -1
- package/cjs/src/auth.js +21 -0
- package/cjs/src/auth.js.map +1 -1
- package/cjs/src/auth.spec.js +48 -0
- package/cjs/src/auth.spec.js.map +1 -1
- package/cjs/src/embed/app.d.ts +99 -0
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +48 -3
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +61 -0
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +7 -0
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +10 -5
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +105 -0
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/types.d.ts +69 -4
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +54 -2
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.d.ts +35 -15
- package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.js +35 -15
- package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/cjs/src/utils/processData.js +6 -4
- package/cjs/src/utils/processData.js.map +1 -1
- package/dist/{index-DnIvX1FR.js → index-m9UtENc9.js} +1 -1
- package/dist/src/auth.d.ts +9 -4
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +99 -0
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/dist/src/types.d.ts +69 -4
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/graphql/answerService/answerService.d.ts +35 -15
- package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +183 -31
- package/dist/tsembed-react.js +182 -30
- package/dist/tsembed.es.js +183 -31
- package/dist/tsembed.js +182 -30
- package/dist/visual-embed-sdk-react-full.d.ts +212 -23
- package/dist/visual-embed-sdk-react.d.ts +212 -23
- package/dist/visual-embed-sdk.d.ts +212 -23
- package/lib/package.json +2 -2
- package/lib/src/auth.d.ts +9 -4
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js +21 -0
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.js +48 -0
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/embed/app.d.ts +99 -0
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +47 -2
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +62 -1
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +7 -0
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +10 -5
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +105 -0
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/types.d.ts +69 -4
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +54 -2
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.d.ts +35 -15
- package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.js +35 -15
- package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/lib/src/utils/processData.js +6 -4
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +212 -23
- package/package.json +2 -2
- package/src/auth.spec.ts +52 -0
- package/src/auth.ts +25 -3
- package/src/embed/app.spec.ts +88 -0
- package/src/embed/app.ts +133 -0
- package/src/embed/base.ts +9 -0
- package/src/embed/ts-embed.spec.ts +130 -0
- package/src/embed/ts-embed.ts +10 -4
- package/src/types.ts +68 -3
- package/src/utils/graphql/answerService/answerService.ts +35 -15
- package/src/utils/processData.ts +6 -6
package/src/embed/app.ts
CHANGED
|
@@ -83,6 +83,47 @@ export enum HomePageSearchBarMode {
|
|
|
83
83
|
AI_ANSWER = 'aiAnswer',
|
|
84
84
|
NONE = 'none'
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Define the version of the primary navbar
|
|
89
|
+
* @version SDK: 1.39.0 | Thoughtspot: 10.10.0.cl
|
|
90
|
+
*/
|
|
91
|
+
export enum PrimaryNavbarVersion {
|
|
92
|
+
/**
|
|
93
|
+
* Sliding (v3) introduces a new left-side navigation hub featuring a tab switcher,
|
|
94
|
+
* along with updates to the top navigation bar.
|
|
95
|
+
* It serves as the foundational version of the PrimaryNavBar.
|
|
96
|
+
*/
|
|
97
|
+
Sliding = 'v3',
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Define the version of the home page
|
|
102
|
+
* @version SDK: 1.39.0 | Thoughtspot: 10.10.0.cl
|
|
103
|
+
*/
|
|
104
|
+
export enum HomePage {
|
|
105
|
+
/**
|
|
106
|
+
* Modular (v2) introduces the updated Modular Home Experience.
|
|
107
|
+
* It serves as the foundational version of the home page.
|
|
108
|
+
*/
|
|
109
|
+
Modular = 'v2',
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Define the discovery experience
|
|
114
|
+
* @version SDK: 1.39.0 | Thoughtspot: 10.10.0.cl
|
|
115
|
+
*/
|
|
116
|
+
export interface DiscoveryExperience {
|
|
117
|
+
/**
|
|
118
|
+
* primaryNavbarVersion determines the version of the navigation version.
|
|
119
|
+
*/
|
|
120
|
+
primaryNavbarVersion?: PrimaryNavbarVersion;
|
|
121
|
+
/**
|
|
122
|
+
* homePage determines the version of the home page.
|
|
123
|
+
*/
|
|
124
|
+
homePage?: HomePage;
|
|
125
|
+
}
|
|
126
|
+
|
|
86
127
|
/**
|
|
87
128
|
* The view configuration for full app embedding.
|
|
88
129
|
* @group Embed components
|
|
@@ -151,6 +192,51 @@ export interface AppViewConfig extends Omit<ViewConfig, 'visibleTabs'> {
|
|
|
151
192
|
* ```
|
|
152
193
|
*/
|
|
153
194
|
enablePendoHelp?: boolean
|
|
195
|
+
/**
|
|
196
|
+
* Control the visibility of the hamburger icon on the top nav bar
|
|
197
|
+
* available when new navigation V3 is enabled.
|
|
198
|
+
*
|
|
199
|
+
* @default false
|
|
200
|
+
* @version SDK: 1.39.0 | Thoughtspot: 10.10.0.cl
|
|
201
|
+
* @example
|
|
202
|
+
* ```js
|
|
203
|
+
* const embed = new AppEmbed('#tsEmbed', {
|
|
204
|
+
* ... // other options
|
|
205
|
+
* hideHamburger : true,
|
|
206
|
+
* })
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
hideHamburger?: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Control the visibility of the Eureka search on the top nav bar
|
|
212
|
+
* this will control for both new V2 and new navigation V3.
|
|
213
|
+
*
|
|
214
|
+
* @default true
|
|
215
|
+
* @version SDK: 1.39.0 | Thoughtspot: 10.10.0.cl
|
|
216
|
+
* @example
|
|
217
|
+
* ```js
|
|
218
|
+
* const embed = new AppEmbed('#tsEmbed', {
|
|
219
|
+
* ... // other options
|
|
220
|
+
* hideObjectSearch: false,
|
|
221
|
+
* })
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
hideObjectSearch?: boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Control the visibility of the notification on the top nav bar V3,
|
|
227
|
+
* available when new navigation V3 is enabled.
|
|
228
|
+
*
|
|
229
|
+
* @default true
|
|
230
|
+
* @version SDK: 1.39.0 | Thoughtspot: 10.10.0.cl
|
|
231
|
+
* @example
|
|
232
|
+
* ```js
|
|
233
|
+
* const embed = new AppEmbed('#tsEmbed', {
|
|
234
|
+
* ... // other options
|
|
235
|
+
* hideNotification: false,
|
|
236
|
+
* })
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
hideNotification?: boolean;
|
|
154
240
|
/**
|
|
155
241
|
* Control the visibility of the application switcher button on the nav-bar.
|
|
156
242
|
* By default, the application switcher is shown.
|
|
@@ -344,6 +430,23 @@ export interface AppViewConfig extends Omit<ViewConfig, 'visibleTabs'> {
|
|
|
344
430
|
* ```
|
|
345
431
|
*/
|
|
346
432
|
modularHomeExperience?: boolean;
|
|
433
|
+
/**
|
|
434
|
+
* To configure the top-left navigation and home page experience
|
|
435
|
+
*
|
|
436
|
+
* @default false
|
|
437
|
+
* @version SDK: 1.39.0 | Thoughtspot: 10.10.0.cl
|
|
438
|
+
* @example
|
|
439
|
+
* ```js
|
|
440
|
+
* const embed = new AppEmbed('#tsEmbed', {
|
|
441
|
+
* ... // other options
|
|
442
|
+
* discoveryExperience : {
|
|
443
|
+
* primaryNavbarVersion: PrimaryNavbarVersion.Sliding,
|
|
444
|
+
* homePage: HompePage.Modular,
|
|
445
|
+
* },
|
|
446
|
+
* })
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
discoveryExperience?: DiscoveryExperience;
|
|
347
450
|
/**
|
|
348
451
|
* Boolean to control if Liveboard header is sticky or not.
|
|
349
452
|
* @example
|
|
@@ -515,6 +618,9 @@ export class AppEmbed extends V1Embed {
|
|
|
515
618
|
liveboardV2,
|
|
516
619
|
showPrimaryNavbar,
|
|
517
620
|
disableProfileAndHelp,
|
|
621
|
+
hideHamburger,
|
|
622
|
+
hideObjectSearch,
|
|
623
|
+
hideNotification,
|
|
518
624
|
hideApplicationSwitcher,
|
|
519
625
|
hideOrgSwitcher,
|
|
520
626
|
enableSearchAssist,
|
|
@@ -541,6 +647,7 @@ export class AppEmbed extends V1Embed {
|
|
|
541
647
|
homePageSearchBarMode,
|
|
542
648
|
isUnifiedSearchExperienceEnabled = true,
|
|
543
649
|
enablePendoHelp = true,
|
|
650
|
+
discoveryExperience,
|
|
544
651
|
} = this.viewConfig;
|
|
545
652
|
|
|
546
653
|
let params = {};
|
|
@@ -561,6 +668,18 @@ export class AppEmbed extends V1Embed {
|
|
|
561
668
|
|
|
562
669
|
params = this.getBaseQueryParams(params);
|
|
563
670
|
|
|
671
|
+
if (hideObjectSearch) {
|
|
672
|
+
params[Param.HideObjectSearch] = !!hideObjectSearch;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (hideHamburger) {
|
|
676
|
+
params[Param.HideHamburger] = !!hideHamburger;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (hideNotification) {
|
|
680
|
+
params[Param.HideNotification] = !!hideNotification;
|
|
681
|
+
}
|
|
682
|
+
|
|
564
683
|
if (fullHeight === true) {
|
|
565
684
|
params[Param.fullHeight] = true;
|
|
566
685
|
}
|
|
@@ -620,6 +739,20 @@ export class AppEmbed extends V1Embed {
|
|
|
620
739
|
/* eslint-disable-next-line max-len */
|
|
621
740
|
params[Param.DataPanelCustomGroupsAccordionInitialState] = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL;
|
|
622
741
|
}
|
|
742
|
+
|
|
743
|
+
if (discoveryExperience) {
|
|
744
|
+
// primaryNavbarVersion v3 will enabled the new left navigation
|
|
745
|
+
if (discoveryExperience.primaryNavbarVersion === PrimaryNavbarVersion.Sliding) {
|
|
746
|
+
params[Param.NavigationVersion] = discoveryExperience.primaryNavbarVersion;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// homePage v2 will enable the modular home page
|
|
750
|
+
// and it will override the modularHomeExperience value
|
|
751
|
+
if (discoveryExperience.homePage === HomePage.Modular) {
|
|
752
|
+
params[Param.ModularHomeExperienceEnabled] = true;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
623
756
|
const queryParams = getQueryParamString(params, true);
|
|
624
757
|
|
|
625
758
|
return queryParams;
|
package/src/embed/base.ts
CHANGED
|
@@ -137,6 +137,15 @@ export const prefetch = (
|
|
|
137
137
|
iFrame.style.width = '0';
|
|
138
138
|
iFrame.style.height = '0';
|
|
139
139
|
iFrame.style.border = '0';
|
|
140
|
+
|
|
141
|
+
// Make it 'fixed' to keep it in a different stacking context.
|
|
142
|
+
// This should solve the focus behaviours inside the iframe from
|
|
143
|
+
// interfering with main body.
|
|
144
|
+
iFrame.style.position = 'fixed';
|
|
145
|
+
// Push it out of viewport.
|
|
146
|
+
iFrame.style.top = '100vh';
|
|
147
|
+
iFrame.style.left = '100vw';
|
|
148
|
+
|
|
140
149
|
iFrame.classList.add('prefetchIframe');
|
|
141
150
|
iFrame.classList.add(`prefetchIframeNum-${index}`);
|
|
142
151
|
document.body.appendChild(iFrame);
|
|
@@ -60,6 +60,7 @@ import { HiddenActionItemByDefaultForSearchEmbed } from './search';
|
|
|
60
60
|
import { processTrigger } from '../utils/processTrigger';
|
|
61
61
|
import { UIPassthroughEvent } from './hostEventClient/contracts';
|
|
62
62
|
import * as sessionInfoService from '../utils/sessionInfoService';
|
|
63
|
+
import * as authToken from '../authToken';
|
|
63
64
|
|
|
64
65
|
jest.mock('../utils/processTrigger');
|
|
65
66
|
|
|
@@ -2578,4 +2579,133 @@ describe('Unit test case for ts embed', () => {
|
|
|
2578
2579
|
expect(iframeAfterInit).not.toBe(null);
|
|
2579
2580
|
});
|
|
2580
2581
|
});
|
|
2582
|
+
|
|
2583
|
+
describe('AutoLogin behavior in updateAuthToken', () => {
|
|
2584
|
+
const mockPort = { postMessage: jest.fn() };
|
|
2585
|
+
const mockEmbedEventPayload = { type: EmbedEvent.AuthExpire, data: {} };
|
|
2586
|
+
|
|
2587
|
+
beforeEach(() => {
|
|
2588
|
+
jest.clearAllMocks();
|
|
2589
|
+
document.body.innerHTML = getDocumentBody();
|
|
2590
|
+
mockPort.postMessage.mockClear();
|
|
2591
|
+
jest.spyOn(authToken, 'getAuthenticationToken').mockResolvedValue('test-token');
|
|
2592
|
+
|
|
2593
|
+
jest.spyOn(baseInstance, 'handleAuth').mockImplementation(() => Promise.resolve(true));
|
|
2594
|
+
jest.spyOn(baseInstance, 'notifyAuthFailure').mockImplementation(() => {});
|
|
2595
|
+
});
|
|
2596
|
+
|
|
2597
|
+
const renderAndTriggerAuthExpire = async () => {
|
|
2598
|
+
const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
|
|
2599
|
+
await searchEmbed.render();
|
|
2600
|
+
await executeAfterWait(() => {
|
|
2601
|
+
const iframe = getIFrameEl();
|
|
2602
|
+
postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
|
|
2603
|
+
});
|
|
2604
|
+
};
|
|
2605
|
+
|
|
2606
|
+
test('Cookieless with autoLogin undefined should default to true', async () => {
|
|
2607
|
+
init({
|
|
2608
|
+
thoughtSpotHost: 'tshost',
|
|
2609
|
+
authType: AuthType.TrustedAuthTokenCookieless,
|
|
2610
|
+
// autoLogin undefined
|
|
2611
|
+
});
|
|
2612
|
+
|
|
2613
|
+
await renderAndTriggerAuthExpire();
|
|
2614
|
+
|
|
2615
|
+
await executeAfterWait(() => {
|
|
2616
|
+
expect(authToken.getAuthenticationToken).toHaveBeenCalled();
|
|
2617
|
+
expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
|
|
2618
|
+
expect(mockPort.postMessage).toHaveBeenCalledWith({
|
|
2619
|
+
type: EmbedEvent.AuthExpire,
|
|
2620
|
+
data: { authToken: 'test-token' },
|
|
2621
|
+
});
|
|
2622
|
+
});
|
|
2623
|
+
});
|
|
2624
|
+
|
|
2625
|
+
test('Cookieless with autoLogin false should not get auth token', async () => {
|
|
2626
|
+
init({
|
|
2627
|
+
thoughtSpotHost: 'tshost',
|
|
2628
|
+
authType: AuthType.TrustedAuthTokenCookieless,
|
|
2629
|
+
autoLogin: false,
|
|
2630
|
+
});
|
|
2631
|
+
|
|
2632
|
+
await renderAndTriggerAuthExpire();
|
|
2633
|
+
|
|
2634
|
+
await executeAfterWait(() => {
|
|
2635
|
+
expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
|
|
2636
|
+
expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
|
|
2637
|
+
expect(mockPort.postMessage).not.toHaveBeenCalled();
|
|
2638
|
+
});
|
|
2639
|
+
});
|
|
2640
|
+
|
|
2641
|
+
test('Cookieless with autoLogin true should get auth token', async () => {
|
|
2642
|
+
init({
|
|
2643
|
+
thoughtSpotHost: 'tshost',
|
|
2644
|
+
authType: AuthType.TrustedAuthTokenCookieless,
|
|
2645
|
+
autoLogin: true,
|
|
2646
|
+
});
|
|
2647
|
+
|
|
2648
|
+
await renderAndTriggerAuthExpire();
|
|
2649
|
+
|
|
2650
|
+
await executeAfterWait(() => {
|
|
2651
|
+
expect(authToken.getAuthenticationToken).toHaveBeenCalled();
|
|
2652
|
+
expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
|
|
2653
|
+
expect(mockPort.postMessage).toHaveBeenCalledWith({
|
|
2654
|
+
type: EmbedEvent.AuthExpire,
|
|
2655
|
+
data: { authToken: 'test-token' },
|
|
2656
|
+
});
|
|
2657
|
+
});
|
|
2658
|
+
});
|
|
2659
|
+
|
|
2660
|
+
test('Other authType with autoLogin undefined should default to false', async () => {
|
|
2661
|
+
init({
|
|
2662
|
+
thoughtSpotHost: 'tshost',
|
|
2663
|
+
authType: AuthType.None,
|
|
2664
|
+
// autoLogin undefined
|
|
2665
|
+
});
|
|
2666
|
+
|
|
2667
|
+
await renderAndTriggerAuthExpire();
|
|
2668
|
+
|
|
2669
|
+
await executeAfterWait(() => {
|
|
2670
|
+
expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
|
|
2671
|
+
expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
|
|
2672
|
+
});
|
|
2673
|
+
});
|
|
2674
|
+
|
|
2675
|
+
test('Other authType with autoLogin true should call handleAuth', async () => {
|
|
2676
|
+
init({
|
|
2677
|
+
thoughtSpotHost: 'tshost',
|
|
2678
|
+
authType: AuthType.None,
|
|
2679
|
+
autoLogin: true,
|
|
2680
|
+
});
|
|
2681
|
+
|
|
2682
|
+
await renderAndTriggerAuthExpire();
|
|
2683
|
+
|
|
2684
|
+
await executeAfterWait(() => {
|
|
2685
|
+
expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
|
|
2686
|
+
expect(baseInstance.handleAuth).toHaveBeenCalledTimes(2);
|
|
2687
|
+
});
|
|
2688
|
+
});
|
|
2689
|
+
|
|
2690
|
+
test('Other authType with autoLogin false should not call handleAuth', async () => {
|
|
2691
|
+
init({
|
|
2692
|
+
thoughtSpotHost: 'tshost',
|
|
2693
|
+
authType: AuthType.None,
|
|
2694
|
+
autoLogin: false,
|
|
2695
|
+
});
|
|
2696
|
+
|
|
2697
|
+
await renderAndTriggerAuthExpire();
|
|
2698
|
+
|
|
2699
|
+
await executeAfterWait(() => {
|
|
2700
|
+
expect(authToken.getAuthenticationToken).not.toHaveBeenCalled();
|
|
2701
|
+
expect(baseInstance.handleAuth).toHaveBeenCalledTimes(1);
|
|
2702
|
+
});
|
|
2703
|
+
});
|
|
2704
|
+
|
|
2705
|
+
afterEach(() => {
|
|
2706
|
+
expect(baseInstance.notifyAuthFailure).toHaveBeenCalledWith(
|
|
2707
|
+
authInstance.AuthFailureType.EXPIRY
|
|
2708
|
+
);
|
|
2709
|
+
});
|
|
2710
|
+
});
|
|
2581
2711
|
});
|
package/src/embed/ts-embed.ts
CHANGED
|
@@ -409,11 +409,13 @@ export class TsEmbed {
|
|
|
409
409
|
* @param responder
|
|
410
410
|
*/
|
|
411
411
|
private updateAuthToken = async (_: any, responder: any) => {
|
|
412
|
-
const {
|
|
413
|
-
|
|
414
|
-
|
|
412
|
+
const { authType } = this.embedConfig;
|
|
413
|
+
let { autoLogin } = this.embedConfig;
|
|
414
|
+
// Default autoLogin: true for cookieless if undefined/null, otherwise false
|
|
415
|
+
autoLogin = autoLogin ?? (authType === AuthType.TrustedAuthTokenCookieless);
|
|
416
|
+
if (autoLogin && authType === AuthType.TrustedAuthTokenCookieless) {
|
|
415
417
|
try {
|
|
416
|
-
authToken = await getAuthenticationToken(this.embedConfig);
|
|
418
|
+
const authToken = await getAuthenticationToken(this.embedConfig);
|
|
417
419
|
responder({
|
|
418
420
|
type: EmbedEvent.AuthExpire,
|
|
419
421
|
data: { authToken },
|
|
@@ -540,6 +542,7 @@ export class TsEmbed {
|
|
|
540
542
|
disableRedirectionLinksInNewTab,
|
|
541
543
|
overrideOrgId,
|
|
542
544
|
exposeTranslationIDs,
|
|
545
|
+
primaryAction,
|
|
543
546
|
} = this.viewConfig;
|
|
544
547
|
|
|
545
548
|
const { additionalFlags: additionalFlagsFromInit } = this.embedConfig;
|
|
@@ -558,6 +561,9 @@ export class TsEmbed {
|
|
|
558
561
|
this.handleError('You cannot have both hidden Tabs and visible Tabs');
|
|
559
562
|
return queryParams;
|
|
560
563
|
}
|
|
564
|
+
if (primaryAction) {
|
|
565
|
+
queryParams[Param.PrimaryAction] = primaryAction;
|
|
566
|
+
}
|
|
561
567
|
|
|
562
568
|
if (disabledActions?.length) {
|
|
563
569
|
queryParams[Param.DisableActions] = disabledActions;
|
package/src/types.ts
CHANGED
|
@@ -204,7 +204,19 @@ export enum HomeLeftNavItem {
|
|
|
204
204
|
/**
|
|
205
205
|
* @version SDK: 1.34.0| ThoughtSpot: 10.3.0.cl
|
|
206
206
|
*/
|
|
207
|
-
LiveboardSchedules = 'liveboard-schedules'
|
|
207
|
+
LiveboardSchedules = 'liveboard-schedules',
|
|
208
|
+
/**
|
|
209
|
+
* Create new options in the insights left navigation,
|
|
210
|
+
* available when new navigation V3 is enabled.
|
|
211
|
+
* @version SDK: 1.39.0 | ThoughtSpot: 10.10.0.cl
|
|
212
|
+
*/
|
|
213
|
+
Create = 'create',
|
|
214
|
+
/**
|
|
215
|
+
* Spotter option in the insights left navigation,
|
|
216
|
+
* available when new navigation V3 is enabled.
|
|
217
|
+
* @version SDK: 1.39.0 | ThoughtSpot: 10.10.0.cl
|
|
218
|
+
*/
|
|
219
|
+
Spotter = 'spotter',
|
|
208
220
|
}
|
|
209
221
|
export type DOMSelector = string | HTMLElement;
|
|
210
222
|
|
|
@@ -712,6 +724,19 @@ export interface ViewConfig {
|
|
|
712
724
|
* ```
|
|
713
725
|
*/
|
|
714
726
|
disabledActions?: Action[];
|
|
727
|
+
/**
|
|
728
|
+
* The primary action to display on top of the viz for Liveboard and App Embed.
|
|
729
|
+
* Use this to set the primary action.
|
|
730
|
+
* @version SDK: 1.37.0 | ThoughtSpot: 10.9.0.cl
|
|
731
|
+
* @example
|
|
732
|
+
* ```js
|
|
733
|
+
* const embed = new LiveboardEmbed('#embed', {
|
|
734
|
+
* ... // other liveboard view config
|
|
735
|
+
* primaryAction: Action.Download
|
|
736
|
+
* });
|
|
737
|
+
* ```
|
|
738
|
+
*/
|
|
739
|
+
primaryAction?: Action | string;
|
|
715
740
|
/**
|
|
716
741
|
* The tooltip to display for disabled actions.
|
|
717
742
|
* @version SDK: 1.6.0 | ThoughtSpot: ts8.nov.cl, 8.4.1.sw
|
|
@@ -2654,9 +2679,12 @@ export enum HostEvent {
|
|
|
2654
2679
|
* @example
|
|
2655
2680
|
* ```js
|
|
2656
2681
|
* searchEmbed.trigger(HostEvent.OpenFilter,
|
|
2657
|
-
* { columnId: '<column-GUID>', name: 'column name', type: 'INT64', dataType: 'ATTRIBUTE'})
|
|
2682
|
+
* {column: { columnId: '<column-GUID>', name: 'column name', type: 'INT64', dataType: 'ATTRIBUTE'}})
|
|
2683
|
+
* ```
|
|
2684
|
+
* @example
|
|
2685
|
+
* ```js
|
|
2658
2686
|
* LiveboardEmbed.trigger(HostEvent.OpenFilter,
|
|
2659
|
-
*
|
|
2687
|
+
* { column: {columnId: '<column-GUID>'}})
|
|
2660
2688
|
* ```
|
|
2661
2689
|
* @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl
|
|
2662
2690
|
*/
|
|
@@ -3265,6 +3293,25 @@ export enum HostEvent {
|
|
|
3265
3293
|
* }]
|
|
3266
3294
|
* });
|
|
3267
3295
|
* ```
|
|
3296
|
+
* If there are multiple columns with the same name, consider
|
|
3297
|
+
* using `WORKSHEET_NAME::COLUMN_NAME` format.
|
|
3298
|
+
*
|
|
3299
|
+
* @example
|
|
3300
|
+
*
|
|
3301
|
+
* ```js
|
|
3302
|
+
* liveboardEmbed.trigger(HostEvent.UpdateFilters, {
|
|
3303
|
+
* filters: [{
|
|
3304
|
+
* column: "(Sample) Retail - Apparel::city",
|
|
3305
|
+
* oper: 'IN',
|
|
3306
|
+
* values: ["atlanta"]
|
|
3307
|
+
* },
|
|
3308
|
+
* {
|
|
3309
|
+
* column: "(Sample) Retail - Apparel::Region",
|
|
3310
|
+
* oper: 'IN',
|
|
3311
|
+
* values: ["West","Midwest"]
|
|
3312
|
+
* }]
|
|
3313
|
+
* });
|
|
3314
|
+
* ```
|
|
3268
3315
|
* @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
|
|
3269
3316
|
*/
|
|
3270
3317
|
UpdateFilters = 'updateFilters',
|
|
@@ -3324,8 +3371,17 @@ export enum HostEvent {
|
|
|
3324
3371
|
/**
|
|
3325
3372
|
* Get the Answer session for a Search or
|
|
3326
3373
|
* Liveboard visualization.
|
|
3374
|
+
*
|
|
3375
|
+
* Note: This event is not typically used directly. Instead, use the
|
|
3376
|
+
* `getAnswerService()` method on the embed instance to get an AnswerService
|
|
3377
|
+
* object that provides a more convenient interface for working with answers.
|
|
3378
|
+
*
|
|
3327
3379
|
* @example
|
|
3328
3380
|
* ```js
|
|
3381
|
+
* // Preferred way to get an AnswerService
|
|
3382
|
+
* const service = await embed.getAnswerService();
|
|
3383
|
+
*
|
|
3384
|
+
* // Alternative direct usage (not recommended)
|
|
3329
3385
|
* const {session} = await embed.trigger(
|
|
3330
3386
|
* HostEvent.GetAnswerSession, {
|
|
3331
3387
|
* vizId: '123', // For Liveboard Visualization.
|
|
@@ -3333,6 +3389,10 @@ export enum HostEvent {
|
|
|
3333
3389
|
* ```
|
|
3334
3390
|
* @example
|
|
3335
3391
|
* ```js
|
|
3392
|
+
* // Preferred way to get an AnswerService
|
|
3393
|
+
* const service = await embed.getAnswerService();
|
|
3394
|
+
*
|
|
3395
|
+
* // Alternative direct usage (not recommended)
|
|
3336
3396
|
* const {session} = await embed.trigger( HostEvent.GetAnswerSession )
|
|
3337
3397
|
* ```
|
|
3338
3398
|
* @version SDK: 1.26.0 | ThoughtSpot: 9.10.0.cl, 10.1.0.sw
|
|
@@ -3541,6 +3601,10 @@ export enum Param {
|
|
|
3541
3601
|
ShowInsertToSlide = 'insertInToSlide',
|
|
3542
3602
|
PrimaryNavHidden = 'primaryNavHidden',
|
|
3543
3603
|
HideProfleAndHelp = 'profileAndHelpInNavBarHidden',
|
|
3604
|
+
NavigationVersion = 'navigationVersion',
|
|
3605
|
+
HideHamburger = 'hideHamburger',
|
|
3606
|
+
HideObjectSearch = 'hideObjectSearch',
|
|
3607
|
+
HideNotification = 'hideNotification',
|
|
3544
3608
|
HideApplicationSwitcher = 'applicationSwitcherHidden',
|
|
3545
3609
|
HideOrgSwitcher = 'orgSwitcherHidden',
|
|
3546
3610
|
IsSageEmbed = 'isSageEmbed',
|
|
@@ -3597,6 +3661,7 @@ export enum Param {
|
|
|
3597
3661
|
preAuthCache = 'preAuthCache',
|
|
3598
3662
|
ShowSpotterLimitations = 'showSpotterLimitations',
|
|
3599
3663
|
CoverAndFilterOptionInPDF = 'coverAndFilterOptionInPDF',
|
|
3664
|
+
PrimaryAction = 'primaryAction',
|
|
3600
3665
|
}
|
|
3601
3666
|
|
|
3602
3667
|
/**
|
|
@@ -26,29 +26,49 @@ export interface UnderlyingDataPoint {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
29
|
+
* AnswerService provides a simple way to work with ThoughtSpot Answers.
|
|
30
|
+
*
|
|
31
|
+
* This service allows you to interact with ThoughtSpot Answers programmatically,
|
|
32
|
+
* making it easy to customize visualizations, filter data, and extract insights
|
|
33
|
+
* directly from your application.
|
|
34
|
+
*
|
|
35
|
+
* You can use this service to:
|
|
36
|
+
* - Add or remove columns from Answers (`addColumns`, `removeColumns`, `addColumnsByName`)
|
|
37
|
+
* - Apply filters to Answers (`addFilter`)
|
|
38
|
+
* - Get data from Answers in different formats (JSON, CSV, PNG) (`fetchData`, `fetchCSVBlob`, `fetchPNGBlob`)
|
|
39
|
+
* - Get data for specific points in visualizations (`getUnderlyingDataForPoint`)
|
|
40
|
+
* - Run custom queries (`executeQuery`)
|
|
41
|
+
* - Add visualizations to liveboards (`addDisplayedVizToLiveboard`)
|
|
42
|
+
*
|
|
33
43
|
* @example
|
|
34
44
|
* ```js
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
45
|
+
* // Get the answer service
|
|
46
|
+
* embed.on(EmbedEvent.Data, async (e) => {
|
|
47
|
+
* const service = await embed.getAnswerService();
|
|
48
|
+
*
|
|
49
|
+
* // Add columns to the answer
|
|
50
|
+
* await service.addColumnsByName(["Sales", "Region"]);
|
|
51
|
+
*
|
|
52
|
+
* // Get the data
|
|
53
|
+
* const data = await service.fetchData();
|
|
54
|
+
* console.log(data);
|
|
55
|
+
* });
|
|
41
56
|
* ```
|
|
57
|
+
*
|
|
42
58
|
* @example
|
|
43
59
|
* ```js
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* await
|
|
47
|
-
*
|
|
60
|
+
* // Get data for a point in a visualization
|
|
61
|
+
* embed.on(EmbedEvent.CustomAction, async (e) => {
|
|
62
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
63
|
+
* 'Product Name',
|
|
64
|
+
* 'Sales Amount'
|
|
48
65
|
* ]);
|
|
49
|
-
*
|
|
66
|
+
*
|
|
67
|
+
* const data = await underlying.fetchData(0, 100);
|
|
68
|
+
* console.log(data);
|
|
50
69
|
* });
|
|
51
70
|
* ```
|
|
71
|
+
*
|
|
52
72
|
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
53
73
|
* @group Events
|
|
54
74
|
*/
|
package/src/utils/processData.ts
CHANGED
|
@@ -80,15 +80,15 @@ export function processAuthFailure(e: any, containerEl: Element) {
|
|
|
80
80
|
const {
|
|
81
81
|
loginFailedMessage, authType, disableLoginFailurePage, autoLogin,
|
|
82
82
|
} = getEmbedConfig();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
) {
|
|
83
|
+
|
|
84
|
+
const isEmbeddedSSO = authType === AuthType.EmbeddedSSO;
|
|
85
|
+
const isTrustedAuth = authType === AuthType.TrustedAuthToken || authType === AuthType.TrustedAuthTokenCookieless;
|
|
86
|
+
const isEmbeddedSSOInfoFailure = isEmbeddedSSO && e?.data?.type === AuthFailureType.UNAUTHENTICATED_FAILURE;
|
|
87
|
+
if (autoLogin && isTrustedAuth) {
|
|
88
88
|
// eslint-disable-next-line no-param-reassign
|
|
89
89
|
containerEl.innerHTML = loginFailedMessage;
|
|
90
90
|
notifyAuthFailure(AuthFailureType.IDLE_SESSION_TIMEOUT);
|
|
91
|
-
} else if (authType !== AuthType.None && !disableLoginFailurePage) {
|
|
91
|
+
} else if (authType !== AuthType.None && !disableLoginFailurePage && !isEmbeddedSSOInfoFailure) {
|
|
92
92
|
// eslint-disable-next-line no-param-reassign
|
|
93
93
|
containerEl.innerHTML = loginFailedMessage;
|
|
94
94
|
notifyAuthFailure(AuthFailureType.OTHER);
|