@thoughtspot/visual-embed-sdk 1.39.2 → 1.39.3

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 (157) 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 +19 -15
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +23 -2
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +56 -8
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/bodyless-conversation.d.ts +23 -7
  11. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/bodyless-conversation.js +31 -5
  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 +0 -17
  23. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  24. package/cjs/src/embed/liveboard.js +2 -4
  25. package/cjs/src/embed/liveboard.js.map +1 -1
  26. package/cjs/src/embed/liveboard.spec.js +12 -11
  27. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  28. package/cjs/src/errors.d.ts +1 -0
  29. package/cjs/src/errors.d.ts.map +1 -1
  30. package/cjs/src/errors.js +1 -0
  31. package/cjs/src/errors.js.map +1 -1
  32. package/cjs/src/index.d.ts +2 -2
  33. package/cjs/src/index.d.ts.map +1 -1
  34. package/cjs/src/index.js +2 -1
  35. package/cjs/src/index.js.map +1 -1
  36. package/cjs/src/react/all-types-export.d.ts +1 -1
  37. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  38. package/cjs/src/react/all-types-export.js +3 -2
  39. package/cjs/src/react/all-types-export.js.map +1 -1
  40. package/cjs/src/react/index.d.ts +73 -20
  41. package/cjs/src/react/index.d.ts.map +1 -1
  42. package/cjs/src/react/index.js +79 -42
  43. package/cjs/src/react/index.js.map +1 -1
  44. package/cjs/src/react/index.spec.js +438 -100
  45. package/cjs/src/react/index.spec.js.map +1 -1
  46. package/cjs/src/types.d.ts +262 -6
  47. package/cjs/src/types.d.ts.map +1 -1
  48. package/cjs/src/types.js +228 -2
  49. package/cjs/src/types.js.map +1 -1
  50. package/cjs/src/utils/global-styles.js +1 -1
  51. package/cjs/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  52. package/cjs/src/utils/graphql/nlsService/conversation-service.js +7 -1
  53. package/cjs/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  54. package/cjs/src/utils.spec.js +25 -0
  55. package/cjs/src/utils.spec.js.map +1 -1
  56. package/dist/{index-CmEQfuE3.js → index-ZrE8YYq8.js} +1 -1
  57. package/dist/src/embed/app.d.ts +19 -15
  58. package/dist/src/embed/app.d.ts.map +1 -1
  59. package/dist/src/embed/bodyless-conversation.d.ts +23 -7
  60. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  61. package/dist/src/embed/embedConfig.d.ts +9 -7
  62. package/dist/src/embed/embedConfig.d.ts.map +1 -1
  63. package/dist/src/embed/liveboard.d.ts +0 -17
  64. package/dist/src/embed/liveboard.d.ts.map +1 -1
  65. package/dist/src/errors.d.ts +1 -0
  66. package/dist/src/errors.d.ts.map +1 -1
  67. package/dist/src/index.d.ts +2 -2
  68. package/dist/src/index.d.ts.map +1 -1
  69. package/dist/src/react/all-types-export.d.ts +1 -1
  70. package/dist/src/react/all-types-export.d.ts.map +1 -1
  71. package/dist/src/react/index.d.ts +73 -20
  72. package/dist/src/react/index.d.ts.map +1 -1
  73. package/dist/src/types.d.ts +262 -6
  74. package/dist/src/types.d.ts.map +1 -1
  75. package/dist/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  76. package/dist/tsembed-react.es.js +385 -71
  77. package/dist/tsembed-react.js +385 -69
  78. package/dist/tsembed.es.js +303 -24
  79. package/dist/tsembed.js +301 -22
  80. package/dist/visual-embed-sdk-react-full.d.ts +386 -72
  81. package/dist/visual-embed-sdk-react.d.ts +386 -72
  82. package/dist/visual-embed-sdk.d.ts +314 -53
  83. package/lib/package.json +1 -1
  84. package/lib/src/config.spec.js +9 -0
  85. package/lib/src/config.spec.js.map +1 -1
  86. package/lib/src/embed/app.d.ts +19 -15
  87. package/lib/src/embed/app.d.ts.map +1 -1
  88. package/lib/src/embed/app.js +22 -1
  89. package/lib/src/embed/app.js.map +1 -1
  90. package/lib/src/embed/app.spec.js +58 -10
  91. package/lib/src/embed/app.spec.js.map +1 -1
  92. package/lib/src/embed/bodyless-conversation.d.ts +23 -7
  93. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  94. package/lib/src/embed/bodyless-conversation.js +30 -5
  95. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  96. package/lib/src/embed/bodyless-conversation.spec.js +9 -191
  97. package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
  98. package/lib/src/embed/conversation.spec.js +30 -2
  99. package/lib/src/embed/conversation.spec.js.map +1 -1
  100. package/lib/src/embed/embedConfig.d.ts +9 -7
  101. package/lib/src/embed/embedConfig.d.ts.map +1 -1
  102. package/lib/src/embed/embedConfig.js +9 -7
  103. package/lib/src/embed/embedConfig.js.map +1 -1
  104. package/lib/src/embed/liveboard.d.ts +0 -17
  105. package/lib/src/embed/liveboard.d.ts.map +1 -1
  106. package/lib/src/embed/liveboard.js +2 -4
  107. package/lib/src/embed/liveboard.js.map +1 -1
  108. package/lib/src/embed/liveboard.spec.js +12 -11
  109. package/lib/src/embed/liveboard.spec.js.map +1 -1
  110. package/lib/src/errors.d.ts +1 -0
  111. package/lib/src/errors.d.ts.map +1 -1
  112. package/lib/src/errors.js +1 -0
  113. package/lib/src/errors.js.map +1 -1
  114. package/lib/src/index.d.ts +2 -2
  115. package/lib/src/index.d.ts.map +1 -1
  116. package/lib/src/index.js +2 -2
  117. package/lib/src/index.js.map +1 -1
  118. package/lib/src/react/all-types-export.d.ts +1 -1
  119. package/lib/src/react/all-types-export.d.ts.map +1 -1
  120. package/lib/src/react/all-types-export.js +1 -1
  121. package/lib/src/react/all-types-export.js.map +1 -1
  122. package/lib/src/react/index.d.ts +73 -20
  123. package/lib/src/react/index.d.ts.map +1 -1
  124. package/lib/src/react/index.js +79 -43
  125. package/lib/src/react/index.js.map +1 -1
  126. package/lib/src/react/index.spec.js +441 -103
  127. package/lib/src/react/index.spec.js.map +1 -1
  128. package/lib/src/types.d.ts +262 -6
  129. package/lib/src/types.d.ts.map +1 -1
  130. package/lib/src/types.js +228 -2
  131. package/lib/src/types.js.map +1 -1
  132. package/lib/src/utils/global-styles.js +1 -1
  133. package/lib/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
  134. package/lib/src/utils/graphql/nlsService/conversation-service.js +7 -1
  135. package/lib/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
  136. package/lib/src/utils.spec.js +26 -1
  137. package/lib/src/utils.spec.js.map +1 -1
  138. package/lib/src/visual-embed-sdk.d.ts +315 -54
  139. package/package.json +1 -1
  140. package/src/config.spec.ts +11 -0
  141. package/src/embed/app.spec.ts +90 -23
  142. package/src/embed/app.ts +27 -15
  143. package/src/embed/bodyless-conversation.spec.ts +9 -203
  144. package/src/embed/bodyless-conversation.ts +34 -10
  145. package/src/embed/conversation.spec.ts +40 -2
  146. package/src/embed/embedConfig.ts +10 -8
  147. package/src/embed/liveboard.spec.ts +5 -4
  148. package/src/embed/liveboard.ts +2 -22
  149. package/src/errors.ts +1 -0
  150. package/src/index.ts +2 -0
  151. package/src/react/all-types-export.ts +2 -1
  152. package/src/react/index.spec.tsx +558 -157
  153. package/src/react/index.tsx +117 -51
  154. package/src/types.ts +301 -44
  155. package/src/utils/global-styles.ts +1 -1
  156. package/src/utils/graphql/nlsService/conversation-service.ts +7 -1
  157. package/src/utils.spec.ts +29 -0
