@thoughtspot/visual-embed-sdk 1.24.0-sage.2 → 1.24.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 (199) hide show
  1. package/README.md +2 -2
  2. package/cjs/package.json +9 -1
  3. package/cjs/src/auth.d.ts.map +1 -1
  4. package/cjs/src/auth.js +4 -3
  5. package/cjs/src/auth.js.map +1 -1
  6. package/cjs/src/css-variables.d.ts +38 -0
  7. package/cjs/src/css-variables.d.ts.map +1 -1
  8. package/cjs/src/embed/app.d.ts +41 -2
  9. package/cjs/src/embed/app.d.ts.map +1 -1
  10. package/cjs/src/embed/app.js +13 -9
  11. package/cjs/src/embed/app.js.map +1 -1
  12. package/cjs/src/embed/app.spec.js +56 -0
  13. package/cjs/src/embed/app.spec.js.map +1 -1
  14. package/cjs/src/embed/base.d.ts +13 -0
  15. package/cjs/src/embed/base.d.ts.map +1 -1
  16. package/cjs/src/embed/base.js +15 -2
  17. package/cjs/src/embed/base.js.map +1 -1
  18. package/cjs/src/embed/liveboard.d.ts +5 -1
  19. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  20. package/cjs/src/embed/liveboard.js +5 -2
  21. package/cjs/src/embed/liveboard.js.map +1 -1
  22. package/cjs/src/embed/liveboard.spec.js +23 -7
  23. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  24. package/cjs/src/embed/sage.d.ts +25 -2
  25. package/cjs/src/embed/sage.d.ts.map +1 -1
  26. package/cjs/src/embed/sage.js +10 -5
  27. package/cjs/src/embed/sage.js.map +1 -1
  28. package/cjs/src/embed/sage.spec.js +26 -0
  29. package/cjs/src/embed/sage.spec.js.map +1 -1
  30. package/cjs/src/embed/search-bar.d.ts +7 -1
  31. package/cjs/src/embed/search-bar.d.ts.map +1 -1
  32. package/cjs/src/embed/search-bar.js +5 -2
  33. package/cjs/src/embed/search-bar.js.map +1 -1
  34. package/cjs/src/embed/search.d.ts +22 -1
  35. package/cjs/src/embed/search.d.ts.map +1 -1
  36. package/cjs/src/embed/search.js +9 -2
  37. package/cjs/src/embed/search.js.map +1 -1
  38. package/cjs/src/embed/search.spec.js +60 -1
  39. package/cjs/src/embed/search.spec.js.map +1 -1
  40. package/cjs/src/embed/ts-embed.d.ts +3 -1
  41. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  42. package/cjs/src/embed/ts-embed.js +28 -8
  43. package/cjs/src/embed/ts-embed.js.map +1 -1
  44. package/cjs/src/embed/ts-embed.spec.js +139 -3
  45. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  46. package/cjs/src/index.d.ts +2 -2
  47. package/cjs/src/index.d.ts.map +1 -1
  48. package/cjs/src/index.js +3 -1
  49. package/cjs/src/index.js.map +1 -1
  50. package/cjs/src/mixpanel-service.d.ts +1 -0
  51. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  52. package/cjs/src/mixpanel-service.js +10 -3
  53. package/cjs/src/mixpanel-service.js.map +1 -1
  54. package/cjs/src/mixpanel-service.spec.js +12 -3
  55. package/cjs/src/mixpanel-service.spec.js.map +1 -1
  56. package/cjs/src/react/index.d.ts +15 -15
  57. package/cjs/src/react/index.d.ts.map +1 -1
  58. package/cjs/src/react/index.js +7 -3
  59. package/cjs/src/react/index.js.map +1 -1
  60. package/cjs/src/react/index.spec.js +13 -1
  61. package/cjs/src/react/index.spec.js.map +1 -1
  62. package/cjs/src/types.d.ts +202 -18
  63. package/cjs/src/types.d.ts.map +1 -1
  64. package/cjs/src/types.js +140 -13
  65. package/cjs/src/types.js.map +1 -1
  66. package/cjs/src/utils.d.ts +7 -1
  67. package/cjs/src/utils.d.ts.map +1 -1
  68. package/cjs/src/utils.js +20 -1
  69. package/cjs/src/utils.js.map +1 -1
  70. package/cjs/src/utils.spec.js +24 -0
  71. package/cjs/src/utils.spec.js.map +1 -1
  72. package/dist/src/auth.d.ts.map +1 -1
  73. package/dist/src/css-variables.d.ts +38 -0
  74. package/dist/src/css-variables.d.ts.map +1 -1
  75. package/dist/src/embed/app.d.ts +41 -2
  76. package/dist/src/embed/app.d.ts.map +1 -1
  77. package/dist/src/embed/base.d.ts +13 -0
  78. package/dist/src/embed/base.d.ts.map +1 -1
  79. package/dist/src/embed/liveboard.d.ts +5 -1
  80. package/dist/src/embed/liveboard.d.ts.map +1 -1
  81. package/dist/src/embed/sage.d.ts +25 -2
  82. package/dist/src/embed/sage.d.ts.map +1 -1
  83. package/dist/src/embed/search-bar.d.ts +7 -1
  84. package/dist/src/embed/search-bar.d.ts.map +1 -1
  85. package/dist/src/embed/search.d.ts +22 -1
  86. package/dist/src/embed/search.d.ts.map +1 -1
  87. package/dist/src/embed/ts-embed.d.ts +3 -1
  88. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  89. package/dist/src/index.d.ts +2 -2
  90. package/dist/src/index.d.ts.map +1 -1
  91. package/dist/src/mixpanel-service.d.ts +1 -0
  92. package/dist/src/mixpanel-service.d.ts.map +1 -1
  93. package/dist/src/react/index.d.ts +15 -15
  94. package/dist/src/react/index.d.ts.map +1 -1
  95. package/dist/src/types.d.ts +202 -18
  96. package/dist/src/types.d.ts.map +1 -1
  97. package/dist/src/utils.d.ts +7 -1
  98. package/dist/src/utils.d.ts.map +1 -1
  99. package/dist/tsembed-react.es.js +329 -17329
  100. package/dist/tsembed-react.js +322 -17328
  101. package/dist/tsembed.es.js +353 -17342
  102. package/dist/tsembed.js +346 -17341
  103. package/dist/visual-embed-sdk-react-full.d.ts +754 -424
  104. package/dist/visual-embed-sdk-react.d.ts +703 -373
  105. package/dist/visual-embed-sdk.d.ts +354 -25
  106. package/lib/package.json +9 -1
  107. package/lib/src/auth.d.ts.map +1 -1
  108. package/lib/src/auth.js +4 -2
  109. package/lib/src/auth.js.map +1 -1
  110. package/lib/src/css-variables.d.ts +38 -0
  111. package/lib/src/css-variables.d.ts.map +1 -1
  112. package/lib/src/embed/app.d.ts +41 -2
  113. package/lib/src/embed/app.d.ts.map +1 -1
  114. package/lib/src/embed/app.js +13 -9
  115. package/lib/src/embed/app.js.map +1 -1
  116. package/lib/src/embed/app.spec.js +56 -0
  117. package/lib/src/embed/app.spec.js.map +1 -1
  118. package/lib/src/embed/base.d.ts +13 -0
  119. package/lib/src/embed/base.d.ts.map +1 -1
  120. package/lib/src/embed/base.js +15 -2
  121. package/lib/src/embed/base.js.map +1 -1
  122. package/lib/src/embed/liveboard.d.ts +5 -1
  123. package/lib/src/embed/liveboard.d.ts.map +1 -1
  124. package/lib/src/embed/liveboard.js +6 -3
  125. package/lib/src/embed/liveboard.js.map +1 -1
  126. package/lib/src/embed/liveboard.spec.js +23 -7
  127. package/lib/src/embed/liveboard.spec.js.map +1 -1
  128. package/lib/src/embed/sage.d.ts +25 -2
  129. package/lib/src/embed/sage.d.ts.map +1 -1
  130. package/lib/src/embed/sage.js +10 -5
  131. package/lib/src/embed/sage.js.map +1 -1
  132. package/lib/src/embed/sage.spec.js +26 -0
  133. package/lib/src/embed/sage.spec.js.map +1 -1
  134. package/lib/src/embed/search-bar.d.ts +7 -1
  135. package/lib/src/embed/search-bar.d.ts.map +1 -1
  136. package/lib/src/embed/search-bar.js +6 -3
  137. package/lib/src/embed/search-bar.js.map +1 -1
  138. package/lib/src/embed/search.d.ts +22 -1
  139. package/lib/src/embed/search.d.ts.map +1 -1
  140. package/lib/src/embed/search.js +10 -3
  141. package/lib/src/embed/search.js.map +1 -1
  142. package/lib/src/embed/search.spec.js +60 -1
  143. package/lib/src/embed/search.spec.js.map +1 -1
  144. package/lib/src/embed/ts-embed.d.ts +3 -1
  145. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  146. package/lib/src/embed/ts-embed.js +29 -9
  147. package/lib/src/embed/ts-embed.js.map +1 -1
  148. package/lib/src/embed/ts-embed.spec.js +140 -4
  149. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  150. package/lib/src/index.d.ts +2 -2
  151. package/lib/src/index.d.ts.map +1 -1
  152. package/lib/src/index.js +2 -2
  153. package/lib/src/index.js.map +1 -1
  154. package/lib/src/mixpanel-service.d.ts +1 -0
  155. package/lib/src/mixpanel-service.d.ts.map +1 -1
  156. package/lib/src/mixpanel-service.js +10 -3
  157. package/lib/src/mixpanel-service.js.map +1 -1
  158. package/lib/src/mixpanel-service.spec.js +12 -3
  159. package/lib/src/mixpanel-service.spec.js.map +1 -1
  160. package/lib/src/react/index.d.ts +15 -15
  161. package/lib/src/react/index.d.ts.map +1 -1
  162. package/lib/src/react/index.js +5 -3
  163. package/lib/src/react/index.js.map +1 -1
  164. package/lib/src/react/index.spec.js +14 -2
  165. package/lib/src/react/index.spec.js.map +1 -1
  166. package/lib/src/types.d.ts +202 -18
  167. package/lib/src/types.d.ts.map +1 -1
  168. package/lib/src/types.js +139 -12
  169. package/lib/src/types.js.map +1 -1
  170. package/lib/src/utils.d.ts +7 -1
  171. package/lib/src/utils.d.ts.map +1 -1
  172. package/lib/src/utils.js +18 -0
  173. package/lib/src/utils.js.map +1 -1
  174. package/lib/src/utils.spec.js +25 -1
  175. package/lib/src/utils.spec.js.map +1 -1
  176. package/lib/src/visual-embed-sdk.d.ts +357 -28
  177. package/package.json +9 -1
  178. package/src/auth.ts +7 -5
  179. package/src/css-variables.ts +47 -0
  180. package/src/embed/app.spec.ts +78 -0
  181. package/src/embed/app.ts +61 -16
  182. package/src/embed/base.ts +18 -5
  183. package/src/embed/liveboard.spec.ts +29 -10
  184. package/src/embed/liveboard.ts +11 -2
  185. package/src/embed/sage.spec.ts +32 -0
  186. package/src/embed/sage.ts +38 -5
  187. package/src/embed/search-bar.tsx +19 -6
  188. package/src/embed/search.spec.ts +76 -1
  189. package/src/embed/search.ts +43 -2
  190. package/src/embed/ts-embed.spec.ts +162 -8
  191. package/src/embed/ts-embed.ts +30 -9
  192. package/src/index.ts +4 -0
  193. package/src/mixpanel-service.spec.ts +12 -3
  194. package/src/mixpanel-service.ts +10 -3
  195. package/src/react/index.spec.tsx +34 -3
  196. package/src/react/index.tsx +37 -26
  197. package/src/types.ts +277 -102
  198. package/src/utils.spec.ts +31 -0
  199. package/src/utils.ts +23 -0
