@thoughtspot/visual-embed-sdk 1.20.0-alpha.2 → 1.20.0-prerender.0
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/dist/src/auth.d.ts +75 -5
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +19 -7
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts +39 -19
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +19 -7
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/search-bar.d.ts +7 -1
- package/dist/src/embed/search-bar.d.ts.map +1 -1
- package/dist/src/embed/search.d.ts +11 -3
- package/dist/src/embed/search.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +76 -5
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/mixpanel-service.d.ts +8 -0
- package/dist/src/mixpanel-service.d.ts.map +1 -1
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/react/util.d.ts +4 -0
- package/dist/src/react/util.d.ts.map +1 -1
- package/dist/src/test/test-utils.d.ts +11 -2
- package/dist/src/test/test-utils.d.ts.map +1 -1
- package/dist/src/types.d.ts +429 -97
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/answerService.d.ts +7 -0
- package/dist/src/utils/answerService.d.ts.map +1 -1
- package/dist/src/utils/authService.d.ts +30 -0
- package/dist/src/utils/authService.d.ts.map +1 -1
- package/dist/src/utils/processData.d.ts +12 -0
- package/dist/src/utils/processData.d.ts.map +1 -1
- package/dist/src/utils/processTrigger.d.ts +7 -0
- package/dist/src/utils/processTrigger.d.ts.map +1 -1
- package/dist/src/utils.d.ts +12 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/tsembed.es.js +818 -285
- package/dist/tsembed.js +791 -284
- package/lib/package.json +4 -3
- package/lib/src/auth.d.ts +75 -5
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js +86 -26
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.js +14 -5
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/config.d.ts +1 -0
- package/lib/src/config.d.ts.map +1 -1
- package/lib/src/config.js +5 -3
- package/lib/src/config.js.map +1 -1
- package/lib/src/config.spec.js.map +1 -1
- package/lib/src/embed/app.d.ts +19 -7
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +26 -16
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +12 -12
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts +39 -19
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +49 -15
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/base.spec.js +2 -2
- package/lib/src/embed/base.spec.js.map +1 -1
- package/lib/src/embed/embed.spec.js +1 -1
- package/lib/src/embed/embed.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +19 -7
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +50 -38
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +37 -30
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/pinboard.spec.js +14 -26
- package/lib/src/embed/pinboard.spec.js.map +1 -1
- package/lib/src/embed/search-bar.d.ts +7 -1
- package/lib/src/embed/search-bar.d.ts.map +1 -1
- package/lib/src/embed/search-bar.js +6 -7
- package/lib/src/embed/search-bar.js.map +1 -1
- package/lib/src/embed/search.d.ts +11 -3
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +19 -15
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/search.spec.js +16 -19
- package/lib/src/embed/search.spec.js.map +1 -1
- package/lib/src/embed/searchEmbed-basic-auth.spec.js +4 -0
- package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +76 -5
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +150 -72
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +23 -24
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.d.ts.map +1 -1
- package/lib/src/errors.js.map +1 -1
- package/lib/src/index.d.ts +3 -3
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +3 -3
- package/lib/src/index.js.map +1 -1
- package/lib/src/mixpanel-service.d.ts +8 -0
- package/lib/src/mixpanel-service.d.ts.map +1 -1
- package/lib/src/mixpanel-service.js +13 -1
- package/lib/src/mixpanel-service.js.map +1 -1
- package/lib/src/mixpanel-service.spec.js.map +1 -1
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +4 -6
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +3 -6
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/react/util.d.ts +4 -0
- package/lib/src/react/util.d.ts.map +1 -1
- package/lib/src/react/util.js +4 -0
- package/lib/src/react/util.js.map +1 -1
- package/lib/src/test/test-utils.d.ts +11 -2
- package/lib/src/test/test-utils.d.ts.map +1 -1
- package/lib/src/test/test-utils.js +36 -25
- package/lib/src/test/test-utils.js.map +1 -1
- package/lib/src/types.d.ts +429 -97
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +310 -72
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/answerService.d.ts +7 -0
- package/lib/src/utils/answerService.d.ts.map +1 -1
- package/lib/src/utils/answerService.js +7 -0
- package/lib/src/utils/answerService.js.map +1 -1
- package/lib/src/utils/answerService.spec.js.map +1 -1
- package/lib/src/utils/authService.d.ts +30 -0
- package/lib/src/utils/authService.d.ts.map +1 -1
- package/lib/src/utils/authService.js +39 -2
- package/lib/src/utils/authService.js.map +1 -1
- package/lib/src/utils/authService.spec.js.map +1 -1
- package/lib/src/utils/processData.d.ts +12 -0
- package/lib/src/utils/processData.d.ts.map +1 -1
- package/lib/src/utils/processData.js +33 -5
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/lib/src/utils/processTrigger.d.ts +7 -0
- package/lib/src/utils/processTrigger.d.ts.map +1 -1
- package/lib/src/utils/processTrigger.js +17 -3
- package/lib/src/utils/processTrigger.js.map +1 -1
- package/lib/src/utils/processTrigger.spec.js.map +1 -1
- package/lib/src/utils.d.ts +12 -0
- package/lib/src/utils.d.ts.map +1 -1
- package/lib/src/utils.js +24 -19
- package/lib/src/utils.js.map +1 -1
- package/lib/src/utils.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +664 -141
- package/package.json +4 -3
- package/src/auth.spec.ts +68 -150
- package/src/auth.ts +141 -101
- package/src/config.spec.ts +2 -4
- package/src/config.ts +5 -3
- package/src/embed/app.spec.ts +25 -14
- package/src/embed/app.ts +49 -37
- package/src/embed/base.spec.ts +6 -12
- package/src/embed/base.ts +74 -57
- package/src/embed/embed.spec.ts +5 -6
- package/src/embed/liveboard.spec.ts +56 -37
- package/src/embed/liveboard.ts +67 -65
- package/src/embed/pinboard.spec.ts +26 -29
- package/src/embed/search-bar.tsx +14 -9
- package/src/embed/search.spec.ts +31 -21
- package/src/embed/search.ts +28 -22
- package/src/embed/searchEmbed-basic-auth.spec.ts +22 -28
- package/src/embed/ts-embed.spec.ts +70 -148
- package/src/embed/ts-embed.ts +180 -157
- package/src/errors.ts +3 -6
- package/src/index.ts +23 -7
- package/src/mixpanel-service.spec.ts +1 -3
- package/src/mixpanel-service.ts +13 -1
- package/src/react/index.spec.tsx +11 -20
- package/src/react/index.tsx +40 -71
- package/src/react/util.ts +8 -4
- package/src/test/test-utils.ts +43 -39
- package/src/types.ts +427 -97
- package/src/utils/answerService.spec.ts +3 -5
- package/src/utils/answerService.ts +21 -17
- package/src/utils/authService.spec.ts +26 -41
- package/src/utils/authService.ts +47 -21
- package/src/utils/processData.spec.ts +26 -59
- package/src/utils/processData.ts +36 -14
- package/src/utils/processTrigger.spec.ts +1 -6
- package/src/utils/processTrigger.ts +18 -9
- package/src/utils.spec.ts +8 -12
- package/src/utils.ts +25 -26
package/src/embed/ts-embed.ts
CHANGED
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
setAttributes,
|
|
16
16
|
getCustomisations,
|
|
17
17
|
getDOMNode,
|
|
18
|
+
getFilterQuery,
|
|
19
|
+
getQueryParamString,
|
|
18
20
|
} from '../utils';
|
|
19
21
|
import {
|
|
20
22
|
getThoughtSpotHost,
|
|
@@ -38,6 +40,7 @@ import {
|
|
|
38
40
|
ViewConfig,
|
|
39
41
|
FrameParams,
|
|
40
42
|
ContextMenuTriggerOptions,
|
|
43
|
+
RuntimeFilter,
|
|
41
44
|
} from '../types';
|
|
42
45
|
import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
|
|
43
46
|
import { processEventData } from '../utils/processData';
|
|
@@ -64,6 +67,7 @@ const TS_EMBED_ID = '_thoughtspot-embed';
|
|
|
64
67
|
* The event id map from v2 event names to v1 event id
|
|
65
68
|
* v1 events are the classic embed events implemented in Blink v1
|
|
66
69
|
* We cannot rename v1 event types to maintain backward compatibility
|
|
70
|
+
*
|
|
67
71
|
* @internal
|
|
68
72
|
*/
|
|
69
73
|
const V1EventMap = {};
|
|
@@ -87,6 +91,8 @@ export class TsEmbed {
|
|
|
87
91
|
*/
|
|
88
92
|
private el: Element;
|
|
89
93
|
|
|
94
|
+
protected isAppInitialized = false;
|
|
95
|
+
|
|
90
96
|
/**
|
|
91
97
|
* A reference to the iframe within which the ThoughtSpot app
|
|
92
98
|
* will be rendered.
|
|
@@ -128,6 +134,7 @@ export class TsEmbed {
|
|
|
128
134
|
* Should we encode URL Query Params using base64 encoding which thoughtspot
|
|
129
135
|
* will generate for embedding. This provides additional security to
|
|
130
136
|
* thoughtspot clusters against Cross site scripting attacks.
|
|
137
|
+
*
|
|
131
138
|
* @default false
|
|
132
139
|
*/
|
|
133
140
|
private shouldEncodeUrlQueryParams = false;
|
|
@@ -156,6 +163,7 @@ export class TsEmbed {
|
|
|
156
163
|
|
|
157
164
|
/**
|
|
158
165
|
* Handles errors within the SDK
|
|
166
|
+
*
|
|
159
167
|
* @param error The error message or object
|
|
160
168
|
*/
|
|
161
169
|
protected handleError(error: string | Record<string, unknown>) {
|
|
@@ -169,6 +177,7 @@ export class TsEmbed {
|
|
|
169
177
|
|
|
170
178
|
/**
|
|
171
179
|
* Extracts the type field from the event payload
|
|
180
|
+
*
|
|
172
181
|
* @param event The window message event
|
|
173
182
|
*/
|
|
174
183
|
private getEventType(event: MessageEvent) {
|
|
@@ -178,6 +187,7 @@ export class TsEmbed {
|
|
|
178
187
|
|
|
179
188
|
/**
|
|
180
189
|
* Extracts the port field from the event payload
|
|
190
|
+
*
|
|
181
191
|
* @param event The window message event
|
|
182
192
|
* @returns
|
|
183
193
|
*/
|
|
@@ -191,6 +201,9 @@ export class TsEmbed {
|
|
|
191
201
|
/**
|
|
192
202
|
* fix for ts7.sep.cl
|
|
193
203
|
* will be removed for ts7.oct.cl
|
|
204
|
+
*
|
|
205
|
+
* @param event
|
|
206
|
+
* @param eventType
|
|
194
207
|
* @hidden
|
|
195
208
|
*/
|
|
196
209
|
private formatEventData(event: MessageEvent, eventType: string) {
|
|
@@ -218,12 +231,7 @@ export class TsEmbed {
|
|
|
218
231
|
if (event.source === this.iFrame.contentWindow) {
|
|
219
232
|
this.executeCallbacks(
|
|
220
233
|
eventType,
|
|
221
|
-
processEventData(
|
|
222
|
-
eventType,
|
|
223
|
-
eventData,
|
|
224
|
-
this.thoughtSpotHost,
|
|
225
|
-
this.el,
|
|
226
|
-
),
|
|
234
|
+
processEventData(eventType, eventData, this.thoughtSpotHost, this.el),
|
|
227
235
|
eventPort,
|
|
228
236
|
);
|
|
229
237
|
}
|
|
@@ -232,19 +240,20 @@ export class TsEmbed {
|
|
|
232
240
|
|
|
233
241
|
/**
|
|
234
242
|
* Send Custom style as part of payload of APP_INIT
|
|
243
|
+
*
|
|
244
|
+
* @param _
|
|
245
|
+
* @param responder
|
|
235
246
|
*/
|
|
236
247
|
private appInitCb = async (_: any, responder: any) => {
|
|
237
248
|
let authToken = '';
|
|
238
249
|
if (this.embedConfig.authType === AuthType.TrustedAuthTokenCookieless) {
|
|
239
250
|
authToken = await getAuthenticaionToken(this.embedConfig);
|
|
240
251
|
}
|
|
252
|
+
this.isAppInitialized = true;
|
|
241
253
|
responder({
|
|
242
254
|
type: EmbedEvent.APP_INIT,
|
|
243
255
|
data: {
|
|
244
|
-
customisations: getCustomisations(
|
|
245
|
-
this.embedConfig,
|
|
246
|
-
this.viewConfig,
|
|
247
|
-
),
|
|
256
|
+
customisations: getCustomisations(this.embedConfig, this.viewConfig),
|
|
248
257
|
authToken,
|
|
249
258
|
},
|
|
250
259
|
});
|
|
@@ -252,6 +261,9 @@ export class TsEmbed {
|
|
|
252
261
|
|
|
253
262
|
/**
|
|
254
263
|
* Sends updated auth token to the iFrame to avoid user logout
|
|
264
|
+
*
|
|
265
|
+
* @param _
|
|
266
|
+
* @param responder
|
|
255
267
|
*/
|
|
256
268
|
private updateAuthToken = async (_: any, responder: any) => {
|
|
257
269
|
const { autoLogin = false, authType } = this.embedConfig; // Set autoLogin default to false
|
|
@@ -277,6 +289,8 @@ export class TsEmbed {
|
|
|
277
289
|
|
|
278
290
|
/**
|
|
279
291
|
* Constructs the base URL string to load the ThoughtSpot app.
|
|
292
|
+
*
|
|
293
|
+
* @param query
|
|
280
294
|
*/
|
|
281
295
|
protected getEmbedBasePath(query: string): string {
|
|
282
296
|
let queryString = query;
|
|
@@ -285,31 +299,25 @@ export class TsEmbed {
|
|
|
285
299
|
queryString.substr(1),
|
|
286
300
|
)}`;
|
|
287
301
|
}
|
|
288
|
-
const basePath = [
|
|
289
|
-
this.thoughtSpotHost,
|
|
290
|
-
this.thoughtSpotV2Base,
|
|
291
|
-
queryString,
|
|
292
|
-
]
|
|
302
|
+
const basePath = [this.thoughtSpotHost, this.thoughtSpotV2Base, queryString]
|
|
293
303
|
.filter((x) => x.length > 0)
|
|
294
304
|
.join('/');
|
|
295
305
|
|
|
296
|
-
return `${basePath}
|
|
306
|
+
return `${basePath}#`;
|
|
297
307
|
}
|
|
298
308
|
|
|
299
309
|
/**
|
|
300
310
|
* Common query params set for all the embed modes.
|
|
311
|
+
*
|
|
312
|
+
* @param queryParams
|
|
301
313
|
* @returns queryParams
|
|
302
314
|
*/
|
|
303
|
-
protected getBaseQueryParams() {
|
|
304
|
-
const queryParams = {};
|
|
315
|
+
protected getBaseQueryParams(queryParams = {}) {
|
|
305
316
|
let hostAppUrl = window?.location?.host || '';
|
|
306
317
|
|
|
307
|
-
// The below check is needed because TS Cloud firewall, blocks
|
|
308
|
-
// in any url param.
|
|
309
|
-
if (
|
|
310
|
-
hostAppUrl.includes('localhost') ||
|
|
311
|
-
hostAppUrl.includes('127.0.0.1')
|
|
312
|
-
) {
|
|
318
|
+
// The below check is needed because TS Cloud firewall, blocks
|
|
319
|
+
// localhost/127.0.0.1 in any url param.
|
|
320
|
+
if (hostAppUrl.includes('localhost') || hostAppUrl.includes('127.0.0.1')) {
|
|
313
321
|
hostAppUrl = 'local-host';
|
|
314
322
|
}
|
|
315
323
|
queryParams[Param.HostAppUrl] = encodeURIComponent(hostAppUrl);
|
|
@@ -317,10 +325,7 @@ export class TsEmbed {
|
|
|
317
325
|
queryParams[Param.ViewPortWidth] = window.innerWidth;
|
|
318
326
|
queryParams[Param.Version] = version;
|
|
319
327
|
queryParams[Param.AuthType] = this.embedConfig.authType;
|
|
320
|
-
if (
|
|
321
|
-
this.embedConfig.disableLoginRedirect === true ||
|
|
322
|
-
this.embedConfig.autoLogin === true
|
|
323
|
-
) {
|
|
328
|
+
if (this.embedConfig.disableLoginRedirect === true || this.embedConfig.autoLogin === true) {
|
|
324
329
|
queryParams[Param.DisableLoginRedirect] = true;
|
|
325
330
|
}
|
|
326
331
|
if (this.embedConfig.authType === AuthType.EmbeddedSSO) {
|
|
@@ -345,16 +350,12 @@ export class TsEmbed {
|
|
|
345
350
|
} = this.viewConfig;
|
|
346
351
|
|
|
347
352
|
if (Array.isArray(visibleActions) && Array.isArray(hiddenActions)) {
|
|
348
|
-
this.handleError(
|
|
349
|
-
'You cannot have both hidden actions and visible actions',
|
|
350
|
-
);
|
|
353
|
+
this.handleError('You cannot have both hidden actions and visible actions');
|
|
351
354
|
return queryParams;
|
|
352
355
|
}
|
|
353
356
|
|
|
354
357
|
// TODO remove embedConfig.customCssUrl
|
|
355
|
-
const cssUrlParam =
|
|
356
|
-
customizations?.style?.customCSSUrl ||
|
|
357
|
-
this.embedConfig.customCssUrl;
|
|
358
|
+
const cssUrlParam = customizations?.style?.customCSSUrl || this.embedConfig.customCssUrl;
|
|
358
359
|
|
|
359
360
|
if (cssUrlParam) {
|
|
360
361
|
queryParams[Param.CustomCSSUrl] = cssUrlParam;
|
|
@@ -366,31 +367,25 @@ export class TsEmbed {
|
|
|
366
367
|
if (disabledActionReason) {
|
|
367
368
|
queryParams[Param.DisableActionReason] = disabledActionReason;
|
|
368
369
|
}
|
|
369
|
-
queryParams[Param.HideActions] = [
|
|
370
|
-
...this.defaultHiddenActions,
|
|
371
|
-
...(hiddenActions ?? []),
|
|
372
|
-
];
|
|
370
|
+
queryParams[Param.HideActions] = [...this.defaultHiddenActions, ...(hiddenActions ?? [])];
|
|
373
371
|
if (Array.isArray(visibleActions)) {
|
|
374
372
|
queryParams[Param.VisibleActions] = visibleActions;
|
|
375
373
|
}
|
|
376
374
|
|
|
377
|
-
/**
|
|
378
|
-
*
|
|
375
|
+
/**
|
|
376
|
+
* Default behavior for context menu will be left-click
|
|
377
|
+
* from version 9.2.0.cl the user have an option to override context
|
|
378
|
+
* menu click
|
|
379
379
|
*/
|
|
380
380
|
if (contextMenuTrigger === ContextMenuTriggerOptions.LEFT_CLICK) {
|
|
381
381
|
queryParams[Param.ContextMenuTrigger] = true;
|
|
382
|
-
} else if (
|
|
383
|
-
contextMenuTrigger === ContextMenuTriggerOptions.RIGHT_CLICK
|
|
384
|
-
) {
|
|
382
|
+
} else if (contextMenuTrigger === ContextMenuTriggerOptions.RIGHT_CLICK) {
|
|
385
383
|
queryParams[Param.ContextMenuTrigger] = false;
|
|
386
384
|
}
|
|
387
385
|
|
|
388
386
|
const spriteUrl = customizations?.iconSpriteUrl;
|
|
389
387
|
if (spriteUrl) {
|
|
390
|
-
queryParams[Param.IconSpriteUrl] = spriteUrl.replace(
|
|
391
|
-
'https://',
|
|
392
|
-
'',
|
|
393
|
-
);
|
|
388
|
+
queryParams[Param.IconSpriteUrl] = spriteUrl.replace('https://', '');
|
|
394
389
|
}
|
|
395
390
|
|
|
396
391
|
if (showAlerts !== undefined) {
|
|
@@ -414,48 +409,72 @@ export class TsEmbed {
|
|
|
414
409
|
/**
|
|
415
410
|
* Constructs the base URL string to load v1 of the ThoughtSpot app.
|
|
416
411
|
* This is used for embedding Liveboards, visualizations, and full application.
|
|
412
|
+
*
|
|
417
413
|
* @param queryString The query string to append to the URL.
|
|
418
414
|
* @param isAppEmbed A Boolean parameter to specify if you are embedding
|
|
419
415
|
* the full application.
|
|
420
416
|
*/
|
|
421
|
-
protected getV1EmbedBasePath(
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
enableSearchAssist = false,
|
|
427
|
-
): string {
|
|
428
|
-
const queryStringFrag = queryString ? `&${queryString}` : '';
|
|
429
|
-
const primaryNavParam = `&primaryNavHidden=${!showPrimaryNavbar}`;
|
|
430
|
-
const disableProfileAndHelpParam = `&profileAndHelpInNavBarHidden=${disableProfileAndHelp}`;
|
|
431
|
-
const enableSearchAssistParam = `&${Param.EnableSearchAssist}=${enableSearchAssist}`;
|
|
432
|
-
let queryParams = `?embedApp=true${isAppEmbed ? primaryNavParam : ''}${
|
|
433
|
-
isAppEmbed ? disableProfileAndHelpParam : ''
|
|
434
|
-
}${
|
|
435
|
-
enableSearchAssist ? enableSearchAssistParam : ''
|
|
436
|
-
}${queryStringFrag}`;
|
|
437
|
-
if (this.shouldEncodeUrlQueryParams) {
|
|
438
|
-
queryParams = `?base64UrlEncodedFlags=${getEncodedQueryParamsString(
|
|
439
|
-
queryParams.substr(1),
|
|
440
|
-
)}`;
|
|
441
|
-
}
|
|
442
|
-
let path = `${this.thoughtSpotHost}/${queryParams}#`;
|
|
443
|
-
if (!isAppEmbed) {
|
|
444
|
-
path = `${path}/embed`;
|
|
445
|
-
}
|
|
417
|
+
protected getV1EmbedBasePath(queryString: string): string {
|
|
418
|
+
const queryParams = this.shouldEncodeUrlQueryParams
|
|
419
|
+
? `?base64UrlEncodedFlags=${getEncodedQueryParamsString(queryString)}`
|
|
420
|
+
: `?${queryString}`;
|
|
421
|
+
const path = `${this.thoughtSpotHost}/${queryParams}#`;
|
|
446
422
|
return path;
|
|
447
423
|
}
|
|
448
424
|
|
|
425
|
+
protected getEmbedParams() {
|
|
426
|
+
const queryParams = this.getBaseQueryParams();
|
|
427
|
+
return getQueryParamString(queryParams);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
protected getRootIframeSrc() {
|
|
431
|
+
const query = this.getEmbedParams();
|
|
432
|
+
return this.getEmbedBasePath(query);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
protected createIframeEl(frameSrc: string): HTMLIFrameElement {
|
|
436
|
+
const iFrame = document.createElement('iframe');
|
|
437
|
+
|
|
438
|
+
iFrame.src = frameSrc;
|
|
439
|
+
iFrame.id = TS_EMBED_ID;
|
|
440
|
+
|
|
441
|
+
// according to screenfull.js documentation
|
|
442
|
+
// allowFullscreen, webkitallowfullscreen and mozallowfullscreen must be
|
|
443
|
+
// true
|
|
444
|
+
iFrame.allowFullscreen = true;
|
|
445
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
446
|
+
// @ts-ignore
|
|
447
|
+
iFrame.webkitallowfullscreen = true;
|
|
448
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
449
|
+
// @ts-ignore
|
|
450
|
+
iFrame.mozallowfullscreen = true;
|
|
451
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
452
|
+
// @ts-ignore
|
|
453
|
+
iFrame.allow = 'clipboard-read; clipboard-write';
|
|
454
|
+
|
|
455
|
+
const {
|
|
456
|
+
height: frameHeight,
|
|
457
|
+
width: frameWidth, ...restParams
|
|
458
|
+
} = this.viewConfig.frameParams || {};
|
|
459
|
+
const width = getCssDimension(frameWidth || DEFAULT_EMBED_WIDTH);
|
|
460
|
+
const height = getCssDimension(frameHeight || DEFAULT_EMBED_HEIGHT);
|
|
461
|
+
setAttributes(iFrame, restParams);
|
|
462
|
+
|
|
463
|
+
iFrame.style.width = `${width}`;
|
|
464
|
+
iFrame.style.height = `${height}`;
|
|
465
|
+
iFrame.style.border = '0';
|
|
466
|
+
iFrame.name = 'ThoughtSpot Embedded Analytics';
|
|
467
|
+
return iFrame;
|
|
468
|
+
}
|
|
469
|
+
|
|
449
470
|
/**
|
|
450
471
|
* Renders the embedded ThoughtSpot app in an iframe and sets up
|
|
451
472
|
* event listeners.
|
|
473
|
+
*
|
|
452
474
|
* @param url
|
|
453
475
|
* @param frameOptions
|
|
454
476
|
*/
|
|
455
|
-
protected async renderIFrame(
|
|
456
|
-
url: string,
|
|
457
|
-
frameOptions: FrameParams = {},
|
|
458
|
-
): Promise<any> {
|
|
477
|
+
protected async renderIFrame(url: string): Promise<any> {
|
|
459
478
|
if (this.isError) {
|
|
460
479
|
return null;
|
|
461
480
|
}
|
|
@@ -484,45 +503,8 @@ export class TsEmbed {
|
|
|
484
503
|
return;
|
|
485
504
|
}
|
|
486
505
|
|
|
487
|
-
uploadMixpanelEvent(
|
|
488
|
-
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
this.iFrame =
|
|
492
|
-
this.iFrame || document.createElement('iframe');
|
|
493
|
-
|
|
494
|
-
this.iFrame.src = url;
|
|
495
|
-
this.iFrame.id = TS_EMBED_ID;
|
|
496
|
-
|
|
497
|
-
// according to screenfull.js documentation
|
|
498
|
-
// allowFullscreen, webkitallowfullscreen and mozallowfullscreen must be true
|
|
499
|
-
this.iFrame.allowFullscreen = true;
|
|
500
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
501
|
-
// @ts-ignore
|
|
502
|
-
this.iFrame.webkitallowfullscreen = true;
|
|
503
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
504
|
-
// @ts-ignore
|
|
505
|
-
this.iFrame.mozallowfullscreen = true;
|
|
506
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
507
|
-
// @ts-ignore
|
|
508
|
-
this.iFrame.allow = 'clipboard-read; clipboard-write';
|
|
509
|
-
const {
|
|
510
|
-
height: frameHeight,
|
|
511
|
-
width: frameWidth,
|
|
512
|
-
...restParams
|
|
513
|
-
} = frameOptions;
|
|
514
|
-
const width = getCssDimension(
|
|
515
|
-
frameWidth || DEFAULT_EMBED_WIDTH,
|
|
516
|
-
);
|
|
517
|
-
const height = getCssDimension(
|
|
518
|
-
frameHeight || DEFAULT_EMBED_HEIGHT,
|
|
519
|
-
);
|
|
520
|
-
setAttributes(this.iFrame, restParams);
|
|
521
|
-
|
|
522
|
-
this.iFrame.style.width = `${width}`;
|
|
523
|
-
this.iFrame.style.height = `${height}`;
|
|
524
|
-
this.iFrame.style.border = '0';
|
|
525
|
-
this.iFrame.name = 'ThoughtSpot Embedded Analytics';
|
|
506
|
+
uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_COMPLETE);
|
|
507
|
+
this.iFrame = this.iFrame || this.createIframeEl(url);
|
|
526
508
|
this.iFrame.addEventListener('load', () => {
|
|
527
509
|
nextInQueue();
|
|
528
510
|
const loadTimestamp = Date.now();
|
|
@@ -532,20 +514,15 @@ export class TsEmbed {
|
|
|
532
514
|
},
|
|
533
515
|
type: EmbedEvent.Load,
|
|
534
516
|
});
|
|
535
|
-
uploadMixpanelEvent(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
timeTookToLoad: loadTimestamp - initTimestamp,
|
|
539
|
-
},
|
|
540
|
-
);
|
|
517
|
+
uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_IFRAME_LOAD_PERFORMANCE, {
|
|
518
|
+
timeTookToLoad: loadTimestamp - initTimestamp,
|
|
519
|
+
});
|
|
541
520
|
});
|
|
542
521
|
this.iFrame.addEventListener('error', () => {
|
|
543
522
|
nextInQueue();
|
|
544
523
|
});
|
|
545
524
|
this.insertIntoDOM(this.iFrame);
|
|
546
|
-
const prefetchIframe = document.querySelectorAll(
|
|
547
|
-
'.prefetchIframe',
|
|
548
|
-
);
|
|
525
|
+
const prefetchIframe = document.querySelectorAll('.prefetchIframe');
|
|
549
526
|
if (prefetchIframe.length) {
|
|
550
527
|
prefetchIframe.forEach((el) => {
|
|
551
528
|
el.remove();
|
|
@@ -555,10 +532,9 @@ export class TsEmbed {
|
|
|
555
532
|
})
|
|
556
533
|
.catch((error) => {
|
|
557
534
|
nextInQueue();
|
|
558
|
-
uploadMixpanelEvent(
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
);
|
|
535
|
+
uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_FAILED, {
|
|
536
|
+
error: JSON.stringify(error),
|
|
537
|
+
});
|
|
562
538
|
this.insertIntoDOM(this.embedConfig.loginFailedMessage);
|
|
563
539
|
this.handleError(error);
|
|
564
540
|
});
|
|
@@ -591,6 +567,7 @@ export class TsEmbed {
|
|
|
591
567
|
|
|
592
568
|
/**
|
|
593
569
|
* Sets the height of the iframe
|
|
570
|
+
*
|
|
594
571
|
* @param height The height in pixels
|
|
595
572
|
*/
|
|
596
573
|
protected setIFrameHeight(height: number): void {
|
|
@@ -599,6 +576,7 @@ export class TsEmbed {
|
|
|
599
576
|
|
|
600
577
|
/**
|
|
601
578
|
* Executes all registered event handlers for a particular event type
|
|
579
|
+
*
|
|
602
580
|
* @param eventType The event type
|
|
603
581
|
* @param data The payload invoked with the event handler
|
|
604
582
|
* @param eventPort The event Port for a specific MessageChannel
|
|
@@ -614,10 +592,12 @@ export class TsEmbed {
|
|
|
614
592
|
const dataStatus = data?.status || embedEventStatus.END;
|
|
615
593
|
callbacks.forEach((callbackObj) => {
|
|
616
594
|
if (
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
(
|
|
620
|
-
|
|
595
|
+
// When start status is true it trigger only start releated
|
|
596
|
+
// payload
|
|
597
|
+
(callbackObj.options.start && dataStatus === embedEventStatus.START)
|
|
598
|
+
// When start status is false it trigger only end releated
|
|
599
|
+
// payload
|
|
600
|
+
|| (!callbackObj.options.start && dataStatus === embedEventStatus.END)
|
|
621
601
|
) {
|
|
622
602
|
callbackObj.callback(data, (payload) => {
|
|
623
603
|
this.triggerEventOnPort(eventPort, payload);
|
|
@@ -635,6 +615,7 @@ export class TsEmbed {
|
|
|
635
615
|
|
|
636
616
|
/**
|
|
637
617
|
* Gets the v1 event type (if applicable) for the EmbedEvent type
|
|
618
|
+
*
|
|
638
619
|
* @param eventType The v2 event type
|
|
639
620
|
* @returns The corresponding v1 event type if one exists
|
|
640
621
|
* or else the v2 event type itself
|
|
@@ -647,6 +628,7 @@ export class TsEmbed {
|
|
|
647
628
|
* Calculates the iframe center for the current visible viewPort
|
|
648
629
|
* of iframe using Scroll position of Host App, offsetTop for iframe
|
|
649
630
|
* in Host app. ViewPort height of the tab.
|
|
631
|
+
*
|
|
650
632
|
* @returns iframe Center in visible viewport,
|
|
651
633
|
* Iframe height,
|
|
652
634
|
* View port height.
|
|
@@ -661,18 +643,11 @@ export class TsEmbed {
|
|
|
661
643
|
let iframeOffset;
|
|
662
644
|
|
|
663
645
|
if (iframeScrolled < 0) {
|
|
664
|
-
iframeVisibleViewPort =
|
|
665
|
-
|
|
666
|
-
iframeVisibleViewPort = Math.min(
|
|
667
|
-
iframeHeight,
|
|
668
|
-
iframeVisibleViewPort,
|
|
669
|
-
);
|
|
646
|
+
iframeVisibleViewPort = viewPortHeight - (offsetTopClient - scrollTopClient);
|
|
647
|
+
iframeVisibleViewPort = Math.min(iframeHeight, iframeVisibleViewPort);
|
|
670
648
|
iframeOffset = 0;
|
|
671
649
|
} else {
|
|
672
|
-
iframeVisibleViewPort = Math.min(
|
|
673
|
-
iframeHeight - iframeScrolled,
|
|
674
|
-
viewPortHeight,
|
|
675
|
-
);
|
|
650
|
+
iframeVisibleViewPort = Math.min(iframeHeight - iframeScrolled, viewPortHeight);
|
|
676
651
|
iframeOffset = iframeScrolled;
|
|
677
652
|
}
|
|
678
653
|
const iframeCenter = iframeOffset + iframeVisibleViewPort / 2;
|
|
@@ -692,6 +667,20 @@ export class TsEmbed {
|
|
|
692
667
|
* @param messageType The message type
|
|
693
668
|
* @param callback A callback as a function
|
|
694
669
|
* @param options The message options
|
|
670
|
+
* @example
|
|
671
|
+
* ```js
|
|
672
|
+
* tsEmbed.on(EmbedEvent.Error, (data) => {
|
|
673
|
+
* console.error(data);
|
|
674
|
+
* });
|
|
675
|
+
* ```
|
|
676
|
+
* @example
|
|
677
|
+
* ```js
|
|
678
|
+
* tsEmbed.on(EmbedEvent.Save, (data) => {
|
|
679
|
+
* console.log("Answer save clicked", data);
|
|
680
|
+
* }, {
|
|
681
|
+
* start: true // This will trigger the callback on start of save
|
|
682
|
+
* });
|
|
683
|
+
* ```
|
|
695
684
|
*/
|
|
696
685
|
public on(
|
|
697
686
|
messageType: EmbedEvent,
|
|
@@ -699,9 +688,7 @@ export class TsEmbed {
|
|
|
699
688
|
options: MessageOptions = { start: false },
|
|
700
689
|
): typeof TsEmbed.prototype {
|
|
701
690
|
if (this.isRendered) {
|
|
702
|
-
this.handleError(
|
|
703
|
-
'Please register event handlers before calling render',
|
|
704
|
-
);
|
|
691
|
+
this.handleError('Please register event handlers before calling render');
|
|
705
692
|
}
|
|
706
693
|
const callbacks = this.eventHandlerMap.get(messageType) || [];
|
|
707
694
|
callbacks.push({ options, callback });
|
|
@@ -712,8 +699,11 @@ export class TsEmbed {
|
|
|
712
699
|
/**
|
|
713
700
|
* Triggers an event on specific Port registered against
|
|
714
701
|
* for the EmbedEvent
|
|
702
|
+
*
|
|
715
703
|
* @param eventType The message type
|
|
716
704
|
* @param data The payload to send
|
|
705
|
+
* @param eventPort
|
|
706
|
+
* @param payload
|
|
717
707
|
*/
|
|
718
708
|
private triggerEventOnPort(eventPort: MessagePort | void, payload: any) {
|
|
719
709
|
if (eventPort) {
|
|
@@ -733,25 +723,20 @@ export class TsEmbed {
|
|
|
733
723
|
|
|
734
724
|
/**
|
|
735
725
|
* Triggers an event to the embedded app
|
|
726
|
+
*
|
|
736
727
|
* @param messageType The event type
|
|
737
728
|
* @param data The payload to send with the message
|
|
738
729
|
*/
|
|
739
730
|
public trigger(messageType: HostEvent, data: any = {}): Promise<any> {
|
|
740
|
-
uploadMixpanelEvent(
|
|
741
|
-
|
|
742
|
-
);
|
|
743
|
-
return processTrigger(
|
|
744
|
-
this.iFrame,
|
|
745
|
-
messageType,
|
|
746
|
-
this.thoughtSpotHost,
|
|
747
|
-
data,
|
|
748
|
-
);
|
|
731
|
+
uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_TRIGGER}-${messageType}`);
|
|
732
|
+
return processTrigger(this.iFrame, messageType, this.thoughtSpotHost, data);
|
|
749
733
|
}
|
|
750
734
|
|
|
751
735
|
/**
|
|
752
736
|
* Marks the ThoughtSpot object to have been rendered
|
|
753
737
|
* Needs to be overridden by subclasses to do the actual
|
|
754
738
|
* rendering of the iframe.
|
|
739
|
+
*
|
|
755
740
|
* @param args
|
|
756
741
|
*/
|
|
757
742
|
public render(): TsEmbed {
|
|
@@ -764,6 +749,7 @@ export class TsEmbed {
|
|
|
764
749
|
* Get the Post Url Params for THOUGHTSPOT from the current
|
|
765
750
|
* host app URL.
|
|
766
751
|
* THOUGHTSPOT URL params starts with a prefix "ts-"
|
|
752
|
+
*
|
|
767
753
|
* @version SDK: 1.14.0 | ThoughtSpot: 8.4.0.cl, 8.4.1-sw
|
|
768
754
|
*/
|
|
769
755
|
public getThoughtSpotPostUrlParams(): string {
|
|
@@ -791,6 +777,7 @@ export class TsEmbed {
|
|
|
791
777
|
|
|
792
778
|
/**
|
|
793
779
|
* Destroys the ThoughtSpot embed, and remove any nodes from the DOM.
|
|
780
|
+
*
|
|
794
781
|
* @version SDK: 1.19.1 | ThoughtSpot: *
|
|
795
782
|
*/
|
|
796
783
|
public destroy(): void {
|
|
@@ -800,12 +787,23 @@ export class TsEmbed {
|
|
|
800
787
|
console.log('Error destroying TS Embed', e);
|
|
801
788
|
}
|
|
802
789
|
}
|
|
790
|
+
|
|
791
|
+
public getUnderlyingFrameElement(): HTMLIFrameElement {
|
|
792
|
+
return this.iFrame;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
public async prerenderGeneric(): Promise<any> {
|
|
796
|
+
const prerenderFrameSrc = this.getRootIframeSrc();
|
|
797
|
+
return this.renderIFrame(prerenderFrameSrc);
|
|
798
|
+
}
|
|
803
799
|
}
|
|
804
800
|
|
|
805
801
|
/**
|
|
806
802
|
* Base class for embedding v1 experience
|
|
807
803
|
* Note: The v1 version of ThoughtSpot Blink works on the AngularJS stack
|
|
808
804
|
* which is currently under migration to v2
|
|
805
|
+
*
|
|
806
|
+
* @inheritdoc
|
|
809
807
|
*/
|
|
810
808
|
export class V1Embed extends TsEmbed {
|
|
811
809
|
protected viewConfig: ViewConfig;
|
|
@@ -816,14 +814,39 @@ export class V1Embed extends TsEmbed {
|
|
|
816
814
|
}
|
|
817
815
|
|
|
818
816
|
/**
|
|
819
|
-
* Render the
|
|
817
|
+
* Render the ap p in an iframe and set up event handlers
|
|
818
|
+
*
|
|
820
819
|
* @param iframeSrc
|
|
821
820
|
*/
|
|
822
821
|
protected renderV1Embed(iframeSrc: string): any {
|
|
823
|
-
return this.renderIFrame(iframeSrc
|
|
822
|
+
return this.renderIFrame(iframeSrc);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
protected getRootIframeSrc(): string {
|
|
826
|
+
const runtimeFilters = this.viewConfig.runtimeFilters;
|
|
827
|
+
const filterQuery = getFilterQuery(runtimeFilters || []);
|
|
828
|
+
const queryParams = this.getEmbedParams();
|
|
829
|
+
const queryString = [filterQuery, queryParams].filter(Boolean).join('&');
|
|
830
|
+
return this.getV1EmbedBasePath(queryString);
|
|
824
831
|
}
|
|
825
832
|
|
|
826
|
-
|
|
833
|
+
/**
|
|
834
|
+
* @inheritdoc
|
|
835
|
+
* @example
|
|
836
|
+
* ```js
|
|
837
|
+
* tsEmbed.on(EmbedEvent.Error, (data) => {
|
|
838
|
+
* console.error(data);
|
|
839
|
+
* });
|
|
840
|
+
* ```
|
|
841
|
+
* @example
|
|
842
|
+
* ```js
|
|
843
|
+
* tsEmbed.on(EmbedEvent.Save, (data) => {
|
|
844
|
+
* console.log("Answer save clicked", data);
|
|
845
|
+
* }, {
|
|
846
|
+
* start: true // This will trigger the callback on start of save
|
|
847
|
+
* });
|
|
848
|
+
* ```
|
|
849
|
+
*/
|
|
827
850
|
public on(
|
|
828
851
|
messageType: EmbedEvent,
|
|
829
852
|
callback: MessageCallback,
|
package/src/errors.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
export const ERROR_MESSAGE = {
|
|
2
|
-
INVALID_THOUGHTSPOT_HOST:
|
|
3
|
-
|
|
4
|
-
LIVEBOARD_VIZ_ID_VALIDATION:
|
|
5
|
-
'Please provide either liveboardId or pinboardId',
|
|
2
|
+
INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
|
|
3
|
+
LIVEBOARD_VIZ_ID_VALIDATION: 'Please provide either liveboardId or pinboardId',
|
|
6
4
|
TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
|
|
7
|
-
SEARCHEMBED_BETA_WRANING_MESSAGE:
|
|
8
|
-
'Search Embed is in Beta in this release.',
|
|
5
|
+
SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
|
|
9
6
|
};
|