@thoughtspot/visual-embed-sdk 1.32.0-alpha.1 → 1.33.0-alpha.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.
Files changed (110) hide show
  1. package/README.md +21 -1
  2. package/cjs/package.json +6 -4
  3. package/cjs/src/embed/app.d.ts +7 -1
  4. package/cjs/src/embed/app.d.ts.map +1 -1
  5. package/cjs/src/embed/app.js.map +1 -1
  6. package/cjs/src/embed/liveboard.d.ts +24 -0
  7. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  8. package/cjs/src/embed/liveboard.js +30 -0
  9. package/cjs/src/embed/liveboard.js.map +1 -1
  10. package/cjs/src/embed/liveboard.spec.js +31 -0
  11. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  12. package/cjs/src/embed/search.d.ts +14 -0
  13. package/cjs/src/embed/search.d.ts.map +1 -1
  14. package/cjs/src/embed/search.js +4 -1
  15. package/cjs/src/embed/search.js.map +1 -1
  16. package/cjs/src/embed/search.spec.js +13 -0
  17. package/cjs/src/embed/search.spec.js.map +1 -1
  18. package/cjs/src/embed/ts-embed.d.ts +7 -1
  19. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  20. package/cjs/src/embed/ts-embed.js +12 -3
  21. package/cjs/src/embed/ts-embed.js.map +1 -1
  22. package/cjs/src/embed/ts-embed.spec.js +16 -3
  23. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  24. package/cjs/src/types.d.ts +18 -8
  25. package/cjs/src/types.d.ts.map +1 -1
  26. package/cjs/src/types.js +4 -7
  27. package/cjs/src/types.js.map +1 -1
  28. package/cjs/src/utils/global-styles.d.ts +2 -0
  29. package/cjs/src/utils/global-styles.d.ts.map +1 -0
  30. package/cjs/src/utils/global-styles.js +44 -0
  31. package/cjs/src/utils/global-styles.js.map +1 -0
  32. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  33. package/cjs/src/utils/graphql/answerService/answer-queries.js +9 -0
  34. package/cjs/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  35. package/cjs/src/utils/graphql/preview-service.d.ts +3 -0
  36. package/cjs/src/utils/graphql/preview-service.d.ts.map +1 -0
  37. package/cjs/src/utils/graphql/preview-service.js +30 -0
  38. package/cjs/src/utils/graphql/preview-service.js.map +1 -0
  39. package/dist/src/embed/app.d.ts +7 -1
  40. package/dist/src/embed/app.d.ts.map +1 -1
  41. package/dist/src/embed/liveboard.d.ts +24 -0
  42. package/dist/src/embed/liveboard.d.ts.map +1 -1
  43. package/dist/src/embed/search.d.ts +14 -0
  44. package/dist/src/embed/search.d.ts.map +1 -1
  45. package/dist/src/embed/ts-embed.d.ts +7 -1
  46. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  47. package/dist/src/types.d.ts +18 -8
  48. package/dist/src/types.d.ts.map +1 -1
  49. package/dist/src/utils/global-styles.d.ts +2 -0
  50. package/dist/src/utils/global-styles.d.ts.map +1 -0
  51. package/dist/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  52. package/dist/src/utils/graphql/preview-service.d.ts +3 -0
  53. package/dist/src/utils/graphql/preview-service.d.ts.map +1 -0
  54. package/dist/tsembed-react.es.js +123 -12
  55. package/dist/tsembed-react.js +123 -12
  56. package/dist/tsembed.es.js +123 -12
  57. package/dist/tsembed.js +123 -12
  58. package/dist/visual-embed-sdk-react-full.d.ts +69 -10
  59. package/dist/visual-embed-sdk-react.d.ts +69 -10
  60. package/dist/visual-embed-sdk.d.ts +69 -10
  61. package/lib/package.json +6 -4
  62. package/lib/src/embed/app.d.ts +7 -1
  63. package/lib/src/embed/app.d.ts.map +1 -1
  64. package/lib/src/embed/app.js.map +1 -1
  65. package/lib/src/embed/liveboard.d.ts +24 -0
  66. package/lib/src/embed/liveboard.d.ts.map +1 -1
  67. package/lib/src/embed/liveboard.js +30 -0
  68. package/lib/src/embed/liveboard.js.map +1 -1
  69. package/lib/src/embed/liveboard.spec.js +31 -0
  70. package/lib/src/embed/liveboard.spec.js.map +1 -1
  71. package/lib/src/embed/search.d.ts +14 -0
  72. package/lib/src/embed/search.d.ts.map +1 -1
  73. package/lib/src/embed/search.js +4 -1
  74. package/lib/src/embed/search.js.map +1 -1
  75. package/lib/src/embed/search.spec.js +13 -0
  76. package/lib/src/embed/search.spec.js.map +1 -1
  77. package/lib/src/embed/ts-embed.d.ts +7 -1
  78. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  79. package/lib/src/embed/ts-embed.js +12 -3
  80. package/lib/src/embed/ts-embed.js.map +1 -1
  81. package/lib/src/embed/ts-embed.spec.js +16 -3
  82. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  83. package/lib/src/types.d.ts +18 -8
  84. package/lib/src/types.d.ts.map +1 -1
  85. package/lib/src/types.js +4 -7
  86. package/lib/src/types.js.map +1 -1
  87. package/lib/src/utils/global-styles.d.ts +2 -0
  88. package/lib/src/utils/global-styles.d.ts.map +1 -0
  89. package/lib/src/utils/global-styles.js +40 -0
  90. package/lib/src/utils/global-styles.js.map +1 -0
  91. package/lib/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  92. package/lib/src/utils/graphql/answerService/answer-queries.js +9 -0
  93. package/lib/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  94. package/lib/src/utils/graphql/preview-service.d.ts +3 -0
  95. package/lib/src/utils/graphql/preview-service.d.ts.map +1 -0
  96. package/lib/src/utils/graphql/preview-service.js +26 -0
  97. package/lib/src/utils/graphql/preview-service.js.map +1 -0
  98. package/lib/src/visual-embed-sdk.d.ts +69 -10
  99. package/package.json +6 -4
  100. package/src/embed/app.ts +13 -4
  101. package/src/embed/liveboard.spec.ts +34 -0
  102. package/src/embed/liveboard.ts +61 -1
  103. package/src/embed/search.spec.ts +17 -0
  104. package/src/embed/search.ts +19 -0
  105. package/src/embed/ts-embed.spec.ts +18 -3
  106. package/src/embed/ts-embed.ts +14 -4
  107. package/src/types.ts +31 -20
  108. package/src/utils/global-styles.ts +40 -0
  109. package/src/utils/graphql/answerService/answer-queries.ts +9 -0
  110. package/src/utils/graphql/preview-service.ts +31 -0
