@thoughtspot/visual-embed-sdk 1.32.4 → 1.32.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/embed/app.d.ts +42 -0
  3. package/cjs/src/embed/app.d.ts.map +1 -1
  4. package/cjs/src/embed/app.js +4 -1
  5. package/cjs/src/embed/app.js.map +1 -1
  6. package/cjs/src/embed/app.spec.js +30 -0
  7. package/cjs/src/embed/app.spec.js.map +1 -1
  8. package/cjs/src/embed/base.d.ts +1 -1
  9. package/cjs/src/embed/base.js +1 -1
  10. package/cjs/src/embed/liveboard.d.ts +42 -0
  11. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  12. package/cjs/src/embed/liveboard.js +4 -1
  13. package/cjs/src/embed/liveboard.js.map +1 -1
  14. package/cjs/src/embed/liveboard.spec.js +33 -0
  15. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  16. package/cjs/src/embed/ts-embed.d.ts +0 -1
  17. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  18. package/cjs/src/embed/ts-embed.js +1 -2
  19. package/cjs/src/embed/ts-embed.js.map +1 -1
  20. package/cjs/src/types.d.ts +62 -7
  21. package/cjs/src/types.d.ts.map +1 -1
  22. package/cjs/src/types.js +55 -6
  23. package/cjs/src/types.js.map +1 -1
  24. package/cjs/src/utils/graphql/answerService/answerService.d.ts +14 -0
  25. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  26. package/cjs/src/utils/graphql/answerService/answerService.js +21 -0
  27. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  28. package/cjs/src/utils/processData.js +2 -2
  29. package/cjs/src/utils/processData.js.map +1 -1
  30. package/cjs/src/utils/processData.spec.js +14 -0
  31. package/cjs/src/utils/processData.spec.js.map +1 -1
  32. package/dist/src/embed/app.d.ts +42 -0
  33. package/dist/src/embed/app.d.ts.map +1 -1
  34. package/dist/src/embed/base.d.ts +1 -1
  35. package/dist/src/embed/liveboard.d.ts +42 -0
  36. package/dist/src/embed/liveboard.d.ts.map +1 -1
  37. package/dist/src/embed/ts-embed.d.ts +0 -1
  38. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  39. package/dist/src/types.d.ts +62 -7
  40. package/dist/src/types.d.ts.map +1 -1
  41. package/dist/src/utils/graphql/answerService/answerService.d.ts +14 -0
  42. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  43. package/dist/tsembed-react.es.js +88 -13
  44. package/dist/tsembed-react.js +88 -13
  45. package/dist/tsembed.es.js +89 -14
  46. package/dist/tsembed.js +89 -14
  47. package/dist/visual-embed-sdk-react-full.d.ts +161 -9
  48. package/dist/visual-embed-sdk-react.d.ts +161 -9
  49. package/dist/visual-embed-sdk.d.ts +161 -9
  50. package/lib/package.json +1 -1
  51. package/lib/src/embed/app.d.ts +42 -0
  52. package/lib/src/embed/app.d.ts.map +1 -1
  53. package/lib/src/embed/app.js +4 -1
  54. package/lib/src/embed/app.js.map +1 -1
  55. package/lib/src/embed/app.spec.js +30 -0
  56. package/lib/src/embed/app.spec.js.map +1 -1
  57. package/lib/src/embed/base.d.ts +1 -1
  58. package/lib/src/embed/base.js +1 -1
  59. package/lib/src/embed/liveboard.d.ts +42 -0
  60. package/lib/src/embed/liveboard.d.ts.map +1 -1
  61. package/lib/src/embed/liveboard.js +4 -1
  62. package/lib/src/embed/liveboard.js.map +1 -1
  63. package/lib/src/embed/liveboard.spec.js +33 -0
  64. package/lib/src/embed/liveboard.spec.js.map +1 -1
  65. package/lib/src/embed/ts-embed.d.ts +0 -1
  66. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  67. package/lib/src/embed/ts-embed.js +1 -2
  68. package/lib/src/embed/ts-embed.js.map +1 -1
  69. package/lib/src/types.d.ts +62 -7
  70. package/lib/src/types.d.ts.map +1 -1
  71. package/lib/src/types.js +55 -6
  72. package/lib/src/types.js.map +1 -1
  73. package/lib/src/utils/graphql/answerService/answerService.d.ts +14 -0
  74. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  75. package/lib/src/utils/graphql/answerService/answerService.js +21 -0
  76. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  77. package/lib/src/utils/processData.js +2 -2
  78. package/lib/src/utils/processData.js.map +1 -1
  79. package/lib/src/utils/processData.spec.js +14 -0
  80. package/lib/src/utils/processData.spec.js.map +1 -1
  81. package/lib/src/visual-embed-sdk.d.ts +161 -9
  82. package/package.json +1 -1
  83. package/src/embed/app.spec.ts +45 -0
  84. package/src/embed/app.ts +48 -0
  85. package/src/embed/base.ts +1 -1
  86. package/src/embed/liveboard.spec.ts +48 -0
  87. package/src/embed/liveboard.ts +48 -0
  88. package/src/embed/ts-embed.ts +1 -2
  89. package/src/types.ts +62 -6
  90. package/src/utils/graphql/answerService/answerService.ts +27 -0
  91. package/src/utils/processData.spec.ts +16 -0
  92. package/src/utils/processData.ts +2 -2