@@ -1,6 +1,4 @@
1
- import {
2
- DOMSelector, Param, Action, ViewConfig,
3
- } from '../types';
1
+ import { Param, ViewConfig } from '../types';
4
2
  import { getQueryParamString } from '../utils';
5
3
  import { TsEmbed } from './ts-embed';
6
4
  import { SearchOptions } from './search';
@@ -8,7 +6,8 @@ import { SearchOptions } from './search';
8
6
  /**
9
7
  * @group Embed components
10
8
  */
11
- export interface SearchBarViewConfig extends Omit<ViewConfig, 'runtimeFilters' | 'showAlerts'> {
9
+ export interface SearchBarViewConfig
10
+ extends Omit<ViewConfig, 'runtimeFilters' | 'showAlerts' | 'dataPanelV2'> {
12
11
  /**
13
12
  * The array of data source GUIDs to set on load.
14
13
  * Only a single dataSource supported currently.
@@ -22,6 +21,12 @@ export interface SearchBarViewConfig extends Omit<ViewConfig, 'runtimeFilters' |
22
21
  * @version: SDK: 1.19.0
23
22
  */
24
23
  dataSource?: string;
24
+ /**
25
+ * Flag to set if last selected dataSource should be used
26
+ *
27
+ * @version: SDK: 1.24.0
28
+ */
29
+ useLastSelectedSources?: boolean;
25
30
  /**
26
31
  * Configuration for search options
27
32
  */
@@ -52,7 +57,12 @@ export class SearchBarEmbed extends TsEmbed {
52
57
  * @param dataSources A list of data source GUIDs
53
58
  */
54
59
  private getIFrameSrc() {
55
- const { searchOptions, dataSource, dataSources } = this.viewConfig;
60
+ const {
61
+ searchOptions,
62
+ dataSource,
63
+ dataSources,
64
+ useLastSelectedSources = false,
65
+ } = this.viewConfig;
56
66
  const path = 'search-bar-embed';
57
67
  const queryParams = this.getBaseQueryParams();
58
68
 
@@ -74,7 +84,10 @@ export class SearchBarEmbed extends TsEmbed {
74
84
  }
75
85
  }
76
86
 
77
- queryParams[Param.UseLastSelectedDataSource] = false;
87
+ queryParams[Param.UseLastSelectedDataSource] = useLastSelectedSources;
88
+ if (dataSource || dataSources) {
89
+ queryParams[Param.UseLastSelectedDataSource] = false;
90
+ }
78
91
  queryParams[Param.searchEmbed] = true;
79
92
  let query = '';
80
93
  const queryParamsString = getQueryParamString(queryParams, true);
@@ -47,7 +47,7 @@ describe('Search embed tests', () => {
47
47
  await executeAfterWait(() => {
48
48
  expectUrlMatchesWithParams(
49
49
  getIFrameSrc(),
50
- `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSourceMode=expand&useLastSelectedSources=false${prefixParams}#/embed/answer`,
50
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&enableDataPanelV2=false&dataSourceMode=expand&useLastSelectedSources=false${prefixParams}#/embed/answer`,
51
51
  );
52
52
  });
53
53
  });
@@ -336,4 +336,79 @@ describe('Search embed tests', () => {
336
336
  );
337
337
  });
338
338
  });