@@ -6,11 +6,10 @@ import {
6
6
  HomePageSearchBarMode,
7
7
  PrimaryNavbarVersion,
8
8
  HomePage,
9
+ ListPage,
9
10
  } from './app';
10
11
  import { init } from '../index';
11
- import {
12
- Action, AuthType, EmbedEvent, HostEvent, RuntimeFilterOp,
13
- } from '../types';
12
+ import { Action, AuthType, EmbedEvent, HostEvent, RuntimeFilterOp } from '../types';
14
13
  import {
15
14
  executeAfterWait,
16
15
  getDocumentBody,
@@ -45,12 +44,13 @@ beforeAll(() => {
45
44
  authType: AuthType.None,
46
45
  });
47
46
  jest.spyOn(auth, 'postLoginService').mockImplementation(() => Promise.resolve({}));
48
- (window as any).ResizeObserver = window.ResizeObserver
49
- || jest.fn().mockImplementation(() => ({
50
- disconnect: jest.fn(),
51
- observe: jest.fn(),
52
- unobserve: jest.fn(),
53
- }));
47
+ (window as any).ResizeObserver =
48
+ window.ResizeObserver ||
49
+ jest.fn().mockImplementation(() => ({
50
+ disconnect: jest.fn(),
51
+ observe: jest.fn(),
52
+ unobserve: jest.fn(),
53
+ }));
54
54
  });
