@thoughtspot/visual-embed-sdk 1.39.1 → 1.39.2-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.
Files changed (190) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/config.spec.js +9 -0
  3. package/cjs/src/config.spec.js.map +1 -1
  4. package/cjs/src/embed/app.d.ts +75 -15
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +69 -9
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +374 -12
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/bodyless-conversation.d.ts +19 -7
  11. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/bodyless-conversation.js +24 -4
  13. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  14. package/cjs/src/embed/bodyless-conversation.spec.js +8 -190
  15. package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/conversation.spec.js +28 -0
  17. package/cjs/src/embed/conversation.spec.js.map +1 -1
  18. package/cjs/src/embed/embedConfig.d.ts +9 -7
  19. package/cjs/src/embed/embedConfig.d.ts.map +1 -1
  20. package/cjs/src/embed/embedConfig.js +9 -7
  21. package/cjs/src/embed/embedConfig.js.map +1 -1
  22. package/cjs/src/embed/liveboard.d.ts +56 -17
  23. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  24. package/cjs/src/embed/liveboard.js +48 -4
  25. package/cjs/src/embed/liveboard.js.map +1 -1
  26. package/cjs/src/embed/liveboard.spec.js +215 -11
  27. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  28. package/cjs/src/embed/ts-embed.d.ts +5 -0
  29. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  30. package/cjs/src/embed/ts-embed.js +16 -1
  31. package/cjs/src/embed/ts-embed.js.map +1 -1
  32. package/cjs/src/embed/ts-embed.spec.js +164 -0
  33. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  34. package/cjs/src/errors.d.ts +1 -0
  35. package/cjs/src/errors.d.ts.map +1 -1
  36. package/cjs/src/errors.js +1 -0
  37. package/cjs/src/errors.js.map +1 -1
  38. package/cjs/src/index.d.ts +2 -2
  39. package/cjs/src/index.d.ts.map +1 -1
  40. package/cjs/src/index.js +2 -1
  41. package/cjs/src/index.js.map +1 -1
  42. package/cjs/src/react/all-types-export.d.ts +1 -1
  43. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  44. package/cjs/src/react/all-types-export.js +3 -2
  45. package/cjs/src/react/all-types-export.js.map +1 -1
  46. package/cjs/src/react/index.d.ts +71 -20
  47. package/cjs/src/react/index.d.ts.map +1 -1
  48. package/cjs/src/react/index.js +79 -42
  49. package/cjs/src/react/index.js.map +1 -1
  50. package/cjs/src/react/index.spec.js +436 -100
  51. package/cjs/src/react/index.spec.js.map +1 -1
  52. package/cjs/src/types.d.ts +80 -6
  53. package/cjs/src/types.d.ts.map +1 -1
  54. package/cjs/src/types.js +45 -1
  55. package/cjs/src/types.js.map +1 -1
  56. package/cjs/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  57. package/cjs/src/utils/graphql/nlsService/conversation-service.js +2 -0
  58. package/cjs/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  59. package/cjs/src/utils/processTrigger.js +2 -1
  60. package/cjs/src/utils/processTrigger.js.map +1 -1
  61. package/cjs/src/utils.d.ts +6 -0
  62. package/cjs/src/utils.d.ts.map +1 -1
  63. package/cjs/src/utils.js +23 -3
  64. package/cjs/src/utils.js.map +1 -1
  65. package/cjs/src/utils.spec.js +237 -1
  66. package/cjs/src/utils.spec.js.map +1 -1
  67. package/dist/{index-JaFaxrvQ.js → index-CmEQfuE3.js} +1 -1
  68. package/dist/index-DeFzsyFF.js +7371 -0
  69. package/dist/index-Dpf0rd6w.js +7371 -0
  70. package/dist/index-UuEbsISo.js +7447 -0
  71. package/dist/index-e3Uw3YFO.js +7371 -0
  72. package/dist/src/embed/app.d.ts +75 -15
  73. package/dist/src/embed/app.d.ts.map +1 -1
  74. package/dist/src/embed/bodyless-conversation.d.ts +19 -7
  75. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  76. package/dist/src/embed/embedConfig.d.ts +9 -7
  77. package/dist/src/embed/embedConfig.d.ts.map +1 -1
  78. package/dist/src/embed/liveboard.d.ts +56 -17
  79. package/dist/src/embed/liveboard.d.ts.map +1 -1
  80. package/dist/src/embed/ts-embed.d.ts +5 -0
  81. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  82. package/dist/src/errors.d.ts +1 -0
  83. package/dist/src/errors.d.ts.map +1 -1
  84. package/dist/src/index.d.ts +2 -2
  85. package/dist/src/index.d.ts.map +1 -1
  86. package/dist/src/react/all-types-export.d.ts +1 -1
  87. package/dist/src/react/all-types-export.d.ts.map +1 -1
  88. package/dist/src/react/index.d.ts +71 -20
  89. package/dist/src/react/index.d.ts.map +1 -1
  90. package/dist/src/types.d.ts +80 -6
  91. package/dist/src/types.d.ts.map +1 -1
  92. package/dist/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  93. package/dist/src/utils.d.ts +6 -0
  94. package/dist/src/utils.d.ts.map +1 -1
  95. package/dist/tsembed-react.es.js +320 -78
  96. package/dist/tsembed-react.js +320 -76
  97. package/dist/tsembed.es.js +238 -31
  98. package/dist/tsembed.js +236 -29
  99. package/dist/visual-embed-sdk-react-full.d.ts +288 -72
  100. package/dist/visual-embed-sdk-react.d.ts +288 -72
  101. package/dist/visual-embed-sdk.d.ts +218 -53
  102. package/lib/package.json +1 -1
  103. package/lib/src/config.spec.js +9 -0
  104. package/lib/src/config.spec.js.map +1 -1
  105. package/lib/src/embed/app.d.ts +75 -15
  106. package/lib/src/embed/app.d.ts.map +1 -1
  107. package/lib/src/embed/app.js +69 -9
  108. package/lib/src/embed/app.js.map +1 -1
  109. package/lib/src/embed/app.spec.js +376 -14
  110. package/lib/src/embed/app.spec.js.map +1 -1
  111. package/lib/src/embed/bodyless-conversation.d.ts +19 -7
  112. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  113. package/lib/src/embed/bodyless-conversation.js +23 -4
  114. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  115. package/lib/src/embed/bodyless-conversation.spec.js +9 -191
  116. package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
  117. package/lib/src/embed/conversation.spec.js +30 -2
  118. package/lib/src/embed/conversation.spec.js.map +1 -1
  119. package/lib/src/embed/embedConfig.d.ts +9 -7
  120. package/lib/src/embed/embedConfig.d.ts.map +1 -1
  121. package/lib/src/embed/embedConfig.js +9 -7
  122. package/lib/src/embed/embedConfig.js.map +1 -1
  123. package/lib/src/embed/liveboard.d.ts +56 -17
  124. package/lib/src/embed/liveboard.d.ts.map +1 -1
  125. package/lib/src/embed/liveboard.js +49 -5
  126. package/lib/src/embed/liveboard.js.map +1 -1
  127. package/lib/src/embed/liveboard.spec.js +215 -11
  128. package/lib/src/embed/liveboard.spec.js.map +1 -1
  129. package/lib/src/embed/ts-embed.d.ts +5 -0
  130. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  131. package/lib/src/embed/ts-embed.js +16 -1
  132. package/lib/src/embed/ts-embed.js.map +1 -1
  133. package/lib/src/embed/ts-embed.spec.js +164 -0
  134. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  135. package/lib/src/errors.d.ts +1 -0
  136. package/lib/src/errors.d.ts.map +1 -1
  137. package/lib/src/errors.js +1 -0
  138. package/lib/src/errors.js.map +1 -1
  139. package/lib/src/index.d.ts +2 -2
  140. package/lib/src/index.d.ts.map +1 -1
  141. package/lib/src/index.js +2 -2
  142. package/lib/src/index.js.map +1 -1
  143. package/lib/src/react/all-types-export.d.ts +1 -1
  144. package/lib/src/react/all-types-export.d.ts.map +1 -1
  145. package/lib/src/react/all-types-export.js +1 -1
  146. package/lib/src/react/all-types-export.js.map +1 -1
  147. package/lib/src/react/index.d.ts +71 -20
  148. package/lib/src/react/index.d.ts.map +1 -1
  149. package/lib/src/react/index.js +79 -43
  150. package/lib/src/react/index.js.map +1 -1
  151. package/lib/src/react/index.spec.js +439 -103
  152. package/lib/src/react/index.spec.js.map +1 -1
  153. package/lib/src/types.d.ts +80 -6
  154. package/lib/src/types.d.ts.map +1 -1
  155. package/lib/src/types.js +45 -1
  156. package/lib/src/types.js.map +1 -1
  157. package/lib/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  158. package/lib/src/utils/graphql/nlsService/conversation-service.js +2 -0
  159. package/lib/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  160. package/lib/src/utils/processTrigger.js +2 -1
  161. package/lib/src/utils/processTrigger.js.map +1 -1
  162. package/lib/src/utils.d.ts +6 -0
  163. package/lib/src/utils.d.ts.map +1 -1
  164. package/lib/src/utils.js +21 -2
  165. package/lib/src/utils.js.map +1 -1
  166. package/lib/src/utils.spec.js +238 -2
  167. package/lib/src/utils.spec.js.map +1 -1
  168. package/lib/src/visual-embed-sdk.d.ts +219 -54
  169. package/package.json +1 -1
  170. package/src/config.spec.ts +11 -0
  171. package/src/embed/app.spec.ts +479 -26
  172. package/src/embed/app.ts +133 -27
  173. package/src/embed/bodyless-conversation.spec.ts +9 -203
  174. package/src/embed/bodyless-conversation.ts +24 -10
  175. package/src/embed/conversation.spec.ts +40 -2
  176. package/src/embed/embedConfig.ts +10 -8
  177. package/src/embed/liveboard.spec.ts +256 -5
  178. package/src/embed/liveboard.ts +99 -27
  179. package/src/embed/ts-embed.spec.ts +225 -0
  180. package/src/embed/ts-embed.ts +19 -0
  181. package/src/errors.ts +1 -0
  182. package/src/index.ts +2 -0
  183. package/src/react/all-types-export.ts +2 -1
  184. package/src/react/index.spec.tsx +556 -157
  185. package/src/react/index.tsx +117 -51
  186. package/src/types.ts +117 -43
  187. package/src/utils/graphql/nlsService/conversation-service.ts +2 -0
  188. package/src/utils/processTrigger.ts +1 -1
  189. package/src/utils.spec.ts +279 -2
  190. package/src/utils.ts +28 -2
