@thoughtspot/visual-embed-sdk 1.33.0-alpha.2 → 1.33.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 (198) hide show
  1. package/cjs/package.json +6 -24
  2. package/cjs/src/css-variables.d.ts +46 -3
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +47 -27
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +10 -1
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +32 -0
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/base.d.ts +35 -33
  11. package/cjs/src/embed/base.d.ts.map +1 -1
  12. package/cjs/src/embed/base.js +35 -33
  13. package/cjs/src/embed/base.js.map +1 -1
  14. package/cjs/src/embed/embed.spec.js +0 -19
  15. package/cjs/src/embed/embed.spec.js.map +1 -1
  16. package/cjs/src/embed/liveboard.d.ts +42 -0
  17. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  18. package/cjs/src/embed/liveboard.js +6 -1
  19. package/cjs/src/embed/liveboard.js.map +1 -1
  20. package/cjs/src/embed/liveboard.spec.js +43 -0
  21. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  22. package/cjs/src/embed/search.d.ts +0 -26
  23. package/cjs/src/embed/search.d.ts.map +1 -1
  24. package/cjs/src/embed/search.js.map +1 -1
  25. package/cjs/src/embed/ts-embed.d.ts +0 -1
  26. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  27. package/cjs/src/embed/ts-embed.js +8 -12
  28. package/cjs/src/embed/ts-embed.js.map +1 -1
  29. package/cjs/src/embed/ts-embed.spec.js +0 -9
  30. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  31. package/cjs/src/mixpanel-service.d.ts +4 -0
  32. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  33. package/cjs/src/mixpanel-service.js +4 -0
  34. package/cjs/src/mixpanel-service.js.map +1 -1
  35. package/cjs/src/tokenizedFetch.d.ts.map +1 -1
  36. package/cjs/src/tokenizedFetch.js +5 -1
  37. package/cjs/src/tokenizedFetch.js.map +1 -1
  38. package/cjs/src/types.d.ts +179 -22
  39. package/cjs/src/types.d.ts.map +1 -1
  40. package/cjs/src/types.js +143 -12
  41. package/cjs/src/types.js.map +1 -1
  42. package/cjs/src/utils/authService/authService.spec.js +3 -1
  43. package/cjs/src/utils/authService/authService.spec.js.map +1 -1
  44. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  45. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  46. package/cjs/src/utils/graphql/answerService/answer-queries.js +9 -2
  47. package/cjs/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  48. package/cjs/src/utils/graphql/answerService/answerService.d.ts +15 -0
  49. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  50. package/cjs/src/utils/graphql/answerService/answerService.js +25 -0
  51. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  52. package/cjs/src/utils/graphql/answerService/answerService.spec.js +53 -0
  53. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  54. package/cjs/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  55. package/cjs/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  56. package/cjs/src/utils/graphql/graphql-request.spec.js +36 -0
  57. package/cjs/src/utils/graphql/graphql-request.spec.js.map +1 -0
  58. package/cjs/src/utils/processData.js +2 -2
  59. package/cjs/src/utils/processData.js.map +1 -1
  60. package/cjs/src/utils/processData.spec.js +14 -0
  61. package/cjs/src/utils/processData.spec.js.map +1 -1
  62. package/cjs/src/utils/processTrigger.d.ts +1 -0
  63. package/cjs/src/utils/processTrigger.d.ts.map +1 -1
  64. package/cjs/src/utils/processTrigger.js +3 -3
  65. package/cjs/src/utils/processTrigger.js.map +1 -1
  66. package/cjs/src/utils/processTrigger.spec.js +10 -0
  67. package/cjs/src/utils/processTrigger.spec.js.map +1 -1
  68. package/cjs/src/utils.d.ts.map +1 -1
  69. package/cjs/src/utils.js +1 -3
  70. package/cjs/src/utils.js.map +1 -1
  71. package/dist/src/css-variables.d.ts +46 -3
  72. package/dist/src/css-variables.d.ts.map +1 -1
  73. package/dist/src/embed/app.d.ts +47 -27
  74. package/dist/src/embed/app.d.ts.map +1 -1
  75. package/dist/src/embed/base.d.ts +35 -33
  76. package/dist/src/embed/base.d.ts.map +1 -1
  77. package/dist/src/embed/liveboard.d.ts +42 -0
  78. package/dist/src/embed/liveboard.d.ts.map +1 -1
  79. package/dist/src/embed/search.d.ts +0 -26
  80. package/dist/src/embed/search.d.ts.map +1 -1
  81. package/dist/src/embed/ts-embed.d.ts +0 -1
  82. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  83. package/dist/src/mixpanel-service.d.ts +4 -0
  84. package/dist/src/mixpanel-service.d.ts.map +1 -1
  85. package/dist/src/tokenizedFetch.d.ts.map +1 -1
  86. package/dist/src/types.d.ts +179 -22
  87. package/dist/src/types.d.ts.map +1 -1
  88. package/dist/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  89. package/dist/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  90. package/dist/src/utils/graphql/answerService/answerService.d.ts +15 -0
  91. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  92. package/dist/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  93. package/dist/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  94. package/dist/src/utils/processTrigger.d.ts +1 -0
  95. package/dist/src/utils/processTrigger.d.ts.map +1 -1
  96. package/dist/src/utils.d.ts.map +1 -1
  97. package/dist/tsembed-react.es.js +442 -107
  98. package/dist/tsembed-react.js +385 -106
  99. package/dist/tsembed.es.js +477 -140
  100. package/dist/tsembed.js +420 -139
  101. package/dist/visual-embed-sdk-react-full.d.ts +368 -112
  102. package/dist/visual-embed-sdk-react.d.ts +368 -112
  103. package/dist/visual-embed-sdk.d.ts +368 -112
  104. package/lib/package.json +6 -24
  105. package/lib/src/css-variables.d.ts +46 -3
  106. package/lib/src/css-variables.d.ts.map +1 -1
  107. package/lib/src/embed/app.d.ts +47 -27
  108. package/lib/src/embed/app.d.ts.map +1 -1
  109. package/lib/src/embed/app.js +10 -1
  110. package/lib/src/embed/app.js.map +1 -1
  111. package/lib/src/embed/app.spec.js +32 -0
  112. package/lib/src/embed/app.spec.js.map +1 -1
  113. package/lib/src/embed/base.d.ts +35 -33
  114. package/lib/src/embed/base.d.ts.map +1 -1
  115. package/lib/src/embed/base.js +35 -33
  116. package/lib/src/embed/base.js.map +1 -1
  117. package/lib/src/embed/embed.spec.js +0 -19
  118. package/lib/src/embed/embed.spec.js.map +1 -1
  119. package/lib/src/embed/liveboard.d.ts +42 -0
  120. package/lib/src/embed/liveboard.d.ts.map +1 -1
  121. package/lib/src/embed/liveboard.js +6 -1
  122. package/lib/src/embed/liveboard.js.map +1 -1
  123. package/lib/src/embed/liveboard.spec.js +43 -0
  124. package/lib/src/embed/liveboard.spec.js.map +1 -1
  125. package/lib/src/embed/search.d.ts +0 -26
  126. package/lib/src/embed/search.d.ts.map +1 -1
  127. package/lib/src/embed/search.js.map +1 -1
  128. package/lib/src/embed/ts-embed.d.ts +0 -1
  129. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  130. package/lib/src/embed/ts-embed.js +8 -12
  131. package/lib/src/embed/ts-embed.js.map +1 -1
  132. package/lib/src/embed/ts-embed.spec.js +0 -9
  133. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  134. package/lib/src/mixpanel-service.d.ts +4 -0
  135. package/lib/src/mixpanel-service.d.ts.map +1 -1
  136. package/lib/src/mixpanel-service.js +4 -0
  137. package/lib/src/mixpanel-service.js.map +1 -1
  138. package/lib/src/tokenizedFetch.d.ts.map +1 -1
  139. package/lib/src/tokenizedFetch.js +5 -1
  140. package/lib/src/tokenizedFetch.js.map +1 -1
  141. package/lib/src/types.d.ts +179 -22
  142. package/lib/src/types.d.ts.map +1 -1
  143. package/lib/src/types.js +143 -12
  144. package/lib/src/types.js.map +1 -1
  145. package/lib/src/utils/authService/authService.spec.js +3 -1
  146. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  147. package/lib/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  148. package/lib/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  149. package/lib/src/utils/graphql/answerService/answer-queries.js +8 -1
  150. package/lib/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  151. package/lib/src/utils/graphql/answerService/answerService.d.ts +15 -0
  152. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  153. package/lib/src/utils/graphql/answerService/answerService.js +25 -0
  154. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  155. package/lib/src/utils/graphql/answerService/answerService.spec.js +54 -1
  156. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  157. package/lib/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  158. package/lib/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  159. package/lib/src/utils/graphql/graphql-request.spec.js +33 -0
  160. package/lib/src/utils/graphql/graphql-request.spec.js.map +1 -0
  161. package/lib/src/utils/processData.js +2 -2
  162. package/lib/src/utils/processData.js.map +1 -1
  163. package/lib/src/utils/processData.spec.js +14 -0
  164. package/lib/src/utils/processData.spec.js.map +1 -1
  165. package/lib/src/utils/processTrigger.d.ts +1 -0
  166. package/lib/src/utils/processTrigger.d.ts.map +1 -1
  167. package/lib/src/utils/processTrigger.js +1 -1
  168. package/lib/src/utils/processTrigger.js.map +1 -1
  169. package/lib/src/utils/processTrigger.spec.js +10 -0
  170. package/lib/src/utils/processTrigger.spec.js.map +1 -1
  171. package/lib/src/utils.d.ts.map +1 -1
  172. package/lib/src/utils.js +1 -3
  173. package/lib/src/utils.js.map +1 -1
  174. package/lib/src/visual-embed-sdk.d.ts +368 -112
  175. package/package.json +6 -24
  176. package/src/css-variables.ts +49 -3
  177. package/src/embed/app.spec.ts +47 -0
  178. package/src/embed/app.ts +54 -26
  179. package/src/embed/base.ts +35 -33
  180. package/src/embed/embed.spec.ts +0 -22
  181. package/src/embed/liveboard.spec.ts +62 -0
  182. package/src/embed/liveboard.ts +52 -0
  183. package/src/embed/search.ts +0 -26
  184. package/src/embed/ts-embed.spec.ts +0 -11
  185. package/src/embed/ts-embed.ts +9 -12
  186. package/src/mixpanel-service.ts +4 -0
  187. package/src/tokenizedFetch.ts +5 -1
  188. package/src/types.ts +180 -21
  189. package/src/utils/authService/authService.spec.ts +3 -1
  190. package/src/utils/graphql/answerService/answer-queries.ts +9 -1
  191. package/src/utils/graphql/answerService/answerService.spec.ts +69 -0
  192. package/src/utils/graphql/answerService/answerService.ts +35 -0
  193. package/src/utils/graphql/graphql-request.spec.ts +38 -0
  194. package/src/utils/processData.spec.ts +16 -0
  195. package/src/utils/processData.ts +2 -2
  196. package/src/utils/processTrigger.spec.ts +19 -0
  197. package/src/utils/processTrigger.ts +1 -1
  198. package/src/utils.ts +1 -3