339
+
340
+ test('should set enableDataPanelV2 to true if data panel v2 flag is true', async () => {
341
+ const searchEmbed = new SearchEmbed(getRootEl(), {
342
+ ...defaultViewConfig,
343
+ dataPanelV2: true,
344
+ });
345
+ searchEmbed.render();
346
+ await executeAfterWait(() => {
347
+ expectUrlMatchesWithParams(
348
+ getIFrameSrc(),
349
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSourceMode=expand&enableDataPanelV2=true&useLastSelectedSources=false${prefixParams}#/embed/saved-answer/${answerId}`,
350
+ );
351
+ });
352
+ });
353
+ test('should set useLastSelectedSources to true if useLastSelectedSources flag is true', async () => {
354
+ const searchEmbed = new SearchEmbed(getRootEl(), {
355
+ ...defaultViewConfig,
356
+ useLastSelectedSources: true,
357
+ });
358
+ searchEmbed.render();
359
+ await executeAfterWait(() => {
360
+ expectUrlMatchesWithParams(
361
+ getIFrameSrc(),
362
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSourceMode=expand&enableDataPanelV2=false&useLastSelectedSources=true${prefixParams}#/embed/saved-answer/${answerId}`,
363
+ );
364
+ });
365
+ });
366
+ test('should set useLastSelectedSources to false if datasource is given irrespective of useLastSelectedSources', async () => {
367
+ const dataSource = 'data-source-1';
368
+ const searchEmbed = new SearchEmbed(getRootEl(), {
369
+ ...defaultViewConfig,
370
+ useLastSelectedSources: true,
371
+ dataSource,
372
+ });
373
+ searchEmbed.render();
374
+ await executeAfterWait(() => {
375
+ expectUrlMatchesWithParams(
376
+ getIFrameSrc(),
377
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSources=[%22data-source-1%22]&dataSourceMode=expand&enableDataPanelV2=false&useLastSelectedSources=false${prefixParams}#/embed/saved-answer/${answerId}`,
378
+ );
379
+ });
380
+ });
381
+ test('should set useLastSelectedSources to false if datasources are given irrespective of useLastSelectedSources', async () => {
382
+ const dataSources = ['data-source-1'];
383
+ const searchEmbed = new SearchEmbed(getRootEl(), {
384
+ ...defaultViewConfig,
385
+ useLastSelectedSources: true,
386
+ dataSources,
387
+ });
388
+ searchEmbed.render();
389
+ await executeAfterWait(() => {
390
+ expectUrlMatchesWithParams(
391
+ getIFrameSrc(),
392
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSources=[%22data-source-1%22]&dataSourceMode=expand&enableDataPanelV2=false&useLastSelectedSources=false${prefixParams}#/embed/saved-answer/${answerId}`,
393
+ );
394
+ });
395
+ });
396
+ test('should set runtime parametere values in url params', async () => {
397
+ const searchEmbed = new SearchEmbed(getRootEl(), {
398
+ ...defaultViewConfig,
399
+ runtimeParameters: [
400
+ {
401
+ name: 'Integer Date Range',
402
+ value: 1,
403
+ },
404
+ ],
405
+ });
406
+ searchEmbed.render();
407
+ await executeAfterWait(() => {
408
+ expectUrlMatchesWithParams(
409
+ getIFrameSrc(),
410
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSourceMode=expand&useLastSelectedSources=false${prefixParams}&param1=Integer%20Date%20Range&paramVal1=1#/embed/saved-answer/${answerId}`,
411
+ );
412
+ });
413
+ });
339
414
  });