package/src/embed/app.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import { logger } from '../utils/logger';
12
- import { getQueryParamString } from '../utils';
12
+ import { calculateVisibleElementData, getQueryParamString } from '../utils';
13
13
  import {
14
14
  Param,
15
15
  DOMSelector,
@@ -23,7 +23,7 @@ import { V1Embed } from './ts-embed';
23
23
  /**
24
24
  * Pages within the ThoughtSpot app that can be embedded.
25
25
  */
26
- // eslint-disable-next-line no-shadow
26
+
27
27
  export enum Page {
28
28
  /**
29
29
  * Home page
@@ -93,7 +93,7 @@ export enum PrimaryNavbarVersion {
93
93
  * Sliding (v3) introduces a new left-side navigation hub featuring a tab switcher,
94
94
  * along with updates to the top navigation bar.
95
95
  * It serves as the foundational version of the PrimaryNavBar.
96
-  */
96
+ */
97
97
  Sliding = 'v3',
98
98
  }
99
99
 
@@ -103,12 +103,28 @@ export enum PrimaryNavbarVersion {
103
103
  */
104
104
  export enum HomePage {
105
105
  /**
106
-  * Modular (v2) introduces the updated Modular Home Experience.
107
-  * It serves as the foundational version of the home page.
108
-  */
106
+ * Modular (v2) introduces the updated Modular Home Experience.
107
+ * It serves as the foundational version of the home page.
108
+ */
109
109
  Modular = 'v2',
110
110
  }
111
111
 
112
+ /**
113
+ * Define the version of the list page
114
+ * @version SDK: 1.40.0 | ThoughtSpot: 10.12.0.cl
115
+ */
116
+ export enum ListPage {
117
+ /**
118
+ * List (v2) is the traditional List Experience.
119
+ * It serves as the foundational version of the list page.
120
+ */
121
+ List = 'v2',
122
+ /**
123
+ * ListWithUXChanges (v3) introduces the new updated list page with UX changes.
124
+ */
125
+ ListWithUXChanges = 'v3',
126
+ }
127
+
112
128
  /**
113
129
  * Define the discovery experience
114
130
  * @version SDK: 1.40.0 | ThoughtSpot: 10.11.0.cl
@@ -122,6 +138,10 @@ export interface DiscoveryExperience {
122
138
  * homePage determines the version of the home page.
123
139
  */
124
140
  homePage?: HomePage;
141
+ /**
142
+ * listPageVersion determines the version of the list page.
143
+ */
144
+ listPageVersion?: ListPage;
125
145
  }
126
146
 
127
147
  /**
@@ -494,21 +514,7 @@ export interface AppViewConfig extends AllEmbedViewConfig {
494
514
  * ```
495
515
  */
496
516
  isUnifiedSearchExperienceEnabled?: boolean;
497
- /**
498
- * Show alert messages and toast messages in the embedded
499
- * view in full app embed.
500
- *
501
- * Supported embed types: `AppEmbed`
502
- * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw
503
- * @example
504
- * ```js
505
- * const embed = new AppEmbed('#tsEmbed', {
506
- * ... // other embed view config
507
- * showAlerts:true,
508
- * })
509
- * ```
510
- */
511
- showAlerts?: boolean;
517
+
512
518
  /**
513
519
  * This flag is used to enable/disable the styling and grouping in a Liveboard
514
520
  *
@@ -525,6 +531,48 @@ export interface AppViewConfig extends AllEmbedViewConfig {
525
531
  * ```
526
532
  */
527
533
  isLiveboardStylingAndGroupingEnabled?: boolean;
534
+
535
+ /**
536
+ * This flag is used to enable the full height lazy load data.
537
+ *
538
+ * @example
539
+ * ```js
540
+ * const embed = new AppEmbed('#embed-container', {
541
+ * // ...other options
542
+ * fullHeight: true,
543
+ * lazyLoadingForFullHeight: true,
544
+ * })
545
+ * ```
546
+ *
547
+ * @type {boolean}
548
+ * @default false
549
+ * @version SDK: 1.39.0 | ThoughtSpot:10.10.0.cl
550
+ */
551
+ lazyLoadingForFullHeight?: boolean;
552
+
553
+ /**
554
+ * The margin to be used for lazy loading.
555
+ *
556
+ * For example, if the margin is set to '10px',
557
+ * the visualization will be loaded 10px before the its top edge is visible in the
558
+ * viewport.
559
+ *
560
+ * The format is similar to CSS margin.
561
+ *
562
+ * @example
563
+ * ```js
564
+ * const embed = new AppEmbed('#embed-container', {
565
+ * // ...other options
566
+ * fullHeight: true,
567
+ * lazyLoadingForFullHeight: true,
568
+ * // Using 0px, the visualization will be only loaded when its visible in the viewport.
569
+ * lazyLoadingMargin: '0px',
570
+ * })
571
+ * ```
572
+ * @type {string}
573
+ * @version SDK: 1.39.0 | ThoughtSpot:10.10.0.cl
574
+ */
575
+ lazyLoadingMargin?: string;
528
576
  }
