@thoughtspot/visual-embed-sdk 1.50.1 → 1.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/css-variables.d.ts +36 -0
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +106 -14
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +47 -36
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +318 -149
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/conversation.d.ts +204 -1
  11. package/cjs/src/embed/conversation.d.ts.map +1 -1
  12. package/cjs/src/embed/conversation.js +19 -15
  13. package/cjs/src/embed/conversation.js.map +1 -1
  14. package/cjs/src/embed/conversation.spec.js +198 -17
  15. package/cjs/src/embed/conversation.spec.js.map +1 -1
  16. package/cjs/src/embed/events.spec.js +42 -0
  17. package/cjs/src/embed/events.spec.js.map +1 -1
  18. package/cjs/src/embed/host-events.spec.js +45 -0
  19. package/cjs/src/embed/host-events.spec.js.map +1 -1
  20. package/cjs/src/embed/hostEventClient/contracts.d.ts +15 -0
  21. package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  22. package/cjs/src/embed/hostEventClient/contracts.js +1 -0
  23. package/cjs/src/embed/hostEventClient/contracts.js.map +1 -1
  24. package/cjs/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  25. package/cjs/src/embed/hostEventClient/host-event-client.js +1 -0
  26. package/cjs/src/embed/hostEventClient/host-event-client.js.map +1 -1
  27. package/cjs/src/embed/hostEventClient/host-event-client.spec.js +9 -0
  28. package/cjs/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  29. package/cjs/src/embed/liveboard.d.ts +36 -1
  30. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  31. package/cjs/src/embed/liveboard.js +26 -6
  32. package/cjs/src/embed/liveboard.js.map +1 -1
  33. package/cjs/src/embed/liveboard.spec.js +83 -2
  34. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  35. package/cjs/src/embed/spotter-utils.d.ts +8 -1
  36. package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
  37. package/cjs/src/embed/spotter-utils.js +14 -1
  38. package/cjs/src/embed/spotter-utils.js.map +1 -1
  39. package/cjs/src/embed/spotter-utils.spec.js +61 -0
  40. package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
  41. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  42. package/cjs/src/embed/ts-embed.js +15 -0
  43. package/cjs/src/embed/ts-embed.js.map +1 -1
  44. package/cjs/src/index.d.ts +2 -2
  45. package/cjs/src/index.d.ts.map +1 -1
  46. package/cjs/src/index.js.map +1 -1
  47. package/cjs/src/mixpanel-service.d.ts +4 -0
  48. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  49. package/cjs/src/mixpanel-service.js +4 -0
  50. package/cjs/src/mixpanel-service.js.map +1 -1
  51. package/cjs/src/types.d.ts +460 -15
  52. package/cjs/src/types.d.ts.map +1 -1
  53. package/cjs/src/types.js +428 -8
  54. package/cjs/src/types.js.map +1 -1
  55. package/dist/{index-fCne7kmU.js → index-aBzH5ZwF.js} +1 -1
  56. package/dist/src/css-variables.d.ts +36 -0
  57. package/dist/src/css-variables.d.ts.map +1 -1
  58. package/dist/src/embed/app.d.ts +106 -14
  59. package/dist/src/embed/app.d.ts.map +1 -1
  60. package/dist/src/embed/conversation.d.ts +204 -1
  61. package/dist/src/embed/conversation.d.ts.map +1 -1
  62. package/dist/src/embed/hostEventClient/contracts.d.ts +15 -0
  63. package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  64. package/dist/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  65. package/dist/src/embed/liveboard.d.ts +36 -1
  66. package/dist/src/embed/liveboard.d.ts.map +1 -1
  67. package/dist/src/embed/spotter-utils.d.ts +8 -1
  68. package/dist/src/embed/spotter-utils.d.ts.map +1 -1
  69. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  70. package/dist/src/index.d.ts +2 -2
  71. package/dist/src/index.d.ts.map +1 -1
  72. package/dist/src/mixpanel-service.d.ts +4 -0
  73. package/dist/src/mixpanel-service.d.ts.map +1 -1
  74. package/dist/src/types.d.ts +460 -15
  75. package/dist/src/types.d.ts.map +1 -1
  76. package/dist/tsembed-react.es.js +558 -69
  77. package/dist/tsembed-react.js +557 -68
  78. package/dist/tsembed.es.js +556 -68
  79. package/dist/tsembed.js +555 -67
  80. package/dist/visual-embed-sdk-react-full.d.ts +845 -27
  81. package/dist/visual-embed-sdk-react.d.ts +851 -29
  82. package/dist/visual-embed-sdk.d.ts +855 -29
  83. package/lib/package.json +1 -1
  84. package/lib/src/css-variables.d.ts +36 -0
  85. package/lib/src/css-variables.d.ts.map +1 -1
  86. package/lib/src/embed/app.d.ts +106 -14
  87. package/lib/src/embed/app.d.ts.map +1 -1
  88. package/lib/src/embed/app.js +48 -37
  89. package/lib/src/embed/app.js.map +1 -1
  90. package/lib/src/embed/app.spec.js +319 -150
  91. package/lib/src/embed/app.spec.js.map +1 -1
  92. package/lib/src/embed/conversation.d.ts +204 -1
  93. package/lib/src/embed/conversation.d.ts.map +1 -1
  94. package/lib/src/embed/conversation.js +21 -17
  95. package/lib/src/embed/conversation.js.map +1 -1
  96. package/lib/src/embed/conversation.spec.js +198 -17
  97. package/lib/src/embed/conversation.spec.js.map +1 -1
  98. package/lib/src/embed/events.spec.js +42 -0
  99. package/lib/src/embed/events.spec.js.map +1 -1
  100. package/lib/src/embed/host-events.spec.js +45 -0
  101. package/lib/src/embed/host-events.spec.js.map +1 -1
  102. package/lib/src/embed/hostEventClient/contracts.d.ts +15 -0
  103. package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
  104. package/lib/src/embed/hostEventClient/contracts.js +1 -0
  105. package/lib/src/embed/hostEventClient/contracts.js.map +1 -1
  106. package/lib/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
  107. package/lib/src/embed/hostEventClient/host-event-client.js +1 -0
  108. package/lib/src/embed/hostEventClient/host-event-client.js.map +1 -1
  109. package/lib/src/embed/hostEventClient/host-event-client.spec.js +9 -0
  110. package/lib/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
  111. package/lib/src/embed/liveboard.d.ts +36 -1
  112. package/lib/src/embed/liveboard.d.ts.map +1 -1
  113. package/lib/src/embed/liveboard.js +26 -6
  114. package/lib/src/embed/liveboard.js.map +1 -1
  115. package/lib/src/embed/liveboard.spec.js +83 -2
  116. package/lib/src/embed/liveboard.spec.js.map +1 -1
  117. package/lib/src/embed/spotter-utils.d.ts +8 -1
  118. package/lib/src/embed/spotter-utils.d.ts.map +1 -1
  119. package/lib/src/embed/spotter-utils.js +12 -0
  120. package/lib/src/embed/spotter-utils.js.map +1 -1
  121. package/lib/src/embed/spotter-utils.spec.js +62 -1
  122. package/lib/src/embed/spotter-utils.spec.js.map +1 -1
  123. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  124. package/lib/src/embed/ts-embed.js +15 -0
  125. package/lib/src/embed/ts-embed.js.map +1 -1
  126. package/lib/src/index.d.ts +2 -2
  127. package/lib/src/index.d.ts.map +1 -1
  128. package/lib/src/index.js.map +1 -1
  129. package/lib/src/mixpanel-service.d.ts +4 -0
  130. package/lib/src/mixpanel-service.d.ts.map +1 -1
  131. package/lib/src/mixpanel-service.js +4 -0
  132. package/lib/src/mixpanel-service.js.map +1 -1
  133. package/lib/src/types.d.ts +460 -15
  134. package/lib/src/types.d.ts.map +1 -1
  135. package/lib/src/types.js +428 -8
  136. package/lib/src/types.js.map +1 -1
  137. package/lib/src/visual-embed-sdk.d.ts +855 -29
  138. package/package.json +1 -1
  139. package/src/css-variables.ts +45 -0
  140. package/src/embed/app.spec.ts +390 -183
  141. package/src/embed/app.ts +172 -65
  142. package/src/embed/conversation.spec.ts +243 -20
  143. package/src/embed/conversation.ts +233 -17
  144. package/src/embed/events.spec.ts +52 -0
  145. package/src/embed/host-events.spec.ts +70 -0
  146. package/src/embed/hostEventClient/contracts.ts +16 -0
  147. package/src/embed/hostEventClient/host-event-client.spec.ts +12 -0
  148. package/src/embed/hostEventClient/host-event-client.ts +1 -0
  149. package/src/embed/liveboard.spec.ts +108 -2
  150. package/src/embed/liveboard.ts +76 -14
  151. package/src/embed/spotter-utils.spec.ts +68 -1
  152. package/src/embed/spotter-utils.ts +16 -1
  153. package/src/embed/ts-embed.ts +18 -0
  154. package/src/index.ts +2 -1
  155. package/src/mixpanel-service.ts +4 -0
  156. package/src/types.ts +462 -14