@@ -282,7 +282,13 @@ declare module '@thoughtspot/visual-embed-sdk/embed/app' {
282
282
  * Flag to control Data panel experience
283
283
  * @default false
284
284
  * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl
285
- * @hidden
285
+ * @example
286
+ * ```js
287
+ * const embed = new AppEmbed('#tsEmbed', {
288
+ * ... // other options
289
+ * dataPanelV2: true,
290
+ * })
291
+ * ```
286
292
  */
287
293
  dataPanelV2?: boolean;
288
294
  /**
@@ -838,6 +844,29 @@ declare module '@thoughtspot/visual-embed-sdk/embed/liveboard' {
838
844
  * ```
839
845
  */
840
846
  enable2ColumnLayout?: boolean;
847
+ /**
848
+ * Show a preview image of the visualization before the visualization loads.
849
+ * Only works for visualizations embeds with a viz id.
850
+ *
851
+ * Also, viz snashot should be enabled in the ThoughtSpot instance.
852
+ * Contact ThoughtSpot support to enable this feature.
853
+ *
854
+ * Since, this will show preview images, be careful that it may show
855
+ * undesired data to the user when using row level security.
856
+ *
857
+ * @example
858
+ * ```js
859
+ * const embed = new LiveboardEmbed('#embed-container', {
860
+ * liveboardId: 'liveboard-id',
861
+ * vizId: 'viz-id',
862
+ * showPreviewLoader: true,
863
+ * });
864
+ * embed.render();
865
+ * ```
866
+ *
867
+ * @version SDK: 1.32.0 | ThoughtSpot: 10.0.0.cl
868
+ */
869
+ showPreviewLoader?: boolean;
841
870
  }
842
871
  /**
843
872
  * Embed a ThoughtSpot Liveboard or visualization. When rendered it already
@@ -1135,6 +1164,20 @@ declare module '@thoughtspot/visual-embed-sdk/embed/search' {
1135
1164
  * ```
1136
1165
  */
1137
1166
  dataPanelCustomGroupsAccordionInitialState?: DataPanelCustomColumnGroupsAccordionState;
1167
+ /**
1168
+ * Flag to remove focus from search bar initially when user
1169
+ * lands on search embed page.
1170
+ * @version SDK: 1.32.0 | Thoughtspot: 10.3.0.cl
1171
+ * @default true
1172
+ * @example
1173
+ * ```js
1174
+ * const embed = new SearchEmbed('#tsEmbed', {
1175
+ * ... // other options
1176
+ * focusSearchBarOnRender: false,
1177
+ * });
1178
+ * ```
1179
+ */
1180
+ focusSearchBarOnRender?: boolean;
1138
1181
  }