529
577
 
530
578
  /**
@@ -536,7 +584,7 @@ export class AppEmbed extends V1Embed {
536
584
 
537
585
  private defaultHeight = '100%';
538
586
 
539
- // eslint-disable-next-line no-useless-constructor
587
+
540
588
  constructor(domSelector: DOMSelector, viewConfig: AppViewConfig) {
541
589
  viewConfig.embedComponentType = 'AppEmbed';
542
590
  super(domSelector, viewConfig);
@@ -544,6 +592,7 @@ export class AppEmbed extends V1Embed {
544
592
  this.on(EmbedEvent.RouteChange, this.setIframeHeightForNonEmbedLiveboard);
545
593
  this.on(EmbedEvent.EmbedHeight, this.updateIFrameHeight);
546
594
  this.on(EmbedEvent.EmbedIframeCenter, this.embedIframeCenter);
595
+ this.on(EmbedEvent.RequestVisibleEmbedCoordinates, this.requestVisibleEmbedCoordinatesHandler);
547
596
  }
548
597
  }
549
598
 
@@ -577,7 +626,7 @@ export class AppEmbed extends V1Embed {
577
626
  enable2ColumnLayout,
578
627
  enableCustomColumnGroups = false,
579
628
  isOnBeforeGetVizDataInterceptEnabled = false,
580
- /* eslint-disable-next-line max-len */
629
+
581
630
  dataPanelCustomGroupsAccordionInitialState = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL,