@@ -45,6 +45,40 @@ describe('ConversationEmbed', () => {
45
45
  );
46
46
  });
47
47
 
48
+ it('should deep-link to the shared-conversation reader view when sharedConversationId is set', async () => {
49
+ const viewConfig: SpotterEmbedViewConfig = {
50
+ worksheetId: 'worksheetId',
51
+ searchOptions: {
52
+ searchQuery: 'searchQuery',
53
+ },
54
+ sharedConversationId: 'conv-123',
55
+ };
56
+
57
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
58
+ await conversationEmbed.render();
59
+ expectUrlMatchesWithParams(
60
+ getIFrameSrc(),
61
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist/s/conv-123?worksheet=worksheetId&query=searchQuery`,
62
+ );
63
+ });
64
+
65
+ it('should URL-encode the sharedConversationId in the reader-view path', async () => {
66
+ const viewConfig: SpotterEmbedViewConfig = {
67
+ worksheetId: 'worksheetId',
68
+ searchOptions: {
69
+ searchQuery: 'searchQuery',
70
+ },
71
+ sharedConversationId: 'conv/1',
72
+ };
73
+
74
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
75
+ await conversationEmbed.render();
76
+ expectUrlMatchesWithParams(
77
+ getIFrameSrc(),
78
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist/s/conv%2F1?worksheet=worksheetId&query=searchQuery`,
79
+ );
80
+ });
81
+
48
82
  it('should render the conversation embed with worksheets disabled', async () => {
49
83
  const viewConfig: SpotterEmbedViewConfig = {
50
84
  worksheetId: 'worksheetId',
@@ -113,26 +147,6 @@ describe('ConversationEmbed', () => {
113
147
  );
114
148
  });
115
149
 
116
- it('should handle error when worksheetId is not provided', async () => {
117
- const viewConfig: SpotterEmbedViewConfig = {
118
- worksheetId: '',
119
- searchOptions: {
120
- searchQuery: 'searchQuery',
121
- },
122
- };
123
- const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
124
- (conversationEmbed as any).handleError = jest.fn();
125
- await conversationEmbed.render();
126
- expect((conversationEmbed as any).handleError).toHaveBeenCalledWith(
127
- {
128
- errorType: ErrorDetailsTypes.VALIDATION_ERROR,
129
- message: ERROR_MESSAGE.SPOTTER_EMBED_WORKSHEED_ID_NOT_FOUND,
130
- code: EmbedErrorCodes.WORKSHEET_ID_NOT_FOUND,
131
- error: ERROR_MESSAGE.SPOTTER_EMBED_WORKSHEED_ID_NOT_FOUND,
132
- },
133
- );
134
- });
135
-
136
150
  it('should render the conversation embed if data panel v2 flag is true', async () => {
137
151
  const viewConfig: SpotterEmbedViewConfig = {
138
152
  worksheetId: 'worksheetId',
@@ -460,6 +474,38 @@ describe('ConversationEmbed', () => {
460
474
  );
461
475
  });
462
476
 
477
+ it('should render the conversation embed with spotter radiance', async () => {
478
+ const viewConfig: SpotterEmbedViewConfig = {
479
+ worksheetId: 'worksheetId',
480
+ searchOptions: {
481
+ searchQuery: 'searchQuery',
482
+ },
483
+ showSpotterRadiance: true,
484
+ };
485
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
486
+ await conversationEmbed.render();
487
+ expectUrlMatchesWithParams(
488
+ getIFrameSrc(),
489
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&showSpotterRadiance=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
490
+ );
491
+ });
492
+
493
+ it('should render the conversation embed with spotter radiance disabled', async () => {
494
+ const viewConfig: SpotterEmbedViewConfig = {
495
+ worksheetId: 'worksheetId',
496
+ searchOptions: {
497
+ searchQuery: 'searchQuery',
498
+ },
499
+ showSpotterRadiance: false,
500
+ };
501
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
502
+ await conversationEmbed.render();
503
+ expectUrlMatchesWithParams(
504
+ getIFrameSrc(),
505
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&showSpotterRadiance=false#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
506
+ );
507
+ });
508
+
463
509
  it('should render the conversation embed with default query mode set to research', async () => {
464
510
  const viewConfig: SpotterEmbedViewConfig = {
465
511
  worksheetId: 'worksheetId',
@@ -615,6 +661,24 @@ describe('SpotterEmbed APP_INIT embedParams', () => {
615
661
  });
616
662
  });
617
663
 
664
+ it('should forward spotterChatPinConfig nested in spotterSidebarConfig', async () => {
665
+ const spotterChatPinConfig = {
666
+ enabled: true,
667
+ pinLabel: 'Pin to top',
668
+ unpinLabel: 'Unpin',
669
+ };
670
+ const response = await getAppInitResponse({
671
+ worksheetId: 'ws1',
672
+ spotterSidebarConfig: {
673
+ enablePastConversationsSidebar: true,
674
+ spotterChatPinConfig,
675
+ },
676
+ });
677
+ expect(
678
+ response.data.embedParams.spotterSidebarConfig.spotterChatPinConfig,
679
+ ).toEqual(spotterChatPinConfig);
680
+ });
681
+
618
682
  it('should populate enablePastConversationsSidebar from deprecated standalone flag', async () => {
619
683
  const response = await getAppInitResponse({
620
684
  worksheetId: 'ws1',
@@ -697,5 +761,164 @@ describe('SpotterEmbed APP_INIT embedParams', () => {
697
761
  expect(mockPort.postMessage.mock.calls[0]?.[0].data.embedParams?.spotterSidebarConfig?.spotterDocumentationUrl).toBeUndefined();
698
762
  });
699
763
 
764
+ it('should include spotterShareConversationConfig in embedParams when provided', async () => {
765
+ const response = await getAppInitResponse({
766
+ worksheetId: 'ws1',
767
+ spotterShareConversationConfig: { enableShareConversation: true },
768
+ });
769
+ expect(response.data.embedParams.spotterShareConversationConfig).toEqual({
770
+ enableShareConversation: true,
771
+ });
772
+ });
773
+
774
+ it('should pass spotterShareConversationConfig label overrides through embedParams', async () => {
775
+ const spotterShareConversationConfig = {
776
+ enableShareConversation: true,
777
+ spotterShareLabel: 'Share',
778
+ spotterShareModalTitle: 'Share conversation',
779
+ };
780
+ const response = await getAppInitResponse({
781
+ worksheetId: 'ws1',
782
+ spotterShareConversationConfig,
783
+ });
784
+ expect(response.data.embedParams.spotterShareConversationConfig).toEqual(spotterShareConversationConfig);
785
+ });
786
+
787
+ it('should include spotterShareConversationConfig alongside spotterSidebarConfig', async () => {
788
+ const response = await getAppInitResponse({
789
+ worksheetId: 'ws1',
790
+ spotterSidebarConfig: { enablePastConversationsSidebar: true },
791
+ spotterShareConversationConfig: { enableShareConversation: true },
792
+ });
793
+ expect(response.data.embedParams.spotterSidebarConfig.enablePastConversationsSidebar).toBe(true);
794
+ expect(response.data.embedParams.spotterShareConversationConfig.enableShareConversation).toBe(true);
795
+ });
796
+
797
+ it('should not handle error when neither worksheetId nor dataSources is provided', async () => {
798
+ const viewConfig: SpotterEmbedViewConfig = {
799
+ searchOptions: {
800
+ searchQuery: 'searchQuery',
801
+ },
802
+ };
803
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
804
+ (conversationEmbed as any).handleError = jest.fn();
805
+ await conversationEmbed.render();
806
+ expect((conversationEmbed as any).handleError).not.toHaveBeenCalled();
807
+ });
808
+
809
+ it('should not handle error when dataSources is an empty array and worksheetId is not provided', async () => {
810
+ const viewConfig: SpotterEmbedViewConfig = {
811
+ dataSources: [],
812
+ };
813
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
814
+ (conversationEmbed as any).handleError = jest.fn();
815
+ await conversationEmbed.render();
816
+ expect((conversationEmbed as any).handleError).not.toHaveBeenCalled();
817
+ });
818
+
819
+ it('should render without worksheet and dataSources params when neither is provided', async () => {
820
+ const viewConfig: SpotterEmbedViewConfig = {};
821
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
822
+ await conversationEmbed.render();
823
+ const src = getIFrameSrc();
824
+ expect(src).not.toContain('worksheet=');
825
+ expect(src).not.toContain('dataSources=');
826
+ });
827
+
828
+ it('should not append dataSources to the URL when it is an empty array', async () => {
829
+ const viewConfig: SpotterEmbedViewConfig = {
830
+ worksheetId: 'worksheetId',
831
+ dataSources: [],
832
+ };
833
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
834
+ await conversationEmbed.render();
835
+ expect(getIFrameSrc()).not.toContain('dataSources=');
836
+ });
837
+
838
+ it('should not handle error when dataSources is provided but worksheetId is not', async () => {
839
+ const viewConfig: SpotterEmbedViewConfig = {
840
+ worksheetId: '',
841
+ dataSources: ['ds-1', 'ds-2'],
842
+ };
843
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
844
+ (conversationEmbed as any).handleError = jest.fn();
845
+ await conversationEmbed.render();
846
+ expect((conversationEmbed as any).handleError).not.toHaveBeenCalled();
847
+ });
848
+
849
+ it('should render the conversation embed with dataSources and no worksheetId in the hash params', async () => {
850
+ const viewConfig: SpotterEmbedViewConfig = {
851
+ worksheetId: '',
852
+ dataSources: ['ds-1', 'ds-2'],
853
+ };
854
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
855
+ await conversationEmbed.render();
856
+ expectUrlMatchesWithParams(
857
+ getIFrameSrc(),
858
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist?dataSources=${encodeURIComponent(JSON.stringify(['ds-1', 'ds-2']))}`,
859
+ );
860
+ });
861
+
862
+ it('should prefer dataSources over worksheetId when both are provided', async () => {
863
+ const viewConfig: SpotterEmbedViewConfig = {
864
+ worksheetId: 'worksheetId',
865
+ dataSources: ['ds-1', 'ds-2'],
866
+ searchOptions: {
867
+ searchQuery: 'searchQuery',
868
+ },
869
+ };
870
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
871
+ await conversationEmbed.render();
872
+ expectUrlMatchesWithParams(
873
+ getIFrameSrc(),
874
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist?query=searchQuery&dataSources=${encodeURIComponent(JSON.stringify(['ds-1', 'ds-2']))}`,
875
+ );
876
+ });
877
+
878
+ it('should render the conversation embed without searchOptions and worksheetId when neither is set', async () => {
879
+ const viewConfig: SpotterEmbedViewConfig = {
880
+ worksheetId: '',
881
+ dataSources: ['ds-1'],
882
+ };
883
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
884
+ await conversationEmbed.render();
885
+ const src = getIFrameSrc();
886
+ expect(src).not.toContain('worksheet=');
887
+ expect(src).not.toContain('query=');
888
+ });
700
889
  });
701
890
 
891
+
892
+ describe('SpotterEmbed updatedSpotterExperience', () => {
893
+ it('should render the conversation embed with updated spotter experience', async () => {
894
+ const viewConfig: SpotterEmbedViewConfig = {
895
+ worksheetId: 'worksheetId',
896
+ searchOptions: {
897
+ searchQuery: 'searchQuery',
898
+ },
899
+ updatedSpotterExperience: true,
900
+ };
901
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
902
+ await conversationEmbed.render();
903
+ expectUrlMatchesWithParams(
904
+ getIFrameSrc(),
905
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&updatedSpotterExperience=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
906
+ );
907
+ });
908
+
909
+ it('should render the conversation embed with updated spotter experience disabled', async () => {
910
+ const viewConfig: SpotterEmbedViewConfig = {
911
+ worksheetId: 'worksheetId',
912
+ searchOptions: {
913
+ searchQuery: 'searchQuery',
914
+ },
915
+ updatedSpotterExperience: false,
916
+ };
917
+ const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
918
+ await conversationEmbed.render();
919
+ expectUrlMatchesWithParams(
920
+ getIFrameSrc(),
921
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&updatedSpotterExperience=false#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
922
+ );
923
+ });
924
+ });
@@ -1,8 +1,6 @@
1
- import isUndefined from 'lodash/isUndefined';
2
- import { ERROR_MESSAGE } from '../errors';
3
1
  import { Param, BaseViewConfig, RuntimeFilter, RuntimeParameter, ErrorDetailsTypes, EmbedErrorCodes, DefaultAppInitData, VisualizationOverrides, SpotterFileUploadFileTypes } from '../types';
4
2
  import { TsEmbed } from './ts-embed';
5
- import { buildSpotterSidebarAppInitData } from './spotter-utils';
3
+ import { buildSpotterSidebarAppInitData, buildSpotterShareConversationAppInitData } from './spotter-utils';
6
4
  import { getQueryParamString, getFilterQuery, getRuntimeParameters, setParamIfDefined } from '../utils';
7
5
 
8
6
  /**
@@ -24,6 +22,38 @@ export enum SpotterQueryMode {
24
22
  RESEARCH = 'research',
25
23
  }
26
24
 
25
+ /**
26
+ * Configuration for the pin/unpin conversation feature in the Spotter sidebar.
27
+ * Grouped into one object because pin exposes several related settings
28
+ * (enable + label overrides), unlike single-item actions like rename or
29
+ * delete.
30
+ * @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
31
+ */
32
+ export interface SpotterChatPinConfig {
33
+ /**
34
+ * Enables the pin/unpin conversation feature in embedded Spotter. Disabled
35
+ * by default — hosts must opt in. When off, the Pin/Unpin menu entry and
36
+ * the pin glyph are hidden and the PinSpotterConversation /
37
+ * UnpinSpotterConversation host events are no-ops. Native (non-embedded)
38
+ * Spotter is unaffected and ships pin enabled.
39
+ * @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
40
+ * @default false
41
+ */
42
+ enabled?: boolean;
43
+ /**
44
+ * Custom label text for the pin action in the conversation edit menu.
45
+ * Defaults to translated "Pin" text.
46
+ * @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
47
+ */
48
+ pinLabel?: string;
49
+ /**
50
+ * Custom label text for the unpin action in the conversation edit menu.
51
+ * Defaults to translated "Unpin" text.
52
+ * @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
53
+ */
54
+ unpinLabel?: string;
55
+ }
56
+
27
57
  /**
28
58
  * Configuration for the Spotter sidebar.
29
59
  * Can be used in SpotterEmbed and AppEmbed.
@@ -61,6 +91,12 @@ export interface SpotterSidebarViewConfig {
61
91
  * @version SDK: 1.47.0 | ThoughtSpot: 26.4.0.cl
62
92
  */
63
93
  spotterChatDeleteLabel?: string;
94
+ /**
95
+ * Pin/unpin conversation feature config (enable + label overrides).
96
+ * Off by default in embed — hosts opt in via `enabled`.
97
+ * @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
98
+ */
99
+ spotterChatPinConfig?: SpotterChatPinConfig;
64
100
  /**
65
101
  * Custom title text for the delete conversation confirmation modal.
66
102
  * Defaults to translated "Delete chat" text.
@@ -112,6 +148,85 @@ export interface SpotterSidebarViewConfig {
112
148
  spotterAnalystsLabel?: string;
113
149
  }
114
150
 
151
+ /**
152
+ * Configuration for the Spotter conversation sharing feature.
153
+ * Can be used in SpotterEmbed and AppEmbed.
154
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
155
+ * @group Embed components
156
+ */
157
+ export interface SpotterShareConversationConfig {
158
+ /**
159
+ * Enables sharing of the conversation.
160
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
161
+ * @default false
162
+ */
163
+ enableShareConversation?: boolean;
164
+ /**
165
+ * Header Share button + sidebar Share item label.
166
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
167
+ * @default "Share"
168
+ */
169
+ spotterShareLabel?: string;
170
+ /**
171
+ * Share modal title.
172
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
173
+ */
174
+ spotterShareModalTitle?: string;
175
+ /**
176
+ * Modal confirm button label.
177
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
178
+ * @default "Share"
179
+ */
180
+ spotterShareConfirmLabel?: string;
181
+ /**
182
+ * Modal cancel button label.
183
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
184
+ * @default "Cancel"
185
+ */
186
+ spotterShareCancelLabel?: string;
187
+ /**
188
+ * "Add users or groups" label.
189
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
190
+ */
191
+ spotterShareAddUsersLabel?: string;
192
+ /**
193
+ * Empty-state title ("No users added yet").
194
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
195
+ */
196
+ spotterShareEmptyTitle?: string;
197
+ /**
198
+ * Empty-state subtitle ("Not shared with any user").
199
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
200
+ */
201
+ spotterShareEmptySubtitle?: string;
202
+ /**
203
+ * "Include new messages since last shared version" checkbox label.
204
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
205
+ */
206
+ spotterShareIncludeNewMessagesLabel?: string;
207
+ /**
208
+ * Footer note when the snapshot is current ("…up to the current moment…").
209
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
210
+ */
211
+ spotterShareUpToCurrentLabel?: string;
212
+ /**
213
+ * Stale-snapshot info banner text ("All added users and groups will receive…").
214
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
215
+ */
216
+ spotterShareStaleInfoLabel?: string;
217
+ /**
218
+ * Read-only shared-view data-access banner message.
219
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
220
+ */
221
+ spotterSharedConversationBannerMessage?: string;
222
+ /**
223
+ * Read-only shared-view Exit button label.
224
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
225
+ * @default "Exit"
226
+ */
227
+ spotterSharedConversationExitLabel?: string;
228
+ }
229
+
115
230
  /**
116
231
  * Configuration for customizing Spotter chat UI branding.
117
232
  * @version SDK: 1.46.0 | ThoughtSpot: 26.4.0.cl
@@ -167,8 +282,27 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
167
282
  /**
168
283
  * The ID of the data source object. For example, Model, View, or Table. Spotter uses
169
284
  * this object to query data and generate Answers.
285
+ * This field is optional. If not provided, Spotter loads using the
286
+ * previously selected user data source.
170
287
  */
171
- worksheetId: string;
288
+ worksheetId?: string;
289
+ /**
290
+ * The array of data source GUIDs to set on load. Spotter uses
291
+ * these GUIDs to query data and generate Answers.
292
+ * dataSources is preferred over worksheetId if both are provided.
293
+ * The feature is currently behind a feature flag.
294
+ *
295
+ * Supported embed types: `SpotterEmbed`
296
+ * @example
297
+ * ```js
298
+ * const embed = new SpotterEmbed('#tsEmbed', {
299
+ * // ...other embed view config
300
+ * dataSources: ['id-2345', 'id-2345'],
301
+ * });
302
+ * ```
303
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
304
+ */
305
+ dataSources?: string[];
172
306
  /**
173
307
  * Ability to pass a starting search query to the conversation.
174
308
  */
@@ -328,6 +462,21 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
328
462
  * ```
329
463
  */
330
464
  updatedSpotterChatPrompt?: boolean;
465
+ /**
466
+ * showSpotterRadiance : Controls the radiance on the Spotter page.
467
+ *
468
+ * Supported embed types: `SpotterEmbed`
469
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
470
+ * @default false
471
+ * @example
472
+ * ```js
473
+ * const embed = new SpotterEmbed('#tsEmbed', {
474
+ * ... //other embed view config
475
+ * showSpotterRadiance : true,
476
+ * })
477
+ * ```
478
+ */
479
+ showSpotterRadiance?: boolean;
331
480
  /**
332
481
  * Sets the default query mode when Spotter loads — Fast Search or
333
482
  * Research Mode. Applies fresh on every new session for this embed
@@ -404,6 +553,59 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
404
553
  * ```
405
554
  */
406
555
  spotterChatConfig?: SpotterChatViewConfig;
556
+ /**
557
+ * Configuration for the Spotter conversation sharing feature.
558
+ *
559
+ * Supported embed types: `SpotterEmbed`, `AppEmbed`
560
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
561
+ * @example
562
+ * ```js
563
+ * const embed = new SpotterEmbed('#tsEmbed', {
564
+ * ... //other embed view config
565
+ * spotterShareConversationConfig: {
566
+ * enableShareConversation: true,
567
+ * },
568
+ * })
569
+ * ```
570
+ */
571
+ spotterShareConversationConfig?: SpotterShareConversationConfig;
572
+ /**
573
+ * The ID of a shared Spotter conversation to open directly in the read-only
574
+ * reader view. Use this to land a share recipient in the shared conversation
575
+ * when they open a host-configured `CONVERSATION_URL` share link: read the
576
+ * `{conversation-id}` from your page URL and pass it here.
577
+ *
578
+ * Requires the Spotter conversation-sharing feature to be enabled
579
+ * (`spotterShareConversationConfig.enableShareConversation`). The recipient
580
+ * must be an authorized sharee — the server returns access-denied otherwise.
581
+ *
582
+ * Supported embed types: `SpotterEmbed`
583
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
584
+ * @example
585
+ * ```js
586
+ * const convId = new URLSearchParams(window.location.search).get('conversation-id');
587
+ * const embed = new SpotterEmbed('#tsEmbed', {
588
+ * ... //other embed view config
589
+ * sharedConversationId: convId,
590
+ * })
591
+ * ```
592
+ */
593
+ sharedConversationId?: string;
594
+ /**
595
+ * updatedSpotterExperience : Controls the updated Spotter experience.
596
+ *
597
+ * Supported embed types: `SpotterEmbed`
598
+ * @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
599
+ * @default false
600
+ * @example
601
+ * ```js
602
+ * const embed = new SpotterEmbed('#tsEmbed', {
603
+ * ... //other embed view config
604
+ * updatedSpotterExperience : true,
605
+ * })
606
+ * ```
607
+ */
608
+ updatedSpotterExperience?: boolean;
407
609
  }
408
610
 
409
611
  /**
@@ -422,6 +624,7 @@ export interface ConversationViewConfig extends SpotterEmbedViewConfig {}
422
624
  export interface SpotterAppInitData extends DefaultAppInitData {
423
625
  embedParams?: {
424
626
  spotterSidebarConfig?: SpotterSidebarViewConfig;
627
+ spotterShareConversationConfig?: SpotterShareConversationConfig;
425
628
  visualOverridesParams?: VisualizationOverrides | null;
426
629
  };
427
630
  }
@@ -466,16 +669,21 @@ export class SpotterEmbed extends TsEmbed {
466
669
  */
467
670
  protected async getAppInitData(): Promise<SpotterAppInitData> {
468
671
  const defaultAppInitData = await super.getAppInitData();
469
- return buildSpotterSidebarAppInitData(defaultAppInitData, this.viewConfig, this.handleError.bind(this));
672
+ const sidebarInitData = buildSpotterSidebarAppInitData(
673
+ defaultAppInitData,
674
+ this.viewConfig,
675
+ this.handleError.bind(this),
676
+ );
677
+ return buildSpotterShareConversationAppInitData(sidebarInitData, this.viewConfig);
470
678
  }
471
679
 
472
680
  protected getEmbedParamsObject() {
473
681
  const {
474
- worksheetId,
475
682
  searchOptions,
476
683
  disableSourceSelection,
477
684
  hideSourceSelection,
478
685
  dataPanelV2,
686
+ updatedSpotterExperience,
479
687
  showSpotterLimitations,
480
688
  hideSampleQuestions,
481
689
  runtimeFilters,
@@ -483,19 +691,12 @@ export class SpotterEmbed extends TsEmbed {
483
691
  runtimeParameters,
484
692
  excludeRuntimeParametersfromURL,
485
693
  updatedSpotterChatPrompt,
694
+ showSpotterRadiance,
486
695
  defaultQueryMode,
487
696
  enableStopAnswerGenerationEmbed,
488
697
  spotterChatConfig,
489
698
  } = this.viewConfig;
490
699
 
491
- if (!worksheetId) {
492
- this.handleError({
493
- errorType: ErrorDetailsTypes.VALIDATION_ERROR,
494
- message: ERROR_MESSAGE.SPOTTER_EMBED_WORKSHEED_ID_NOT_FOUND,
495
- code: EmbedErrorCodes.WORKSHEET_ID_NOT_FOUND,
496
- error: ERROR_MESSAGE.SPOTTER_EMBED_WORKSHEED_ID_NOT_FOUND,
497
- });
498
- }
499
700
  const queryParams = this.getBaseQueryParams();
500
701
  queryParams[Param.SpotterEnabled] = true;
501
702
 
@@ -506,6 +707,7 @@ export class SpotterEmbed extends TsEmbed {
506
707
  setParamIfDefined(queryParams, Param.ShowSpotterLimitations, showSpotterLimitations, true);
507
708
  setParamIfDefined(queryParams, Param.HideSampleQuestions, hideSampleQuestions, true);
508
709
  setParamIfDefined(queryParams, Param.UpdatedSpotterChatPrompt, updatedSpotterChatPrompt, true);
710
+ setParamIfDefined(queryParams, Param.ShowSpotterRadiance, showSpotterRadiance, true);
509
711
  setParamIfDefined(queryParams, Param.DefaultQueryMode, defaultQueryMode);
510
712
  setParamIfDefined(queryParams, Param.EnableStopAnswerGenerationEmbed, enableStopAnswerGenerationEmbed, true);
511
713
 
@@ -528,6 +730,8 @@ export class SpotterEmbed extends TsEmbed {
528
730
  }
529
731
  }
530
732
 
733
+ setParamIfDefined(queryParams, Param.UpdatedSpotterExperience, updatedSpotterExperience, true);
734
+
531
735
  return queryParams;
532
736
  }
533
737
 
@@ -539,8 +743,16 @@ export class SpotterEmbed extends TsEmbed {
539
743
  excludeRuntimeFiltersfromURL,
540
744
  runtimeParameters,
541
745
  excludeRuntimeParametersfromURL,
746
+ sharedConversationId,
747
+ dataSources,
542
748
  } = this.viewConfig;
543
- const path = 'insights/conv-assist';
749
+ // Deep-link into the read-only shared-conversation reader view when a
750
+ // shared conversation id is supplied (e.g. a recipient landing from a
751
+ // host-configured CONVERSATION_URL share link); otherwise the normal
752
+ // Spotter conversation surface.
753
+ const path = sharedConversationId
754
+ ? `insights/conv-assist/s/${encodeURIComponent(sharedConversationId)}`
755
+ : 'insights/conv-assist';
544
756
  const queryParams = this.getEmbedParamsObject();
545
757
 
546
758
  let query = '';
@@ -560,8 +772,12 @@ export class SpotterEmbed extends TsEmbed {
560
772
  }
561
773
 
562
774
  const tsPostHashParams = this.getThoughtSpotPostUrlParams({
563
- worksheet: worksheetId,
564
- query: searchOptions?.searchQuery || '',
775
+ ...(!(Array.isArray(dataSources) && dataSources.length > 0) && worksheetId
776
+ && { worksheet: worksheetId }),
777
+ ...(searchOptions?.searchQuery && { query: searchOptions.searchQuery }),
778
+ ...(Array.isArray(dataSources)
779
+ && dataSources.length > 0
780
+ && { dataSources: JSON.stringify(dataSources) }),
565
781
  });
566
782
  return `${this.getEmbedBasePath(query)}/embed/${path}${tsPostHashParams}`;
567
783
  }