@@ -56,7 +56,6 @@ beforeAll(() => {
56
56
  const customisations = {
57
57
  style: {
58
58
  customCSS: {},
59
- customCSSUrl: 'http://localhost:3000',
60
59
  },
61
60
  content: {},
62
61
  };
@@ -64,7 +63,6 @@ const customisations = {
64
63
  const customisationsView = {
65
64
  style: {
66
65
  customCSS: {},
67
- customCSSUrl: 'http://localhost:8000',
68
66
  },
69
67
  content: {
70
68
  strings: {
@@ -95,7 +93,6 @@ describe('Unit test case for ts embed', () => {
95
93
  init({
96
94
  thoughtSpotHost: 'tshost',
97
95
  customizations: customisations,
98
- customCssUrl: 'http://localhost:5000',
99
96
  authType: AuthType.TrustedAuthTokenCookieless,
100
97
  getAuthToken: () => Promise.resolve('test_auth_token2'),
101
98
  });
@@ -136,7 +133,6 @@ describe('Unit test case for ts embed', () => {
136
133
  thoughtSpotHost: 'tshost',
137
134
  authType: AuthType.None,
138
135
  customizations: customisations,
139
- customCssUrl: 'http://localhost:5000',
140
136
  });
141
137
  });
142
138
 
@@ -199,9 +195,6 @@ describe('Unit test case for ts embed', () => {
199
195
  reorderedHomepageModules: [],
200
196
  },
201
197
  });
202
- expect(getIFrameSrc()).toContain(
203
- `customCssUrl=${customisationsView.style.customCSSUrl}`,
204
- );
205
198
  });
206
199
 
207
200
  test('hide home page modules from view Config should be part of app_init payload', async () => {
@@ -601,7 +594,6 @@ describe('Unit test case for ts embed', () => {
601
594
  init({
602
595
  thoughtSpotHost: 'tshost',
603
596
  customizations: customisations,
604
- customCssUrl: 'http://localhost:5000',
605
597
  authType: AuthType.TrustedAuthTokenCookieless,
606
598
  getAuthToken: () => Promise.resolve('test_auth_token1'),
607
599
  });
@@ -655,7 +647,6 @@ describe('Unit test case for ts embed', () => {
655
647
  init({
656
648
  thoughtSpotHost: 'tshost',
657
649
  customizations: customisations,
658
- customCssUrl: 'http://localhost:5000',
659
650
  authType: AuthType.TrustedAuthTokenCookieless,
660
651
  getAuthToken: () => Promise.reject(),
661
652
  });
@@ -790,7 +781,6 @@ describe('Unit test case for ts embed', () => {
790
781
  init({
791
782
  thoughtSpotHost: 'tshost',
792
783
  customizations: customisations,
793
- customCssUrl: 'http://localhost:5000',
794
784
  authType: AuthType.TrustedAuthToken,
795
785
  username: 'tsadmin',
796
786
  getAuthToken: () => Promise.resolve('test_auth_token3'),
@@ -819,7 +809,6 @@ describe('Unit test case for ts embed', () => {
819
809
  init({
820
810
  thoughtSpotHost: 'tshost',
821
811
  customizations: customisations,
822
- customCssUrl: 'http://localhost:5000',
823
812
  authType: AuthType.TrustedAuthToken,
824
813
  username: 'tsadmin',
825
814
  getAuthToken: () => Promise.resolve('test_auth_token4'),
@@ -454,13 +454,6 @@ export class TsEmbed {
454
454
  return queryParams;
455
455
  }
456
456
 
457
- // TODO remove embedConfig.customCssUrl
458
- const cssUrlParam = customizations?.style?.customCSSUrl || this.embedConfig.customCssUrl;
459
-
460
- if (cssUrlParam) {
461
- queryParams[Param.CustomCSSUrl] = cssUrlParam;
462
- }
463
-
464
457
  if (disabledActions?.length) {
465
458
  queryParams[Param.DisableActions] = disabledActions;
466
459
  }
@@ -500,9 +493,7 @@ export class TsEmbed {
500
493
  if (locale !== undefined) {
501
494
  queryParams[Param.Locale] = locale;
502
495
  }
503
- if (additionalFlags && additionalFlags.constructor.name === 'Object') {
504
- Object.assign(queryParams, additionalFlags);
505
- }
496
+
506
497
  if (linkOverride) {
507
498
  queryParams[Param.LinkOverride] = linkOverride;
508
499
  }
@@ -516,6 +507,13 @@ export class TsEmbed {
516
507
  queryParams[Param.OverrideNativeConsole] = true;
517
508
  queryParams[Param.ClientLogLevel] = this.embedConfig.logLevel;
518
509
 
510
+ if (additionalFlags && additionalFlags.constructor.name === 'Object') {
511
+ Object.assign(queryParams, additionalFlags);
512
+ }
513
+
514
+ // Do not add any flags below this, as we want additional flags to
515
+ // override other flags
516
+
519
517
  return queryParams;
520
518
  }
521
519
 
@@ -1221,7 +1219,7 @@ export class TsEmbed {
1221
1219
  * @version SDK: 1.25.0 / ThoughtSpot 9.10.0
1222
1220
  */
1223
1221
  public async getAnswerService(vizId?: string): Promise<AnswerService> {
1224
- const { session } = await this.trigger(HostEvent.GetAnswerSession, vizId);
1222
+ const { session } = await this.trigger(HostEvent.GetAnswerSession, vizId ? { vizId } : {});
1225
1223
 
1226
1224
  return new AnswerService(session, null, this.embedConfig.thoughtSpotHost);
1227
1225
  }
@@ -1298,7 +1296,6 @@ export class V1Embed extends TsEmbed {
1298
1296
 
1299
1297
  /**
1300
1298
  * Only for testing purposes.
1301
- *
1302
1299
  * @hidden
1303
1300
  */
1304
1301
  // eslint-disable-next-line camelcase
@@ -11,6 +11,10 @@ export const EndPoints = {
11
11
  const mixpanelLib = mixpanel.default || mixpanel;
12
12
  let mixpanelInstance: mixpanel.Mixpanel;
13
13
 
14
+ /**
15
+ * Enum of mixpanel events
16
+ * @hidden
17
+ */
14
18
  export const MIXPANEL_EVENT = {
15
19
  VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
16
20
  VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
@@ -22,7 +22,11 @@ import { AuthType } from './types';
22
22
  export const tokenizedFetch: typeof fetch = async (input, init): Promise<Response> => {
23
23
  const embedConfig = getEmbedConfig();
24
24
  if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
25
- return fetch(input, init);
25
+ return fetch(input, {
26
+ // ensure cookies are included for the non cookie-less api calls.
27
+ credentials: 'include',
28
+ ...init,
29
+ });
26
30
  }
27
31
 
28
32
  const req = new Request(input, init);
package/src/types.ts CHANGED
@@ -449,13 +449,6 @@ export interface EmbedConfig {
449
449
  */
450
450
  queueMultiRenders?: boolean;
451
451
 
452
- /**
453
- * Dynamic CSS URL to be injected in the loaded application.
454
- * You would also need to set `style-src` in the CSP settings.
455
- * @version SDK: 1.6.0 | ThoughtSpot: ts8.nov.cl, 8.4.1.sw
456
- * @default ''
457
- */
458
- customCssUrl?: string;
459
452
  /**
460
453
  * [AuthServer|Basic] Detect if third-party party cookies are enabled by doing an
461
454
  * additional call. This is slower and should be avoided. Listen to the
@@ -589,6 +582,13 @@ export interface EmbedConfig {
589
582
  * @version SDK: 1.28.5 | Thoughtspot: *
590
583
  */
591
584
  disableTokenVerification?: boolean;
585
+
586
+ /**
587
+ * This flag is used to disable showing the login failure page in the embedded app.
588
+ *
589
+ * @version SDK 1.32.3 | Thoughtspot: *
590
+ */
591
+ disableLoginFailurePage?: boolean;
592
592
  }
593
593
 
594
594
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
@@ -715,11 +715,12 @@ export interface ViewConfig {
715
715
  */
716
716
  visibleActions?: Action[];
717
717
  /**
718
- * Show alert messages and toast messages in the embedded view.
718
+ * Show alert messages and toast messages in the embedded
719
+ * view in full app embed.
719
720
  * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw
720
721
  * @example
721
722
  * ```js
722
- * const embed = new LiveboardEmbed('#embed-container', {
723
+ * const embed = new AppEmbed('#embed-container', {
723
724
  * ... // other options
724
725
  * showAlerts:true,
725
726
  * })
@@ -1040,6 +1041,32 @@ export interface ViewConfig {
1040
1041
  * @version SDK: 1.32.1 | ThoughtSpot: 10.3.0.cl
1041
1042
  */
1042
1043
  disableRedirectionLinksInNewTab?: boolean;
1044
+ /**
1045
+ * Flag to control Data panel experience
1046
+ * @default true
1047
+ * @version SDK: 1.34.0 | Thoughtspot: 10.3.0.cl
1048
+ * @example
1049
+ * ```js
1050
+ * const embed = new AppEmbed('#tsEmbed', {
1051
+ * ... // other options
1052
+ * dataPanelV2: true,
1053
+ * })
1054
+ * ```
1055
+ */
1056
+ dataPanelV2?: boolean;
1057
+ /**
1058
+ * To enable custom column groups in data panel v2
1059
+ * @version SDK: 1.32.0 | Thoughtspot: 10.0.0.cl
1060
+ * @default false
1061
+ * @example
1062
+ * ```js
1063
+ * const embed = new SearchEmbed('#tsEmbed', {
1064
+ * ... // other options
1065
+ * enableCustomColumnGroups: true,
1066
+ * });
1067
+ * ```
1068
+ */
1069
+ enableCustomColumnGroups?: boolean;
1043
1070
  }
1044
1071
 
1045
1072
  /**
@@ -1252,6 +1279,28 @@ export interface RuntimeParameter {
1252
1279
  * console.log('Drilldown event', drilldown);
1253
1280
  * }));
1254
1281
  * ```
1282
+ *
1283
+ * If you are using React components for embedding, you can register to any
1284
+ * events from the `EmbedEvent` list by using the `on<EventName>` convention.
1285
+ * For example,`onAlert`, `onCopyToClipboard` and so on.
1286
+ *
1287
+ * @example
1288
+ * ```js
1289
+ * // ...
1290
+ * const MyComponent = ({ dataSources }) => {
1291
+ * const onLoad = () => {
1292
+ * console.log(EmbedEvent.Load, {});
1293
+ * };
1294
+ *
1295
+ * return (
1296
+ * <SearchEmbed
1297
+ * dataSources={dataSources}
1298
+ * onLoad = {logEvent("Load")}
1299
+ * />
1300
+ * );
1301
+ * };
1302
+ * ```
1303
+ *
1255
1304
  * @group Events
1256
1305
  */
1257
1306
  // eslint-disable-next-line no-shadow
@@ -2121,21 +2170,61 @@ export enum EmbedEvent {
2121
2170
  */
2122
2171
  Rename = 'rename',
2123
2172
  /**
2124
- * Emitted when user wants to intercept the search execution
2173
+ * Emitted if the user wants to intercept the search execution
2174
+ * and implement logic to decide whether to run the search or not
2125
2175
  *
2126
- * Set IsOnBeforeGetVizDataInterceptEnabled : true to use
2127
- * this embed event
2176
+ * Prerequisite: Set isOnBeforeGetVizDataInterceptEnabled : true
2177
+ * for this embed event to get emitted.
2178
+ *
2179
+ * @param: payload
2180
+ * @param: responder
2181
+ * Contains elements that lets developers define whether ThoughtSpot
2182
+ * will run the search or not, and if not, which error message to provide.
2183
+ *
2184
+ * execute: When execute returns true, the search will be run.
2185
+ * When execute returns false, the search will not be executed.
2186
+ *
2187
+ * error: Developers can customize the user facing message when execute is
2188
+ * set to false using the error parameter in responder
2189
+ *
2190
+ * @version SDK : 1.29.0 | Thoughtspot : 10.2.0.cl
2128
2191
  *
2192
+ * @example
2129
2193
  *```js
2130
- * searchEmbed.on(EmbedEvent.OnBeforeGetVizDataIntercept,
2194
+ * .on(EmbedEvent.OnBeforeGetVizDataIntercept,
2131
2195
  * (payload, responder) => {
2132
2196
  * responder({
2133
2197
  * data: {
2134
- * execute: true,
2135
- * }})
2198
+ * execute:false,
2199
+ * error: {
2200
+ * //Provide a custom error message to explain to your end user
2201
+ * //why their search did not run
2202
+ * errorText: "This search query cannot be run.
2203
+ * Please contact your administrator for more details."
2204
+ * }
2205
+ * }})
2206
+ * })
2207
+ * ```
2208
+ *
2209
+ *```js
2210
+ * .on(EmbedEvent.OnBeforeGetVizDataIntercept,
2211
+ * (payload, responder) => {
2212
+ * const query = payload.data.data.answer.search_query
2213
+ * responder({
2214
+ * data: {
2215
+ * // returns true as long as the query does not include
2216
+ * // both the 'sales' AND the 'county' column
2217
+ * execute: !(query.includes("sales")&&query.includes("county")),
2218
+ * error: {
2219
+ * //Provide a custom error message to explain to your end user
2220
+ * // why their search did not run, and which searches are accepted by your custom logic.
2221
+ * errorText: "You can't use this query :" + query + ".
2222
+ * The 'sales' measures can never be used at the 'county' level.
2223
+ * Please try another measure, or remove 'county' from your search."
2224
+ * }
2225
+ * }})
2136
2226
  * })
2137
2227
  *```
2138
- * @version SDK : 1.29.0 | Thoughtspot : 10.2.0.cl
2139
2228
  */
2140
2229
  OnBeforeGetVizDataIntercept = 'onBeforeGetVizDataIntercept',
2141
2230
  /**
@@ -2154,7 +2243,7 @@ export enum EmbedEvent {
2154
2243
 
2155
2244
  /**
2156
2245
  * Event types that can be triggered by the host application
2157
- * to the embedded ThoughtSpot app
2246
+ * to the embedded ThoughtSpot app.
2158
2247
  *
2159
2248
  * To trigger an event use the corresponding
2160
2249
  * {@link LiveboardEmbed.trigger} or {@link AppEmbed.trigger} or {@link
@@ -2171,6 +2260,40 @@ export enum EmbedEvent {
2171
2260
  * { columnName: 'state, operator: RuntimeFilterOp.EQ, values: ['california']}
2172
2261
  * ]);
2173
2262
  * ```
2263
+ * @example
2264
+ * If using React components to embed, use the format shown in this example:
2265
+ *
2266
+ * ```js
2267
+ * const selectVizs = () => {
2268
+ * embedRef.current.trigger(HostEvent.SetVisibleVizs, [
2269
+ * "715e4613-c891-4884-be44-aa8d13701c06",
2270
+ * "3f84d633-e325-44b2-be25-c6650e5a49cf"
2271
+ * ]);
2272
+ * };
2273
+ * ```
2274
+ *
2275
+ *
2276
+ * You can also attach an Embed event to a Host event to trigger
2277
+ * a specific action as shown in this example:
2278
+ *
2279
+ * @example
2280
+ * ```js
2281
+ * const EmbeddedComponent = () => {
2282
+ * const embedRef = useRef(null); // import { useRef } from react
2283
+ * const onLiveboardRendered = () => {
2284
+ * embedRef.current.trigger(HostEvent.SetVisibleVizs, ['viz1', 'viz2']);
2285
+ * };
2286
+ *
2287
+ * return (
2288
+ * <LiveboardEmbed
2289
+ * ref={embedRef}
2290
+ * liveboardId="<liveboard-guid>"
2291
+ * onLiveboardRendered={onLiveboardRendered}
2292
+ * />
2293
+ * );
2294
+ * }
2295
+ * ```
2296
+ *
2174
2297
  * @group Events
2175
2298
  */
2176
2299
  // eslint-disable-next-line no-shadow
@@ -2255,6 +2378,15 @@ export enum HostEvent {
2255
2378
  * @hidden
2256
2379
  */
2257
2380
  Reload = 'reload',
2381
+ /**
2382
+ * Get current iframe src
2383
+ * @example
2384
+ * ```js
2385
+ * const frameUrl = AppEmbed.trigger(HostEvent.GetIframeUrl)
2386
+ * ```
2387
+ * @version SDK: 1.35.0 | Thoughtspot: 10.4.0.cl
2388
+ */
2389
+ GetIframeUrl = 'GetIframeUrl',
2258
2390
  /**
2259
2391
  * Display specific visualizations on a Liveboard.
2260
2392
  * @param - An array of GUIDs of the visualization to show. The visualization IDs not passed
@@ -2856,10 +2988,23 @@ export enum HostEvent {
2856
2988
  * filter: {
2857
2989
  * column: "item type",
2858
2990
  * oper: "IN",
2859
- * values: ["bags","shirts"],
2991
+ * values: ["bags","shirts"]
2992
+ * }
2993
+ * });
2994
+ * ```
2995
+ * @example
2996
+ * ```js
2997
+ *
2998
+ * liveboardEmbed.trigger(HostEvent.UpdateFilters, {
2999
+ * filter: {
3000
+ * column: "date",
3001
+ * oper: "EQ",
3002
+ * values: ["JULY","2023"],
3003
+ * type: "MONTH_YEAR"
2860
3004
  * }
2861
3005
  * });
2862
3006
  * ```
3007
+ *
2863
3008
  * @example
2864
3009
  *
2865
3010
  * ```js
@@ -2877,7 +3022,8 @@ export enum HostEvent {
2877
3022
  * {
2878
3023
  * column: "Date",
2879
3024
  * oper: 'EQ',
2880
- * values: ["1656680400"]
3025
+ * values: ["2023-07-31"],
3026
+ * types: "EXACT_DATE"
2881
3027
  * }]
2882
3028
  * });
2883
3029
  * ```
@@ -3067,7 +3213,6 @@ export enum Param {
3067
3213
  ViewPortHeight = 'viewPortHeight',
3068
3214
  ViewPortWidth = 'viewPortWidth',
3069
3215
  VisibleActions = 'visibleAction',
3070
- CustomCSSUrl = 'customCssUrl',
3071
3216
  DisableLoginRedirect = 'disableLoginRedirect',
3072
3217
  visibleVizs = 'pinboardVisibleVizs',
3073
3218
  LiveboardV2Enabled = 'isPinboardV2Enabled',
@@ -3126,6 +3271,9 @@ export enum Param {
3126
3271
  FocusSearchBarOnRender = 'focusSearchBarOnRender',
3127
3272
  DisableRedirectionLinksInNewTab = 'disableRedirectionLinksInNewTab',
3128
3273
  HomePageSearchBarMode = 'homePageSearchBarMode',
3274
+ ShowLiveboardVerifiedBadge = 'showLiveboardVerifiedBadge',
3275
+ ShowLiveboardReverifyBanner = 'showLiveboardReverifyBanner',
3276
+ LiveboardHeaderV2 = 'isLiveboardHeaderV2Enabled',
3129
3277
  }
3130
3278
 
3131
3279
  /**
@@ -4052,7 +4200,7 @@ export enum Action {
4052
4200
  *
4053
4201
  * @version SDK: 1.32.0 | Thoughtspot: 10.1.0.cl
4054
4202
  */
4055
- CreateLiveboard = 'CreateLiveboard',
4203
+ CreateLiveboard = 'createLiveboard',
4056
4204
 
4057
4205
  /**
4058
4206
  * Action ID for to hide Verified Liveboard Banner
@@ -4154,6 +4302,17 @@ export enum Action {
4154
4302
  */
4155
4303
  UnsubscribeScheduleHomepage = 'unsubscribeScheduleHomepage',
4156
4304
 
4305
+ /**
4306
+ * The **Manage Tags** action on Homepage Favourite Module.
4307
+ *
4308
+ * @example
4309
+ * ```js
4310
+ * disabledActions: [Action.ManageTags]
4311
+ * ```
4312
+ * @version SDK : 1.34.0 | Thoughtspot: 10.3.0.cl
4313
+ */
4314
+ ManageTags = 'manageTags',
4315
+
4157
4316
  /**
4158
4317
  * Action ID for delete schedule action on schedule on homepage
4159
4318
  * @example
@@ -29,7 +29,9 @@ describe('Unit test for authService', () => {
29
29
  const response = await fetchSessionInfoService(thoughtSpotHost);
30
30
  expect(response.success).toBe(true);
31
31
  expect(fetch).toHaveBeenCalledTimes(1);
32
- expect(fetch).toBeCalledWith(`${thoughtSpotHost}${EndPoints.SESSION_INFO}`, {});
32
+ expect(fetch).toBeCalledWith(`${thoughtSpotHost}${EndPoints.SESSION_INFO}`, {
33
+ credentials: 'include',
34
+ });
33
35
  });
34
36
 
35
37
  test('fetchAuthTokenService', async () => {
@@ -101,7 +101,6 @@ export const getAnswer = `
101
101
  isDiscoverable
102
102
  isHidden
103
103
  modifiedAt
104
- tags
105
104
  }
106
105
  visualizations {
107
106
  ... on TableViz {
@@ -164,3 +163,12 @@ export const addVizToLiveboard = `
164
163
  }
165
164
  }
166
165
  `;
166
+
167
+ export const getSQLQuery = `
168
+ mutation GetSQLQuery($session: BachSessionIdInput!) {
169
+ Answer__getQuery(session: $session) {
170
+ ${bachSessionId}
171
+ sql
172
+ }
173
+ }
174
+ `;
@@ -3,7 +3,9 @@ import { AuthType, RuntimeFilterOp, VizPoint } from '../../../types';
3
3
  import { AnswerService } from './answerService';
4
4
  import {
5
5
  getAnswerData, removeColumns, addFilter, addColumns,
6
+ getSQLQuery,
6
7
  } from './answer-queries';
8
+ import * as queries from './answer-queries';
7
9
  import * as authTokenInstance from '../../../authToken';
8
10
  import * as tokenizedFetch from '../../../tokenizedFetch';
9
11
  import * as embedConfigInstance from '../../../embed/embedConfig';
@@ -34,6 +36,23 @@ describe('Answer service tests', () => {
34
36
  beforeEach(() => {
35
37
  fetchMock.resetMocks();
36
38
  });
39
+
40
+ test('should call executeQuery with correct parameters to add columns', async () => {
41
+ const service = createAnswerService();
42
+ const executeQuerySpy = jest.spyOn(service, 'executeQuery').mockResolvedValue({
43
+ id: { genNo: 2 },
44
+
45
+ });
46
+
47
+ const columnIds = ['col1', 'col2'];
48
+ const result = await service.addColumns(columnIds);
49
+
50
+ expect(executeQuerySpy).toHaveBeenCalledWith(queries.addColumns, {
51
+ columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
52
+ });
53
+ expect(result.id.genNo).toBe(2);
54
+ });
55
+
37
56
  test('Execute query should execute the supplied graphql on the session', async () => {
38
57
  fetchMock.mockResponseOnce(JSON.stringify({
39
58
  data: {
@@ -146,6 +165,30 @@ describe('Answer service tests', () => {
146
165
  );
147
166
  });
148
167
 
168
+ test('fetchPNGBlob should call the right API', () => {
169
+ const answerService = createAnswerService();
170
+
171
+ const mockEmbedConfig = {
172
+ thougthspotHost: '/test',
173
+ authType: AuthType.TrustedAuthTokenCookieless,
174
+ };
175
+ jest.spyOn(embedConfigInstance, 'getEmbedConfig').mockReturnValueOnce(mockEmbedConfig);
176
+ jest.spyOn(authTokenInstance, 'getAuthenticationToken').mockReturnValueOnce(Promise.resolve('token'));
177
+ const mockTokenizedFetch = jest.spyOn(tokenizedFetch, 'tokenizedFetch');
178
+ answerService.fetchPNGBlob(undefined, true);
179
+
180
+ expect(mockTokenizedFetch).toHaveBeenCalledWith(`https://tshost/prism/download/answer/png?sessionId=${defaultSession.sessionId}&deviceScaleFactor=2&omitBackground=true&genNo=${defaultSession.genNo}&userLocale=en-us&exportFileName=data`, expect.objectContaining({}));
181
+
182
+ answerService.fetchPNGBlob('en-uk', true);
183
+ expect(mockTokenizedFetch).toHaveBeenCalledWith(`https://tshost/prism/download/answer/png?sessionId=${defaultSession.sessionId}&deviceScaleFactor=2&omitBackground=true&genNo=${defaultSession.genNo}&userLocale=en-uk&exportFileName=data`, expect.objectContaining({}));
184
+
185
+ answerService.fetchPNGBlob(undefined, false);
186
+ expect(mockTokenizedFetch).toHaveBeenCalledWith(`https://tshost/prism/download/answer/png?sessionId=${defaultSession.sessionId}&deviceScaleFactor=2&omitBackground=false&genNo=${defaultSession.genNo}&userLocale=en-us&exportFileName=data`, expect.objectContaining({}));
187
+
188
+ answerService.fetchPNGBlob(undefined, true, 3);
189
+ expect(mockTokenizedFetch).toHaveBeenCalledWith(`https://tshost/prism/download/answer/png?sessionId=${defaultSession.sessionId}&deviceScaleFactor=3&omitBackground=true&genNo=${defaultSession.genNo}&userLocale=en-us&exportFileName=data`, expect.objectContaining({}));
190
+ });
191
+
149
192
  test('getUnderlyingDataForPoint should call the right APIs', async () => {
150
193
  fetchMock.mockResponses(
151
194
  JSON.stringify({
@@ -404,4 +447,30 @@ describe('Answer service tests', () => {
404
447
  }),
405
448
  );
406
449
  });
450
+
451
+ test('Get SQL query should call the right API', async () => {
452
+ fetchMock.mockResponseOnce(JSON.stringify({
453
+ data: {
454
+ Answer__getQuery: {
455
+ id: {},
456
+ sql: 'SELECT * FROM table',
457
+ },
458
+ },
459
+ }));
460
+ const answerService = createAnswerService();
461
+ const sql = await answerService.getSQLQuery();
462
+ expect(fetchMock).toHaveBeenCalledWith(
463
+ 'https://tshost/prism/?op=GetSQLQuery',
464
+ expect.objectContaining({
465
+ body: JSON.stringify({
466
+ operationName: 'GetSQLQuery',
467
+ query: getSQLQuery,
468
+ variables: {
469
+ session: defaultSession,
470
+ },
471
+ }),
472
+ }),
473
+ );
474
+ expect(sql).toBe('SELECT * FROM table');
475
+ });
407
476
  });
@@ -173,6 +173,14 @@ export class AnswerService {
173
173
  );
174
174
  }
175
175
 
176
+ public async getSQLQuery(): Promise<string> {
177
+ const { sql } = await this.executeQuery(
178
+ queries.getSQLQuery,
179
+ {},
180
+ );
181
+ return sql;
182
+ }
183
+
176
184
  /**
177
185
  * Fetch data from the answer.
178
186
  * @param offset
@@ -214,6 +222,25 @@ export class AnswerService {
214
222
  });
215
223
  }
216
224
 
225
+ /**
226
+ * Fetch the data for the answer as a PNG blob. This might be
227
+ * quicker for larger data.
228
+ * @param userLocale
229
+ * @param omitBackground Omit the background in the PNG
230
+ * @param deviceScaleFactor The scale factor for the PNG
231
+ * @return Response
232
+ */
233
+ public async fetchPNGBlob(userLocale = 'en-us', omitBackground = false, deviceScaleFactor = 2): Promise<Response> {
234
+ const fetchUrl = this.getFetchPNGBlobUrl(
235
+ userLocale,
236
+ omitBackground,
237
+ deviceScaleFactor,
238
+ );
239
+ return tokenizedFetch(fetchUrl, {
240
+ credentials: 'include',
241
+ });
242
+ }
243
+
217
244
  /**
218
245
  * Just get the internal URL for this answer's data
219
246
  * as a CSV blob.
@@ -225,6 +252,14 @@ export class AnswerService {
225
252
  return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
226
253
  }
227
254
 
255
+ /**
256
+ * Just get the internal URL for this answer's data
257
+ * as a PNG blob.
258
+ */
259
+ public getFetchPNGBlobUrl(userLocale = 'en-us', omitBackground = false, deviceScaleFactor = 2): string {
260
+ return `${this.thoughtSpotHost}/prism/download/answer/png?sessionId=${this.session.sessionId}&deviceScaleFactor=${deviceScaleFactor}&omitBackground=${omitBackground}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data`;
261
+ }
262
+
228
263
  /**
229
264
  * Get underlying data given a point and the output column names.
230
265
  * In case of a context menu action, the selectedPoints are
@@ -0,0 +1,38 @@
1
+ import 'jest-fetch-mock';
2
+ import { getSourceDetail } from './sourceService';
3
+ import * as tokenizedFetchUtil from '../../tokenizedFetch';
4
+ import { graphqlQuery } from './graphql-request';
5
+
6
+ const getSourceDetailQuery = `
7
+ query GetSourceDetail($ids: [GUID!]!) {
8
+ getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
9
+ id
10
+ name
11
+ }
12
+ }
13
+ `;
14
+
15
+ const thoughtSpotHost = 'TSHOST';
16
+
17
+ describe('graphQl tests', () => {
18
+ test('should call tokenizedFetch with correct parameters when graphqlQuery is called', async () => {
19
+ jest.spyOn(tokenizedFetchUtil, 'tokenizedFetch');
20
+
21
+ const details = await graphqlQuery({
22
+ query: getSourceDetailQuery,
23
+ variables: {
24
+ ids: [2],
25
+ },
26
+ thoughtSpotHost,
27
+ });
28
+
29
+ expect(tokenizedFetchUtil.tokenizedFetch).toBeCalledWith('TSHOST/prism/?op=GetSourceDetail', {
30
+ body: '{"operationName":"GetSourceDetail","query":"\\n query GetSourceDetail($ids: [GUID!]!) {\\n getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {\\n id\\n name\\n }\\n } \\n","variables":{"ids":[2]}}',
31
+ credentials: 'include',
32
+ headers: {
33
+ accept: '*/*', 'accept-language': 'en-us', 'content-type': 'application/json;charset=UTF-8', 'x-requested-by': 'ThoughtSpot',
34
+ },
35
+ method: 'POST',
36
+ });
37
+ });
38
+ });