@thoughtspot/visual-embed-sdk 1.41.0-pre-render-1 → 1.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/README.md +2 -4
  2. package/cjs/package.json +3 -3
  3. package/cjs/src/authToken.d.ts +1 -0
  4. package/cjs/src/authToken.d.ts.map +1 -1
  5. package/cjs/src/authToken.js +13 -3
  6. package/cjs/src/authToken.js.map +1 -1
  7. package/cjs/src/authToken.spec.js +29 -0
  8. package/cjs/src/authToken.spec.js.map +1 -1
  9. package/cjs/src/css-variables.d.ts +2 -1
  10. package/cjs/src/css-variables.d.ts.map +1 -1
  11. package/cjs/src/embed/app.d.ts +22 -1
  12. package/cjs/src/embed/app.d.ts.map +1 -1
  13. package/cjs/src/embed/app.js +22 -1
  14. package/cjs/src/embed/app.js.map +1 -1
  15. package/cjs/src/embed/app.spec.js +70 -3
  16. package/cjs/src/embed/app.spec.js.map +1 -1
  17. package/cjs/src/embed/bodyless-conversation.d.ts +0 -1
  18. package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
  19. package/cjs/src/embed/bodyless-conversation.js +3 -7
  20. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  21. package/cjs/src/embed/conversation.d.ts +2 -3
  22. package/cjs/src/embed/conversation.d.ts.map +1 -1
  23. package/cjs/src/embed/conversation.js +2 -7
  24. package/cjs/src/embed/conversation.js.map +1 -1
  25. package/cjs/src/embed/liveboard.d.ts +32 -1
  26. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  27. package/cjs/src/embed/liveboard.js +8 -25
  28. package/cjs/src/embed/liveboard.js.map +1 -1
  29. package/cjs/src/embed/liveboard.spec.js +96 -28
  30. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  31. package/cjs/src/embed/sage.d.ts +0 -1
  32. package/cjs/src/embed/sage.d.ts.map +1 -1
  33. package/cjs/src/embed/sage.js +6 -10
  34. package/cjs/src/embed/sage.js.map +1 -1
  35. package/cjs/src/embed/sage.spec.js +20 -10
  36. package/cjs/src/embed/sage.spec.js.map +1 -1
  37. package/cjs/src/embed/search-bar.d.ts +0 -1
  38. package/cjs/src/embed/search-bar.d.ts.map +1 -1
  39. package/cjs/src/embed/search-bar.js +7 -11
  40. package/cjs/src/embed/search-bar.js.map +1 -1
  41. package/cjs/src/embed/search.d.ts +0 -1
  42. package/cjs/src/embed/search.d.ts.map +1 -1
  43. package/cjs/src/embed/search.js +8 -7
  44. package/cjs/src/embed/search.js.map +1 -1
  45. package/cjs/src/embed/search.spec.js +10 -10
  46. package/cjs/src/embed/search.spec.js.map +1 -1
  47. package/cjs/src/embed/ts-embed.d.ts +5 -7
  48. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  49. package/cjs/src/embed/ts-embed.js +25 -22
  50. package/cjs/src/embed/ts-embed.js.map +1 -1
  51. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  52. package/cjs/src/embed/ts-embed.spec.js +122 -0
  53. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  54. package/cjs/src/errors.d.ts +11 -0
  55. package/cjs/src/errors.d.ts.map +1 -1
  56. package/cjs/src/errors.js +12 -1
  57. package/cjs/src/errors.js.map +1 -1
  58. package/cjs/src/index.d.ts +2 -2
  59. package/cjs/src/index.d.ts.map +1 -1
  60. package/cjs/src/index.js +3 -1
  61. package/cjs/src/index.js.map +1 -1
  62. package/cjs/src/react/index.d.ts +1 -1
  63. package/cjs/src/react/index.d.ts.map +1 -1
  64. package/cjs/src/react/index.js +4 -2
  65. package/cjs/src/react/index.js.map +1 -1
  66. package/cjs/src/react/index.spec.js +1 -1
  67. package/cjs/src/react/index.spec.js.map +1 -1
  68. package/cjs/src/types.d.ts +163 -21
  69. package/cjs/src/types.d.ts.map +1 -1
  70. package/cjs/src/types.js +65 -22
  71. package/cjs/src/types.js.map +1 -1
  72. package/cjs/src/utils/custom-actions.d.ts +12 -0
  73. package/cjs/src/utils/custom-actions.d.ts.map +1 -0
  74. package/cjs/src/utils/custom-actions.js +180 -0
  75. package/cjs/src/utils/custom-actions.js.map +1 -0
  76. package/cjs/src/utils/custom-actions.spec.d.ts +2 -0
  77. package/cjs/src/utils/custom-actions.spec.d.ts.map +1 -0
  78. package/cjs/src/utils/custom-actions.spec.js +399 -0
  79. package/cjs/src/utils/custom-actions.spec.js.map +1 -0
  80. package/cjs/src/utils/processData.d.ts.map +1 -1
  81. package/cjs/src/utils/processData.js +10 -0
  82. package/cjs/src/utils/processData.js.map +1 -1
  83. package/cjs/src/utils/processData.spec.js +11 -0
  84. package/cjs/src/utils/processData.spec.js.map +1 -1
  85. package/cjs/src/utils.d.ts +21 -0
  86. package/cjs/src/utils.d.ts.map +1 -1
  87. package/cjs/src/utils.js +32 -1
  88. package/cjs/src/utils.js.map +1 -1
  89. package/cjs/src/utils.spec.js +38 -0
  90. package/cjs/src/utils.spec.js.map +1 -1
  91. package/dist/{index-CmEQfuE3.js → index-DQueHwfQ.js} +1 -1
  92. package/dist/src/authToken.d.ts +1 -0
  93. package/dist/src/authToken.d.ts.map +1 -1
  94. package/dist/src/css-variables.d.ts +2 -1
  95. package/dist/src/css-variables.d.ts.map +1 -1
  96. package/dist/src/embed/app.d.ts +22 -1
  97. package/dist/src/embed/app.d.ts.map +1 -1
  98. package/dist/src/embed/bodyless-conversation.d.ts +0 -1
  99. package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
  100. package/dist/src/embed/conversation.d.ts +2 -3
  101. package/dist/src/embed/conversation.d.ts.map +1 -1
  102. package/dist/src/embed/liveboard.d.ts +32 -1
  103. package/dist/src/embed/liveboard.d.ts.map +1 -1
  104. package/dist/src/embed/sage.d.ts +0 -1
  105. package/dist/src/embed/sage.d.ts.map +1 -1
  106. package/dist/src/embed/search-bar.d.ts +0 -1
  107. package/dist/src/embed/search-bar.d.ts.map +1 -1
  108. package/dist/src/embed/search.d.ts +0 -1
  109. package/dist/src/embed/search.d.ts.map +1 -1
  110. package/dist/src/embed/ts-embed.d.ts +5 -7
  111. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  112. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  113. package/dist/src/errors.d.ts +11 -0
  114. package/dist/src/errors.d.ts.map +1 -1
  115. package/dist/src/index.d.ts +2 -2
  116. package/dist/src/index.d.ts.map +1 -1
  117. package/dist/src/react/index.d.ts +1 -1
  118. package/dist/src/react/index.d.ts.map +1 -1
  119. package/dist/src/types.d.ts +163 -21
  120. package/dist/src/types.d.ts.map +1 -1
  121. package/dist/src/utils/custom-actions.d.ts +12 -0
  122. package/dist/src/utils/custom-actions.d.ts.map +1 -0
  123. package/dist/src/utils/custom-actions.spec.d.ts +2 -0
  124. package/dist/src/utils/custom-actions.spec.d.ts.map +1 -0
  125. package/dist/src/utils/processData.d.ts.map +1 -1
  126. package/dist/src/utils.d.ts +21 -0
  127. package/dist/src/utils.d.ts.map +1 -1
  128. package/dist/tsembed-react.es.js +1773 -251
  129. package/dist/tsembed-react.js +1772 -250
  130. package/dist/tsembed.es.js +1771 -250
  131. package/dist/tsembed.js +1770 -249
  132. package/dist/visual-embed-sdk-react-full.d.ts +228 -39
  133. package/dist/visual-embed-sdk-react.d.ts +228 -39
  134. package/dist/visual-embed-sdk.d.ts +228 -39
  135. package/lib/package.json +3 -3
  136. package/lib/src/authToken.d.ts +1 -0
  137. package/lib/src/authToken.d.ts.map +1 -1
  138. package/lib/src/authToken.js +11 -2
  139. package/lib/src/authToken.js.map +1 -1
  140. package/lib/src/authToken.spec.js +30 -1
  141. package/lib/src/authToken.spec.js.map +1 -1
  142. package/lib/src/css-variables.d.ts +2 -1
  143. package/lib/src/css-variables.d.ts.map +1 -1
  144. package/lib/src/embed/app.d.ts +22 -1
  145. package/lib/src/embed/app.d.ts.map +1 -1
  146. package/lib/src/embed/app.js +22 -1
  147. package/lib/src/embed/app.js.map +1 -1
  148. package/lib/src/embed/app.spec.js +70 -3
  149. package/lib/src/embed/app.spec.js.map +1 -1
  150. package/lib/src/embed/bodyless-conversation.d.ts +0 -1
  151. package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
  152. package/lib/src/embed/bodyless-conversation.js +3 -7
  153. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  154. package/lib/src/embed/conversation.d.ts +2 -3
  155. package/lib/src/embed/conversation.d.ts.map +1 -1
  156. package/lib/src/embed/conversation.js +2 -7
  157. package/lib/src/embed/conversation.js.map +1 -1
  158. package/lib/src/embed/liveboard.d.ts +32 -1
  159. package/lib/src/embed/liveboard.d.ts.map +1 -1
  160. package/lib/src/embed/liveboard.js +8 -25
  161. package/lib/src/embed/liveboard.js.map +1 -1
  162. package/lib/src/embed/liveboard.spec.js +96 -28
  163. package/lib/src/embed/liveboard.spec.js.map +1 -1
  164. package/lib/src/embed/sage.d.ts +0 -1
  165. package/lib/src/embed/sage.d.ts.map +1 -1
  166. package/lib/src/embed/sage.js +6 -10
  167. package/lib/src/embed/sage.js.map +1 -1
  168. package/lib/src/embed/sage.spec.js +20 -10
  169. package/lib/src/embed/sage.spec.js.map +1 -1
  170. package/lib/src/embed/search-bar.d.ts +0 -1
  171. package/lib/src/embed/search-bar.d.ts.map +1 -1
  172. package/lib/src/embed/search-bar.js +7 -11
  173. package/lib/src/embed/search-bar.js.map +1 -1
  174. package/lib/src/embed/search.d.ts +0 -1
  175. package/lib/src/embed/search.d.ts.map +1 -1
  176. package/lib/src/embed/search.js +8 -7
  177. package/lib/src/embed/search.js.map +1 -1
  178. package/lib/src/embed/search.spec.js +11 -11
  179. package/lib/src/embed/search.spec.js.map +1 -1
  180. package/lib/src/embed/ts-embed.d.ts +5 -7
  181. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  182. package/lib/src/embed/ts-embed.js +25 -22
  183. package/lib/src/embed/ts-embed.js.map +1 -1
  184. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  185. package/lib/src/embed/ts-embed.spec.js +123 -1
  186. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  187. package/lib/src/errors.d.ts +11 -0
  188. package/lib/src/errors.d.ts.map +1 -1
  189. package/lib/src/errors.js +11 -0
  190. package/lib/src/errors.js.map +1 -1
  191. package/lib/src/index.d.ts +2 -2
  192. package/lib/src/index.d.ts.map +1 -1
  193. package/lib/src/index.js +2 -2
  194. package/lib/src/index.js.map +1 -1
  195. package/lib/src/react/index.d.ts +1 -1
  196. package/lib/src/react/index.d.ts.map +1 -1
  197. package/lib/src/react/index.js +3 -2
  198. package/lib/src/react/index.js.map +1 -1
  199. package/lib/src/react/index.spec.js +1 -1
  200. package/lib/src/react/index.spec.js.map +1 -1
  201. package/lib/src/types.d.ts +163 -21
  202. package/lib/src/types.d.ts.map +1 -1
  203. package/lib/src/types.js +64 -21
  204. package/lib/src/types.js.map +1 -1
  205. package/lib/src/utils/custom-actions.d.ts +12 -0
  206. package/lib/src/utils/custom-actions.d.ts.map +1 -0
  207. package/lib/src/utils/custom-actions.js +175 -0
  208. package/lib/src/utils/custom-actions.js.map +1 -0
  209. package/lib/src/utils/custom-actions.spec.d.ts +2 -0
  210. package/lib/src/utils/custom-actions.spec.d.ts.map +1 -0
  211. package/lib/src/utils/custom-actions.spec.js +397 -0
  212. package/lib/src/utils/custom-actions.spec.js.map +1 -0
  213. package/lib/src/utils/processData.d.ts.map +1 -1
  214. package/lib/src/utils/processData.js +10 -0
  215. package/lib/src/utils/processData.js.map +1 -1
  216. package/lib/src/utils/processData.spec.js +11 -0
  217. package/lib/src/utils/processData.spec.js.map +1 -1
  218. package/lib/src/utils.d.ts +21 -0
  219. package/lib/src/utils.d.ts.map +1 -1
  220. package/lib/src/utils.js +29 -0
  221. package/lib/src/utils.js.map +1 -1
  222. package/lib/src/utils.spec.js +39 -1
  223. package/lib/src/utils.spec.js.map +1 -1
  224. package/lib/src/visual-embed-sdk.d.ts +229 -40
  225. package/package.json +3 -3
  226. package/src/authToken.spec.ts +48 -1
  227. package/src/authToken.ts +13 -2
  228. package/src/css-variables.ts +2 -1
  229. package/src/embed/app.spec.ts +99 -3
  230. package/src/embed/app.ts +44 -1
  231. package/src/embed/bodyless-conversation.ts +3 -8
  232. package/src/embed/conversation.ts +4 -19
  233. package/src/embed/liveboard.spec.ts +128 -30
  234. package/src/embed/liveboard.ts +66 -52
  235. package/src/embed/sage.spec.ts +24 -10
  236. package/src/embed/sage.ts +7 -12
  237. package/src/embed/search-bar.tsx +7 -14
  238. package/src/embed/search.spec.ts +13 -14
  239. package/src/embed/search.ts +8 -19
  240. package/src/embed/ts-embed.spec.ts +136 -2
  241. package/src/embed/ts-embed.ts +31 -28
  242. package/src/errors.ts +12 -0
  243. package/src/index.ts +4 -0
  244. package/src/react/index.spec.tsx +1 -1
  245. package/src/react/index.tsx +5 -2
  246. package/src/types.ts +225 -79
  247. package/src/utils/custom-actions.spec.ts +431 -0
  248. package/src/utils/custom-actions.ts +217 -0
  249. package/src/utils/processData.spec.ts +12 -0
  250. package/src/utils/processData.ts +10 -0
  251. package/src/utils.spec.ts +52 -0
  252. package/src/utils.ts +31 -0
  253. package/dist/index-BDlM0f0T.js +0 -7371
  254. package/dist/index-D1pyb7RG.js +0 -7371
  255. package/dist/index-DeFzsyFF.js +0 -7371
  256. package/dist/index-Dpf0rd6w.js +0 -7371
  257. package/dist/index-UuEbsISo.js +0 -7447
  258. package/dist/index-e3Uw3YFO.js +0 -7371
  259. package/dist/index-k7pkZMhx.js +0 -7371