55
55
 
56
56
  const cleanUp = () => {
@@ -316,6 +316,20 @@ describe('App embed tests', () => {
316
316
  });
317
317
  });
318
318
 
319
+ test('should set coverAndFilterOptionInPDF to false in url', async () => {
320
+ const appEmbed = new AppEmbed(getRootEl(), {
321
+ ...defaultViewConfig,
322
+ coverAndFilterOptionInPDF: false,
323
+ } as AppViewConfig);
324
+ appEmbed.render();
325
+ await executeAfterWait(() => {
326
+ expectUrlMatchesWithParams(
327
+ getIFrameSrc(),
328
+ `http://${thoughtSpotHost}/?embedApp=true&profileAndHelpInNavBarHidden=false&arePdfCoverFilterPageCheckboxesEnabled=false${defaultParamsPost}#/home`,
329
+ );
330
+ });
331
+ });
332
+
319
333
  test('should set isLiveboardStylingAndGroupingEnabled to true in url', async () => {
320
334
  const appEmbed = new AppEmbed(getRootEl(), {
321
335
  ...defaultViewConfig,
@@ -611,6 +625,59 @@ describe('App embed tests', () => {
611
625
  });
612
626
  });
613
627
 
628
+ test('Should add listpageVersion=v3 when listPageVersion is ListWithUXChanges to the iframe src', async () => {
629
+ const appEmbed = new AppEmbed(getRootEl(), {
630
+ ...defaultViewConfig,
631
+ discoveryExperience: {
632
+ listPageVersion: ListPage.ListWithUXChanges,
633
+ },
634
+ } as AppViewConfig);
635
+
636
+ appEmbed.render();
637
+ await executeAfterWait(() => {
638
+ expectUrlMatchesWithParams(
639
+ getIFrameSrc(),
640
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&modularHomeExperience=false&listpageVersion=v3${defaultParams}${defaultParamsPost}#/home`,
641
+ );
642
+ });
643
+ });
644
+
645
+ test('Should not add listpageVersion when listPageVersion is List (v2) to the iframe src', async () => {
646
+ const appEmbed = new AppEmbed(getRootEl(), {
647
+ ...defaultViewConfig,
648
+ discoveryExperience: {
649
+ listPageVersion: ListPage.List,
650
+ },
651
+ } as AppViewConfig);
652
+
653
+ appEmbed.render();
654
+ await executeAfterWait(() => {
655
+ expectUrlMatchesWithParams(
656
+ getIFrameSrc(),
657
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&modularHomeExperience=false${defaultParams}${defaultParamsPost}#/home`,
658
+ );
659
+ });
660
+ });
661
+
662
+ test('Should add listpageVersion=v3 combined with other discoveryExperience options to the iframe src', async () => {
663
+ const appEmbed = new AppEmbed(getRootEl(), {
664
+ ...defaultViewConfig,
665
+ discoveryExperience: {
666
+ primaryNavbarVersion: PrimaryNavbarVersion.Sliding,
667
+ homePage: HomePage.Modular,
668
+ listPageVersion: ListPage.ListWithUXChanges,
669
+ },
670
+ } as AppViewConfig);
671
+
672
+ appEmbed.render();
673
+ await executeAfterWait(() => {
674
+ expectUrlMatchesWithParams(
675
+ getIFrameSrc(),
676
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&modularHomeExperience=true&navigationVersion=v3&listpageVersion=v3${defaultParams}${defaultParamsPost}#/home`,
677
+ );
678
+ });
679
+ });
680
+
614
681
  test('Should add enablePendoHelp flag to the iframe src conditional on navbar', async () => {
615
682
  const appEmbed = new AppEmbed(getRootEl(), {
616
683
  ...defaultViewConfig,
@@ -687,7 +754,8 @@ describe('App embed tests', () => {
687
754
  const appEmbed = new AppEmbed(getRootEl(), {
688
755
  ...defaultViewConfig,
689
756
  // eslint-disable-next-line max-len
690
- dataPanelCustomGroupsAccordionInitialState: DataPanelCustomColumnGroupsAccordionState.EXPAND_FIRST,
757
+ dataPanelCustomGroupsAccordionInitialState:
758
+ DataPanelCustomColumnGroupsAccordionState.EXPAND_FIRST,
691
759
  } as AppViewConfig);
692
760
 
693
761
  appEmbed.render();
@@ -700,19 +768,18 @@ describe('App embed tests', () => {
700
768
  });
701
769
 
702
770
  test('should register event handlers to adjust iframe height', async () => {
703
- const onSpy = jest.spyOn(AppEmbed.prototype, 'on')
704
- .mockImplementation((event, callback) => {
705
- if (event === EmbedEvent.RouteChange) {
706
- callback({ data: { currentPath: '/answers' } }, jest.fn());
707
- }
708
- if (event === EmbedEvent.EmbedHeight) {
709
- callback({ data: '100%' });
710
- }
711
- if (event === EmbedEvent.EmbedIframeCenter) {
712
- callback({}, jest.fn());
713
- }
714
- return null;
715
- });
771
+ const onSpy = jest.spyOn(AppEmbed.prototype, 'on').mockImplementation((event, callback) => {
772
+ if (event === EmbedEvent.RouteChange) {
773
+ callback({ data: { currentPath: '/answers' } }, jest.fn());
774
+ }
775
+ if (event === EmbedEvent.EmbedHeight) {
776
+ callback({ data: '100%' });
777
+ }
778
+ if (event === EmbedEvent.EmbedIframeCenter) {
779
+ callback({}, jest.fn());
780
+ }
781
+ return null;
782
+ });
716
783
  jest.spyOn(TsEmbed.prototype as any, 'getIframeCenter').mockReturnValue({});
717
784
  jest.spyOn(TsEmbed.prototype as any, 'setIFrameHeight').mockReturnValue({});
718
785
  const appEmbed = new AppEmbed(getRootEl(), {
package/src/embed/app.ts CHANGED
@@ -109,6 +109,22 @@ export enum HomePage {
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
  *
@@ -588,6 +594,7 @@ export class AppEmbed extends V1Embed {
588
594
  isUnifiedSearchExperienceEnabled = true,
589
595
  enablePendoHelp = true,
590
596
  discoveryExperience,
597
+ coverAndFilterOptionInPDF = false,
591
598
  isLiveboardStylingAndGroupingEnabled,
592
599
  } = this.viewConfig;
593
600
 
@@ -606,6 +613,7 @@ export class AppEmbed extends V1Embed {
606
613
  params[Param.ShowLiveboardReverifyBanner] = showLiveboardReverifyBanner;
607
614
  params[Param.HideIrrelevantFiltersInTab] = hideIrrelevantChipsInLiveboardTabs;
608
615
  params[Param.IsUnifiedSearchExperienceEnabled] = isUnifiedSearchExperienceEnabled;
616
+ params[Param.CoverAndFilterOptionInPDF] = !!coverAndFilterOptionInPDF;
609
617
 
610
618
  params = this.getBaseQueryParams(params);
611
619
 
@@ -696,6 +704,10 @@ export class AppEmbed extends V1Embed {
696
704
  if (discoveryExperience.homePage === HomePage.Modular) {
697
705
  params[Param.ModularHomeExperienceEnabled] = true;
698
706
  }
707
+ // listPageVersion v3 will enable the new list page
708
+ if (discoveryExperience.listPageVersion === ListPage.ListWithUXChanges) {
709
+ params[Param.ListPageVersion] = discoveryExperience.listPageVersion;
710
+ }
699
711
  }
700
712
 
701
713
  const queryParams = getQueryParamString(params, true);
@@ -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,16 @@ 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;
32
+ convId: string;
33
+ messageId: string;
37
34
  }
38
35
 
39
- class ConversationMessage extends TsEmbed {
36
+ export class ConversationMessage extends TsEmbed {
40
37
  constructor(container: HTMLElement, protected viewConfig: SpotterAgentMessageViewConfig) {
41
38
  viewConfig.embedComponentType = 'bodyless-conversation';
42
39
  super(container, viewConfig);
@@ -48,6 +45,8 @@ class ConversationMessage extends TsEmbed {
48
45
  genNo,
49
46
  acSessionId,
50
47
  acGenNo,
48
+ convId,
49
+ messageId,
51
50
  } = this.viewConfig;
52
51
  const path = 'conv-assist-answer';
53
52
  const queryParams = this.getBaseQueryParams();
@@ -64,6 +63,8 @@ class ConversationMessage extends TsEmbed {
64
63
  genNo,
65
64
  acSessionId,
66
65
  acGenNo,
66
+ convId,
67
+ messageId,
67
68
  });
68
69
 
69
70
  return `${this.getEmbedBasePath(query)}/embed/${path}${tsPostHashParams}`;
@@ -116,12 +117,11 @@ export class SpotterAgentEmbed {
116
117
  }
117
118
 
118
119
  const container = document.createElement('div');
119
- if (this.viewConfig.containerClassName) {
120
- container.className = this.viewConfig.containerClassName;
121
- }
122
120
 
123
121
  const embed = new ConversationMessage(container, {
124
122
  ...this.viewConfig,
123
+ convId: data.convId,
124
+ messageId: data.messageId,
125
125
  sessionId: data.sessionId,
126
126
  genNo: data.genNo,
127
127
  acSessionId: data.stateKey.transactionId,
@@ -130,6 +130,30 @@ export class SpotterAgentEmbed {
130
130
  await embed.render();
131
131
  return { container, viz: embed };
132
132
  }
133
+
134
+ /**
135
+ * Send a message to the conversation service and return only the data.
136
+ * @param userMessage - The message to send to the conversation service.
137
+ * @returns The data from the conversation service.
138
+ */
139
+ public async sendMessageData(userMessage: string) {
140
+ try {
141
+ const { data, error } = await this.conversationService.sendMessage(userMessage);
142
+ if (error) {
143
+ return { error };
144
+ }
145
+ return { data: {
146
+ convId: data.convId,
147
+ messageId: data.messageId,
148
+ sessionId: data.sessionId,
149
+ genNo: data.genNo,
150
+ acSessionId: data.stateKey.transactionId,
151
+ acGenNo: data.stateKey.generationNumber,
152
+ } };
153
+ } catch (error) {
154
+ return { error: error as Error };
155
+ }
156
+ }
133
157
  }
134
158
 
135
159
  /**
@@ -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
  });
@@ -10,13 +10,14 @@ const configKey = 'embedConfig';
10
10
  *
11
11
  * @example
12
12
  * ```js
13
+ * import { getInitConfig } from '@thoughtspot/visual-embed-sdk';
14
+ * // Call the getInitConfig method to retrieve the embed configuration
13
15
  * const config = getInitConfig();
16
+ * // Log the configuration settings
14
17
  * console.log(config);
15
18
  * ```
16
- * @example
17
- *
18
- * Returns the `EmbedConfig` object, which
19
- * contains the configuration settings used to
19
+ * Returns the link:https://developers.thoughtspot.com/docs/Interface_EmbedConfig[EmbedConfig]
20
+ * object, which contains the configuration settings used to
20
21
  * initialize the SDK, including the following:
21
22
  *
22
23
  * - `thoughtSpotHost` - ThoughtSpot host URL
@@ -24,10 +25,11 @@ const configKey = 'embedConfig';
24
25
  * `AuthServerCookieless` for `AuthType.TrustedAuthTokenCookieless`
25
26
  * - `customizations` - Style, text, and icon customization settings
26
27
  * that were applied during the SDK initialization.
27
- *
28
- * For a comprehensive list of embed configuration settings,
29
- * see link:https://developers.thoughtspot.com/docs/Interface_EmbedConfig[Developer Documentation].
30
28
  *
29
+ * The following JSON output shows the embed configuration
30
+ * settings returned from the code in the previous example:
31
+ *
32
+ * @example
31
33
  * ```json
32
34
  * {
33
35
  * "thoughtSpotHost": "https://{ThoughtSpot-Host}",
@@ -49,7 +51,7 @@ const configKey = 'embedConfig';
49
51
  * "authTriggerContainer": "#your-own-div"
50
52
  * }
51
53
  * ```
52
- * @version SDK: 1.19.0 | ThoughtSpot: 9.0.0.cl, 9.0.1.cl, and later
54
+ * @version SDK: 1.19.0 | ThoughtSpot: 9.0.0.cl, 9.0.1.sw, and later
53
55
  * @group Global methods
54
56
  */
55
57
  export const getEmbedConfig = (): EmbedConfig => getValueFromWindow(configKey) || ({} as any);