@@ -241,6 +241,54 @@ describe('Liveboard/viz embed tests', () => {
241
241
  });
242
242
  });
243
243
 
244
+ test('Should add isLiveboardCompactHeaderEnabled flag to the iframe src', async () => {
245
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
246
+ ...defaultViewConfig,
247
+ liveboardId,
248
+ isLiveboardCompactHeaderEnabled: false,
249
+ } as LiveboardViewConfig);
250
+
251
+ liveboardEmbed.render();
252
+ await executeAfterWait(() => {
253
+ expectUrlMatchesWithParams(
254
+ getIFrameSrc(),
255
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&isLiveboardHeaderV2Enabled=false${prefixParams}#/embed/viz/${liveboardId}`,
256
+ );
257
+ });
258
+ });
259
+
260
+ test('Should add showLiveboardReverifyBanner flag to the iframe src', async () => {
261
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
262
+ ...defaultViewConfig,
263
+ liveboardId,
264
+ showLiveboardReverifyBanner: false,
265
+ } as LiveboardViewConfig);
266
+
267
+ liveboardEmbed.render();
268
+ await executeAfterWait(() => {
269
+ expectUrlMatchesWithParams(
270
+ getIFrameSrc(),
271
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&showLiveboardReverifyBanner=false${prefixParams}#/embed/viz/${liveboardId}`,
272
+ );
273
+ });
274
+ });
275
+
276
+ test('Should add showLiveboardVerifiedBadge flag to the iframe src', async () => {
277
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
278
+ ...defaultViewConfig,
279
+ liveboardId,
280
+ showLiveboardVerifiedBadge: false,
281
+ } as LiveboardViewConfig);
282
+
283
+ liveboardEmbed.render();
284
+ await executeAfterWait(() => {
285
+ expectUrlMatchesWithParams(
286
+ getIFrameSrc(),
287
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&showLiveboardVerifiedBadge=false${prefixParams}#/embed/viz/${liveboardId}`,
288
+ );
289
+ });
290
+ });
291
+
244
292
  test('should not append runtime filters in URL if excludeRuntimeFiltersfromURL is true', async () => {
245
293
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
246
294
  ...defaultViewConfig,
@@ -284,6 +284,48 @@ export interface LiveboardViewConfig
284
284
  * @version SDK: 1.32.0 | ThoughtSpot: 10.0.0.cl
285
285
  */
286
286
  showPreviewLoader?: boolean;
287
+ /**
288
+ * This flag is used to enable the compact header in liveboard
289
+ * @type {boolean}
290
+ * @default false
291
+ * @version SDK: 1.35.0 | ThoughtSpot:10.3.0.cl
292
+ * @example
293
+ * ```js
294
+ * const embed = new LiveboardEmbed('#embed-container', {
295
+ * ... // other options
296
+ * isLiveboardCompactHeaderEnabled: true,
297
+ * })
298
+ * ```
299
+ */
300
+ isLiveboardCompactHeaderEnabled?: boolean;
301
+ /**
302
+ * This flag is used to show/hide verified Icon in liveboard compact header
303
+ * @type {boolean}
304
+ * @default true
305
+ * @version SDK: 1.35.0 | ThoughtSpot:10.4.0.cl
306
+ * @example
307
+ * ```js
308
+ * const embed = new LiveboardEmbed('#embed-container', {
309
+ * ... // other options
310
+ * showLiveboardVerifiedBadge: true,
311
+ * })
312
+ * ```
313
+ */
314
+ showLiveboardVerifiedBadge?: boolean;
315
+ /**
316
+ * This flag is used to show/hide re-verify banner in liveboard compact header
317
+ * @type {boolean}
318
+ * @default true
319
+ * @version SDK: 1.35.0 | ThoughtSpot:10.4.0.cl
320
+ * @example
321
+ * ```js
322
+ * const embed = new LiveboardEmbed('#embed-container', {
323
+ * ... // other options
324
+ * showLiveboardReverifyBanner: true,
325
+ * })
326
+ * ```
327
+ */
328
+ showLiveboardReverifyBanner?: boolean;
287
329
  }
288
330
 
289
331
  /**
@@ -338,6 +380,9 @@ export class LiveboardEmbed extends V1Embed {
338
380
  showLiveboardDescription,
339
381
  showLiveboardTitle,
340
382
  isLiveboardHeaderSticky = true,
383
+ isLiveboardCompactHeaderEnabled = false,
384
+ showLiveboardVerifiedBadge = true,
385
+ showLiveboardReverifyBanner = true,
341
386
  enableAskSage,
342
387
  enable2ColumnLayout,
343
388
  dataPanelV2 = true,
@@ -388,6 +433,9 @@ export class LiveboardEmbed extends V1Embed {
388
433
  }
389
434
 
390
435
  params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
436
+ params[Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled;
437
+ params[Param.ShowLiveboardVerifiedBadge] = showLiveboardVerifiedBadge;
438
+ params[Param.ShowLiveboardReverifyBanner] = showLiveboardReverifyBanner;
391
439
 
392
440
  params[Param.DataPanelV2Enabled] = dataPanelV2;
393
441
  const queryParams = getQueryParamString(params, true);
@@ -1214,7 +1214,7 @@ export class TsEmbed {
1214
1214
  * @version SDK: 1.25.0 / ThoughtSpot 9.10.0
1215
1215
  */
1216
1216
  public async getAnswerService(vizId?: string): Promise<AnswerService> {
1217
- const { session } = await this.trigger(HostEvent.GetAnswerSession, vizId);
1217
+ const { session } = await this.trigger(HostEvent.GetAnswerSession, vizId ? { vizId } : {});
1218
1218
 
1219
1219
  return new AnswerService(session, null, this.embedConfig.thoughtSpotHost);
1220
1220
  }
@@ -1291,7 +1291,6 @@ export class V1Embed extends TsEmbed {
1291
1291
 
1292
1292
  /**
1293
1293
  * Only for testing purposes.
1294
- *
1295
1294
  * @hidden
1296
1295
  */
1297
1296
  // eslint-disable-next-line camelcase
package/src/types.ts CHANGED
@@ -581,6 +581,13 @@ export interface EmbedConfig {
581
581
  * @version SDK: 1.28.5 | Thoughtspot: *
582
582
  */
583
583
  disableTokenVerification?: boolean;
584
+
585
+ /**
586
+ * This flag is used to disable showing the login failure page in the embedded app.
587
+ *
588
+ * @version SDK 1.32.3 | Thoughtspot: *
589
+ */
590
+ disableLoginFailurePage?: boolean;
584
591
  }
585
592
 
586
593
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
@@ -2126,20 +2133,57 @@ export enum EmbedEvent {
2126
2133
  */
2127
2134
  Rename = 'rename',
2128
2135
  /**
2129
- * Emitted when user wants to intercept the search execution
2136
+ * Emitted if the user wants to intercept the search execution
2137
+ * and implement logic to decide whether to run the search or not
2130
2138
  *
2131
- * Set IsOnBeforeGetVizDataInterceptEnabled : true to use
2132
- * this embed event
2139
+ * Prerequisite: Set isOnBeforeGetVizDataInterceptEnabled : true
2140
+ * for this embed event to get emitted.
2141
+ *
2142
+ * Parameter: payload
2143
+ * Parameter: responder
2144
+ * Contains elements that lets developers define whether ThoughtSpot
2145
+ * will run the search or not, and if not, which error message to provide.
2146
+ * execute: When execute returns true, the search will be run.
2147
+ * When execute returns false, the search will not be executed.
2148
+ * error: Developers can customize the user facing message when execute is
2149
+ * set to false using the error parameter in responder
2133
2150
  *
2134
2151
  *```js
2135
- * searchEmbed.on(EmbedEvent.OnBeforeGetVizDataIntercept,
2152
+ * .on(EmbedEvent.OnBeforeGetVizDataIntercept,
2136
2153
  * (payload, responder) => {
2137
2154
  * responder({
2138
2155
  * data: {
2139
- * execute: true,
2140
- * }})
2156
+ * execute:false,
2157
+ * error: {
2158
+ * //Provide a custom error message to explain to your end user
2159
+ * //why their search did not run
2160
+ * errorText: "This search query cannot be run.
2161
+ * Please contact your administrator for more details."
2162
+ * }
2163
+ * }})
2164
+ * })
2165
+ * ```
2166
+ *
2167
+ *```js
2168
+ * .on(EmbedEvent.OnBeforeGetVizDataIntercept,
2169
+ * (payload, responder) => {
2170
+ * const query = payload.data.data.answer.search_query
2171
+ * responder({
2172
+ * data: {
2173
+ * // returns true as long as the query does not include
2174
+ * // both the 'sales' AND the 'county' column
2175
+ * execute: !(query.includes("sales")&&query.includes("county")),
2176
+ * error: {
2177
+ * //Provide a custom error message to explain to your end user
2178
+ * // why their search did not run, and which searches are accepted by your custom logic.
2179
+ * errorText: "You can't use this query :" + query + ".
2180
+ * The 'sales' measures can never be used at the 'county' level.
2181
+ * Please try another measure, or remove 'county' from your search."
2182
+ * }
2183
+ * }})
2141
2184
  * })
2142
2185
  *```
2186
+ *
2143
2187
  * @version SDK : 1.29.0 | Thoughtspot : 10.2.0.cl
2144
2188
  */
2145
2189
  OnBeforeGetVizDataIntercept = 'onBeforeGetVizDataIntercept',
@@ -2260,6 +2304,15 @@ export enum HostEvent {
2260
2304
  * @hidden
2261
2305
  */
2262
2306
  Reload = 'reload',
2307
+ /**
2308
+ * Get current iframe src
2309
+ * @example
2310
+ * ```js
2311
+ * const frameUrl = AppEmbed.trigger(HostEvent.GetIframeUrl)
2312
+ * ```
2313
+ * @version SDK: 1.35.0 | Thoughtspot: 10.4.0.cl
2314
+ */
2315
+ GetIframeUrl = 'GetIframeUrl',
2263
2316
  /**
2264
2317
  * Display specific visualizations on a Liveboard.
2265
2318
  * @param - An array of GUIDs of the visualization to show. The visualization IDs not passed
@@ -3130,6 +3183,9 @@ export enum Param {
3130
3183
  FocusSearchBarOnRender = 'focusSearchBarOnRender',
3131
3184
  DisableRedirectionLinksInNewTab = 'disableRedirectionLinksInNewTab',
3132
3185
  HomePageSearchBarMode = 'homePageSearchBarMode',
3186
+ ShowLiveboardVerifiedBadge = 'showLiveboardVerifiedBadge',
3187
+ ShowLiveboardReverifyBanner = 'showLiveboardReverifyBanner',
3188
+ LiveboardHeaderV2 = 'isLiveboardHeaderV2Enabled',
3133
3189
  }
3134
3190
 
3135
3191
  /**
@@ -222,6 +222,25 @@ export class AnswerService {
222
222
  });
223
223
  }
224
224
 
225
+ /**
226
+ * Fetch the data for the answer as a PNG blob. This might be
227
+ * quicker for larger data.
228
+ * @param userLocale
229
+ * @param omitBackground Omit the background in the PNG
230
+ * @param deviceScaleFactor The scale factor for the PNG
231
+ * @return Response
232
+ */
233
+ public async fetchPNGBlob(userLocale = 'en-us', includeInfo = false, omitBackground = false, deviceScaleFactor = 2): Promise<Response> {
234
+ const fetchUrl = this.getFetchPNGBlobUrl(
235
+ userLocale,
236
+ omitBackground,
237
+ deviceScaleFactor,
238
+ );
239
+ return tokenizedFetch(fetchUrl, {
240
+ credentials: 'include',
241
+ });
242
+ }
243
+
225
244
  /**
226
245
  * Just get the internal URL for this answer's data
227
246
  * as a CSV blob.
@@ -233,6 +252,14 @@ export class AnswerService {
233
252
  return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
234
253
  }
235
254
 
255
+ /**
256
+ * Just get the internal URL for this answer's data
257
+ * as a PNG blob.
258
+ */
259
+ public getFetchPNGBlobUrl(userLocale = 'en-us', omitBackground = false, deviceScaleFactor = 2): string {
260
+ return `${this.thoughtSpotHost}/prism/download/answer/png?sessionId=${this.session.sessionId}&deviceScaleFactor=${deviceScaleFactor}&omitBackground=${omitBackground}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data`;
261
+ }
262
+
236
263
  /**
237
264
  * Get underlying data given a point and the output column names.
238
265
  * In case of a context menu action, the selectedPoints are
@@ -1,3 +1,4 @@
1
+ import { disable } from 'mixpanel-browser';
1
2
  import * as processDataInstance from './processData';
2
3
  import * as answerServiceInstance from './graphql/answerService/answerService';
3
4
  import * as auth from '../auth';
@@ -171,4 +172,19 @@ describe('Unit test for process data', () => {
171
172
  expect(el.innerHTML).toBe('Hello');
172
173
  expect(embedConfigInstance.getEmbedConfig().autoLogin).toBe(false);
173
174
  });
175
+
176
+ test('process authFailure AuthType=None', () => {
177
+ const e = { type: EmbedEvent.AuthFailure };
178
+ jest.spyOn(embedConfigInstance, 'getEmbedConfig').mockReturnValue({
179
+ loginFailedMessage: 'Hello',
180
+ authType: AuthType.EmbeddedSSO,
181
+ disableLoginFailurePage: true,
182
+ });
183
+ const el: any = {};
184
+ expect(processDataInstance.processEventData(e.type, e, '', el)).toEqual({
185
+ type: e.type,
186
+ });
187
+ expect(base.notifyAuthFailure).not.toBeCalled();
188
+ expect(el.innerHTML).not.toBe('Hello');
189
+ });
174
190
  });
@@ -78,8 +78,8 @@ function processNoCookieAccess(e: any, containerEl: Element) {
78
78
  * @param containerEl
79
79
  */
80
80
  export function processAuthFailure(e: any, containerEl: Element) {
81
- const { loginFailedMessage, authType } = getEmbedConfig();
82
- if (authType !== AuthType.None) {
81
+ const { loginFailedMessage, authType, disableLoginFailurePage } = getEmbedConfig();
82
+ if (authType !== AuthType.None && !disableLoginFailurePage) {
83
83
  // eslint-disable-next-line no-param-reassign
84
84
  containerEl.innerHTML = loginFailedMessage;
85
85
  notifyAuthFailure(AuthFailureType.OTHER);