@@ -14,8 +14,14 @@ import {
14
14
  Action,
15
15
  ViewConfig,
16
16
  RuntimeFilter,
17
+ RuntimeParameter,
17
18
  } from '../types';
18
- import { getQueryParamString, checkReleaseVersionInBeta, getFilterQuery } from '../utils';
19
+ import {
20
+ getQueryParamString,
21
+ checkReleaseVersionInBeta,
22
+ getFilterQuery,
23
+ getRuntimeParameters,
24
+ } from '../utils';
19
25
  import { TsEmbed } from './ts-embed';
20
26
  import { version } from '../../package.json';
21
27
  import { ERROR_MESSAGE } from '../errors';
@@ -60,6 +66,10 @@ export interface SearchViewConfig extends ViewConfig {
60
66
  * using raw answer data.
61
67
  */
62
68
  hideResults?: boolean;
69
+ /**
70
+ * If set to true, expands all the data sources panel.
71
+ */
72
+ expandAllDataSource?: boolean;
63
73
  /**
64
74
  * If set to true, the Search Assist feature is enabled.
65
75
  *
@@ -105,6 +115,23 @@ export interface SearchViewConfig extends ViewConfig {
105
115
  * @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl
106
116
  */
107
117
  hideSearchBar?: boolean;
118
+ /**
119
+ * Flag to control Data panel experience
120
+ *
121
+ * @default false
122
+ * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl
123
+ */
124
+ dataPanelV2?: boolean;
125
+ /**
126
+ * Flag to set if last selected dataSource should be used
127
+ *
128
+ * @version: SDK: 1.24.0
129
+ */
130
+ useLastSelectedSources?: boolean;
131
+ /**
132
+ * The list of parameter override to apply to a search answer.
133
+ */
134
+ runtimeParameters?: RuntimeParameter[];
108
135
  }
109
136
 
