@thoughtspot/visual-embed-sdk 1.21.0-alpha.0 → 1.21.0-alpha.2
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/README.md +1 -1
- package/dist/src/auth.d.ts +10 -6
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/auth.spec.d.ts +3 -0
- package/dist/src/auth.spec.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts +3 -1
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +11 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/react/index.d.ts +15 -0
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +95 -24
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsembed.es.js +17546 -249
- package/dist/tsembed.js +17546 -249
- package/lib/package.json +1 -1
- package/lib/src/auth.d.ts +10 -6
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js +25 -10
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.d.ts +3 -0
- package/lib/src/auth.spec.d.ts.map +1 -1
- package/lib/src/auth.spec.js +23 -1
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts +3 -1
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +3 -1
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +11 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +11 -1
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +3 -2
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/react/index.d.ts +15 -0
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +15 -0
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/types.d.ts +95 -24
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +95 -24
- package/lib/src/types.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +119 -32
- package/package.json +1 -1
- package/src/auth.spec.ts +40 -8
- package/src/auth.ts +43 -16
- package/src/embed/base.ts +4 -2
- package/src/embed/liveboard.ts +11 -1
- package/src/embed/ts-embed.ts +2 -1
- package/src/react/index.tsx +15 -0
- package/src/types.ts +95 -24
|
@@ -187,7 +187,9 @@ declare module '@thoughtspot/visual-embed-sdk/embed/base' {
|
|
|
187
187
|
export const prefetch: (url?: string, prefetchFeatures?: PrefetchFeatures[]) => void;
|
|
188
188
|
/**
|
|
189
189
|
* Initializes the Visual Embed SDK globally and perform
|
|
190
|
-
* authentication if applicable.
|
|
190
|
+
* authentication if applicable. This function needs to be called before any ThoughtSpot
|
|
191
|
+
* component like liveboard etc can be embedded. But need not wait for AuthEvent.SUCCESS
|
|
192
|
+
* to actually embed. That is handled internally.
|
|
191
193
|
*
|
|
192
194
|
* @param embedConfig The configuration object containing ThoughtSpot host,
|
|
193
195
|
* authentication mechanism and so on.
|
|
@@ -326,8 +328,18 @@ declare module '@thoughtspot/visual-embed-sdk/embed/liveboard' {
|
|
|
326
328
|
activeTabId?: string;
|
|
327
329
|
}
|
|
328
330
|
/**
|
|
329
|
-
* Embed a ThoughtSpot Liveboard or visualization
|
|
331
|
+
* Embed a ThoughtSpot Liveboard or a Thoughtspot visualization. When rendered it already
|
|
332
|
+
* waits for the authentication to complete, so no need to wait for AuthStatus.SUCCESS.
|
|
330
333
|
*
|
|
334
|
+
* @example
|
|
335
|
+
* ```js
|
|
336
|
+
* import { .. } from '@thoughtspot/visual-embed-sdk';
|
|
337
|
+
* init({ ... });
|
|
338
|
+
* const embed = new LiveboardEmbed("#container", {
|
|
339
|
+
* liveboardId: <your-id-here>,
|
|
340
|
+
* // .. other params here.
|
|
341
|
+
* })
|
|
342
|
+
* ```
|
|
331
343
|
* @group Embed components
|
|
332
344
|
*/
|
|
333
345
|
export class LiveboardEmbed extends V1Embed {
|
|
@@ -535,6 +547,12 @@ declare module '@thoughtspot/visual-embed-sdk/auth' {
|
|
|
535
547
|
BASIC_LOGIN: string;
|
|
536
548
|
LOGOUT: string;
|
|
537
549
|
};
|
|
550
|
+
interface sessionInfoInterface {
|
|
551
|
+
userGUID: any;
|
|
552
|
+
isPublicUser: any;
|
|
553
|
+
mixpanelToken: any;
|
|
554
|
+
[key: string]: any;
|
|
555
|
+
}
|
|
538
556
|
/**
|
|
539
557
|
* Enum for auth failure types. This is the parameter passed to the listner
|
|
540
558
|
* of {@link AuthStatus.FAILURE}.
|
|
@@ -647,6 +665,8 @@ declare module '@thoughtspot/visual-embed-sdk/auth' {
|
|
|
647
665
|
*
|
|
648
666
|
*/
|
|
649
667
|
export function notifyLogout(): void;
|
|
668
|
+
export const initSession: (sessionDetails: sessionInfoInterface) => void;
|
|
669
|
+
export const getSessionDetails: (sessionInfoResp: any) => sessionInfoInterface;
|
|
650
670
|
/**
|
|
651
671
|
* Return releaseVersion if available
|
|
652
672
|
*/
|
|
@@ -657,12 +677,7 @@ declare module '@thoughtspot/visual-embed-sdk/auth' {
|
|
|
657
677
|
*
|
|
658
678
|
* @group Global methods
|
|
659
679
|
*/
|
|
660
|
-
export function getSessionInfo(): Promise<
|
|
661
|
-
/**
|
|
662
|
-
*
|
|
663
|
-
* @param sessionDetails
|
|
664
|
-
*/
|
|
665
|
-
export function initSession(sessionDetails: any): void;
|
|
680
|
+
export function getSessionInfo(): Promise<sessionInfoInterface>;
|
|
666
681
|
export const getAuthenticaionToken: (embedConfig: EmbedConfig) => Promise<any>;
|
|
667
682
|
/**
|
|
668
683
|
* Perform token based authentication
|
|
@@ -699,6 +714,7 @@ declare module '@thoughtspot/visual-embed-sdk/auth' {
|
|
|
699
714
|
* Check if we are authenticated to the ThoughtSpot cluster
|
|
700
715
|
*/
|
|
701
716
|
export const isAuthenticated: () => boolean;
|
|
717
|
+
export {};
|
|
702
718
|
}
|
|
703
719
|
|
|
704
720
|
declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
@@ -738,16 +754,47 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
738
754
|
SAML = "SSO_SAML",
|
|
739
755
|
/**
|
|
740
756
|
* SSO using SAML
|
|
741
|
-
* Will make the host application redirect to the SAML Idp.
|
|
757
|
+
* Will make the host application redirect to the SAML Idp. Use this
|
|
758
|
+
* when the idp does not allow itself to be embedded.
|
|
759
|
+
*
|
|
760
|
+
* This redirects the host application to the SAML Idp. The host application
|
|
761
|
+
* will be redirected back to the ThoughtSpot app after authentication.
|
|
742
762
|
*
|
|
743
763
|
* @example
|
|
744
764
|
* ```js
|
|
745
765
|
* init({
|
|
746
766
|
* // ...
|
|
747
767
|
* authType: AuthType.SAMLRedirect,
|
|
768
|
+
* });
|
|
769
|
+
* ```
|
|
770
|
+
*
|
|
771
|
+
* This opens the SAML Idp in a popup window. The popup is triggered
|
|
772
|
+
* when the user clicks the trigger button. The popup window will be
|
|
773
|
+
* closed automatically after authentication.
|
|
774
|
+
* @example
|
|
775
|
+
* ```js
|
|
776
|
+
* init({
|
|
777
|
+
* // ...
|
|
778
|
+
* authType: AuthType.SAMLRedirect,
|
|
748
779
|
* authTriggerText: 'Login with SAML',
|
|
749
780
|
* authTriggerContainer: '#embed-container',
|
|
750
|
-
*
|
|
781
|
+
* inPopup: true,
|
|
782
|
+
* });
|
|
783
|
+
* ```
|
|
784
|
+
*
|
|
785
|
+
* Can also use event to trigger the popup flow. Works the same
|
|
786
|
+
* as above example.
|
|
787
|
+
* @example
|
|
788
|
+
* ```js
|
|
789
|
+
* const authEE = init({
|
|
790
|
+
* // ...
|
|
791
|
+
* authType: AuthType.SAMLRedirect,
|
|
792
|
+
* inPopup: true,
|
|
793
|
+
* });
|
|
794
|
+
*
|
|
795
|
+
* someButtonOnYourPage.addEventListener('click', () => {
|
|
796
|
+
* authEE.emit(AuthEvent.TRIGGER_SSO_POPUP);
|
|
797
|
+
* });
|
|
751
798
|
* ```
|
|
752
799
|
*/
|
|
753
800
|
SAMLRedirect = "SSO_SAML",
|
|
@@ -761,6 +808,7 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
761
808
|
/**
|
|
762
809
|
* SSO using OIDC
|
|
763
810
|
* Will make the host application redirect to the OIDC Idp.
|
|
811
|
+
* See code samples in {@link SAMLRedirect}.
|
|
764
812
|
*/
|
|
765
813
|
OIDCRedirect = "SSO_OIDC",
|
|
766
814
|
/**
|
|
@@ -1336,18 +1384,17 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
1336
1384
|
Load = "load",
|
|
1337
1385
|
/**
|
|
1338
1386
|
* Data pertaining to answer or Liveboard is received
|
|
1339
|
-
*
|
|
1340
|
-
* @
|
|
1387
|
+
* @return data - The answer or Liveboard data
|
|
1388
|
+
* @important
|
|
1341
1389
|
*/
|
|
1342
1390
|
Data = "data",
|
|
1343
1391
|
/**
|
|
1344
|
-
* Search/answer/Liveboard filters have been applied/updated
|
|
1345
|
-
*
|
|
1392
|
+
* Search/answer/Liveboard filters have been applied/updated by the user.
|
|
1346
1393
|
* @hidden
|
|
1347
1394
|
*/
|
|
1348
1395
|
FiltersChanged = "filtersChanged",
|
|
1349
1396
|
/**
|
|
1350
|
-
* Search query has been updated
|
|
1397
|
+
* Search query has been updated by the user.
|
|
1351
1398
|
*/
|
|
1352
1399
|
QueryChanged = "queryChanged",
|
|
1353
1400
|
/**
|
|
@@ -1379,17 +1426,29 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
1379
1426
|
*/
|
|
1380
1427
|
CustomAction = "customAction",
|
|
1381
1428
|
/**
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
* @returns ContextMenuInputPoints - data point that is double clicked
|
|
1429
|
+
* Listen to double clicks on a visualization
|
|
1430
|
+
* @return ContextMenuInputPoints - data point that is double clicked
|
|
1385
1431
|
* @version SDK: 1.5.0 | ThoughtSpot: ts7.oct.cl, 7.2.1
|
|
1386
1432
|
*/
|
|
1387
1433
|
VizPointDoubleClick = "vizPointDoubleClick",
|
|
1388
1434
|
/**
|
|
1389
|
-
*
|
|
1435
|
+
* Listen to clicks on a visualization in a liveboard or Search result.
|
|
1390
1436
|
*
|
|
1391
|
-
* @
|
|
1437
|
+
* @example
|
|
1438
|
+
* ```js
|
|
1439
|
+
* embed.on(ThoughtSpotEmbed.Event.VizPointClick, (data) => {
|
|
1440
|
+
* console.log(
|
|
1441
|
+
* data.vizId, // viz id
|
|
1442
|
+
* data.clickedPoint.selectedAttributes[0].value,
|
|
1443
|
+
* data.clickedPoint.selectedAttributes[0].column.name,
|
|
1444
|
+
* data.clickedPoint.selectedMeasures[0].value,
|
|
1445
|
+
* data.clickedPoint.selectedMeasures[0].column.name,
|
|
1446
|
+
* )
|
|
1447
|
+
* });
|
|
1448
|
+
* ```
|
|
1449
|
+
* @return {vizId, clickedPoint} - metadata about point that is clicked
|
|
1392
1450
|
* @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1-sw
|
|
1451
|
+
* @important
|
|
1393
1452
|
*/
|
|
1394
1453
|
VizPointClick = "vizPointClick",
|
|
1395
1454
|
/**
|
|
@@ -1504,6 +1563,12 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
1504
1563
|
* @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1-sw
|
|
1505
1564
|
*/
|
|
1506
1565
|
Download = "download",
|
|
1566
|
+
/**
|
|
1567
|
+
* Emitted when the download action is triggered on an answer
|
|
1568
|
+
*
|
|
1569
|
+
* @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl, 9.4.0-sw
|
|
1570
|
+
*/
|
|
1571
|
+
DownloadAsPng = "downloadAsPng",
|
|
1507
1572
|
/**
|
|
1508
1573
|
* Emitted when the Download as PDF action is triggered on an answer
|
|
1509
1574
|
*
|
|
@@ -1687,8 +1752,7 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
1687
1752
|
*/
|
|
1688
1753
|
CrossFilterChanged = "cross-filter-changed",
|
|
1689
1754
|
/**
|
|
1690
|
-
* Emitted when a user right clicks on chart or table
|
|
1691
|
-
*
|
|
1755
|
+
* Emitted when a user right clicks on a visualization (chart or table)
|
|
1692
1756
|
* @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl
|
|
1693
1757
|
*/
|
|
1694
1758
|
VizPointRightClick = "vizPointRightClick",
|
|
@@ -1777,10 +1841,11 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
1777
1841
|
* @param - {@link RuntimeFilter}[] an array of {@link RuntimeFilter} Types.
|
|
1778
1842
|
* @example
|
|
1779
1843
|
* liveboardEmbed.trigger(HostEvent.UpdateRuntimeFilters, [
|
|
1780
|
-
*
|
|
1781
|
-
*
|
|
1782
|
-
*
|
|
1844
|
+
* {columnName: "state",operator: RuntimeFilterOp.EQ,values: ["michigan"]},
|
|
1845
|
+
* {columnName: "item type",operator: RuntimeFilterOp.EQ,values: ["Jackets"]}
|
|
1846
|
+
* ])
|
|
1783
1847
|
* @version SDK: 1.9.0 | ThoughtSpot: 8.1.0.cl, 8.4.1-sw
|
|
1848
|
+
* @important
|
|
1784
1849
|
*/
|
|
1785
1850
|
UpdateRuntimeFilters = "UpdateRuntimeFilters",
|
|
1786
1851
|
/**
|
|
@@ -2032,9 +2097,14 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
2032
2097
|
*
|
|
2033
2098
|
* @example
|
|
2034
2099
|
* ```js
|
|
2035
|
-
* searchEmbed.trigger(HostEvent.GetTML)
|
|
2100
|
+
* searchEmbed.trigger(HostEvent.GetTML).then((tml) => {
|
|
2101
|
+
* console.log(
|
|
2102
|
+
* tml.search_query // TML representation of the search query
|
|
2103
|
+
* );
|
|
2104
|
+
* })
|
|
2036
2105
|
* ```
|
|
2037
|
-
* @version SDK: 1.18.0 | ThoughtSpot: 8.10.0.cl
|
|
2106
|
+
* @version SDK: 1.18.0 | ThoughtSpot: 8.10.0.cl, 9.0.1-sw
|
|
2107
|
+
* @important
|
|
2038
2108
|
*/
|
|
2039
2109
|
GetTML = "getTML",
|
|
2040
2110
|
/**
|
|
@@ -2083,12 +2153,29 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
2083
2153
|
* '730496d6-6903-4601-937e-2c691821af3c'})
|
|
2084
2154
|
* vizEmbed.trigger(HostEvent.Download)
|
|
2085
2155
|
* searchEmbed.trigger(HostEvent.Download)
|
|
2156
|
+
* @deprecated from SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl, 9.4.1-sw, Please use DownloadAsPng
|
|
2086
2157
|
* @version SDK: 1.19.0 | ThoughtSpot: 9.0.0.cl, 9.0.1-sw
|
|
2087
2158
|
*/
|
|
2088
|
-
Download = "
|
|
2159
|
+
Download = "downloadAsPng",
|
|
2160
|
+
/**
|
|
2161
|
+
* Triggers the Download action on visualization or search when Displaymode is Chart
|
|
2162
|
+
*
|
|
2163
|
+
* @example
|
|
2164
|
+
* ```js
|
|
2165
|
+
* liveboardEmbed.trigger(HostEvent.DownloadAsPng,
|
|
2166
|
+
* {vizId:'730496d6-6903-4601-937e-2c691821af3c'})
|
|
2167
|
+
* ```
|
|
2168
|
+
* ```js
|
|
2169
|
+
* vizEmbed.trigger(HostEvent.DownloadAsPng)
|
|
2170
|
+
* ```
|
|
2171
|
+
* ```js
|
|
2172
|
+
* searchEmbed.trigger(HostEvent.DownloadAsPng)
|
|
2173
|
+
* ```
|
|
2174
|
+
* @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl, 9.4.1-sw
|
|
2175
|
+
*/
|
|
2176
|
+
DownloadAsPng = "downloadAsPng",
|
|
2089
2177
|
/**
|
|
2090
|
-
* Triggers the downloadAsCSV action on visualization or search
|
|
2091
|
-
* Table
|
|
2178
|
+
* Triggers the downloadAsCSV action on visualization or search
|
|
2092
2179
|
*
|
|
2093
2180
|
* @example
|
|
2094
2181
|
* liveboardEmbed.trigger(HostEvent.DownloadAsCsv, {vizId:
|
|
@@ -2099,8 +2186,7 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
2099
2186
|
*/
|
|
2100
2187
|
DownloadAsCsv = "downloadAsCSV",
|
|
2101
2188
|
/**
|
|
2102
|
-
* Triggers the downloadAsXLSX action on visualization or search
|
|
2103
|
-
* Table
|
|
2189
|
+
* Triggers the downloadAsXLSX action on visualization or search
|
|
2104
2190
|
*
|
|
2105
2191
|
* @example
|
|
2106
2192
|
* liveboardEmbed.trigger(HostEvent.DownloadAsXlsx, {vizId:
|
|
@@ -2287,6 +2373,7 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
|
|
|
2287
2373
|
ReplaySearch = "replaySearch",
|
|
2288
2374
|
ShowUnderlyingData = "showUnderlyingData",
|
|
2289
2375
|
Download = "download",
|
|
2376
|
+
DownloadAsPng = "downloadAsPng",
|
|
2290
2377
|
DownloadAsPdf = "downloadAsPdf",
|
|
2291
2378
|
DownloadAsCsv = "downloadAsCSV",
|
|
2292
2379
|
DownloadAsXlsx = "downloadAsXLSX",
|
package/package.json
CHANGED
package/src/auth.spec.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as authInstance from './auth';
|
|
2
2
|
import * as authService from './utils/authService';
|
|
3
3
|
import * as checkReleaseVersionInBetaInstance from './utils';
|
|
4
|
+
import * as mixPanelService from './mixpanel-service';
|
|
4
5
|
import { AuthType, EmbedEvent } from './types';
|
|
5
6
|
import { executeAfterWait } from './test/test-utils';
|
|
6
7
|
|
|
@@ -91,6 +92,9 @@ export const embedConfig: any = {
|
|
|
91
92
|
|
|
92
93
|
const originalWindow = window;
|
|
93
94
|
export const mockSessionInfo = {
|
|
95
|
+
userGUID: '1234',
|
|
96
|
+
mixpanelToken: 'abc123',
|
|
97
|
+
isPublicUser: false,
|
|
94
98
|
sessionId: '6588e7d9-710c-453e-a7b4-535fb3a8cbb2',
|
|
95
99
|
genNo: 3,
|
|
96
100
|
acSession: {
|
|
@@ -110,6 +114,7 @@ describe('Unit test for auth', () => {
|
|
|
110
114
|
});
|
|
111
115
|
|
|
112
116
|
test('when session info giving response', async () => {
|
|
117
|
+
jest.spyOn(mixPanelService, 'initMixpanel').mockImplementation(() => Promise.resolve());
|
|
113
118
|
authInstance.initSession(mockSessionInfo);
|
|
114
119
|
const sessionInfo = await authInstance.getSessionInfo();
|
|
115
120
|
expect(sessionInfo).toStrictEqual(mockSessionInfo);
|
|
@@ -138,11 +143,17 @@ describe('Unit test for auth', () => {
|
|
|
138
143
|
});
|
|
139
144
|
|
|
140
145
|
test('doTokenAuth: when user is loggedIn', async () => {
|
|
141
|
-
jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(
|
|
147
|
+
async () => ({
|
|
148
|
+
json: () => mockSessionInfo,
|
|
149
|
+
status: 200,
|
|
150
|
+
}),
|
|
151
|
+
);
|
|
152
|
+
jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
|
|
153
|
+
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
154
|
+
await authInstance.doTokenAuth(
|
|
155
|
+
embedConfig.doTokenAuthSuccess('authToken'),
|
|
156
|
+
);
|
|
146
157
|
expect(authService.fetchSessionInfoService).toBeCalled();
|
|
147
158
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
148
159
|
});
|
|
@@ -260,14 +271,24 @@ describe('Unit test for auth', () => {
|
|
|
260
271
|
});
|
|
261
272
|
|
|
262
273
|
it('when user is loggedIn', async () => {
|
|
263
|
-
spyOn(
|
|
264
|
-
|
|
274
|
+
spyOn(
|
|
275
|
+
checkReleaseVersionInBetaInstance,
|
|
276
|
+
'checkReleaseVersionInBeta',
|
|
277
|
+
);
|
|
278
|
+
jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
|
|
279
|
+
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
280
|
+
jest.spyOn(
|
|
281
|
+
authService,
|
|
282
|
+
'fetchSessionInfoService',
|
|
283
|
+
).mockImplementation(async () => ({
|
|
265
284
|
json: () => mockSessionInfo,
|
|
266
285
|
status: 200,
|
|
267
286
|
}));
|
|
268
287
|
await authInstance.doBasicAuth(embedConfig.doBasicAuth);
|
|
269
288
|
expect(authService.fetchSessionInfoService).toBeCalled();
|
|
270
289
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
290
|
+
expect(authInstance.getSessionDetails).toBeCalled();
|
|
291
|
+
expect(authInstance.initSession).toBeCalled();
|
|
271
292
|
});
|
|
272
293
|
|
|
273
294
|
it('when user is not loggedIn', async () => {
|
|
@@ -304,6 +325,8 @@ describe('Unit test for auth', () => {
|
|
|
304
325
|
json: () => mockSessionInfo,
|
|
305
326
|
status: 200,
|
|
306
327
|
}));
|
|
328
|
+
jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
|
|
329
|
+
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
307
330
|
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
|
|
308
331
|
expect(authService.fetchSessionInfoService).toBeCalled();
|
|
309
332
|
expect(window.location.hash).toBe('');
|
|
@@ -340,7 +363,14 @@ describe('Unit test for auth', () => {
|
|
|
340
363
|
});
|
|
341
364
|
spyOn(authInstance, 'samlCompletionPromise');
|
|
342
365
|
global.window.open = jest.fn();
|
|
343
|
-
jest.spyOn(authService, 'fetchSessionInfoService')
|
|
366
|
+
jest.spyOn(authService, 'fetchSessionInfoService')
|
|
367
|
+
.mockImplementationOnce(() => Promise.reject())
|
|
368
|
+
.mockImplementationOnce(async () => ({
|
|
369
|
+
json: () => mockSessionInfo,
|
|
370
|
+
status: 200,
|
|
371
|
+
}));
|
|
372
|
+
jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
|
|
373
|
+
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
344
374
|
expect(await authInstance.samlCompletionPromise).not.toBe(null);
|
|
345
375
|
expect(
|
|
346
376
|
await authInstance.doSamlAuth({
|
|
@@ -351,6 +381,8 @@ describe('Unit test for auth', () => {
|
|
|
351
381
|
window.postMessage({ type: EmbedEvent.SAMLComplete }, '*');
|
|
352
382
|
await authInstance.samlCompletionPromise;
|
|
353
383
|
expect(authService.fetchSessionInfoService).toBeCalled();
|
|
384
|
+
expect(authInstance.getSessionDetails).toBeCalled();
|
|
385
|
+
expect(authInstance.initSession).toBeCalled();
|
|
354
386
|
});
|
|
355
387
|
});
|
|
356
388
|
|
package/src/auth.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import EventEmitter from 'eventemitter3';
|
|
2
|
+
import _ from 'lodash';
|
|
2
3
|
import { initMixpanel } from './mixpanel-service';
|
|
3
4
|
import {
|
|
4
5
|
AuthType, DOMSelector, EmbedConfig, EmbedEvent, Param,
|
|
@@ -20,9 +21,9 @@ export let loggedInStatus = false;
|
|
|
20
21
|
export let samlAuthWindow: Window = null;
|
|
21
22
|
// eslint-disable-next-line import/no-mutable-exports
|
|
22
23
|
export let samlCompletionPromise: Promise<void> = null;
|
|
23
|
-
let sessionInfo:
|
|
24
|
-
let sessionInfoResolver: (value:
|
|
25
|
-
const sessionInfoPromise = new Promise((resolve) => {
|
|
24
|
+
let sessionInfo: sessionInfoInterface = null;
|
|
25
|
+
let sessionInfoResolver: (value: sessionInfoInterface) => void = null;
|
|
26
|
+
const sessionInfoPromise = new Promise((resolve:(value: sessionInfoInterface) => void) => {
|
|
26
27
|
sessionInfoResolver = resolve;
|
|
27
28
|
});
|
|
28
29
|
let releaseVersion = '';
|
|
@@ -38,6 +39,13 @@ export const EndPoints = {
|
|
|
38
39
|
LOGOUT: '/callosum/v1/session/logout',
|
|
39
40
|
};
|
|
40
41
|
|
|
42
|
+
interface sessionInfoInterface {
|
|
43
|
+
userGUID: any;
|
|
44
|
+
isPublicUser: any;
|
|
45
|
+
mixpanelToken: any;
|
|
46
|
+
[key:string]:any;
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
/**
|
|
42
50
|
* Enum for auth failure types. This is the parameter passed to the listner
|
|
43
51
|
* of {@link AuthStatus.FAILURE}.
|
|
@@ -196,6 +204,28 @@ export function notifyLogout(): void {
|
|
|
196
204
|
authEE.emit(AuthStatus.LOGOUT);
|
|
197
205
|
}
|
|
198
206
|
|
|
207
|
+
export const initSession = (sessionDetails: sessionInfoInterface) => {
|
|
208
|
+
if (_.isNull(sessionInfo)) {
|
|
209
|
+
sessionInfo = sessionDetails;
|
|
210
|
+
initMixpanel(sessionInfo);
|
|
211
|
+
sessionInfoResolver(sessionInfo);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export const getSessionDetails = (sessionInfoResp: any):sessionInfoInterface => {
|
|
216
|
+
const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
|
|
217
|
+
const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
|
|
218
|
+
const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
|
|
219
|
+
? prodMixpanelToken
|
|
220
|
+
: devMixpanelToken;
|
|
221
|
+
return {
|
|
222
|
+
userGUID: sessionInfoResp.userGUID,
|
|
223
|
+
mixpanelToken,
|
|
224
|
+
isPublicUser: sessionInfoResp.configInfo.isPublicUser,
|
|
225
|
+
...sessionInfoResp,
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
|
|
199
229
|
/**
|
|
200
230
|
* Check if we are logged into the ThoughtSpot cluster
|
|
201
231
|
*
|
|
@@ -207,6 +237,9 @@ async function isLoggedIn(thoughtSpotHost: string): Promise<boolean> {
|
|
|
207
237
|
try {
|
|
208
238
|
response = await fetchSessionInfoService(authVerificationUrl);
|
|
209
239
|
const sessionInfoResp = await response.json();
|
|
240
|
+
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
241
|
+
// Store user session details from session info
|
|
242
|
+
initSession(sessionDetails);
|
|
210
243
|
releaseVersion = sessionInfoResp.releaseVersion;
|
|
211
244
|
} catch (e) {
|
|
212
245
|
return false;
|
|
@@ -227,20 +260,10 @@ export function getReleaseVersion() {
|
|
|
227
260
|
*
|
|
228
261
|
* @group Global methods
|
|
229
262
|
*/
|
|
230
|
-
export function getSessionInfo(): Promise<
|
|
263
|
+
export function getSessionInfo(): Promise<sessionInfoInterface> {
|
|
231
264
|
return sessionInfoPromise;
|
|
232
265
|
}
|
|
233
266
|
|
|
234
|
-
/**
|
|
235
|
-
*
|
|
236
|
-
* @param sessionDetails
|
|
237
|
-
*/
|
|
238
|
-
export function initSession(sessionDetails: any) {
|
|
239
|
-
sessionInfo = sessionDetails;
|
|
240
|
-
initMixpanel(sessionInfo);
|
|
241
|
-
sessionInfoResolver(sessionInfo);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
267
|
const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
|
|
245
268
|
+ 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
|
|
246
269
|
let prevAuthToken: string = null;
|
|
@@ -425,8 +448,12 @@ const doSSOAuth = async (embedConfig: EmbedConfig, ssoEndPoint: string): Promise
|
|
|
425
448
|
|
|
426
449
|
const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
|
|
427
450
|
if (embedConfig.inPopup) {
|
|
428
|
-
await samlPopupFlow(
|
|
429
|
-
|
|
451
|
+
await samlPopupFlow(
|
|
452
|
+
ssoURL,
|
|
453
|
+
embedConfig.authTriggerContainer,
|
|
454
|
+
embedConfig.authTriggerText,
|
|
455
|
+
);
|
|
456
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
430
457
|
return;
|
|
431
458
|
}
|
|
432
459
|
|
package/src/embed/base.ts
CHANGED
|
@@ -142,7 +142,9 @@ function backwardCompat(embedConfig: EmbedConfig): EmbedConfig {
|
|
|
142
142
|
|
|
143
143
|
/**
|
|
144
144
|
* Initializes the Visual Embed SDK globally and perform
|
|
145
|
-
* authentication if applicable.
|
|
145
|
+
* authentication if applicable. This function needs to be called before any ThoughtSpot
|
|
146
|
+
* component like liveboard etc can be embedded. But need not wait for AuthEvent.SUCCESS
|
|
147
|
+
* to actually embed. That is handled internally.
|
|
146
148
|
*
|
|
147
149
|
* @param embedConfig The configuration object containing ThoughtSpot host,
|
|
148
150
|
* authentication mechanism and so on.
|
|
@@ -232,7 +234,7 @@ export const renderInQueue = (fn: (next?: (val?: any) => void) => Promise<any>):
|
|
|
232
234
|
return renderQueue;
|
|
233
235
|
}
|
|
234
236
|
// Sending an empty function to keep it consistent with the above usage.
|
|
235
|
-
return fn(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function
|
|
237
|
+
return fn(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function
|
|
236
238
|
};
|
|
237
239
|
|
|
238
240
|
// For testing purposes only
|
package/src/embed/liveboard.ts
CHANGED
|
@@ -102,8 +102,18 @@ export interface LiveboardViewConfig extends ViewConfig {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* Embed a ThoughtSpot Liveboard or visualization
|
|
105
|
+
* Embed a ThoughtSpot Liveboard or a Thoughtspot visualization. When rendered it already
|
|
106
|
+
* waits for the authentication to complete, so no need to wait for AuthStatus.SUCCESS.
|
|
106
107
|
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```js
|
|
110
|
+
* import { .. } from '@thoughtspot/visual-embed-sdk';
|
|
111
|
+
* init({ ... });
|
|
112
|
+
* const embed = new LiveboardEmbed("#container", {
|
|
113
|
+
* liveboardId: <your-id-here>,
|
|
114
|
+
* // .. other params here.
|
|
115
|
+
* })
|
|
116
|
+
* ```
|
|
107
117
|
* @group Embed components
|
|
108
118
|
*/
|
|
109
119
|
export class LiveboardEmbed extends V1Embed {
|
package/src/embed/ts-embed.ts
CHANGED
|
@@ -383,7 +383,8 @@ export class TsEmbed {
|
|
|
383
383
|
queryParams[Param.ContextMenuTrigger] = false;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
const spriteUrl = customizations?.iconSpriteUrl
|
|
386
|
+
const spriteUrl = customizations?.iconSpriteUrl
|
|
387
|
+
|| this.embedConfig.customizations?.iconSpriteUrl;
|
|
387
388
|
if (spriteUrl) {
|
|
388
389
|
queryParams[Param.IconSpriteUrl] = spriteUrl.replace('https://', '');
|
|
389
390
|
}
|
package/src/react/index.tsx
CHANGED
|
@@ -79,6 +79,21 @@ export const AppEmbed = componentFactory<typeof _AppEmbed, AppProps, AppViewConf
|
|
|
79
79
|
|
|
80
80
|
interface LiveboardProps extends EmbedProps, LiveboardViewConfig {}
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* React component for Liveboard embed.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```tsx
|
|
87
|
+
* function Liveboard() {
|
|
88
|
+
* return <LiveboardEmbed
|
|
89
|
+
* liveboardId="liveboardId"
|
|
90
|
+
* fullHeight={true} {/* default false *\/}
|
|
91
|
+
* onLiveboardRendered={() => console.log('Liveboard rendered')}
|
|
92
|
+
* vizId="vizId" {/* if doing viz embed *\/}
|
|
93
|
+
* />
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
82
97
|
export const LiveboardEmbed = componentFactory<
|
|
83
98
|
typeof _LiveboardEmbed,
|
|
84
99
|
LiveboardProps,
|