@thoughtspot/visual-embed-sdk 1.47.2 → 1.48.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 (190) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/auth.d.ts.map +1 -1
  3. package/cjs/src/auth.js +11 -1
  4. package/cjs/src/auth.js.map +1 -1
  5. package/cjs/src/auth.spec.js +38 -0
  6. package/cjs/src/auth.spec.js.map +1 -1
  7. package/cjs/src/authToken.d.ts +2 -0
  8. package/cjs/src/authToken.d.ts.map +1 -1
  9. package/cjs/src/authToken.js +7 -5
  10. package/cjs/src/authToken.js.map +1 -1
  11. package/cjs/src/embed/app.d.ts +7 -2
  12. package/cjs/src/embed/app.d.ts.map +1 -1
  13. package/cjs/src/embed/app.js +4 -1
  14. package/cjs/src/embed/app.js.map +1 -1
  15. package/cjs/src/embed/app.spec.js +121 -0
  16. package/cjs/src/embed/app.spec.js.map +1 -1
  17. package/cjs/src/embed/conversation.d.ts +2 -1
  18. package/cjs/src/embed/conversation.d.ts.map +1 -1
  19. package/cjs/src/embed/conversation.js.map +1 -1
  20. package/cjs/src/embed/liveboard.d.ts +1 -1
  21. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  22. package/cjs/src/embed/liveboard.js +4 -1
  23. package/cjs/src/embed/liveboard.js.map +1 -1
  24. package/cjs/src/embed/liveboard.spec.js +32 -0
  25. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  26. package/cjs/src/embed/search.d.ts +24 -1
  27. package/cjs/src/embed/search.d.ts.map +1 -1
  28. package/cjs/src/embed/search.js +15 -2
  29. package/cjs/src/embed/search.js.map +1 -1
  30. package/cjs/src/embed/search.spec.js +99 -0
  31. package/cjs/src/embed/search.spec.js.map +1 -1
  32. package/cjs/src/embed/spotter-utils.d.ts +3 -0
  33. package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
  34. package/cjs/src/embed/spotter-utils.js +11 -3
  35. package/cjs/src/embed/spotter-utils.js.map +1 -1
  36. package/cjs/src/embed/spotter-utils.spec.js +51 -0
  37. package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
  38. package/cjs/src/embed/ts-embed.d.ts +1 -0
  39. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  40. package/cjs/src/embed/ts-embed.js +17 -5
  41. package/cjs/src/embed/ts-embed.js.map +1 -1
  42. package/cjs/src/embed/ts-embed.spec.js +168 -0
  43. package/cjs/src/embed/ts-embed.spec.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 +8 -1
  47. package/cjs/src/index.js.map +1 -1
  48. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  49. package/cjs/src/mixpanel-service.js +2 -0
  50. package/cjs/src/mixpanel-service.js.map +1 -1
  51. package/cjs/src/mixpanel-service.spec.js +2 -0
  52. package/cjs/src/mixpanel-service.spec.js.map +1 -1
  53. package/cjs/src/test/test-utils.d.ts +1 -0
  54. package/cjs/src/test/test-utils.d.ts.map +1 -1
  55. package/cjs/src/test/test-utils.js +26 -1
  56. package/cjs/src/test/test-utils.js.map +1 -1
  57. package/cjs/src/tokenizedFetch.d.ts.map +1 -1
  58. package/cjs/src/tokenizedFetch.js +12 -9
  59. package/cjs/src/tokenizedFetch.js.map +1 -1
  60. package/cjs/src/tokenizedFetch.spec.d.ts +2 -0
  61. package/cjs/src/tokenizedFetch.spec.d.ts.map +1 -0
  62. package/cjs/src/tokenizedFetch.spec.js +68 -0
  63. package/cjs/src/tokenizedFetch.spec.js.map +1 -0
  64. package/cjs/src/types.d.ts +466 -13
  65. package/cjs/src/types.d.ts.map +1 -1
  66. package/cjs/src/types.js +149 -5
  67. package/cjs/src/types.js.map +1 -1
  68. package/dist/{index-CFZ7RDZ9.js → index-Ck-r09gt.js} +1 -1
  69. package/dist/src/auth.d.ts.map +1 -1
  70. package/dist/src/authToken.d.ts +2 -0
  71. package/dist/src/authToken.d.ts.map +1 -1
  72. package/dist/src/embed/app.d.ts +7 -2
  73. package/dist/src/embed/app.d.ts.map +1 -1
  74. package/dist/src/embed/conversation.d.ts +2 -1
  75. package/dist/src/embed/conversation.d.ts.map +1 -1
  76. package/dist/src/embed/liveboard.d.ts +1 -1
  77. package/dist/src/embed/liveboard.d.ts.map +1 -1
  78. package/dist/src/embed/search.d.ts +24 -1
  79. package/dist/src/embed/search.d.ts.map +1 -1
  80. package/dist/src/embed/spotter-utils.d.ts +3 -0
  81. package/dist/src/embed/spotter-utils.d.ts.map +1 -1
  82. package/dist/src/embed/ts-embed.d.ts +1 -0
  83. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  84. package/dist/src/index.d.ts +2 -2
  85. package/dist/src/index.d.ts.map +1 -1
  86. package/dist/src/mixpanel-service.d.ts.map +1 -1
  87. package/dist/src/test/test-utils.d.ts +1 -0
  88. package/dist/src/test/test-utils.d.ts.map +1 -1
  89. package/dist/src/tokenizedFetch.d.ts.map +1 -1
  90. package/dist/src/tokenizedFetch.spec.d.ts +2 -0
  91. package/dist/src/tokenizedFetch.spec.d.ts.map +1 -0
  92. package/dist/src/types.d.ts +466 -13
  93. package/dist/src/types.d.ts.map +1 -1
  94. package/dist/tsembed-react.es.js +226 -29
  95. package/dist/tsembed-react.js +225 -28
  96. package/dist/tsembed.es.js +227 -30
  97. package/dist/tsembed.js +225 -28
  98. package/dist/visual-embed-sdk-react-full.d.ts +469 -15
  99. package/dist/visual-embed-sdk-react.d.ts +469 -15
  100. package/dist/visual-embed-sdk.d.ts +497 -15
  101. package/lib/package.json +1 -1
  102. package/lib/src/auth.d.ts.map +1 -1
  103. package/lib/src/auth.js +12 -2
  104. package/lib/src/auth.js.map +1 -1
  105. package/lib/src/auth.spec.js +38 -0
  106. package/lib/src/auth.spec.js.map +1 -1
  107. package/lib/src/authToken.d.ts +2 -0
  108. package/lib/src/authToken.d.ts.map +1 -1
  109. package/lib/src/authToken.js +2 -2
  110. package/lib/src/authToken.js.map +1 -1
  111. package/lib/src/embed/app.d.ts +7 -2
  112. package/lib/src/embed/app.d.ts.map +1 -1
  113. package/lib/src/embed/app.js +4 -1
  114. package/lib/src/embed/app.js.map +1 -1
  115. package/lib/src/embed/app.spec.js +122 -1
  116. package/lib/src/embed/app.spec.js.map +1 -1
  117. package/lib/src/embed/conversation.d.ts +2 -1
  118. package/lib/src/embed/conversation.d.ts.map +1 -1
  119. package/lib/src/embed/conversation.js.map +1 -1
  120. package/lib/src/embed/liveboard.d.ts +1 -1
  121. package/lib/src/embed/liveboard.d.ts.map +1 -1
  122. package/lib/src/embed/liveboard.js +4 -1
  123. package/lib/src/embed/liveboard.js.map +1 -1
  124. package/lib/src/embed/liveboard.spec.js +32 -0
  125. package/lib/src/embed/liveboard.spec.js.map +1 -1
  126. package/lib/src/embed/search.d.ts +24 -1
  127. package/lib/src/embed/search.d.ts.map +1 -1
  128. package/lib/src/embed/search.js +15 -2
  129. package/lib/src/embed/search.js.map +1 -1
  130. package/lib/src/embed/search.spec.js +100 -1
  131. package/lib/src/embed/search.spec.js.map +1 -1
  132. package/lib/src/embed/spotter-utils.d.ts +3 -0
  133. package/lib/src/embed/spotter-utils.d.ts.map +1 -1
  134. package/lib/src/embed/spotter-utils.js +11 -3
  135. package/lib/src/embed/spotter-utils.js.map +1 -1
  136. package/lib/src/embed/spotter-utils.spec.js +51 -0
  137. package/lib/src/embed/spotter-utils.spec.js.map +1 -1
  138. package/lib/src/embed/ts-embed.d.ts +1 -0
  139. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  140. package/lib/src/embed/ts-embed.js +16 -4
  141. package/lib/src/embed/ts-embed.js.map +1 -1
  142. package/lib/src/embed/ts-embed.spec.js +168 -0
  143. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  144. package/lib/src/index.d.ts +2 -2
  145. package/lib/src/index.d.ts.map +1 -1
  146. package/lib/src/index.js +2 -2
  147. package/lib/src/index.js.map +1 -1
  148. package/lib/src/mixpanel-service.d.ts.map +1 -1
  149. package/lib/src/mixpanel-service.js +2 -0
  150. package/lib/src/mixpanel-service.js.map +1 -1
  151. package/lib/src/mixpanel-service.spec.js +2 -0
  152. package/lib/src/mixpanel-service.spec.js.map +1 -1
  153. package/lib/src/test/test-utils.d.ts +1 -0
  154. package/lib/src/test/test-utils.d.ts.map +1 -1
  155. package/lib/src/test/test-utils.js +25 -1
  156. package/lib/src/test/test-utils.js.map +1 -1
  157. package/lib/src/tokenizedFetch.d.ts.map +1 -1
  158. package/lib/src/tokenizedFetch.js +13 -10
  159. package/lib/src/tokenizedFetch.js.map +1 -1
  160. package/lib/src/tokenizedFetch.spec.d.ts +2 -0
  161. package/lib/src/tokenizedFetch.spec.d.ts.map +1 -0
  162. package/lib/src/tokenizedFetch.spec.js +65 -0
  163. package/lib/src/tokenizedFetch.spec.js.map +1 -0
  164. package/lib/src/types.d.ts +466 -13
  165. package/lib/src/types.d.ts.map +1 -1
  166. package/lib/src/types.js +148 -4
  167. package/lib/src/types.js.map +1 -1
  168. package/lib/src/visual-embed-sdk.d.ts +497 -15
  169. package/package.json +1 -1
  170. package/src/auth.spec.ts +55 -1
  171. package/src/auth.ts +11 -2
  172. package/src/authToken.ts +2 -2
  173. package/src/embed/app.spec.ts +154 -0
  174. package/src/embed/app.ts +13 -2
  175. package/src/embed/conversation.ts +2 -1
  176. package/src/embed/liveboard.spec.ts +46 -0
  177. package/src/embed/liveboard.ts +9 -4
  178. package/src/embed/search.spec.ts +118 -0
  179. package/src/embed/search.ts +43 -1
  180. package/src/embed/spotter-utils.spec.ts +52 -0
  181. package/src/embed/spotter-utils.ts +19 -3
  182. package/src/embed/ts-embed.spec.ts +220 -0
  183. package/src/embed/ts-embed.ts +15 -4
  184. package/src/index.ts +16 -0
  185. package/src/mixpanel-service.spec.ts +2 -0
  186. package/src/mixpanel-service.ts +2 -0
  187. package/src/test/test-utils.ts +33 -1
  188. package/src/tokenizedFetch.spec.ts +81 -0
  189. package/src/tokenizedFetch.ts +14 -11
  190. package/src/types.ts +496 -13