@@ -1,4 +1,3 @@
1
-
2
1
  import { resetValueFromWindow } from '../utils';
3
2
  import { ERROR_MESSAGE } from '../errors';
4
3
  import { resetCachedAuthToken } from '../authToken';
@@ -27,6 +26,8 @@ import {
27
26
  RuntimeParameter,
28
27
  Param,
29
28
  ContextMenuTriggerOptions,
29
+ CustomActionTarget,
30
+ CustomActionsPosition,
30
31
  } from '../types';
31
32
  import {
32
33
  executeAfterWait,
@@ -346,6 +347,7 @@ describe('Unit test case for ts embed', () => {
346
347
  hiddenHomeLeftNavItems: [],
347
348
  hiddenHomepageModules: [],
348
349
  hiddenListColumns: [],
350
+ customActions: [],
349
351
  hostConfig: undefined,
350
352
  reorderedHomepageModules: [],
351
353
  customVariablesForThirdPartyTools,
@@ -382,6 +384,7 @@ describe('Unit test case for ts embed', () => {
382
384
  hiddenHomeLeftNavItems: [],
383
385
  hiddenHomepageModules: [],
384
386
  hiddenListColumns: [],
387
+ customActions: [],
385
388
  hostConfig: undefined,
386
389
  reorderedHomepageModules: [],
387
390
  customVariablesForThirdPartyTools,
@@ -424,6 +427,7 @@ describe('Unit test case for ts embed', () => {
424
427
  hiddenHomeLeftNavItems: [],
425
428
  hiddenHomepageModules: [HomepageModule.MyLibrary, HomepageModule.Learning],
426
429
  hiddenListColumns: [],
430
+ customActions: [],
427
431
  reorderedHomepageModules: [],
428
432
  customVariablesForThirdPartyTools,
429
433
  },
@@ -462,6 +466,7 @@ describe('Unit test case for ts embed', () => {
462
466
  hiddenHomeLeftNavItems: [],
463
467
  hiddenHomepageModules: [],
464
468
  hiddenListColumns: [],
469
+ customActions: [],
465
470
  reorderedHomepageModules: [],
466
471
  customVariablesForThirdPartyTools,
467
472
  },
@@ -503,6 +508,7 @@ describe('Unit test case for ts embed', () => {
503
508
  hiddenHomeLeftNavItems: [],
504
509
  hiddenHomepageModules: [],
505
510
  hiddenListColumns: [],
511
+ customActions: [],
506
512
  reorderedHomepageModules:
507
513
  [HomepageModule.MyLibrary, HomepageModule.Watchlist],
508
514
  customVariablesForThirdPartyTools,
@@ -547,6 +553,7 @@ describe('Unit test case for ts embed', () => {
547
553
  hiddenHomeLeftNavItems: [],
548
554
  hiddenHomepageModules: [],
549
555
  hiddenListColumns: [],
556
+ customActions: [],
550
557
  hostConfig: undefined,
551
558
  reorderedHomepageModules: [],
552
559
  customVariablesForThirdPartyTools,
@@ -592,6 +599,7 @@ describe('Unit test case for ts embed', () => {
592
599
  hiddenHomeLeftNavItems: [],
593
600
  hiddenHomepageModules: [],
594
601
  hiddenListColumns: [],
602
+ customActions: [],
595
603
  hostConfig: undefined,
596
604
  reorderedHomepageModules: [],
597
605
  customVariablesForThirdPartyTools,
@@ -636,6 +644,7 @@ describe('Unit test case for ts embed', () => {
636
644
  hiddenHomeLeftNavItems: [],
637
645
  hiddenHomepageModules: [],
638
646
  hiddenListColumns: [],
647
+ customActions: [],
639
648
  hostConfig: undefined,
640
649
  reorderedHomepageModules: [],
641
650
  customVariablesForThirdPartyTools,
@@ -681,6 +690,7 @@ describe('Unit test case for ts embed', () => {
681
690
  hiddenHomeLeftNavItems: [],
682
691
  hiddenHomepageModules: [],
683
692
  hiddenListColumns: [],
693
+ customActions: [],
684
694
  hostConfig: undefined,
685
695
  reorderedHomepageModules: [],
686
696
  customVariablesForThirdPartyTools,
@@ -725,6 +735,7 @@ describe('Unit test case for ts embed', () => {
725
735
  [HomeLeftNavItem.Home, HomeLeftNavItem.MonitorSubscription],
726
736
  hiddenHomepageModules: [],
727
737
  hiddenListColumns: [],
738
+ customActions: [],
728
739
  reorderedHomepageModules: [],
729
740
  customVariablesForThirdPartyTools,
730
741
  },
@@ -893,6 +904,7 @@ describe('Unit test case for ts embed', () => {
893
904
  hiddenHomeLeftNavItems: [],
894
905
  hiddenHomepageModules: [],
895
906
  hiddenListColumns: [],
907
+ customActions: [],
896
908
  hostConfig: undefined,
897
909
  reorderedHomepageModules: [],
898
910
  customVariablesForThirdPartyTools: {},
@@ -977,6 +989,7 @@ describe('Unit test case for ts embed', () => {
977
989
  hiddenHomeLeftNavItems: [],
978
990
  hiddenHomepageModules: [],
979
991
  hiddenListColumns: [],
992
+ customActions: [],
980
993
  hostConfig: undefined,
981
994
  reorderedHomepageModules: [],
982
995
  customVariablesForThirdPartyTools: {},
@@ -1011,6 +1024,127 @@ describe('Unit test case for ts embed', () => {
1011
1024
  });
1012
1025
  });
1013
1026
 
1027
+ describe('getDefaultAppInitData with CustomActionsValidationResult', () => {
1028
+ beforeEach(() => {
1029
+ jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
1030
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValue(true);
1031
+ init({
1032
+ thoughtSpotHost: 'tshost',
1033
+ authType: AuthType.TrustedAuthTokenCookieless,
1034
+ getAuthToken: () => Promise.resolve('test_auth_token1'),
1035
+ });
1036
+ });
1037
+
1038
+ afterEach(() => {
1039
+ baseInstance.reset();
1040
+ jest.clearAllMocks();
1041
+ });
1042
+
1043
+ test('should handle valid custom actions and sort them by name in getDefaultAppInitData', async () => {
1044
+ const mockEmbedEventPayload = {
1045
+ type: EmbedEvent.APP_INIT,
1046
+ data: {},
1047
+ };
1048
+
1049
+ // Create a SearchEmbed with valid custom actions to test
1050
+ // CustomActionsValidationResult
1051
+ const searchEmbed = new SearchEmbed(getRootEl(), {
1052
+ ...defaultViewConfig,
1053
+ customActions: [
1054
+ {
1055
+ id: 'action1',
1056
+ name: 'Valid Action',
1057
+ target: CustomActionTarget.LIVEBOARD,
1058
+ position: CustomActionsPosition.PRIMARY,
1059
+ metadataIds: { liveboardIds: ['lb123'] }
1060
+ },
1061
+ {
1062
+ id: 'action2',
1063
+ name: 'Another Valid Action',
1064
+ target: CustomActionTarget.VIZ,
1065
+ position: CustomActionsPosition.MENU,
1066
+ metadataIds: { vizIds: ['viz456'] }
1067
+ }
1068
+ ]
1069
+ });
1070
+
1071
+ searchEmbed.render();
1072
+ const mockPort: any = {
1073
+ postMessage: jest.fn(),
1074
+ };
1075
+
1076
+ await executeAfterWait(() => {
1077
+ const iframe = getIFrameEl();
1078
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
1079
+ });
1080
+
1081
+ await executeAfterWait(() => {
1082
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
1083
+ type: EmbedEvent.APP_INIT,
1084
+ data: {
1085
+ customisations: {
1086
+ content: {},
1087
+ style: {
1088
+ customCSS: {},
1089
+ customCSSUrl: undefined,
1090
+ },
1091
+ },
1092
+ authToken: 'test_auth_token1',
1093
+ runtimeFilterParams: null,
1094
+ runtimeParameterParams: null,
1095
+ hiddenHomeLeftNavItems: [],
1096
+ hiddenHomepageModules: [],
1097
+ hiddenListColumns: [],
1098
+ customActions: [
1099
+ {
1100
+ id: 'action2',
1101
+ name: 'Another Valid Action',
1102
+ target: CustomActionTarget.VIZ,
1103
+ position: CustomActionsPosition.MENU,
1104
+ metadataIds: { vizIds: ['viz456'] }
1105
+ },
1106
+ {
1107
+ id: 'action1',
1108
+ name: 'Valid Action',
1109
+ target: CustomActionTarget.LIVEBOARD,
1110
+ position: CustomActionsPosition.PRIMARY,
1111
+ metadataIds: { liveboardIds: ['lb123'] }
1112
+ }
1113
+ ], // Actions should be sorted by name
1114
+ hostConfig: undefined,
1115
+ reorderedHomepageModules: [],
1116
+ customVariablesForThirdPartyTools: {},
1117
+ },
1118
+ });
1119
+
1120
+ // Verify that CustomActionsValidationResult structure is
1121
+ // correct
1122
+ const appInitData = mockPort.postMessage.mock.calls[0][0].data;
1123
+ expect(appInitData.customActions).toHaveLength(2);
1124
+ expect(appInitData.customActions).toEqual(
1125
+ expect.arrayContaining([
1126
+ expect.objectContaining({
1127
+ id: 'action1',
1128
+ name: 'Valid Action',
1129
+ target: CustomActionTarget.LIVEBOARD,
1130
+ position: CustomActionsPosition.PRIMARY
1131
+ }),
1132
+ expect.objectContaining({
1133
+ id: 'action2',
1134
+ name: 'Another Valid Action',
1135
+ target: CustomActionTarget.VIZ,
1136
+ position: CustomActionsPosition.MENU
1137
+ })
1138
+ ])
1139
+ );
1140
+
1141
+ // Verify actions are sorted by name (alphabetically)
1142
+ expect(appInitData.customActions[0].name).toBe('Another Valid Action');
1143
+ expect(appInitData.customActions[1].name).toBe('Valid Action');
1144
+ });
1145
+ });
1146
+ });
1147
+
1014
1148
  describe('Token fetch fails in cookieless authentication authType', () => {
1015
1149
  beforeEach(() => {
1016
1150
  jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
@@ -2354,7 +2488,7 @@ describe('Unit test case for ts embed', () => {
2354
2488
  });
2355
2489
 
2356
2490
  afterAll((): void => {
2357
- window.location = location as any;
2491
+ window.location = location;
2358
2492
  });
2359
2493
 
2360
2494
  it('get url params for TS', () => {
@@ -35,6 +35,7 @@ import {
35
35
  removeStyleProperties,
36
36
  isUndefined,
37
37
  } from '../utils';
38
+ import { getCustomActions } from '../utils/custom-actions';
38
39
  import {
39
40
  getThoughtSpotHost,
40
41
  URL_MAX_LENGTH,
@@ -198,11 +199,11 @@ export class TsEmbed {
198
199
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, {
199
200
  ...viewConfig,
200
201
  });
201
- const embedConfig = getEmbedConfig();
202
- this.embedConfig = embedConfig;
203
-
204
202
  this.hostEventClient = new HostEventClient(this.iFrame);
203
+
205
204
  this.isReadyForRenderPromise = getInitPromise().then(async () => {
205
+ const embedConfig = getEmbedConfig();
206
+ this.embedConfig = embedConfig;
206
207
  if (!embedConfig.authTriggerContainer && !embedConfig.useEventForSAMLPopup) {
207
208
  this.embedConfig.authTriggerContainer = domSelector;
208
209
  }
@@ -380,6 +381,16 @@ export class TsEmbed {
380
381
 
381
382
  protected async getDefaultAppInitData(): Promise<DefaultAppInitData> {
382
383
  const authToken = await this.getAuthTokenForCookielessInit();
384
+ const customActionsResult = getCustomActions([
385
+ ...(this.viewConfig.customActions || []),
386
+ ...(this.embedConfig.customActions || [])
387
+ ]);
388
+ if (customActionsResult.errors.length > 0) {
389
+ this.handleError({
390
+ type: 'CUSTOM_ACTION_VALIDATION',
391
+ message: customActionsResult.errors,
392
+ });
393
+ }
383
394
  return {
384
395
  customisations: getCustomisations(this.embedConfig, this.viewConfig),
385
396
  authToken,
@@ -398,6 +409,7 @@ export class TsEmbed {
398
409
  customVariablesForThirdPartyTools:
399
410
  this.embedConfig.customVariablesForThirdPartyTools || {},
400
411
  hiddenListColumns: this.viewConfig.hiddenListColumns || [],
412
+ customActions: customActionsResult.actions,
401
413
  };
402
414
  }
403
415
 
@@ -482,10 +494,10 @@ export class TsEmbed {
482
494
  this.on(EmbedEvent.APP_INIT, this.appInitCb, { start: false }, true);
483
495
  this.on(EmbedEvent.AuthExpire, this.updateAuthToken, { start: false }, true);
484
496
  this.on(EmbedEvent.IdleSessionTimeout, this.idleSessionTimeout, { start: false }, true);
485
-
486
- const embedListenerReadyHandler = this.createEmbedContainerHandler(EmbedEvent.EmbedListenerReady);
497
+
498
+ const embedListenerReadyHandler = this.createEmbedContainerHandler(EmbedEvent.EmbedListenerReady);
487
499
  this.on(EmbedEvent.EmbedListenerReady, embedListenerReadyHandler, { start: false }, true);
488
-
500
+
489
501
  const authInitHandler = this.createEmbedContainerHandler(EmbedEvent.AuthInit);
490
502
  this.on(EmbedEvent.AuthInit, authInitHandler, { start: false }, true);
491
503
  };
@@ -508,12 +520,6 @@ export class TsEmbed {
508
520
  return `${basePath}#`;
509
521
  }
510
522
 
511
- protected getUpdateEmbedParamsObject() {
512
- let queryParams = this.getEmbedParamsObject();
513
- queryParams = { ...this.viewConfig, ...queryParams };
514
- return queryParams;
515
- }
516
-
517
523
  /**
518
524
  * Common query params set for all the embed modes.
519
525
  * @param queryParams
@@ -696,15 +702,10 @@ export class TsEmbed {
696
702
  }
697
703
 
698
704
  protected getEmbedParams() {
699
- const queryParams = this.getEmbedParamsObject();
705
+ const queryParams = this.getBaseQueryParams();
700
706
  return getQueryParamString(queryParams);
701
707
  }
702
708
 
703
- protected getEmbedParamsObject() {
704
- const params = this.getBaseQueryParams();
705
- return params;
706
- }
707
-
708
709
  protected getRootIframeSrc() {
709
710
  const query = this.getEmbedParams();
710
711
  return this.getEmbedBasePath(query);
@@ -1139,12 +1140,12 @@ export class TsEmbed {
1139
1140
  }
1140
1141
  }
1141
1142
 
1142
- /**
1143
+ /**
1143
1144
  * @hidden
1144
1145
  * Internal state to track if the embed container is loaded.
1145
1146
  * This is used to trigger events after the embed container is loaded.
1146
1147
  */
1147
- public isEmbedContainerLoaded = false;
1148
+ public isEmbedContainerLoaded = false;
1148
1149
 
1149
1150
  /**
1150
1151
  * @hidden
@@ -1190,7 +1191,7 @@ export class TsEmbed {
1190
1191
  } else {
1191
1192
  logger.debug('pushing callback to embedContainerReadyCallbacks', callback);
1192
1193
  this.embedContainerReadyCallbacks.push(callback);
1193
- }
1194
+ }
1194
1195
  }
1195
1196
 
1196
1197
  protected createEmbedContainerHandler = (source: EmbedEvent.AuthInit | EmbedEvent.EmbedListenerReady) => () => {
@@ -1278,13 +1279,19 @@ export class TsEmbed {
1278
1279
  * Creates the preRender shell
1279
1280
  * @param showPreRenderByDefault - Show the preRender after render, hidden by default
1280
1281
  */
1281
- public async preRender(showPreRenderByDefault = false): Promise<TsEmbed> {
1282
+ public async preRender(showPreRenderByDefault = false, replaceExistingPreRender = false): Promise<TsEmbed> {
1282
1283
  if (!this.viewConfig.preRenderId) {
1283
1284
  logger.error(ERROR_MESSAGE.PRERENDER_ID_MISSING);
1284
1285
  return this;
1285
1286
  }
1286
1287
  this.isPreRendered = true;
1287
1288
  this.showPreRenderByDefault = showPreRenderByDefault;
1289
+
1290
+ const isAlreadyRendered = this.connectPreRendered();
1291
+ if (isAlreadyRendered && !replaceExistingPreRender) {
1292
+ return this;
1293
+ }
1294
+
1288
1295
  return this.handleRenderForPrerender();
1289
1296
  }
1290
1297
 
@@ -1406,14 +1413,8 @@ export class TsEmbed {
1406
1413
  return this.preRender(true);
1407
1414
  }
1408
1415
  this.validatePreRenderViewConfig(this.viewConfig);
1409
- logger.debug('triggering UpdateEmbedParams', this.viewConfig);
1410
- this.executeAfterEmbedContainerLoaded(() => {
1411
- this.trigger(HostEvent.UpdateEmbedParams, this.getUpdateEmbedParamsObject());
1412
- });
1413
1416
  }
1414
1417
 
1415
- this.beforePrerenderVisible();
1416
-
1417
1418
  if (this.el) {
1418
1419
  this.syncPreRenderStyle();
1419
1420
  if (!this.viewConfig.doNotTrackPreRenderSize) {
@@ -1431,6 +1432,8 @@ export class TsEmbed {
1431
1432
  }
1432
1433
  }
1433
1434
 
1435
+ this.beforePrerenderVisible();
1436
+
1434
1437
  removeStyleProperties(this.preRenderWrapper, ['z-index', 'opacity', 'pointer-events']);
1435
1438
 
1436
1439
  this.subscribeToEvents();
package/src/errors.ts CHANGED
@@ -10,6 +10,7 @@ export const ERROR_MESSAGE = {
10
10
  SDK_NOT_INITIALIZED: 'SDK not initialized',
11
11
  SESSION_INFO_FAILED: 'Failed to get session information',
12
12
  INVALID_TOKEN_ERROR: 'Received invalid token from getAuthToken callback or authToken endpoint.',
13
+ INVALID_TOKEN_TYPE_ERROR: 'Expected getAuthToken to return a string, but received a {invalidType}.',
13
14
  MIXPANEL_TOKEN_NOT_FOUND: 'Mixpanel token not found in session info',
14
15
  PRERENDER_ID_MISSING: 'PreRender ID is required for preRender',
15
16
  SYNC_STYLE_CALLED_BEFORE_RENDER: 'PreRender should be called before using syncPreRenderStyle',
@@ -19,3 +20,14 @@ export const ERROR_MESSAGE = {
19
20
  RENDER_CALLED_BEFORE_INIT: 'Looks like render was called before calling init, the render won\'t start until init is called.\nFor more info check\n1. https://developers.thoughtspot.com/docs/Function_init#_init\n2.https://developers.thoughtspot.com/docs/getting-started#initSdk',
20
21
  SPOTTER_AGENT_NOT_INITIALIZED: 'SpotterAgent not initialized',
21
22
  };
23
+
24
+ export const CUSTOM_ACTIONS_ERROR_MESSAGE = {
25
+ INVALID_ACTION_OBJECT: 'Custom Action Validation Error: Invalid action object provided',
26
+ MISSING_REQUIRED_FIELDS: (id: string, missingFields: string[]) => `Custom Action Validation Error for '${id}': Missing required fields: ${missingFields.join(', ')}`,
27
+ UNSUPPORTED_TARGET: (id: string, targetType: string) => `Custom Action Validation Error for '${id}': Target type '${targetType}' is not supported`,
28
+ INVALID_POSITION: (position: string, targetType: string, supportedPositions: string) => `Position '${position}' is not supported for ${targetType.toLowerCase()}-level custom actions. Supported positions: ${supportedPositions}`,
29
+ INVALID_METADATA_IDS: (targetType: string, invalidIds: string[], supportedIds: string) => `Invalid metadata IDs for ${targetType.toLowerCase()}-level custom actions: ${invalidIds.join(', ')}. Supported metadata IDs: ${supportedIds}`,
30
+ INVALID_DATA_MODEL_IDS: (targetType: string, invalidIds: string[], supportedIds: string) => `Invalid data model IDs for ${targetType.toLowerCase()}-level custom actions: ${invalidIds.join(', ')}. Supported data model IDs: ${supportedIds}`,
31
+ INVALID_FIELDS: (targetType: string, invalidFields: string[], supportedFields: string) => `Invalid fields for ${targetType.toLowerCase()}-level custom actions: ${invalidFields.join(', ')}. Supported fields: ${supportedFields}`,
32
+ DUPLICATE_IDS: (id: string, duplicateNames: string[], keptName: string) => `Duplicate custom action ID '${id}' found. Actions with names '${duplicateNames.join("', '")}' will be ignored. Keeping '${keptName}'.`,
33
+ };
package/src/index.ts CHANGED
@@ -62,6 +62,8 @@ import {
62
62
  VizPoint,
63
63
  CustomActionPayload,
64
64
  ListPageColumns,
65
+ CustomActionsPosition,
66
+ CustomActionTarget,
65
67
  } from './types';
66
68
  import { CustomCssVariables } from './css-variables';
67
69
  import { SageEmbed, SageViewConfig } from './embed/sage';
@@ -148,6 +150,8 @@ export {
148
150
  UIPassthroughEvent,
149
151
  ListPageColumns,
150
152
  DataPanelCustomColumnGroupsAccordionState,
153
+ CustomActionsPosition,
154
+ CustomActionTarget,
151
155
  };
152
156
 
153
157
  export { resetCachedAuthToken } from './authToken';
@@ -56,7 +56,7 @@ describe('React Components', () => {
56
56
  ),
57
57
  ).toBe(true);
58
58
  expect(getIFrameSrc(container)).toBe(
59
- `http://${thoughtSpotHost}/?embedApp=true&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&authType=None&blockNonEmbedFullAppAccess=true&hideAction=[%22${Action.ReportError}%22,%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&preAuthCache=true&overrideConsoleLogs=true&clientLogLevel=ERROR&enableDataPanelV2=false&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true&collapseSearchBarInitially=true&enableCustomColumnGroups=false&dataPanelCustomGroupsAccordionInitialState=EXPAND_ALL#/embed/answer`,
59
+ `http://${thoughtSpotHost}/?embedApp=true&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&authType=None&blockNonEmbedFullAppAccess=true&hideAction=[%22${Action.ReportError}%22,%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&preAuthCache=true&overrideConsoleLogs=true&clientLogLevel=ERROR&enableDataPanelV2=true&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true&collapseSearchBarInitially=true&enableCustomColumnGroups=false&dataPanelCustomGroupsAccordionInitialState=EXPAND_ALL#/embed/answer`,
60
60
  );
61
61
  });
62
62
 
@@ -94,10 +94,12 @@ const componentFactory = <T extends typeof TsEmbed, U extends EmbedProps, V exte
94
94
  };
95
95
  }, [viewConfig, listeners]);
96
96
 
97
+ const preRenderStyles = isPreRenderedComponent ? { display: 'none' } : {};
98
+
97
99
  return viewConfig.insertAsSibling ? (
98
- <span data-testid="tsEmbed" ref={ref} style={{ position: 'absolute' }}></span>
100
+ <span data-testid="tsEmbed" ref={ref} style={{ position: 'absolute', ...preRenderStyles }}></span>
99
101
  ) : (
100
- <div data-testid="tsEmbed" ref={ref} style={style} className={`ts-embed-container ${className}`}></div>
102
+ <div data-testid="tsEmbed" ref={ref} style={{ ...style, ...preRenderStyles }} className={`ts-embed-container ${className}`}></div>
101
103
  );
102
104
  },
103
105
  );
@@ -600,4 +602,5 @@ export {
600
602
  LogLevel,
601
603
  getSessionInfo,
602
604
  ListPageColumns,
605
+ CustomActionsPosition,
603
606
  } from '../index';