1139
1182
  export const HiddenActionItemByDefaultForSearchEmbed: Action[];
1140
1183
  /**
@@ -2464,6 +2507,19 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
2464
2507
  * @version SDK: 1.29.0 | ThoughtSpot: 10.1.0.cl
2465
2508
  */
2466
2509
  excludeRuntimeParametersfromURL?: boolean;
2510
+ /**
2511
+ * Enable the V2 shell. This can provide performance benefits
2512
+ * due to a lighterweight shell.
2513
+ * @example
2514
+ * ```js
2515
+ * const embed = new LiveboardEmbed('#embed', {
2516
+ * liveboardId: '123',
2517
+ * enableV2Shell_experimental: true
2518
+ * });
2519
+ * ```
2520
+ * @version SDK: 1.31.2 | ThoughtSpot: 10.0.0.cl
2521
+ */
2522
+ enableV2Shell_experimental?: boolean;
2467
2523
  }
2468
2524
  /**
2469
2525
  * MessagePayload: Embed event payload: message type, data and status (start/end)
@@ -2715,11 +2771,6 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
2715
2771
  * @important
2716
2772
  */
2717
2773
  Data = "data",
2718
- /**
2719
- * Search/Answer/Liveboard filters have been applied/updated by the user.
2720
- * @hidden
2721
- */
2722
- FiltersChanged = "filtersChanged",
2723
2774
  /**
2724
2775
  * Search query has been updated by the user.
2725
2776
  * @version SDK: 1.4.0 | ThoughtSpot: ts7.sep.cl, 8.4.1.sw
@@ -4515,7 +4566,8 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
4515
4566
  CurrencyFormat = "currencyFormat",
4516
4567
  Enable2ColumnLayout = "enable2ColumnLayout",
4517
4568
  IsFullAppEmbed = "isFullAppEmbed",
4518
- IsOnBeforeGetVizDataInterceptEnabled = "isOnBeforeGetVizDataInterceptEnabled"
4569
+ IsOnBeforeGetVizDataInterceptEnabled = "isOnBeforeGetVizDataInterceptEnabled",
4570
+ FocusSearchBarOnRender = "focusSearchBarOnRender"
4519
4571
  }
4520
4572
  /**
4521
4573
  * ThoughtSpot application pages include actions and menu commands
@@ -5337,7 +5389,7 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
5337
5389
  * disabledActions: [Action.ManageMonitor]
5338
5390
  * ```
5339
5391
  */
5340
- ManageMonitor = "ManageMonitor",
5392
+ ManageMonitor = "manageMonitor",
5341
5393
  /**
5342
5394
  * Action ID for Liveboard Personalised Views dropdown
5343
5395
  * @example
@@ -5380,8 +5432,9 @@ declare module '@thoughtspot/visual-embed-sdk/types' {
5380
5432
  * ```js
5381
5433
  * hiddenAction: [Action.CreateLiveboard]
5382
5434
  * disabledActions: [Action.CreateLiveboard]
5435
+ * ```
5383
5436
  *
5384
- * @version SDK: 1.31.1 | Thoughtspot: 10.1.0.cl
5437
+ * @version SDK: 1.32.0 | Thoughtspot: 10.1.0.cl
5385
5438
  */
5386
5439
  CreateLiveboard = "CreateLiveboard",
5387
5440
  /**
@@ -6337,7 +6390,7 @@ declare module '@thoughtspot/visual-embed-sdk/embed/ts-embed' {
6337
6390
  /**
6338
6391
  * The DOM node where the ThoughtSpot app is to be embedded.
6339
6392
  */
6340
- protected el: Element;
6393
+ protected el: HTMLElement;
6341
6394
  /**
6342
6395
  * The key to store the embed instance in the DOM node
6343
6396
  */