110
137
  export const HiddenActionItemByDefaultForSearchEmbed = [
@@ -150,6 +177,7 @@ export class SearchEmbed extends TsEmbed {
150
177
  protected getEmbedParams(): string {
151
178
  const {
152
179
  hideResults,
180
+ expandAllDataSource,
153
181
  enableSearchAssist,
154
182
  forceTable,
155
183
  searchOptions,
@@ -157,6 +185,9 @@ export class SearchEmbed extends TsEmbed {
157
185
  dataSource,
158
186
  dataSources,
159
187
  excludeRuntimeFiltersfromURL,
188
+ dataPanelV2 = false,
189
+ useLastSelectedSources = false,
190
+ runtimeParameters,
160
191
  } = this.viewConfig;
161
192
  const queryParams = this.getBaseQueryParams();
162
193
 
@@ -190,14 +221,24 @@ export class SearchEmbed extends TsEmbed {
190
221
  queryParams[Param.ForceTable] = true;
191
222
  }
192
223
 
224
+ queryParams[Param.DataPanelV2Enabled] = dataPanelV2;
193
225
  queryParams[Param.DataSourceMode] = this.getDataSourceMode();
194
- queryParams[Param.UseLastSelectedDataSource] = false;
226
+
227
+ queryParams[Param.UseLastSelectedDataSource] = useLastSelectedSources;
228
+ if (dataSource || dataSources) {
229
+ queryParams[Param.UseLastSelectedDataSource] = false;
230
+ }
231
+
195
232
  queryParams[Param.searchEmbed] = true;
196
233
  let query = '';
197
234
  const queryParamsString = getQueryParamString(queryParams, true);
198
235
  if (queryParamsString) {
199
236
  query = `?${queryParamsString}`;
200
237
  }
238
+
239
+ const parameterQuery = getRuntimeParameters(runtimeParameters || []);
240
+ if (parameterQuery) query += `&${parameterQuery}`;
241
+
201
242
  const filterQuery = getFilterQuery(runtimeFilters || []);
202
243
  if (filterQuery && !excludeRuntimeFiltersfromURL) {
203
244
  query += `&${filterQuery}`;
@@ -9,7 +9,13 @@ import {
9
9
  AppEmbed,
10
10
  LiveboardEmbed,
11
11
  } from '../index';
12
- import { Action, RuntimeFilter, RuntimeFilterOp } from '../types';
12
+ import {
13
+ Action,
14
+ HomeLeftNavItem,
15
+ RuntimeFilter,
16
+ RuntimeFilterOp,
17
+ HomepageModule,
18
+ } from '../types';
13
19
  import {
14
20
  executeAfterWait,
15
21
  getDocumentBody,
@@ -101,7 +107,13 @@ describe('Unit test case for ts embed', () => {
101
107
  });
102
108
  expect(mockPort.postMessage).toHaveBeenCalledWith({
103
109
  type: EmbedEvent.APP_INIT,
104
- data: { customisations, authToken: '', runtimeFilterParams: null },
110
+ data: {
111
+ customisations,
112
+ authToken: '',
113
+ runtimeFilterParams: null,
114
+ hiddenHomeLeftNavItems: [],
115
+ hiddenHomepageModules: [],
116
+ },
105
117
  });
106
118
  });
107
119
 
@@ -128,6 +140,8 @@ describe('Unit test case for ts embed', () => {
128
140
  customisations: customisationsView,
129
141
  authToken: '',
130
142
  runtimeFilterParams: null,
143
+ hiddenHomeLeftNavItems: [],
144
+ hiddenHomepageModules: [],
131
145
  },
132
146
  });
133
147
  expect(getIFrameSrc()).toContain(
@@ -135,7 +149,43 @@ describe('Unit test case for ts embed', () => {
135
149
  );
136
150
  });
137
151
 
138
- test('Runtime filters from view Config should be part of app_init payload', async () => {
152
+ test('hide home page modules from view Config should be part of app_init payload', async () => {
153
+ const mockEmbedEventPayload = {
154
+ type: EmbedEvent.APP_INIT,
155
+ data: {},
156
+ };
157
+ const mockedHiddenHomepageModules: HomepageModule[] = [
158
+ HomepageModule.MyLibrary,
159
+ HomepageModule.Learning,
160
+ ];
161
+
162
+ const searchEmbed = new SearchEmbed(getRootEl(), {
163
+ ...defaultViewConfig,
164
+ hiddenHomepageModules: mockedHiddenHomepageModules,
165
+ });
166
+ searchEmbed.render();
167
+ const mockPort: any = {
168
+ postMessage: jest.fn(),
169
+ };
170
+ await executeAfterWait(() => {
171
+ const iframe = getIFrameEl();
172
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
173
+ });
174
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
175
+ type: EmbedEvent.APP_INIT,
176
+ data: {
177
+ customisations,
178
+ authToken: '',
179
+ hostConfig: undefined,
180
+ runtimeFilterParams: null,
181
+ hiddenHomeLeftNavItems: [],
182
+ hiddenHomepageModules: [HomepageModule.MyLibrary,
183
+ HomepageModule.Learning],
184
+ },
185
+ });
186
+ });
187
+
188
+ test('Runtime filters from view Config should be part of app_init payload when excludeRuntimeFiltersfromURL is true', async () => {
139
189
  const mockEmbedEventPayload = {
140
190
  type: EmbedEvent.APP_INIT,
141
191
  data: {},
@@ -150,6 +200,7 @@ describe('Unit test case for ts embed', () => {
150
200
 
151
201
  const searchEmbed = new SearchEmbed(getRootEl(), {
152
202
  ...defaultViewConfig,
203
+ excludeRuntimeFiltersfromURL: true,
153
204
  runtimeFilters: mockRuntimeFilters,
154
205
  });
155
206
  searchEmbed.render();
@@ -166,6 +217,82 @@ describe('Unit test case for ts embed', () => {
166
217
  customisations,
167
218
  authToken: '',
168
219
  runtimeFilterParams: 'col1=color&op1=EQ&val1=blue',
220
+ hiddenHomeLeftNavItems: [],
221
+ hiddenHomepageModules: [],
222
+ },
223
+ });
224
+ });
225
+
226
+ test('Runtime filters from view Config should not be part of app_init payload when excludeRuntimeFiltersfromURL is false', async () => {
227
+ const mockEmbedEventPayload = {
228
+ type: EmbedEvent.APP_INIT,
229
+ data: {},
230
+ };
231
+ const mockRuntimeFilters: RuntimeFilter[] = [
232
+ {
233
+ columnName: 'color',
234
+ operator: RuntimeFilterOp.EQ,
235
+ values: ['blue'],
236
+ },
237
+ ];
238
+
239
+ const searchEmbed = new SearchEmbed(getRootEl(), {
240
+ ...defaultViewConfig,
241
+ excludeRuntimeFiltersfromURL: false,
242
+ runtimeFilters: mockRuntimeFilters,
243
+ });
244
+ searchEmbed.render();
245
+ const mockPort: any = {
246
+ postMessage: jest.fn(),
247
+ };
248
+ await executeAfterWait(() => {
249
+ const iframe = getIFrameEl();
250
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
251
+ });
252
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
253
+ type: EmbedEvent.APP_INIT,
254
+ data: {
255
+ customisations,
256
+ authToken: '',
257
+ runtimeFilterParams: null,
258
+ hiddenHomeLeftNavItems: [],
259
+ hiddenHomepageModules: [],
260
+ },
261
+ });
262
+ });
263
+
264
+ test('homeLeftNav from view Config should be part of app_init payload', async () => {
265
+ const mockEmbedEventPayload = {
266
+ type: EmbedEvent.APP_INIT,
267
+ data: {},
268
+ };
269
+ const mockedHiddenHomeLeftNavItems: HomeLeftNavItem[] = [
270
+ HomeLeftNavItem.Home,
271
+ HomeLeftNavItem.Documentation,
272
+ ];
273
+
274
+ const searchEmbed = new SearchEmbed(getRootEl(), {
275
+ ...defaultViewConfig,
276
+ hiddenHomeLeftNavItems: mockedHiddenHomeLeftNavItems,
277
+ });
278
+ searchEmbed.render();
279
+ const mockPort: any = {
280
+ postMessage: jest.fn(),
281
+ };
282
+ await executeAfterWait(() => {
283
+ const iframe = getIFrameEl();
284
+ postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
285
+ });
286
+ expect(mockPort.postMessage).toHaveBeenCalledWith({
287
+ type: EmbedEvent.APP_INIT,
288
+ data: {
289
+ customisations,
290
+ authToken: '',
291
+ hostConfig: undefined,
292
+ runtimeFilterParams: null,
293
+ hiddenHomeLeftNavItems: [HomeLeftNavItem.Home,
294
+ HomeLeftNavItem.Documentation],
295
+ hiddenHomepageModules: [],
169
296
  },
170
297
  });
171
298
  });
@@ -319,6 +446,8 @@ describe('Unit test case for ts embed', () => {
319
446
  customisations,
320
447
  authToken: 'test_auth_token1',
321
448
  runtimeFilterParams: null,
449
+ hiddenHomeLeftNavItems: [],
450
+ hiddenHomepageModules: [],
322
451
  },
323
452
  });
324
453
  });