package/src/auth.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import EventEmitter from 'eventemitter3';
2
- import { getAuthenticationToken } from './authToken';
2
+ import { getAuthenticationToken, storeAuthTokenInCache, getCacheAuthToken } from './authToken';
3
3
  import { getEmbedConfig } from './embed/embedConfig';
4
4
  import { initMixpanel } from './mixpanel-service';
5
5
  import {
@@ -462,6 +462,10 @@ async function samlPopupFlow(ssoURL: string, triggerContainer: DOMSelector, trig
462
462
  samlCompletionPromise = samlCompletionPromise || new Promise<void>((resolve, reject) => {
463
463
  window.addEventListener('message', (e) => {
464
464
  if (e.data.type === EmbedEvent.SAMLComplete) {
465
+ if (e.data.accessToken) {
466
+ const decodedToken = decodeURIComponent(e.data.accessToken);
467
+ storeAuthTokenInCache(decodedToken);
468
+ }
465
469
  samlCompletionResolved = true;
466
470
  if (popupClosedCheck) {
467
471
  clearInterval(popupClosedCheck);
@@ -503,7 +507,12 @@ const doSSOAuth = async (embedConfig: EmbedConfig, ssoEndPoint: string): Promise
503
507
  const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
504
508
  if (embedConfig.inPopup) {
505
509
  await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
506
- loggedInStatus = await isLoggedIn(thoughtSpotHost);
510
+ const cachedToken = getCacheAuthToken();
511
+ if (cachedToken) {
512
+ loggedInStatus = true;
513
+ } else {
514
+ loggedInStatus = await isLoggedIn(thoughtSpotHost);
515
+ }
507
516
  return;
508
517
  }
509
518
 
package/src/authToken.ts CHANGED
@@ -6,8 +6,8 @@ import { logger } from './utils/logger';
6
6
 
7
7
  const cacheAuthTokenKey = 'cachedAuthToken';
8
8
 
9
- const getCacheAuthToken = (): string | null => getValueFromWindow(cacheAuthTokenKey);
10
- const storeAuthTokenInCache = (token: string): void => {
9
+ export const getCacheAuthToken = (): string | null => getValueFromWindow(cacheAuthTokenKey);
10
+ export const storeAuthTokenInCache = (token: string): void => {
11
11
  storeValueInWindow(cacheAuthTokenKey, token);
12
12
  };
13
13
 
@@ -21,6 +21,8 @@ import {
21
21
  defaultParamsForPinboardEmbed,
22
22
  defaultParamsWithoutHiddenActions,
23
23
  expectUrlMatchesWithParams,
24
+ postMessageToParent,
25
+ testVisualOverridesInEmbed,
24
26
  } from '../test/test-utils';
25
27
  import { version } from '../../package.json';
26
28
  import * as config from '../config';
@@ -478,6 +480,19 @@ describe('App embed tests', () => {
478
480
  });
479
481
  });
480
482
 
483
+ test('should disable isWYSIWYGLiveboardPDFEnabled by default in url', async () => {
484
+ const appEmbed = new AppEmbed(getRootEl(), {
485
+ ...defaultViewConfig,
486
+ } as AppViewConfig);
487
+ appEmbed.render();
488
+ await executeAfterWait(() => {
489
+ expectUrlMatchesWithParams(
490
+ getIFrameSrc(),
491
+ `http://${thoughtSpotHost}/?embedApp=true&profileAndHelpInNavBarHidden=false&isWYSIWYGLiveboardPDFEnabled=false${defaultParamsPost}#/home`,
492
+ );
493
+ });
494
+ });
495
+
481
496
  test('should set isLinkParametersEnabled to true in url', async () => {
482
497
  const appEmbed = new AppEmbed(getRootEl(), {
483
498
  ...defaultViewConfig,
@@ -805,6 +820,53 @@ describe('App embed tests', () => {
805
820
  });
806
821
  });
807
822
 
823
+ test('Should add newChartsLibrary true to the iframe src', async () => {
824
+ const appEmbed = new AppEmbed(getRootEl(), {
825
+ ...defaultViewConfig,
826
+ showPrimaryNavbar: false,
827
+ newChartsLibrary: true,
828
+ } as AppViewConfig);
829
+
830
+ appEmbed.render();
831
+ await executeAfterWait(() => {
832
+ expectUrlMatchesWithParams(
833
+ getIFrameSrc(),
834
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&muzeChartPhase1EnabledGA=true${defaultParams}${defaultParamsPost}#/home`,
835
+ );
836
+ });
837
+ });
838
+
839
+ test('Should add newChartsLibrary false to the iframe src', async () => {
840
+ const appEmbed = new AppEmbed(getRootEl(), {
841
+ ...defaultViewConfig,
842
+ showPrimaryNavbar: false,
843
+ newChartsLibrary: false,
844
+ } as AppViewConfig);
845
+
846
+ appEmbed.render();
847
+ await executeAfterWait(() => {
848
+ expectUrlMatchesWithParams(
849
+ getIFrameSrc(),
850
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&muzeChartPhase1EnabledGA=false${defaultParams}${defaultParamsPost}#/home`,
851
+ );
852
+ });
853
+ });
854
+
855
+ test('Should not add newChartsLibrary to the iframe src when not specified', async () => {
856
+ const appEmbed = new AppEmbed(getRootEl(), {
857
+ ...defaultViewConfig,
858
+ showPrimaryNavbar: false,
859
+ } as AppViewConfig);
860
+
861
+ appEmbed.render();
862
+ await executeAfterWait(() => {
863
+ expectUrlMatchesWithParams(
864
+ getIFrameSrc(),
865
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
866
+ );
867
+ });
868
+ });
869
+
808
870
  test('Should add enableSearchAssist flagto the iframe src', async () => {
809
871
  const appEmbed = new AppEmbed(getRootEl(), {
810
872
  ...defaultViewConfig,
@@ -1812,4 +1874,96 @@ describe('App Embed Default Height and Minimum Height Handling', () => {
1812
1874
  });
1813
1875
  });
1814
1876
 
1877
+ describe('AppEmbed visualOverrides tests', () => {
1878
+ test('should include visualOverridesParams in APP_INIT when visualOverrides config is provided', async () => {
1879
+ const visualOverrides = {
1880
+ chart: {
1881
+ legend: {
1882
+ show: true,
1883
+ position: 'bottom' as const,
1884
+ },
1885
+ },
1886
+ };
1887
+ const appEmbed = new AppEmbed(getRootEl(), {
1888
+ ...defaultViewConfig,
1889
+ visualOverrides,
1890
+ } as AppViewConfig);
1891
+
1892
+ mockMessageChannel();
1893
+ await testVisualOverridesInEmbed(appEmbed, visualOverrides);
1894
+ });
1895
+
1896
+ test('should not include visualOverridesParams when visualOverrides is not provided', async () => {
1897
+ const appEmbed = new AppEmbed(getRootEl(), {
1898
+ ...defaultViewConfig,
1899
+ } as AppViewConfig);
1900
+
1901
+ const mockEmbedEventPayload = {
1902
+ type: EmbedEvent.APP_INIT,
1903
+ data: {},
1904
+ };
1905
+
1906
+ mockMessageChannel();
1907
+ appEmbed.render();
1908
+
1909
+ const mockPort: any = {
1910
+ postMessage: jest.fn(),
1911
+ };
1912
+
1913
+ await executeAfterWait(() => {
1914
+ const iframe = getIFrameEl();
1915
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
1916
+ });
1917
+
1918
+ await executeAfterWait(() => {
1919
+ const callArgs = mockPort.postMessage.mock.calls[0][0];
1920
+ expect(callArgs.type).toBe(EmbedEvent.APP_INIT);
1921
+ if (callArgs.data.embedParams) {
1922
+ expect(callArgs.data.embedParams.visualOverridesParams).toBeUndefined();
1923
+ }
1924
+ });
1925
+ });
1926
+
1927
+ test('should pass visualOverrides with table config in AppEmbed', async () => {
1928
+ const visualOverrides = {
1929
+ table: {
1930
+ display: {
1931
+ tableTheme: 'ZEBRA',
1932
+ tableContentDensity: 'COMPACT',
1933
+ },
1934
+ },
1935
+ };
1936
+ const appEmbed = new AppEmbed(getRootEl(), {
1937
+ ...defaultViewConfig,
1938
+ visualOverrides,
1939
+ } as AppViewConfig);
1940
+
1941
+ mockMessageChannel();
1942
+ await testVisualOverridesInEmbed(appEmbed, visualOverrides);
1943
+ });
1944
+
1945
+ test('should pass visualOverrides with both chart and table configs', async () => {
1946
+ const visualOverrides = {
1947
+ chart: {
1948
+ legend: {
1949
+ show: true,
1950
+ position: 'right' as const,
1951
+ },
1952
+ },
1953
+ table: {
1954
+ display: {
1955
+ tableTheme: 'STRIPED',
1956
+ },
1957
+ },
1958
+ };
1959
+ const appEmbed = new AppEmbed(getRootEl(), {
1960
+ ...defaultViewConfig,
1961
+ visualOverrides,
1962
+ } as AppViewConfig);
1963
+
1964
+ mockMessageChannel();
1965
+ await testVisualOverridesInEmbed(appEmbed, visualOverrides);
1966
+ });
1967
+ });
1968
+
1815
1969
 
package/src/embed/app.ts CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  MessagePayload,
19
19
  AllEmbedViewConfig,
20
20
  DefaultAppInitData,
21
+ VisualizationOverrides,
21
22
  } from '../types';
22
23
  import { V1Embed } from './ts-embed';
23
24
  import { SpotterChatViewConfig, SpotterSidebarViewConfig } from './conversation';
@@ -589,7 +590,7 @@ export interface AppViewConfig extends AllEmbedViewConfig {
589
590
  /**
590
591
  * Enables the 'what you see is what you get' PDF export for Liveboards. Each tab is rendered on a single page
591
592
  * following the exact UI layout, instead of splitting visualizations across multiple A4 pages.
592
- * This feature is GA from version 26.5.0.cl and is enabled by default on embed deployments.
593
+ * This feature is GA from version 26.5.0.cl. It is disabled by default in embed deployments.
593
594
  *
594
595
  * Supported embed types: `AppEmbed`, `LiveboardEmbed`
595
596
  * @type {boolean}
@@ -798,6 +799,12 @@ export interface AppViewConfig extends AllEmbedViewConfig {
798
799
  * ```
799
800
  */
800
801
  enableLiveboardDataCache?: boolean;
802
+
803
+ /**
804
+ * Visual overrides to customize the chart or table properties.
805
+ * @version SDK: 1.49.0 | ThoughtSpot: 26.6.0.cl
806
+ */
807
+ visualOverrides?: VisualizationOverrides;
801
808
  }
802
809
 
803
810
  /**
@@ -875,6 +882,7 @@ export class AppEmbed extends V1Embed {
875
882
  showLiveboardDescription = true,
876
883
  showMaskedFilterChip = false,
877
884
  isLiveboardMasterpiecesEnabled = false,
885
+ newChartsLibrary,
878
886
  hideHomepageLeftNav = false,
879
887
  modularHomeExperience = false,
880
888
  isLiveboardHeaderSticky = true,
@@ -906,7 +914,7 @@ export class AppEmbed extends V1Embed {
906
914
  minimumHeight,
907
915
  isThisPeriodInDateFiltersEnabled,
908
916
  enableHomepageAnnouncement = false,
909
- isContinuousLiveboardPDFEnabled,
917
+ isContinuousLiveboardPDFEnabled = false,
910
918
  enableLiveboardDataCache,
911
919
  } = this.viewConfig;
912
920
 
@@ -920,6 +928,9 @@ export class AppEmbed extends V1Embed {
920
928
  params[Param.ShowLiveboardDescription] = !!showLiveboardDescription;
921
929
  params[Param.ShowMaskedFilterChip] = showMaskedFilterChip;
922
930
  params[Param.IsLiveboardMasterpiecesEnabled] = isLiveboardMasterpiecesEnabled;
931
+ if (newChartsLibrary !== undefined) {
932
+ params[Param.EnableNewChartLibrary] = newChartsLibrary;
933
+ }
923
934
  params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
924
935
  params[Param.IsFullAppEmbed] = true;
925
936
  params[Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled;
@@ -1,6 +1,6 @@
1
1
  import isUndefined from 'lodash/isUndefined';
2
2
  import { ERROR_MESSAGE } from '../errors';
3
- import { Param, BaseViewConfig, RuntimeFilter, RuntimeParameter, ErrorDetailsTypes, EmbedErrorCodes, DefaultAppInitData } from '../types';
3
+ import { Param, BaseViewConfig, RuntimeFilter, RuntimeParameter, ErrorDetailsTypes, EmbedErrorCodes, DefaultAppInitData, VisualizationOverrides } from '../types';
4
4
  import { TsEmbed } from './ts-embed';
5
5
  import { buildSpotterSidebarAppInitData } from './spotter-utils';
6
6
  import { getQueryParamString, getFilterQuery, getRuntimeParameters, setParamIfDefined } from '../utils';
@@ -360,6 +360,7 @@ export interface ConversationViewConfig extends SpotterEmbedViewConfig {}
360
360
  export interface SpotterAppInitData extends DefaultAppInitData {
361
361
  embedParams?: {
362
362
  spotterSidebarConfig?: SpotterSidebarViewConfig;
363
+ visualOverridesParams?: VisualizationOverrides | null;
363
364
  };
364
365
  }
365
366
 
@@ -275,6 +275,20 @@ describe('Liveboard/viz embed tests', () => {
275
275
  });
276
276
  });
277
277
 
278
+ test('should disable isWYSIWYGLiveboardPDFEnabled by default in url', async () => {
279
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
280
+ ...defaultViewConfig,
281
+ liveboardId,
282
+ } as LiveboardViewConfig);
283
+ liveboardEmbed.render();
284
+ await executeAfterWait(() => {
285
+ expectUrlMatchesWithParams(
286
+ getIFrameSrc(),
287
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&isWYSIWYGLiveboardPDFEnabled=false${prefixParams}#/embed/viz/${liveboardId}`,
288
+ );
289
+ });
290
+ });
291
+
278
292
  test('should set isLiveboardXLSXCSVDownloadEnabled to true in url', async () => {
279
293
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
280
294
  isLiveboardXLSXCSVDownloadEnabled: true,
@@ -634,6 +648,38 @@ describe('Liveboard/viz embed tests', () => {
634
648
  });
635
649
  });
636
650
 
651
+ test('Should add newChartsLibrary flag set to true to the iframe src', async () => {
652
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
653
+ ...defaultViewConfig,
654
+ liveboardId,
655
+ newChartsLibrary: true,
656
+ } as LiveboardViewConfig);
657
+
658
+ liveboardEmbed.render();
659
+ await executeAfterWait(() => {
660
+ expectUrlMatchesWithParams(
661
+ getIFrameSrc(),
662
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&muzeChartPhase1EnabledGA=true${prefixParams}#/embed/viz/${liveboardId}`,
663
+ );
664
+ });
665
+ });
666
+
667
+ test('Should add newChartsLibrary flag set to false to the iframe src', async () => {
668
+ const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
669
+ ...defaultViewConfig,
670
+ liveboardId,
671
+ newChartsLibrary: false,
672
+ } as LiveboardViewConfig);
673
+
674
+ liveboardEmbed.render();
675
+ await executeAfterWait(() => {
676
+ expectUrlMatchesWithParams(
677
+ getIFrameSrc(),
678
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&muzeChartPhase1EnabledGA=false${prefixParams}#/embed/viz/${liveboardId}`,
679
+ );
680
+ });
681
+ });
682
+
637
683
  test('Should add hideIrrelevantFiltersAtTabLevel flag to the iframe src', async () => {
638
684
  const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
639
685
  ...defaultViewConfig,
@@ -388,9 +388,9 @@ export interface LiveboardViewConfig extends BaseViewConfig, LiveboardOtherViewC
388
388
  */
389
389
  isPNGInScheduledEmailsEnabled?: boolean;
390
390
  /**
391
- * Enables the 'what you see is what you get' PDF export for Liveboards. Each tab is rendered on a single page
392
- * following the exact UI layout, instead of splitting visualizations across multiple A4 pages.
393
- * This feature is GA from version 26.5.0.cl and is enabled by default on embed deployments.
391
+ * Enables the 'what you see is what you get' PDF export for Liveboards. Each tab is rendered on a single page
392
+ * following the exact UI layout, instead of splitting visualizations across multiple A4 pages.
393
+ * This feature is GA from version 26.5.0.cl. It is disabled by default in embed deployments.
394
394
  *
395
395
  * Supported embed types: `AppEmbed`, `LiveboardEmbed`
396
396
  * @type {boolean}
@@ -619,6 +619,7 @@ export class LiveboardEmbed extends V1Embed {
619
619
  hideIrrelevantChipsInLiveboardTabs = false,
620
620
  showMaskedFilterChip = false,
621
621
  isLiveboardMasterpiecesEnabled = false,
622
+ newChartsLibrary,
622
623
  isEnhancedFilterInteractivityEnabled = false,
623
624
  enableAskSage,
624
625
  enable2ColumnLayout,
@@ -639,7 +640,7 @@ export class LiveboardEmbed extends V1Embed {
639
640
  enableStopAnswerGenerationEmbed,
640
641
  spotterChatConfig,
641
642
  isThisPeriodInDateFiltersEnabled,
642
- isContinuousLiveboardPDFEnabled,
643
+ isContinuousLiveboardPDFEnabled = false,
643
644
  enableLiveboardDataCache,
644
645
  } = this.viewConfig;
645
646
 
@@ -762,6 +763,10 @@ export class LiveboardEmbed extends V1Embed {
762
763
  params[Param.EnableLiveboardDataCache] = enableLiveboardDataCache;
763
764
  }
764
765
 
766
+ if (newChartsLibrary !== undefined) {
767
+ params[Param.EnableNewChartLibrary] = newChartsLibrary;
768
+ }
769
+
765
770
  params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
766
771
  params[Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled;
767
772
  params[Param.ShowLiveboardVerifiedBadge] = showLiveboardVerifiedBadge;
@@ -17,6 +17,7 @@ import {
17
17
  expectUrlMatchesWithParams,
18
18
  getIFrameEl,
19
19
  postMessageToParent,
20
+ testVisualOverridesInEmbed,
20
21
  } from '../test/test-utils';
21
22
  import { version } from '../../package.json';
22
23
  import { SearchBarEmbed } from './search-bar';
@@ -524,6 +525,34 @@ describe('Search embed tests', () => {
524
525
  });
525
526
  });
526
527
 
528
+ test('Should add newChartsLibrary flag set to true to the iframe src', async () => {
529
+ const searchEmbed = new SearchEmbed(getRootEl(), {
530
+ ...defaultViewConfig,
531
+ newChartsLibrary: true,
532
+ });
533
+ searchEmbed.render();
534
+ await executeAfterWait(() => {
535
+ expectUrlMatchesWithParams(
536
+ getIFrameSrc(),
537
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&enableDataPanelV2=true&muzeChartPhase1EnabledGA=true&dataSourceMode=expand&useLastSelectedSources=false${prefixParams}#/embed/answer`,
538
+ );
539
+ });
540
+ });
541
+
542
+ test('Should add newChartsLibrary flag set to false to the iframe src', async () => {
543
+ const searchEmbed = new SearchEmbed(getRootEl(), {
544
+ ...defaultViewConfig,
545
+ newChartsLibrary: false,
546
+ });
547
+ searchEmbed.render();
548
+ await executeAfterWait(() => {
549
+ expectUrlMatchesWithParams(
550
+ getIFrameSrc(),
551
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&enableDataPanelV2=true&muzeChartPhase1EnabledGA=false&dataSourceMode=expand&useLastSelectedSources=false${prefixParams}#/embed/answer`,
552
+ );
553
+ });
554
+ });
555
+
527
556
  test('should set dataPanelCustomGroupsAccordionInitialState to EXPAND_FIRST when passed', async () => {
528
557
  const searchEmbed = new SearchBarEmbed(getRootEl() as any, {
529
558
  ...defaultViewConfig,
@@ -811,3 +840,92 @@ describe('SearchBarEmbed tests', () => {
811
840
  });
812
841
  });
813
842
  });
843
+
844
+ describe('SearchEmbed visualOverrides tests', () => {
845
+ test('should pass visualOverrides in embedParams when visualOverrides config is provided', async () => {
846
+ const visualOverrides = {
847
+ chart: {
848
+ legend: {
849
+ show: true,
850
+ position: 'bottom' as const,
851
+ },
852
+ },
853
+ };
854
+ const searchEmbed = new SearchEmbed(getRootEl(), {
855
+ ...defaultViewConfig,
856
+ visualOverrides,
857
+ });
858
+
859
+ await testVisualOverridesInEmbed(searchEmbed, visualOverrides);
860
+ });
861
+
862
+ test('should not include visualOverridesParams when visualOverrides is not provided', async () => {
863
+ const searchEmbed = new SearchEmbed(getRootEl(), {
864
+ ...defaultViewConfig,
865
+ });
866
+ const mockEmbedEventPayload = {
867
+ type: EmbedEvent.APP_INIT,
868
+ data: {},
869
+ };
870
+
871
+ searchEmbed.render();
872
+
873
+ const mockPort: any = {
874
+ postMessage: jest.fn(),
875
+ };
876
+
877
+ await executeAfterWait(() => {
878
+ const iframe = getIFrameEl();
879
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
880
+ });
881
+
882
+ await executeAfterWait(() => {
883
+ const callArgs = mockPort.postMessage.mock.calls[0][0];
884
+ expect(callArgs.type).toBe(EmbedEvent.APP_INIT);
885
+ expect(callArgs.data.embedParams?.visualOverridesParams).toBeUndefined();
886
+ });
887
+ });
888
+
889
+ test('should pass visualOverrides with complex chart config', async () => {
890
+ const visualOverrides = {
891
+ chart: {
892
+ legend: {
893
+ show: true,
894
+ position: 'right' as const,
895
+ colorPalette: {
896
+ colors: ['#ff0000', '#00ff00', '#0000ff'],
897
+ },
898
+ },
899
+ columns: [
900
+ {
901
+ name: 'Revenue',
902
+ color: '#1f77b4',
903
+ },
904
+ ],
905
+ },
906
+ };
907
+ const searchEmbed = new SearchEmbed(getRootEl(), {
908
+ ...defaultViewConfig,
909
+ visualOverrides,
910
+ });
911
+
912
+ await testVisualOverridesInEmbed(searchEmbed, visualOverrides);
913
+ });
914
+
915
+ test('should pass visualOverrides with table config', async () => {
916
+ const visualOverrides = {
917
+ table: {
918
+ display: {
919
+ tableTheme: 'ZEBRA',
920
+ tableContentDensity: 'COMPACT',
921
+ },
922
+ },
923
+ };
924
+ const searchEmbed = new SearchEmbed(getRootEl(), {
925
+ ...defaultViewConfig,
926
+ visualOverrides,
927
+ });
928
+
929
+ await testVisualOverridesInEmbed(searchEmbed, visualOverrides);
930
+ });
931
+ });
@@ -15,6 +15,7 @@ import {
15
15
  SearchLiveboardCommonViewConfig,
16
16
  DefaultAppInitData,
17
17
  BaseViewConfig,
18
+ VisualizationOverrides,
18
19
  } from '../types';
19
20
  import {
20
21
  getQueryParamString,
@@ -317,6 +318,27 @@ export interface SearchViewConfig
317
318
  * ```
318
319
  */
319
320
  focusSearchBarOnRender?: boolean;
321
+ /**
322
+ * Enable or disable Muze chart phase 1 GA
323
+ *
324
+ * Supported embed types: `SearchEmbed`
325
+ * @version SDK: 1.49.0 | ThoughtSpot Cloud: 26.6.0.cl
326
+ * @default false
327
+ * @example
328
+ * ```js
329
+ * const embed = new SearchEmbed('#tsEmbed', {
330
+ * ... // other embed view config
331
+ * newChartsLibrary: true,
332
+ * })
333
+ * ```
334
+ */
335
+ newChartsLibrary?: boolean;
336
+
337
+ /**
338
+ * Visual overrides to customize the chart or table properties.
339
+ * @version SDK: 1.49.0 | ThoughtSpot: 26.6.0.cl
340
+ */
341
+ visualOverrides?: VisualizationOverrides;
320
342
  }
321
343
 
322
344
  export const HiddenActionItemByDefaultForSearchEmbed = [
@@ -329,6 +351,9 @@ export const HiddenActionItemByDefaultForSearchEmbed = [
329
351
 
330
352
  export interface SearchAppInitData extends DefaultAppInitData {
331
353
  searchOptions?: SearchOptions;
354
+ embedParams?: {
355
+ visualOverridesParams?: VisualizationOverrides | null;
356
+ };
332
357
  }
333
358
 
334
359
  /**
@@ -380,7 +405,19 @@ export class SearchEmbed extends TsEmbed {
380
405
 
381
406
  protected async getAppInitData(): Promise<SearchAppInitData> {
382
407
  const defaultAppInitData = await super.getAppInitData();
383
- return { ...defaultAppInitData, ...this.getSearchInitData() };
408
+ const result: SearchAppInitData = {
409
+ ...defaultAppInitData,
410
+ ...this.getSearchInitData(),
411
+ };
412
+
413
+ if (this.viewConfig.visualOverrides) {
414
+ result.embedParams = {
415
+ ...((defaultAppInitData as any).embedParams || {}),
416
+ visualOverridesParams: this.viewConfig.visualOverrides,
417
+ };
418
+ }
419
+
420
+ return result;
384
421
  }
385
422
 
386
423
  protected getEmbedParamsObject() {
@@ -405,6 +442,7 @@ export class SearchEmbed extends TsEmbed {
405
442
  excludeSearchTokenStringFromURL,
406
443
  collapseSearchBar = true,
407
444
  isThisPeriodInDateFiltersEnabled,
445
+ newChartsLibrary,
408
446
  } = this.viewConfig;
409
447
  const queryParams = this.getBaseQueryParams();
410
448
 
@@ -451,6 +489,10 @@ export class SearchEmbed extends TsEmbed {
451
489
  queryParams[Param.IsThisPeriodInDateFiltersEnabled] = isThisPeriodInDateFiltersEnabled;
452
490
  }
453
491
 
492
+ if (newChartsLibrary !== undefined) {
493
+ queryParams[Param.EnableNewChartLibrary] = newChartsLibrary;
494
+ }
495
+
454
496
  queryParams[Param.DataPanelV2Enabled] = dataPanelV2;
455
497
  queryParams[Param.DataSourceMode] = this.getDataSourceMode();
456
498
 
@@ -53,4 +53,56 @@ describe('buildSpotterSidebarAppInitData', () => {
53
53
  }));
54
54
  expect(result.embedParams?.spotterSidebarConfig?.spotterDocumentationUrl).toBeUndefined();
55
55
  });
56
+
57
+ it('returns base with visualOverridesParams when only visualOverrides is provided', () => {
58
+ const visualOverrides = {
59
+ chart: {
60
+ legend: { show: true, position: 'bottom' as const },
61
+ },
62
+ };
63
+ const result = buildSpotterSidebarAppInitData(base, {
64
+ visualOverrides,
65
+ }, noopError);
66
+ expect(result).toEqual({
67
+ ...base,
68
+ embedParams: { visualOverridesParams: visualOverrides },
69
+ });
70
+ });
71
+
72
+ it('includes visualOverridesParams with spotterSidebarConfig', () => {
73
+ const visualOverrides = {
74
+ table: {
75
+ display: { tableTheme: 'ZEBRA' },
76
+ },
77
+ };
78
+ const result = buildSpotterSidebarAppInitData(base, {
79
+ spotterSidebarConfig: { enablePastConversationsSidebar: true },
80
+ visualOverrides,
81
+ }, noopError);
82
+ expect(result.embedParams?.spotterSidebarConfig?.enablePastConversationsSidebar).toBe(true);
83
+ expect(result.embedParams?.visualOverridesParams).toEqual(visualOverrides);
84
+ });
85
+
86
+ it('includes visualOverridesParams with standalone enablePastConversationsSidebar flag', () => {
87
+ const visualOverrides = {
88
+ chart: {
89
+ legend: { show: false },
90
+ },
91
+ };
92
+ const result = buildSpotterSidebarAppInitData(base, {
93
+ enablePastConversationsSidebar: true,
94
+ visualOverrides,
95
+ }, noopError);
96
+ expect(result.embedParams?.spotterSidebarConfig?.enablePastConversationsSidebar).toBe(true);
97
+ expect(result.embedParams?.visualOverridesParams).toEqual(visualOverrides);
98
+ });
99
+
100
+ it('does not include visualOverridesParams when it is undefined', () => {
101
+ const result = buildSpotterSidebarAppInitData(base, {
102
+ spotterSidebarConfig: { enablePastConversationsSidebar: true },
103
+ visualOverrides: undefined,
104
+ }, noopError);
105
+ expect(result.embedParams?.visualOverridesParams).toBeUndefined();
106
+ expect(result.embedParams?.spotterSidebarConfig?.enablePastConversationsSidebar).toBe(true);
107
+ });
56
108
  });