@@ -6591,6 +6644,12 @@ declare module '@thoughtspot/visual-embed-sdk/embed/ts-embed' {
6591
6644
  * ```
6592
6645
  */
6593
6646
  on(messageType: EmbedEvent, callback: MessageCallback, options?: MessageOptions): typeof TsEmbed.prototype;
6647
+ /**
6648
+ * Only for testing purposes.
6649
+ *
6650
+ * @hidden
6651
+ */
6652
+ test__executeCallbacks: (eventType: EmbedEvent, data: any, eventPort?: void | MessagePort) => void;
6594
6653
  }
6595
6654
  }
6596
6655
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thoughtspot/visual-embed-sdk",
3
- "version": "1.32.0-alpha.1",
3
+ "version": "1.33.0-alpha.1",
4
4
  "description": "ThoughtSpot Embed SDK",
5
5
  "module": "lib/src/index.js",
6
6
  "main": "dist/tsembed.js",
@@ -38,7 +38,7 @@
38
38
  "size-limit": [
39
39
  {
40
40
  "path": "dist/tsembed.js",
41
- "limit": "46 kB"
41
+ "limit": "48 kB"
42
42
  }
43
43
  ],
44
44
  "scripts": {
@@ -67,7 +67,8 @@
67
67
  "prepublishOnly": "npm run is-publish-allowed && npm run test && npm run tsc && npm run bundle-dts-file && npm run bundle-dts && npm run bundle-dts-react && npm run bundle-dts-react-full && npm run build",
68
68
  "check-size": "npm run build && size-limit",
69
69
  "publish-dev": "npm publish --tag dev",
70
- "publish-prod": "npm publish --tag latest"
70
+ "publish-prod": "npm publish --tag latest",
71
+ "dev": "vite -c vite.local.config.ts"
71
72
  },
72
73
  "peerDependencies": {
73
74
  "react": "> 16.8.0",
@@ -157,7 +158,8 @@
157
158
  "typedoc-plugin-toc-group": "thoughtspot/typedoc-plugin-toc-group",
158
159
  "typescript": "^4.9.4",
159
160
  "url-search-params-polyfill": "^8.1.0",
160
- "util": "^0.12.4"
161
+ "util": "^0.12.4",
162
+ "vite": "^5.3.4"
161
163
  },
162
164
  "author": "ThoughtSpot",
163
165
  "email": "support@thoughtspot.com",
package/src/embed/app.ts CHANGED
@@ -264,7 +264,13 @@ export interface AppViewConfig extends Omit<ViewConfig, 'visibleTabs'> {
264
264
  * Flag to control Data panel experience
265
265
  * @default false
266
266
  * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl
267
- * @hidden
267
+ * @example
268
+ * ```js
269
+ * const embed = new AppEmbed('#tsEmbed', {
270
+ * ... // other options
271
+ * dataPanelV2: true,
272
+ * })
273
+ * ```
268
274
  */
269
275
  dataPanelV2?: boolean;
270
276
  /**
@@ -445,7 +451,6 @@ export class AppEmbed extends V1Embed {
445
451
  isOnBeforeGetVizDataInterceptEnabled = false,
446
452
  /* eslint-disable-next-line max-len */
447
453
  dataPanelCustomGroupsAccordionInitialState = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL,
448
-
449
454
  } = this.viewConfig;
450
455
 
451
456
  let params = {};
@@ -490,7 +495,9 @@ export class AppEmbed extends V1Embed {
490
495
 
491
496
  if (isOnBeforeGetVizDataInterceptEnabled) {
492
497
  /* eslint-disable-next-line max-len */
493
- params[Param.IsOnBeforeGetVizDataInterceptEnabled] = isOnBeforeGetVizDataInterceptEnabled;
498
+ params[
499
+ Param.IsOnBeforeGetVizDataInterceptEnabled
500
+ ] = isOnBeforeGetVizDataInterceptEnabled;
494
501
  }
495
502
 
496
503
  params[Param.DataPanelV2Enabled] = dataPanelV2;
@@ -504,7 +511,9 @@ export class AppEmbed extends V1Embed {
504
511
  === DataPanelCustomColumnGroupsAccordionState.EXPAND_FIRST
505
512
  ) {
506
513
  /* eslint-disable-next-line max-len */
507
- params[Param.DataPanelCustomGroupsAccordionInitialState] = dataPanelCustomGroupsAccordionInitialState;
514
+ params[
515
+ Param.DataPanelCustomGroupsAccordionInitialState
516
+ ] = dataPanelCustomGroupsAccordionInitialState;
508
517
  } else {
509
518
  /* eslint-disable-next-line max-len */
510
519
  params[Param.DataPanelCustomGroupsAccordionInitialState] = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL;
@@ -24,6 +24,7 @@ import {
24
24
  import * as tsEmbed from './ts-embed';
25
25
  import * as processTriggerInstance from '../utils/processTrigger';
26
26
  import * as auth from '../auth';
27
+ import * as previewService from '../utils/graphql/preview-service';
27
28
 
28
29
  const defaultViewConfig = {
29
30
  frameParams: {
@@ -553,6 +554,39 @@ describe('Liveboard/viz embed tests', () => {
553
554
  });
554
555
  });
555
556
 
557
+ test('Show preview loader should not show the loader if not viz embed or showPreviewLoader is false', async () => {
558
+ const libEmbed = new LiveboardEmbed(getRootEl(), {
559
+ liveboardId: '1234',
560
+ });
561
+ await libEmbed.render();
562
+ await executeAfterWait(() => {
563
+ expect(getRootEl().innerHTML).not.toContain('ts-viz-preview-loader');
564
+ });
565
+ });
566
+
567
+ test('Show preview loader should show the loader if viz embed and showPreviewLoader is true', async () => {
568
+ jest.spyOn(previewService, 'getPreview').mockResolvedValue({
569
+ vizContent: '<div id=test>test</div>',
570
+ });
571
+ const libEmbed = new LiveboardEmbed(getRootEl(), {
572
+ liveboardId: '1234',
573
+ vizId: '5678',
574
+ showPreviewLoader: true,
575
+ });
576
+ await libEmbed.render();
577
+ expect(previewService.getPreview).toHaveBeenCalledWith('http://tshost', '5678', '1234');
578
+ await executeAfterWait(() => {
579
+ expect(getRootEl().style.position).toEqual('relative');
580
+ expect(getRootEl().innerHTML).toContain('<div class="ts-viz-preview-loader">');
581
+ expect(getRootEl().innerHTML).toContain('<div id="test">test</div>');
582
+ });
583
+
584
+ libEmbed.test__executeCallbacks(EmbedEvent.Data, {});
585
+ await executeAfterWait(() => {
586
+ expect(getRootEl().innerHTML).not.toContain('ts-viz-preview-loader');
587
+ });
588
+ });
589
+
556
590
  test('it should navigateToLiveboard with liveboard id is not passed', async (done) => {
557
591
  mockMessageChannel();
558
592
  const consoleSpy = jest.spyOn(console, 'error');
@@ -8,6 +8,7 @@
8
8
  * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
9
9
  */
10
10
 
11
+ import { getPreview } from '../utils/graphql/preview-service';
11
12
  import { ERROR_MESSAGE } from '../errors';
12
13
  import {
13
14
  EmbedEvent,
@@ -21,6 +22,7 @@ import {
21
22
  import { getQueryParamString, isUndefined } from '../utils';
22
23
  import { getAuthPromise } from './base';
23
24
  import { V1Embed } from './ts-embed';
25
+ import { addPreviewStylesIfNotPresent } from '../utils/global-styles';
24
26
 
25
27
  /**
26
28
  * The configuration for the embedded Liveboard or visualization page view.
@@ -259,6 +261,29 @@ export interface LiveboardViewConfig
259
261
  * ```
260
262
  */
261
263
  enable2ColumnLayout?: boolean;
264
+ /**
265
+ * Show a preview image of the visualization before the visualization loads.
266
+ * Only works for visualizations embeds with a viz id.
267
+ *
268
+ * Also, viz snashot should be enabled in the ThoughtSpot instance.
269
+ * Contact ThoughtSpot support to enable this feature.
270
+ *
271
+ * Since, this will show preview images, be careful that it may show
272
+ * undesired data to the user when using row level security.
273
+ *
274
+ * @example
275
+ * ```js
276
+ * const embed = new LiveboardEmbed('#embed-container', {
277
+ * liveboardId: 'liveboard-id',
278
+ * vizId: 'viz-id',
279
+ * showPreviewLoader: true,
280
+ * });
281
+ * embed.render();
282
+ * ```
283
+ *
284
+ * @version SDK: 1.32.0 | ThoughtSpot: 10.0.0.cl
285
+ */
286
+ showPreviewLoader?: boolean;
262
287
  }