@@ -463,7 +592,13 @@ describe('Unit test case for ts embed', () => {
463
592
  test('mixpanel should call with VISUAL_SDK_RENDER_COMPLETE', async () => {
464
593
  await setup(true);
465
594
  expect(mockMixPanelEvent).toBeCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_START);
466
- expect(mockMixPanelEvent).toBeCalledWith(MIXPANEL_EVENT.VISUAL_SDK_RENDER_COMPLETE);
595
+ expect(mockMixPanelEvent).toBeCalledWith(
596
+ MIXPANEL_EVENT.VISUAL_SDK_RENDER_COMPLETE,
597
+ expect.objectContaining({
598
+ elWidth: 0,
599
+ elHeight: 0,
600
+ }),
601
+ );
467
602
  });
468
603
 
469
604
  test('Should remove prefetch iframe', async () => {
@@ -840,7 +975,7 @@ describe('Unit test case for ts embed', () => {
840
975
  expectUrlMatchesWithParams(
841
976
  getIFrameSrc(),
842
977
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
843
- + `&foo=bar&baz=1&bool=true${defaultParamsPost}#/home`,
978
+ + `&foo=bar&baz=1&bool=true${defaultParamsPost}#/home`,
844
979
  );
845
980
  });
846
981
 
@@ -856,7 +991,7 @@ describe('Unit test case for ts embed', () => {
856
991
  expectUrlMatchesWithParams(
857
992
  getIFrameSrc(),
858
993
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
859
- + `&showAlerts=true${defaultParamsPost}#/home`,
994
+ + `&showAlerts=true${defaultParamsPost}#/home`,
860
995
  );
861
996
  });
862
997
  it('Sets the locale param', async () => {
@@ -871,7 +1006,7 @@ describe('Unit test case for ts embed', () => {
871
1006
  expectUrlMatchesWithParams(
872
1007
  getIFrameSrc(),
873
1008
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
874
- + `&locale=ja-JP${defaultParamsPost}#/home`,
1009
+ + `&locale=ja-JP${defaultParamsPost}#/home`,
875
1010
  );
876
1011
  });
877
1012
  it('Sets the iconSprite url', async () => {
@@ -888,7 +1023,7 @@ describe('Unit test case for ts embed', () => {
888
1023
  expectUrlMatchesWithParams(
889
1024
  getIFrameSrc(),
890
1025
  `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
891
- + `&iconSprite=iconSprite.com${defaultParamsPost}#/home`,
1026
+ + `&iconSprite=iconSprite.com${defaultParamsPost}#/home`,
892
1027
  );
893
1028
  });
894
1029
 
@@ -916,6 +1051,25 @@ describe('Unit test case for ts embed', () => {
916
1051
  await appEmbed.render();
917
1052
  expect(getRootEl().nextSibling.nextSibling).not.toBe(getIFrameEl());
918
1053
  });
1054
+ it('Should set the pendo tracking key when specified', async () => {
1055
+ jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValue(true);
1056
+ init({
1057
+ thoughtSpotHost: 'tshost',
1058
+ authType: AuthType.None,
1059
+ pendoTrackingKey: '1234',
1060
+ });
1061
+ const appEmbed = new AppEmbed(getRootEl(), {
1062
+ frameParams: {
1063
+ width: '100%',
1064
+ height: '100%',
1065
+ },
1066
+ });
1067
+ await appEmbed.render();
1068
+ expectUrlMatchesWithParams(
1069
+ getIFrameSrc(),
1070
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&additionalPendoKey=1234${defaultParamsPost}#/home`,
1071
+ );
1072
+ });
919
1073
  xit('Sets the forceSAMLAutoRedirect param', async (done) => {
920
1074
  jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValue(true);
921
1075
  init({
@@ -18,6 +18,7 @@ import {
18
18
  getDOMNode,
19
19
  getFilterQuery,
20
20
  getQueryParamString,
21
+ getRuntimeParameters,
21
22
  } from '../utils';
22
23
  import {
23
24
  getThoughtSpotHost,
@@ -156,6 +157,9 @@ export class TsEmbed {
156
157
  this.viewConfig = viewConfig;
157
158
  this.shouldEncodeUrlQueryParams = this.embedConfig.shouldEncodeUrlQueryParams;
158
159
  this.registerAppInit();
160
+ uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_EMBED_CREATE, {
161
+ ...viewConfig,
162
+ });
159
163
  }
160
164
 
161
165
  /**
@@ -269,8 +273,14 @@ export class TsEmbed {
269
273
  data: {
270
274
  customisations: getCustomisations(this.embedConfig, this.viewConfig),
271
275
  authToken,
272
- runtimeFilterParams: getRuntimeFilters(this.viewConfig.runtimeFilters),
276
+ runtimeFilterParams: this.viewConfig.excludeRuntimeFiltersfromURL
277
+ ? getRuntimeFilters(this.viewConfig.runtimeFilters)
278
+ : null,
279
+ hiddenHomepageModules: this.viewConfig.hiddenHomepageModules || [],
273
280
  hostConfig: this.embedConfig.hostConfig,
281
+ hiddenHomeLeftNavItems: this.viewConfig?.hiddenHomeLeftNavItems
282
+ ? this.viewConfig?.hiddenHomeLeftNavItems
283
+ : [],
274
284
  },
275
285
  });
276
286
  };
@@ -299,8 +309,8 @@ export class TsEmbed {
299
309
  * Register APP_INIT event and sendback init payload
300
310
  */
301
311
  private registerAppInit = () => {
302
- this.on(EmbedEvent.APP_INIT, this.appInitCb);
303
- this.on(EmbedEvent.AuthExpire, this.updateAuthToken);
312
+ this.on(EmbedEvent.APP_INIT, this.appInitCb, { start: false }, true);
313
+ this.on(EmbedEvent.AuthExpire, this.updateAuthToken, { start: false }, true);
304
314
  };
305
315
 
306
316
  /**
@@ -352,6 +362,9 @@ export class TsEmbed {
352
362
  if (this.embedConfig.authType === AuthType.TrustedAuthTokenCookieless) {
353
363
  queryParams[Param.cookieless] = true;
354
364
  }
365
+ if (this.embedConfig.pendoTrackingKey) {
366
+ queryParams[Param.PendoTrackingKey] = this.embedConfig.pendoTrackingKey;
367
+ }
355
368
 
356
369
  const {
357
370
  disabledActions,
@@ -497,8 +510,7 @@ export class TsEmbed {
497
510
  iFrame.allow = 'clipboard-read; clipboard-write';
498
511
 
499
512
  const {
500
- height: frameHeight,
501
- width: frameWidth, ...restParams
513
+ height: frameHeight, width: frameWidth, ...restParams
502
514
  } = this.viewConfig.frameParams || {};
503
515
  const width = getCssDimension(frameWidth || DEFAULT_EMBED_WIDTH);
504
516
  const height = getCssDimension(frameHeight || DEFAULT_EMBED_HEIGHT);
@@ -547,7 +559,6 @@ export class TsEmbed {
547
559
  return;
548
560
  }
549
561
 
550
- uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_COMPLETE);
551
562
  this.iFrame = this.iFrame || this.createIframeEl(url);
552
563
  this.iFrame.addEventListener('load', () => {
553
564
  nextInQueue();
@@ -558,7 +569,9 @@ export class TsEmbed {
558
569
  },
559
570
  type: EmbedEvent.Load,
560
571
  });
561
- uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_IFRAME_LOAD_PERFORMANCE, {
572
+ uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_COMPLETE, {
573
+ elWidth: this.iFrame.clientWidth,
574
+ elHeight: this.iFrame.clientHeight,
562
575
  timeTookToLoad: loadTimestamp - initTimestamp,
563
576
  });
564
577
  });
@@ -711,6 +724,8 @@ export class TsEmbed {
711
724
  * @param messageType The message type
712
725
  * @param callback A callback as a function
713
726
  * @param options The message options
727
+ * @param isSelf
728
+ * @param isRegisteredBySDK
714
729
  * @example
715
730
  * ```js
716
731
  * tsEmbed.on(EmbedEvent.Error, (data) => {
@@ -730,7 +745,11 @@ export class TsEmbed {
730
745
  messageType: EmbedEvent,
731
746
  callback: MessageCallback,
732
747
  options: MessageOptions = { start: false },
748
+ isRegisteredBySDK = false,
733
749
  ): typeof TsEmbed.prototype {
750
+ uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_ON}-${messageType}`, {
751
+ isRegisteredBySDK,
752
+ });
734
753
  if (this.isRendered) {
735
754
  this.handleError('Please register event handlers before calling render');
736
755
  }
@@ -900,8 +919,11 @@ export class V1Embed extends TsEmbed {
900
919
  let queryString = queryParams;
901
920
  if (!this.viewConfig.excludeRuntimeFiltersfromURL) {
902
921
  const runtimeFilters = this.viewConfig.runtimeFilters;
922
+ const runtimeParameters = this.viewConfig.runtimeParameters;
923
+
924
+ const parameterQuery = getRuntimeParameters(runtimeParameters || []);
903
925
  const filterQuery = getFilterQuery(runtimeFilters || []);
904
- queryString = [filterQuery, queryParams].filter(Boolean).join('&');
926
+ queryString = [parameterQuery, filterQuery, queryParams].filter(Boolean).join('&');
905
927
  }
906
928
  return this.getV1EmbedBasePath(queryString);
907
929
  }
@@ -929,7 +951,6 @@ export class V1Embed extends TsEmbed {
929
951
  options: MessageOptions = { start: false },
930
952
  ): typeof TsEmbed.prototype {
931
953
  const eventType = this.getCompatibleEventType(messageType);
932
- uploadMixpanelEvent(`${MIXPANEL_EVENT.VISUAL_SDK_ON}-${messageType}`);
933
954
  return super.on(eventType, callback, options);
934
955
  }
935
956
  }
package/src/index.ts CHANGED
@@ -29,6 +29,8 @@ import {
29
29
  PrefetchFeatures,
30
30
  FrameParams,
31
31
  DOMSelector,
32
+ HomeLeftNavItem,
33
+ HomepageModule,
32
34
  MessageOptions,
33
35
  MessageCallback,
34
36
  MessagePayload,
@@ -76,6 +78,8 @@ export {
76
78
  AppViewConfig,
77
79
  PrefetchFeatures,
78
80
  FrameParams,
81
+ HomeLeftNavItem,
82
+ HomepageModule,
79
83
  DOMSelector,
80
84
  MessageOptions,
81
85
  MessageCallback,
@@ -14,9 +14,10 @@ const config = {
14
14
 
15
15
  jest.mock('mixpanel-browser', () => ({
16
16
  __esModule: true,
17
- init: jest.fn(),
17
+ init: jest.fn().mockReturnThis(),
18
18
  identify: jest.fn(),
19
19
  track: jest.fn(),
20
+ register_once: jest.fn(),
20
21
  }));
21
22
 
22
23
  describe('Unit test for mixpanel', () => {
@@ -30,7 +31,7 @@ describe('Unit test for mixpanel', () => {
30
31
  isPublicUser: false,
31
32
  };
32
33
  initMixpanel(sessionInfo);
33
- expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken);
34
+ expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken, undefined, 'tsEmbed');
34
35
  expect(mixpanel.identify).toHaveBeenCalledWith(sessionInfo.userGUID);
35
36
 
36
37
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_CALLED_INIT, {
@@ -45,10 +46,18 @@ describe('Unit test for mixpanel', () => {
45
46
  mixpanelToken: 'newToken',
46
47
  isPublicUser: true,
47
48
  userGUID: 'newUser',
49
+ clusterId: 'newClusterId',
50
+ clusterName: 'newClusterName',
51
+ releaseVersion: 'newReleaseVersion',
48
52
  };
49
53
  initMixpanel(sessionInfo);
50
54
 
51
- expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken);
55
+ expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken, undefined, 'tsEmbed');
56
+ expect(mixpanel.register_once).toHaveBeenCalledWith({
57
+ clusterId: sessionInfo.clusterId,
58
+ clusterName: sessionInfo.clusterName,
59
+ releaseVersion: sessionInfo.releaseVersion,
60
+ });
52
61
  expect(mixpanel.identify).not.toHaveBeenCalledWith(sessionInfo.userGUID);
53
62
  });
54
63