582
631
  collapseSearchBar = true,
583
632
  isLiveboardCompactHeaderEnabled = false,
@@ -588,10 +637,11 @@ export class AppEmbed extends V1Embed {
588
637
  isUnifiedSearchExperienceEnabled = true,
589
638
  enablePendoHelp = true,
590
639
  discoveryExperience,
640
+ coverAndFilterOptionInPDF = false,
591
641
  isLiveboardStylingAndGroupingEnabled,
592
642
  } = this.viewConfig;
593
643
 
594
- let params = {};
644
+ let params: any = {};
595
645
  params[Param.PrimaryNavHidden] = !showPrimaryNavbar;
596
646
  params[Param.HideProfleAndHelp] = !!disableProfileAndHelp;
597
647
  params[Param.HideApplicationSwitcher] = !!hideApplicationSwitcher;
@@ -606,6 +656,7 @@ export class AppEmbed extends V1Embed {
606
656
  params[Param.ShowLiveboardReverifyBanner] = showLiveboardReverifyBanner;
607
657
  params[Param.HideIrrelevantFiltersInTab] = hideIrrelevantChipsInLiveboardTabs;
608
658
  params[Param.IsUnifiedSearchExperienceEnabled] = isUnifiedSearchExperienceEnabled;
659
+ params[Param.CoverAndFilterOptionInPDF] = !!coverAndFilterOptionInPDF;
609
660
 
610
661
  params = this.getBaseQueryParams(params);
611
662
 
@@ -623,6 +674,10 @@ export class AppEmbed extends V1Embed {
623
674
 
624
675
  if (fullHeight === true) {
625
676
  params[Param.fullHeight] = true;
677
+ if (this.viewConfig.lazyLoadingForFullHeight) {
678
+ params[Param.IsLazyLoadingForEmbedEnabled] = true;
679
+ params[Param.RootMarginForLazyLoad] = this.viewConfig.lazyLoadingMargin;
680
+ }
626
681
  }
627
682
 
628
683
  if (tag) {
@@ -648,7 +703,7 @@ export class AppEmbed extends V1Embed {
648
703
  }
649
704
 
650
705
  if (isOnBeforeGetVizDataInterceptEnabled) {
651
- /* eslint-disable-next-line max-len */
706
+
652
707
  params[
653
708
  Param.IsOnBeforeGetVizDataInterceptEnabled
654
709
  ] = isOnBeforeGetVizDataInterceptEnabled;
@@ -676,12 +731,12 @@ export class AppEmbed extends V1Embed {
676
731
  || dataPanelCustomGroupsAccordionInitialState
677
732
  === DataPanelCustomColumnGroupsAccordionState.EXPAND_FIRST
678
733
  ) {
679
- /* eslint-disable-next-line max-len */
734
+
680
735
  params[
681
736
  Param.DataPanelCustomGroupsAccordionInitialState
682
737
  ] = dataPanelCustomGroupsAccordionInitialState;
683
738
  } else {
684
- /* eslint-disable-next-line max-len */
739
+
685
740
  params[Param.DataPanelCustomGroupsAccordionInitialState] = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL;
686
741
  }
687
742
 
@@ -696,6 +751,10 @@ export class AppEmbed extends V1Embed {
696
751
  if (discoveryExperience.homePage === HomePage.Modular) {
697
752
  params[Param.ModularHomeExperienceEnabled] = true;
698
753
  }
754
+ // listPageVersion v3 will enable the new list page
755
+ if (discoveryExperience.listPageVersion === ListPage.ListWithUXChanges) {
756
+ params[Param.ListPageVersion] = discoveryExperience.listPageVersion;
757
+ }
699
758
  }
700
759
 
701
760
  const queryParams = getQueryParamString(params, true);
@@ -703,6 +762,23 @@ export class AppEmbed extends V1Embed {
703
762
  return queryParams;
704
763
  }
705
764
 
765
+ private sendFullHeightLazyLoadData = () => {
766
+ const data = calculateVisibleElementData(this.iFrame);
767
+ this.trigger(HostEvent.VisibleEmbedCoordinates, data);
768
+ }
769
+
770
+ /**
771
+ * This is a handler for the RequestVisibleEmbedCoordinates event.
772
+ * It is used to send the visible coordinates data to the host application.
773
+ * @param data The event payload
774
+ * @param responder The responder function
775
+ */
776
+ private requestVisibleEmbedCoordinatesHandler = (data: MessagePayload, responder: any) => {
777
+ logger.info('Sending RequestVisibleEmbedCoordinates', data);
778
+ const visibleCoordinatesData = calculateVisibleElementData(this.iFrame);
779
+ responder({ type: EmbedEvent.RequestVisibleEmbedCoordinates, data: visibleCoordinatesData });
780
+ }
781
+
706
782
  /**
707
783
  * Constructs the URL of the ThoughtSpot app page to be rendered.
708
784
  * @param pageId The ID of the page to be embedded.
@@ -725,6 +801,7 @@ export class AppEmbed extends V1Embed {
725
801
  */
726
802
  protected updateIFrameHeight = (data: MessagePayload) => {
727
803
  this.setIFrameHeight(Math.max(data.data, this.iFrame?.scrollHeight));
804
+ this.sendFullHeightLazyLoadData();
728
805
  };
729
806
 
730
807
  private embedIframeCenter = (data: MessagePayload, responder: any) => {
@@ -833,6 +910,34 @@ export class AppEmbed extends V1Embed {
833
910
  }
834
911
  }
835
912
 
913
+ /**
914
+ * Destroys the ThoughtSpot embed, and remove any nodes from the DOM.
915
+ * @version SDK: 1.39.0 | ThoughtSpot: 10.10.0.cl
916
+ */
917
+ public destroy() {
918
+ super.destroy();
919
+ this.unregisterLazyLoadEvents();
920
+ }
921
+
922
+ private postRender() {
923
+ this.registerLazyLoadEvents();
924
+ }
925
+
926
+ private registerLazyLoadEvents() {
927
+ if (this.viewConfig.fullHeight && this.viewConfig.lazyLoadingForFullHeight) {
928
+ // TODO: Use passive: true, install modernizr to check for passive
929
+ window.addEventListener('resize', this.sendFullHeightLazyLoadData);
930
+ window.addEventListener('scroll', this.sendFullHeightLazyLoadData);
931
+ }
932
+ }
933
+
934
+ private unregisterLazyLoadEvents() {
935
+ if (this.viewConfig.fullHeight && this.viewConfig.lazyLoadingForFullHeight) {
936
+ window.removeEventListener('resize', this.sendFullHeightLazyLoadData);
937
+ window.removeEventListener('scroll', this.sendFullHeightLazyLoadData);
938
+ }
939
+ }
940
+
836
941
  /**
837
942
  * Renders the embedded application pages in the ThoughtSpot app.
838
943
  * @param renderOptions An object containing the page ID
@@ -844,6 +949,7 @@ export class AppEmbed extends V1Embed {
844
949
  const src = this.getIFrameSrc();
845
950
  await this.renderV1Embed(src);
846
951
 
952
+ this.postRender();
847
953
  return this;
848
954
  }
849
955
  }
@@ -1,5 +1,5 @@
1
1
  import 'jest-fetch-mock';
2
- import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig } from './bodyless-conversation';
2
+ import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig, ConversationMessage } from './bodyless-conversation';
3
3
  import * as authInstance from '../auth';
4
4
  import { init } from '../index';
5
5
  import { Action, AuthType, RuntimeFilterOp } from '../types';
@@ -138,7 +138,7 @@ describe('SpotterAgentEmbed', () => {
138
138
  expect(errorResult.error instanceof Error).toBeTruthy();
139
139
  });
140
140
 
141
- test('should apply containerClassName to the container element', async () => {
141
+ test('should handle hideActions parameter correctly', async () => {
142
142
  fetchMock.mockResponses(
143
143
  JSON.stringify({
144
144
  data: {
@@ -227,221 +227,27 @@ describe('SpotterAgentEmbed', () => {
227
227
 
228
228
  const viewConfig: SpotterAgentEmbedViewConfig = {
229
229
  worksheetId: 'worksheetId',
230
- containerClassName: 'custom-conversation-container',
230
+ hiddenActions: [Action.Download, Action.Save], // This should trigger the HideActions branch
231
231
  };
232
232
 
233
233
  const spotterAgentEmbed = new SpotterAgentEmbed(viewConfig);
234
234
  const result = await spotterAgentEmbed.sendMessage('userMessage');
235
235
 
236
- // Verify that the container has the custom class name
237
- expect(result.container.className).toBe('custom-conversation-container');
238
-
239
- // Also verify the iframe src is correct
236
+ // Verify the iframe src contains the hideActions parameter
240
237
  const iframeSrc = getIFrameSrc(result.container);
241
- expectUrlToHaveParamsWithValues(iframeSrc, {
242
- sessionId: 'sessionId',
243
- genNo: 2,
244
- acSessionId: 'transactionId',
245
- acGenNo: 1,
246
- });
238
+ expect(iframeSrc).toContain('hideAction');
247
239
  });
248
240
 
249
- test('should not set className when containerClassName is not provided', async () => {
250
- fetchMock.mockResponses(
251
- JSON.stringify({
252
- data: {
253
- ConvAssist__createConversation: {
254
- convId: 'conversationId',
255
- initialCtx: {
256
- type: 'TS_ANSWER',
257
- tsAnsCtx: {
258
- sessionId: 'sessionId',
259
- genNo: 1,
260
- stateKey: {
261
- transactionId: 'transactionId',
262
- generationNumber: 1,
263
- },
264
- worksheet: {
265
- worksheetId: 'worksheetId',
266
- worksheetName: 'GTM',
267
- },
268
- },
269
- },
270
- },
271
- },
272
- }),
273
- JSON.stringify({
274
- data: {
275
- ConvAssist__sendMessage: {
276
- responses: [
277
- {
278
- msgId: 'msgId',
279
- data: {
280
- asstRespData: {
281
- tool: 'TS_NLS',
282
- asstRespText: '',
283
- nlsAnsData: {
284
- sageQuerySuggestions: [
285
- {
286
- llmReasoning: {
287
- assumptions: 'You want the total [COL|sales] for [COL|item_type] [VAL|jackets] for [VAL|this year].',
288
- clarifications: '',
289
- interpretation: '',
290
- __typename: 'eureka_SageQuerySuggestion_LLMReasoning',
291
- },
292
- tokens: [
293
- 'sum sales',
294
- "item type = 'jackets'",
295
- "date = 'this year'",
296
- ],
297
- tmlTokens: [
298
- 'sum [sales]',
299
- "[date] = [date].'this year'",
300
- "[item type] = [item type].'jackets'",
301
- ],
302
- worksheetId: 'worksheetId',
303
- description: '',
304
- title: '',
305
- cached: false,
306
- sqlQuery: "SELECT SUM(sales) FROM __Sample_Retail_Apparel WHERE item_type = 'jackets' AND date = _this_year();",
307
- sessionId: 'sessionId',
308
- genNo: 2,
309
- formulaInfo: [],
310
- tmlPhrases: [],
311
- stateKey: {
312
- transactionId: 'transactionId',
313
- generationNumber: 1,
314
- __typename: 'sage_auto_complete_v2_ACStateKey',
315
- },
316
- __typename: 'eureka_SageQuerySuggestion',
317
- },
318
- ],
319
- responseType: 'ANSWER',
320
- __typename: 'convassist_nls_tool_NLSToolAsstRespData',
321
- },
322
- __typename: 'convassist_AsstResponseData',
323
- },
324
- __typename: 'convassist_MessageData',
325
- },
326
- type: 'ASST_RESPONSE',
327
- __typename: 'convassist_MessagePayload',
328
- },
329
- ],
330
- __typename: 'convassist_SendMessageResponse',
331
- },
332
- },
333
- }),
334
- );
335
-
241
+ test('should have sendMessageData method', () => {
336
242
  const viewConfig: SpotterAgentEmbedViewConfig = {
337
243
  worksheetId: 'worksheetId',
338
- // No containerClassName provided
339
244
  };
340
245
 
341
246
  const spotterAgentEmbed = new SpotterAgentEmbed(viewConfig);
342
- const result = await spotterAgentEmbed.sendMessage('userMessage');
343
-
344
- // Verify that the container has no class name (empty string)
345
- expect(result.container.className).toBe('');
247
+ expect(typeof spotterAgentEmbed.sendMessageData).toBe('function');
346
248
  });
347
249
 
348
- test('should handle hideActions parameter correctly', async () => {
349
- fetchMock.mockResponses(
350
- JSON.stringify({
351
- data: {
352
- ConvAssist__createConversation: {
353
- convId: 'conversationId',
354
- initialCtx: {
355
- type: 'TS_ANSWER',
356
- tsAnsCtx: {
357
- sessionId: 'sessionId',
358
- genNo: 1,
359
- stateKey: {
360
- transactionId: 'transactionId',
361
- generationNumber: 1,
362
- },
363
- worksheet: {
364
- worksheetId: 'worksheetId',
365
- worksheetName: 'GTM',
366
- },
367
- },
368
- },
369
- },
370
- },
371
- }),
372
- JSON.stringify({
373
- data: {
374
- ConvAssist__sendMessage: {
375
- responses: [
376
- {
377
- msgId: 'msgId',
378
- data: {
379
- asstRespData: {
380
- tool: 'TS_NLS',
381
- asstRespText: '',
382
- nlsAnsData: {
383
- sageQuerySuggestions: [
384
- {
385
- llmReasoning: {
386
- assumptions: 'You want the total [COL|sales] for [COL|item_type] [VAL|jackets] for [VAL|this year].',
387
- clarifications: '',
388
- interpretation: '',
389
- __typename: 'eureka_SageQuerySuggestion_LLMReasoning',
390
- },
391
- tokens: [
392
- 'sum sales',
393
- "item type = 'jackets'",
394
- "date = 'this year'",
395
- ],
396
- tmlTokens: [
397
- 'sum [sales]',
398
- "[date] = [date].'this year'",
399
- "[item type] = [item type].'jackets'",
400
- ],
401
- worksheetId: 'worksheetId',
402
- description: '',
403
- title: '',
404
- cached: false,
405
- sqlQuery: "SELECT SUM(sales) FROM __Sample_Retail_Apparel WHERE item_type = 'jackets' AND date = _this_year();",
406
- sessionId: 'sessionId',
407
- genNo: 2,
408
- formulaInfo: [],
409
- tmlPhrases: [],
410
- stateKey: {
411
- transactionId: 'transactionId',
412
- generationNumber: 1,
413
- __typename: 'sage_auto_complete_v2_ACStateKey',
414
- },
415
- __typename: 'eureka_SageQuerySuggestion',
416
- },
417
- ],
418
- responseType: 'ANSWER',
419
- __typename: 'convassist_nls_tool_NLSToolAsstRespData',
420
- },
421
- __typename: 'convassist_AsstResponseData',
422
- },
423
- __typename: 'convassist_MessageData',
424
- },
425
- type: 'ASST_RESPONSE',
426
- __typename: 'convassist_MessagePayload',
427
- },
428
- ],
429
- __typename: 'convassist_SendMessageResponse',
430
- },
431
- },
432
- }),
433
- );
434
-
435
- const viewConfig: SpotterAgentEmbedViewConfig = {
436
- worksheetId: 'worksheetId',
437
- hiddenActions: [Action.Download, Action.Save], // This should trigger the HideActions branch
438
- };
439
-
440
- const spotterAgentEmbed = new SpotterAgentEmbed(viewConfig);
441
- const result = await spotterAgentEmbed.sendMessage('userMessage');
442
-
443
- // Verify the iframe src contains the hideActions parameter
444
- const iframeSrc = getIFrameSrc(result.container);
445
- expect(iframeSrc).toContain('hideAction');
250
+ test('should export ConversationMessage class', () => {
251
+ expect(typeof ConversationMessage).toBe('function');
446
252
  });
447
253
  });
@@ -13,11 +13,6 @@ export interface SpotterAgentEmbedViewConfig extends Omit<BaseViewConfig, 'prima
13
13
  * The ID of the worksheet to use for the conversation.
14
14
  */
15
15
  worksheetId: string;
16
-
17
- /**
18
- * Optional CSS class name to add to the container div.
19
- */
20
- containerClassName?: string;
21
16
  }
22
17
 
23
18
  /**
@@ -29,14 +24,14 @@ export interface SpotterAgentEmbedViewConfig extends Omit<BaseViewConfig, 'prima
29
24
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
30
25
  export interface BodylessConversationViewConfig extends SpotterAgentEmbedViewConfig {}
31
26
 
32
- interface SpotterAgentMessageViewConfig extends SpotterAgentEmbedViewConfig {
27
+ export interface SpotterAgentMessageViewConfig extends SpotterAgentEmbedViewConfig {
33
28
  sessionId: string;
34
29
  genNo: number;
35
30
  acSessionId: string;
36
31
  acGenNo: number;
37
32
  }
38
33
 
39
- class ConversationMessage extends TsEmbed {
34
+ export class ConversationMessage extends TsEmbed {
40
35
  constructor(container: HTMLElement, protected viewConfig: SpotterAgentMessageViewConfig) {
41
36
  viewConfig.embedComponentType = 'bodyless-conversation';
42
37
  super(container, viewConfig);
@@ -116,9 +111,6 @@ export class SpotterAgentEmbed {
116
111
  }
117
112
 
118
113
  const container = document.createElement('div');
119
- if (this.viewConfig.containerClassName) {
120
- container.className = this.viewConfig.containerClassName;
121
- }
122
114
 
123
115
  const embed = new ConversationMessage(container, {
124
116
  ...this.viewConfig,
@@ -130,6 +122,28 @@ export class SpotterAgentEmbed {
130
122
  await embed.render();
131
123
  return { container, viz: embed };
132
124
  }
125
+
126
+ /**
127
+ * Send a message to the conversation service and return only the data.
128
+ * @param userMessage - The message to send to the conversation service.
129
+ * @returns The data from the conversation service.
130
+ */
131
+ public async sendMessageData(userMessage: string) {
132
+ try {
133
+ const { data, error } = await this.conversationService.sendMessage(userMessage);
134
+ if (error) {
135
+ return { error };
136
+ }
137
+ return { data: {
138
+ sessionId: data.sessionId,
139
+ genNo: data.genNo,
140
+ acSessionId: data.stateKey.transactionId,
141
+ acGenNo: data.stateKey.generationNumber,
142
+ } };
143
+ } catch (error) {
144
+ return { error: error as Error };
145
+ }
146
+ }
133
147
  }
134
148
 
135
149
  /**
@@ -3,8 +3,8 @@ import {
3
3
  SpotterEmbedViewConfig,
4
4
  } from './conversation';
5
5
  import * as authInstance from '../auth';
6
- import { init } from '../index';
7
- import { AuthType } from '../types';
6
+ import { Action, init } from '../index';
7
+ import { AuthType, Param } from '../types';
8
8
  import {
9
9
  getDocumentBody,
10
10
  getIFrameSrc,
@@ -142,4 +142,42 @@ describe('ConversationEmbed', () => {
142
142
  `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&enableDataPanelV2=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
143
143
  );
144
144
  });
145
+
146
+ it('should render the conversation embed with hidden actions of InConversationTraining if set', async () => {
147
+ const viewConfig: SpotterEmbedViewConfig = {
148
+ worksheetId: 'worksheetId',
149
+ searchOptions: {
150
+ searchQuery: 'searchQuery',
151
+ },
152
+ dataPanelV2: true,
153
+ hiddenActions: [Action.InConversationTraining]
154
+ };
155
+
156
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
157
+ await conversationEmbed.render();
158
+ expectUrlMatchesWithParams(
159
+ getIFrameSrc(),
160
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&hideAction=[%22${Action.ReportError}%22,%22${Action.InConversationTraining}%22]&isSpotterExperienceEnabled=true&enableDataPanelV2=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
161
+ );
162
+ });
163
+
164
+ it('should render the conversation embed with disabled actions of InConversationTraining if set', async () => {
165
+ const disabledReason = 'testing disabled reason';
166
+ const viewConfig: SpotterEmbedViewConfig = {
167
+ worksheetId: 'worksheetId',
168
+ searchOptions: {
169
+ searchQuery: 'searchQuery',
170
+ },
171
+ dataPanelV2: true,
172
+ disabledActions: [Action.InConversationTraining],
173
+ disabledActionReason: disabledReason,
174
+ };
175
+
176
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
177
+ await conversationEmbed.render();
178
+ expectUrlMatchesWithParams(
179
+ getIFrameSrc(),
180
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&${Param.DisableActions}=[%22${Action.InConversationTraining}%22]&${Param.DisableActionReason}=${disabledReason}&isSpotterExperienceEnabled=true&enableDataPanelV2=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
181
+ );
182
+ });
145
183
  });