263
288
 
264
289
  /**
@@ -431,6 +456,40 @@ export class LiveboardEmbed extends V1Embed {
431
456
  }
432
457
  }
433
458
 
459
+ private async showPreviewLoader() {
460
+ if (!this.viewConfig.showPreviewLoader || !this.viewConfig.vizId) {
461
+ return;
462
+ }
463
+
464
+ try {
465
+ const preview = await getPreview(
466
+ this.thoughtSpotHost,
467
+ this.viewConfig.vizId,
468
+ this.viewConfig.liveboardId,
469
+ );
470
+
471
+ if (!preview.vizContent) {
472
+ return;
473
+ }
474
+ addPreviewStylesIfNotPresent();
475
+
476
+ const div = document.createElement('div');
477
+ div.innerHTML = `
478
+ <div class=ts-viz-preview-loader>
479
+ ${preview.vizContent}
480
+ </div>
481
+ `;
482
+ const previewDiv = div.firstElementChild as HTMLElement;
483
+ this.el.appendChild(previewDiv);
484
+ this.el.style.position = 'relative';
485
+ this.on(EmbedEvent.Data, () => {
486
+ previewDiv.remove();
487
+ });
488
+ } catch (error) {
489
+ console.error('Error fetching preview', error);
490
+ }
491
+ }
492
+
434
493
  protected beforePrerenderVisible(): void {
435
494
  const embedObj = this.insertedDomEl?.[this.embedNodeKey] as LiveboardEmbed;
436
495
 
@@ -480,6 +539,7 @@ export class LiveboardEmbed extends V1Embed {
480
539
 
481
540
  const src = this.getIFrameSrc();
482
541
  await this.renderV1Embed(src);
542
+ this.showPreviewLoader();
483
543
 
484
544
  return this;
485
545
  }
@@ -502,4 +562,4 @@ export class LiveboardEmbed extends V1Embed {
502
562
  /**
503
563
  * @hidden
504
564
  */
505
- export class PinboardEmbed extends LiveboardEmbed {}
565
+ export class PinboardEmbed extends LiveboardEmbed { }
@@ -166,6 +166,23 @@ describe('Search embed tests', () => {
166
166
  });
167
167
  });
168
168
 
169
+ test('should remove focus from search bar', async () => {
170
+ const dataSources = ['data-source-1'];
171
+ const searchEmbed = new SearchEmbed(getRootEl(), {
172
+ ...defaultViewConfig,
173
+ hideDataSources: true,
174
+ dataSources,
175
+ focusSearchBarOnRender: false,
176
+ });
177
+ searchEmbed.render();
178
+ await executeAfterWait(() => {
179
+ expectUrlMatchesWithParams(
180
+ getIFrameSrc(),
181
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&dataSources=[%22data-source-1%22]&dataSourceMode=hide&useLastSelectedSources=false&focusSearchBarOnRender=false${prefixParams}#/embed/answer`,
182
+ );
183
+ });
184
+ });
185
+
169
186
  test('should add runtime filters', async () => {
170
187
  const dataSources = ['data-source-1'];
171
188
  const searchOptions = {
@@ -275,6 +275,20 @@ export interface SearchViewConfig
275
275
  * ```
276
276
  */
277
277
  dataPanelCustomGroupsAccordionInitialState?: DataPanelCustomColumnGroupsAccordionState;
278
+ /**
279
+ * Flag to remove focus from search bar initially when user
280
+ * lands on search embed page.
281
+ * @version SDK: 1.32.0 | Thoughtspot: 10.3.0.cl
282
+ * @default true
283
+ * @example
284
+ * ```js
285
+ * const embed = new SearchEmbed('#tsEmbed', {
286
+ * ... // other options
287
+ * focusSearchBarOnRender: false,
288
+ * });
289
+ * ```
290
+ */
291
+ focusSearchBarOnRender?: boolean;
278
292
  }
279
293
 
280
294
  export const HiddenActionItemByDefaultForSearchEmbed = [
@@ -335,6 +349,7 @@ export class SearchEmbed extends TsEmbed {
335
349
  isOnBeforeGetVizDataInterceptEnabled = false,
336
350
  /* eslint-disable-next-line max-len */
337
351
  dataPanelCustomGroupsAccordionInitialState = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL,
352
+ focusSearchBarOnRender = true,
338
353
  excludeRuntimeParametersfromURL,
339
354
  } = this.viewConfig;
340
355
  const queryParams = this.getBaseQueryParams();
@@ -378,6 +393,10 @@ export class SearchEmbed extends TsEmbed {
378
393
  queryParams[Param.IsOnBeforeGetVizDataInterceptEnabled] = isOnBeforeGetVizDataInterceptEnabled;
379
394
  }
380
395
 
396
+ if (!focusSearchBarOnRender) {
397
+ queryParams[Param.FocusSearchBarOnRender] = focusSearchBarOnRender;
398
+ }
399
+
381
400
  queryParams[Param.DataPanelV2Enabled] = dataPanelV2;
382
401
  queryParams[Param.DataSourceMode] = this.getDataSourceMode();
383
402
 
@@ -1108,17 +1108,32 @@ describe('Unit test case for ts embed', () => {
1108
1108
  });
1109
1109
 
1110
1110
  describe('V1Embed ', () => {
1111
+ beforeEach(() => {
1112
+ jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(() => 'http://tshost');
1113
+ });
1114
+
1111
1115
  test('when isRendered is true than isError will be true', () => {
1112
- spyOn(logger, 'error');
1116
+ spyOn(logger, 'warn');
1113
1117
  const viEmbedIns = new tsEmbedInstance.V1Embed(getRootEl(), defaultViewConfig);
1114
1118
  expect(viEmbedIns['isError']).toBe(false);
1115
1119
  viEmbedIns.render();
1116
1120
  viEmbedIns.on(EmbedEvent.CustomAction, jest.fn()).render();
1117
- expect(viEmbedIns['isError']).toBe(true);
1118
- expect(logger.error).toHaveBeenCalledWith(
1121
+ expect(logger.warn).toHaveBeenCalledWith(
1119
1122
  'Please register event handlers before calling render',
1120
1123
  );
1121
1124
  });
1125
+
1126
+ test('Generates the correct url for V1Embed when V2 shell is enabled', async () => {
1127
+ const v1Embed = new LiveboardEmbed(getRootEl(), {
1128
+ ...defaultViewConfig,
1129
+ liveboardId: '123',
1130
+ enableV2Shell_experimental: true,
1131
+ });
1132
+ await v1Embed.render();
1133
+ await executeAfterWait(() => {
1134
+ expect(getIFrameSrc()).toContain('/v2/?');
1135
+ });
1136
+ });
1122
1137
  });
1123
1138
 
1124
1139
  describe('Navigate to Page API', () => {
@@ -93,7 +93,7 @@ export class TsEmbed {
93
93
  /**
94
94
  * The DOM node where the ThoughtSpot app is to be embedded.
95
95
  */
96
- protected el: Element;
96
+ protected el: HTMLElement;
97
97
 
98
98
  /**
99
99
  * The key to store the embed instance in the DOM node
@@ -369,7 +369,7 @@ export class TsEmbed {
369
369
  * @param query
370
370
  */
371
371
  protected getEmbedBasePath(query: string): string {
372
- let queryString = query;
372
+ let queryString = (query.startsWith('?')) ? query : `?${query}`;
373
373
  if (this.shouldEncodeUrlQueryParams) {
374
374
  queryString = `?base64UrlEncodedFlags=${getEncodedQueryParamsString(
375
375
  queryString.substr(1),
@@ -902,7 +902,7 @@ export class TsEmbed {
902
902
  isRegisteredBySDK,
903
903
  });
904
904
  if (this.isRendered) {
905
- this.handleError('Please register event handlers before calling render');
905
+ logger.warn('Please register event handlers before calling render');
906
906
  }
907
907
  const callbacks = this.eventHandlerMap.get(messageType) || [];
908
908
  callbacks.push({ options, callback });
@@ -1258,7 +1258,9 @@ export class V1Embed extends TsEmbed {
1258
1258
  const filterQuery = getFilterQuery(runtimeFilters || []);
1259
1259
  queryString = [filterQuery, queryString].filter(Boolean).join('&');
1260
1260
  }
1261
- return this.getV1EmbedBasePath(queryString);
1261
+ return (this.viewConfig.enableV2Shell_experimental)
1262
+ ? this.getEmbedBasePath(queryString)
1263
+ : this.getV1EmbedBasePath(queryString);
1262
1264
  }
1263
1265
 
1264
1266
  /**
@@ -1286,4 +1288,12 @@ export class V1Embed extends TsEmbed {
1286
1288
  const eventType = this.getCompatibleEventType(messageType);
1287
1289
  return super.on(eventType, callback, options);
1288
1290
  }
1291
+
1292
+ /**
1293
+ * Only for testing purposes.
1294
+ *
1295
+ * @hidden
1296
+ */
1297
+ // eslint-disable-next-line camelcase
1298
+ public test__executeCallbacks = this.executeCallbacks;
1289
1299
  }
package/src/types.ts CHANGED
@@ -998,6 +998,20 @@ export interface ViewConfig {
998
998
  * @version SDK: 1.29.0 | ThoughtSpot: 10.1.0.cl
999
999
  */
1000
1000
  excludeRuntimeParametersfromURL?: boolean;
1001
+ /**
1002
+ * Enable the V2 shell. This can provide performance benefits
1003
+ * due to a lighterweight shell.
1004
+ * @example
1005
+ * ```js
1006
+ * const embed = new LiveboardEmbed('#embed', {
1007
+ * liveboardId: '123',
1008
+ * enableV2Shell_experimental: true
1009
+ * });
1010
+ * ```
1011
+ * @version SDK: 1.31.2 | ThoughtSpot: 10.0.0.cl
1012
+ */
1013
+ // eslint-disable-next-line camelcase
1014
+ enableV2Shell_experimental?: boolean;
1001
1015
  }
1002
1016
 
1003
1017
  /**
@@ -1266,11 +1280,6 @@ export enum EmbedEvent {
1266
1280
  * @important
1267
1281
  */
1268
1282
  Data = 'data',
1269
- /**
1270
- * Search/Answer/Liveboard filters have been applied/updated by the user.
1271
- * @hidden
1272
- */
1273
- FiltersChanged = 'filtersChanged',
1274
1283
  /**
1275
1284
  * Search query has been updated by the user.
1276
1285
  * @version SDK: 1.4.0 | ThoughtSpot: ts7.sep.cl, 8.4.1.sw
@@ -2100,19 +2109,19 @@ export enum EmbedEvent {
2100
2109
  *```
2101
2110
  * @version SDK : 1.29.0 | Thoughtspot : 10.2.0.cl
2102
2111
  */
2103
- OnBeforeGetVizDataIntercept = 'onBeforeGetVizDataIntercept',
2104
- /**
2105
- * Emitted when parameter changes in an answer
2106
- * or liveboard
2107
- *
2108
- * ```js
2109
- * liveboardEmbed.on(EmbedEvent.ParameterChanged, (payload) => {
2110
- * console.log('payload', payload);
2111
- * })
2112
- *```
2113
- * @version SDK : 1.29.0 | Thoughtspot : 10.2.0.cl
2114
- */
2115
- ParameterChanged = 'parameterChanged'
2112
+ OnBeforeGetVizDataIntercept = 'onBeforeGetVizDataIntercept',
2113
+ /**
2114
+ * Emitted when parameter changes in an answer
2115
+ * or liveboard
2116
+ *
2117
+ * ```js
2118
+ * liveboardEmbed.on(EmbedEvent.ParameterChanged, (payload) => {
2119
+ * console.log('payload', payload);
2120
+ * })
2121
+ *```
2122
+ * @version SDK : 1.29.0 | Thoughtspot : 10.2.0.cl
2123
+ */
2124
+ ParameterChanged = 'parameterChanged',
2116
2125
  }
2117
2126
 
2118
2127
  /**
@@ -3074,6 +3083,7 @@ export enum Param {
3074
3083
  Enable2ColumnLayout = 'enable2ColumnLayout',
3075
3084
  IsFullAppEmbed = 'isFullAppEmbed',
3076
3085
  IsOnBeforeGetVizDataInterceptEnabled = 'isOnBeforeGetVizDataInterceptEnabled',
3086
+ FocusSearchBarOnRender = 'focusSearchBarOnRender',
3077
3087
  }
3078
3088
 
3079
3089
  /**
@@ -3898,7 +3908,7 @@ export enum Action {
3898
3908
  * disabledActions: [Action.ManageMonitor]
3899
3909
  * ```
3900
3910
  */
3901
- ManageMonitor = 'ManageMonitor',
3911
+ ManageMonitor = 'manageMonitor',
3902
3912
  /**
3903
3913
  * Action ID for Liveboard Personalised Views dropdown
3904
3914
  * @example
@@ -3943,8 +3953,9 @@ export enum Action {
3943
3953
  * ```js
3944
3954
  * hiddenAction: [Action.CreateLiveboard]
3945
3955
  * disabledActions: [Action.CreateLiveboard]
3956
+ * ```
3946
3957
  *
3947
- * @version SDK: 1.31.1 | Thoughtspot: 10.1.0.cl
3958
+ * @version SDK: 1.32.0 | Thoughtspot: 10.1.0.cl
3948
3959
  */
3949
3960
  CreateLiveboard = 'CreateLiveboard',
3950
3961
 
@@ -0,0 +1,40 @@
1
+ export const addPreviewStylesIfNotPresent = () => {
2
+ const styleEl = document.getElementById('ts-preview-style');
3
+ if (styleEl) {
4
+ return;
5
+ }
6
+
7
+ const previewStyles = `
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@32.0.2/styles/ag-grid.min.css">
9
+ <style id="ts-preview-style">
10
+ .ts-viz-preview-loader {
11
+ position: absolute;
12
+ top: 0;
13
+ left: 0;
14
+ right: 0;
15
+ bottom: 0;
16
+ display: flex;
17
+ justify-content: center;
18
+ align-items: center;
19
+ background: linear-gradient(-45deg, #eee 40%, #fafafa 50%, #eee 60%);
20
+ background-size: 300%;
21
+ background-position-x: 100%;
22
+ animation: shimmer 1s infinite linear;
23
+ z-index: 999;
24
+ filter: grayscale(0.2);
25
+ }
26
+
27
+ @keyframes shimmer {
28
+ to {
29
+ background-position-x: 0%
30
+ }
31
+ }
32
+
33
+ .ts-viz-preview-loader .table-module__fullContainer {
34
+ width: 100%;
35
+ height: 100%;
36
+ }
37
+ </style>
38
+ `;
39
+ document.head.insertAdjacentHTML('beforeend', previewStyles);
40
+ };
@@ -94,6 +94,15 @@ export const getAnswer = `
94
94
  }
95
95
  }
96
96
  }
97
+ metadata {
98
+ author
99
+ authorId
100
+ createdAt
101
+ isDiscoverable
102
+ isHidden
103
+ modifiedAt
104
+ tags
105
+ }
97
106
  visualizations {
98
107
  ... on TableViz {
99
108
  columns {