@thoughtspot/visual-embed-sdk 1.26.6 → 1.26.7

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 (263) hide show
  1. package/README.md +2 -2
  2. package/cjs/package.json +1 -1
  3. package/cjs/src/auth.d.ts +4 -4
  4. package/cjs/src/auth.d.ts.map +1 -1
  5. package/cjs/src/auth.js +16 -9
  6. package/cjs/src/auth.js.map +1 -1
  7. package/cjs/src/embed/app.d.ts +15 -15
  8. package/cjs/src/embed/app.d.ts.map +1 -1
  9. package/cjs/src/embed/app.js +4 -3
  10. package/cjs/src/embed/app.js.map +1 -1
  11. package/cjs/src/embed/app.spec.js +5 -4
  12. package/cjs/src/embed/app.spec.js.map +1 -1
  13. package/cjs/src/embed/base.d.ts +1 -1
  14. package/cjs/src/embed/base.d.ts.map +1 -1
  15. package/cjs/src/embed/base.js +9 -6
  16. package/cjs/src/embed/base.js.map +1 -1
  17. package/cjs/src/embed/base.spec.js +4 -3
  18. package/cjs/src/embed/base.spec.js.map +1 -1
  19. package/cjs/src/embed/embed.spec.js +2 -1
  20. package/cjs/src/embed/embed.spec.js.map +1 -1
  21. package/cjs/src/embed/embedConfig.d.ts +2 -1
  22. package/cjs/src/embed/embedConfig.d.ts.map +1 -1
  23. package/cjs/src/embed/embedConfig.js +2 -0
  24. package/cjs/src/embed/embedConfig.js.map +1 -1
  25. package/cjs/src/embed/events.spec.js +3 -2
  26. package/cjs/src/embed/events.spec.js.map +1 -1
  27. package/cjs/src/embed/liveboard.d.ts +35 -23
  28. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  29. package/cjs/src/embed/liveboard.js +8 -4
  30. package/cjs/src/embed/liveboard.js.map +1 -1
  31. package/cjs/src/embed/liveboard.spec.js +2 -1
  32. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  33. package/cjs/src/embed/sage.d.ts +48 -30
  34. package/cjs/src/embed/sage.d.ts.map +1 -1
  35. package/cjs/src/embed/sage.js +7 -6
  36. package/cjs/src/embed/sage.js.map +1 -1
  37. package/cjs/src/embed/sage.spec.js +3 -3
  38. package/cjs/src/embed/sage.spec.js.map +1 -1
  39. package/cjs/src/embed/search-bar.d.ts +22 -6
  40. package/cjs/src/embed/search-bar.d.ts.map +1 -1
  41. package/cjs/src/embed/search-bar.js.map +1 -1
  42. package/cjs/src/embed/search.d.ts +35 -16
  43. package/cjs/src/embed/search.d.ts.map +1 -1
  44. package/cjs/src/embed/search.js +10 -6
  45. package/cjs/src/embed/search.js.map +1 -1
  46. package/cjs/src/embed/search.spec.js +10 -0
  47. package/cjs/src/embed/search.spec.js.map +1 -1
  48. package/cjs/src/embed/ts-embed.d.ts +2 -1
  49. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  50. package/cjs/src/embed/ts-embed.js +45 -22
  51. package/cjs/src/embed/ts-embed.js.map +1 -1
  52. package/cjs/src/embed/ts-embed.spec.js +153 -32
  53. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  54. package/cjs/src/index.d.ts +2 -2
  55. package/cjs/src/index.d.ts.map +1 -1
  56. package/cjs/src/index.js +2 -1
  57. package/cjs/src/index.js.map +1 -1
  58. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  59. package/cjs/src/mixpanel-service.js +2 -1
  60. package/cjs/src/mixpanel-service.js.map +1 -1
  61. package/cjs/src/react/index.d.ts +1 -1
  62. package/cjs/src/react/index.d.ts.map +1 -1
  63. package/cjs/src/react/index.js +2 -1
  64. package/cjs/src/react/index.js.map +1 -1
  65. package/cjs/src/react/index.spec.js +2 -2
  66. package/cjs/src/react/index.spec.js.map +1 -1
  67. package/cjs/src/types.d.ts +742 -237
  68. package/cjs/src/types.d.ts.map +1 -1
  69. package/cjs/src/types.js +653 -169
  70. package/cjs/src/types.js.map +1 -1
  71. package/cjs/src/utils/authService/authService.d.ts.map +1 -1
  72. package/cjs/src/utils/authService/authService.js +3 -2
  73. package/cjs/src/utils/authService/authService.js.map +1 -1
  74. package/cjs/src/utils/authService/authService.spec.js +3 -2
  75. package/cjs/src/utils/authService/authService.spec.js.map +1 -1
  76. package/cjs/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
  77. package/cjs/src/utils/authService/tokenizedAuthService.js +2 -1
  78. package/cjs/src/utils/authService/tokenizedAuthService.js.map +1 -1
  79. package/cjs/src/utils/graphql/answerService/answerService.d.ts +2 -4
  80. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  81. package/cjs/src/utils/graphql/answerService/answerService.js +2 -4
  82. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  83. package/cjs/src/utils/logger.d.ts +18 -0
  84. package/cjs/src/utils/logger.d.ts.map +1 -0
  85. package/cjs/src/utils/logger.js +80 -0
  86. package/cjs/src/utils/logger.js.map +1 -0
  87. package/cjs/src/utils/logger.spec.d.ts +25 -0
  88. package/cjs/src/utils/logger.spec.d.ts.map +1 -0
  89. package/cjs/src/utils/logger.spec.js +116 -0
  90. package/cjs/src/utils/logger.spec.js.map +1 -0
  91. package/cjs/src/utils/processData.d.ts +6 -0
  92. package/cjs/src/utils/processData.d.ts.map +1 -1
  93. package/cjs/src/utils/processData.js +5 -1
  94. package/cjs/src/utils/processData.js.map +1 -1
  95. package/cjs/src/utils/processTrigger.js +1 -1
  96. package/dist/src/auth.d.ts +4 -4
  97. package/dist/src/auth.d.ts.map +1 -1
  98. package/dist/src/embed/app.d.ts +15 -15
  99. package/dist/src/embed/app.d.ts.map +1 -1
  100. package/dist/src/embed/base.d.ts +1 -1
  101. package/dist/src/embed/base.d.ts.map +1 -1
  102. package/dist/src/embed/embedConfig.d.ts +2 -1
  103. package/dist/src/embed/embedConfig.d.ts.map +1 -1
  104. package/dist/src/embed/liveboard.d.ts +35 -23
  105. package/dist/src/embed/liveboard.d.ts.map +1 -1
  106. package/dist/src/embed/sage.d.ts +48 -30
  107. package/dist/src/embed/sage.d.ts.map +1 -1
  108. package/dist/src/embed/search-bar.d.ts +22 -6
  109. package/dist/src/embed/search-bar.d.ts.map +1 -1
  110. package/dist/src/embed/search.d.ts +35 -16
  111. package/dist/src/embed/search.d.ts.map +1 -1
  112. package/dist/src/embed/ts-embed.d.ts +2 -1
  113. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  114. package/dist/src/index.d.ts +2 -2
  115. package/dist/src/index.d.ts.map +1 -1
  116. package/dist/src/mixpanel-service.d.ts.map +1 -1
  117. package/dist/src/react/index.d.ts +1 -1
  118. package/dist/src/react/index.d.ts.map +1 -1
  119. package/dist/src/types.d.ts +742 -237
  120. package/dist/src/types.d.ts.map +1 -1
  121. package/dist/src/utils/authService/authService.d.ts.map +1 -1
  122. package/dist/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
  123. package/dist/src/utils/graphql/answerService/answerService.d.ts +2 -4
  124. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  125. package/dist/src/utils/logger.d.ts +18 -0
  126. package/dist/src/utils/logger.d.ts.map +1 -0
  127. package/dist/src/utils/logger.spec.d.ts +25 -0
  128. package/dist/src/utils/logger.spec.d.ts.map +1 -0
  129. package/dist/src/utils/processData.d.ts +6 -0
  130. package/dist/src/utils/processData.d.ts.map +1 -1
  131. package/dist/tsembed-react.es.js +3716 -3107
  132. package/dist/tsembed-react.js +3620 -3012
  133. package/dist/tsembed.es.js +9830 -9212
  134. package/dist/tsembed.js +15079 -14462
  135. package/dist/visual-embed-sdk-react-full.d.ts +923 -332
  136. package/dist/visual-embed-sdk-react.d.ts +923 -332
  137. package/dist/visual-embed-sdk.d.ts +923 -332
  138. package/lib/package.json +1 -1
  139. package/lib/src/auth.d.ts +4 -4
  140. package/lib/src/auth.d.ts.map +1 -1
  141. package/lib/src/auth.js +17 -10
  142. package/lib/src/auth.js.map +1 -1
  143. package/lib/src/embed/app.d.ts +15 -15
  144. package/lib/src/embed/app.d.ts.map +1 -1
  145. package/lib/src/embed/app.js +4 -3
  146. package/lib/src/embed/app.js.map +1 -1
  147. package/lib/src/embed/app.spec.js +5 -4
  148. package/lib/src/embed/app.spec.js.map +1 -1
  149. package/lib/src/embed/base.d.ts +1 -1
  150. package/lib/src/embed/base.d.ts.map +1 -1
  151. package/lib/src/embed/base.js +9 -6
  152. package/lib/src/embed/base.js.map +1 -1
  153. package/lib/src/embed/base.spec.js +5 -4
  154. package/lib/src/embed/base.spec.js.map +1 -1
  155. package/lib/src/embed/embed.spec.js +2 -1
  156. package/lib/src/embed/embed.spec.js.map +1 -1
  157. package/lib/src/embed/embedConfig.d.ts +2 -1
  158. package/lib/src/embed/embedConfig.d.ts.map +1 -1
  159. package/lib/src/embed/embedConfig.js +2 -0
  160. package/lib/src/embed/embedConfig.js.map +1 -1
  161. package/lib/src/embed/events.spec.js +3 -2
  162. package/lib/src/embed/events.spec.js.map +1 -1
  163. package/lib/src/embed/liveboard.d.ts +35 -23
  164. package/lib/src/embed/liveboard.d.ts.map +1 -1
  165. package/lib/src/embed/liveboard.js +8 -4
  166. package/lib/src/embed/liveboard.js.map +1 -1
  167. package/lib/src/embed/liveboard.spec.js +2 -1
  168. package/lib/src/embed/liveboard.spec.js.map +1 -1
  169. package/lib/src/embed/sage.d.ts +48 -30
  170. package/lib/src/embed/sage.d.ts.map +1 -1
  171. package/lib/src/embed/sage.js +7 -6
  172. package/lib/src/embed/sage.js.map +1 -1
  173. package/lib/src/embed/sage.spec.js +3 -3
  174. package/lib/src/embed/sage.spec.js.map +1 -1
  175. package/lib/src/embed/search-bar.d.ts +22 -6
  176. package/lib/src/embed/search-bar.d.ts.map +1 -1
  177. package/lib/src/embed/search-bar.js.map +1 -1
  178. package/lib/src/embed/search.d.ts +35 -16
  179. package/lib/src/embed/search.d.ts.map +1 -1
  180. package/lib/src/embed/search.js +11 -7
  181. package/lib/src/embed/search.js.map +1 -1
  182. package/lib/src/embed/search.spec.js +10 -0
  183. package/lib/src/embed/search.spec.js.map +1 -1
  184. package/lib/src/embed/ts-embed.d.ts +2 -1
  185. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  186. package/lib/src/embed/ts-embed.js +48 -25
  187. package/lib/src/embed/ts-embed.js.map +1 -1
  188. package/lib/src/embed/ts-embed.spec.js +153 -32
  189. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  190. package/lib/src/index.d.ts +2 -2
  191. package/lib/src/index.d.ts.map +1 -1
  192. package/lib/src/index.js +2 -2
  193. package/lib/src/index.js.map +1 -1
  194. package/lib/src/mixpanel-service.d.ts.map +1 -1
  195. package/lib/src/mixpanel-service.js +2 -1
  196. package/lib/src/mixpanel-service.js.map +1 -1
  197. package/lib/src/react/index.d.ts +1 -1
  198. package/lib/src/react/index.d.ts.map +1 -1
  199. package/lib/src/react/index.js +1 -1
  200. package/lib/src/react/index.js.map +1 -1
  201. package/lib/src/react/index.spec.js +2 -2
  202. package/lib/src/react/index.spec.js.map +1 -1
  203. package/lib/src/types.d.ts +742 -237
  204. package/lib/src/types.d.ts.map +1 -1
  205. package/lib/src/types.js +652 -168
  206. package/lib/src/types.js.map +1 -1
  207. package/lib/src/utils/authService/authService.d.ts.map +1 -1
  208. package/lib/src/utils/authService/authService.js +3 -2
  209. package/lib/src/utils/authService/authService.js.map +1 -1
  210. package/lib/src/utils/authService/authService.spec.js +4 -3
  211. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  212. package/lib/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
  213. package/lib/src/utils/authService/tokenizedAuthService.js +2 -1
  214. package/lib/src/utils/authService/tokenizedAuthService.js.map +1 -1
  215. package/lib/src/utils/graphql/answerService/answerService.d.ts +2 -4
  216. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  217. package/lib/src/utils/graphql/answerService/answerService.js +2 -4
  218. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  219. package/lib/src/utils/logger.d.ts +18 -0
  220. package/lib/src/utils/logger.d.ts.map +1 -0
  221. package/lib/src/utils/logger.js +74 -0
  222. package/lib/src/utils/logger.js.map +1 -0
  223. package/lib/src/utils/logger.spec.d.ts +25 -0
  224. package/lib/src/utils/logger.spec.d.ts.map +1 -0
  225. package/lib/src/utils/logger.spec.js +93 -0
  226. package/lib/src/utils/logger.spec.js.map +1 -0
  227. package/lib/src/utils/processData.d.ts +6 -0
  228. package/lib/src/utils/processData.d.ts.map +1 -1
  229. package/lib/src/utils/processData.js +4 -1
  230. package/lib/src/utils/processData.js.map +1 -1
  231. package/lib/src/utils/processTrigger.js +1 -1
  232. package/lib/src/visual-embed-sdk.d.ts +927 -336
  233. package/package.json +1 -1
  234. package/src/auth.ts +20 -13
  235. package/src/embed/app.spec.ts +5 -4
  236. package/src/embed/app.ts +23 -22
  237. package/src/embed/base.spec.ts +6 -5
  238. package/src/embed/base.ts +18 -11
  239. package/src/embed/embed.spec.ts +2 -1
  240. package/src/embed/embedConfig.ts +2 -0
  241. package/src/embed/events.spec.ts +3 -2
  242. package/src/embed/liveboard.spec.ts +2 -1
  243. package/src/embed/liveboard.ts +43 -27
  244. package/src/embed/sage.spec.ts +3 -3
  245. package/src/embed/sage.ts +54 -36
  246. package/src/embed/search-bar.tsx +22 -6
  247. package/src/embed/search.spec.ts +13 -0
  248. package/src/embed/search.ts +46 -21
  249. package/src/embed/ts-embed.spec.ts +182 -43
  250. package/src/embed/ts-embed.ts +78 -59
  251. package/src/index.ts +2 -0
  252. package/src/mixpanel-service.ts +2 -1
  253. package/src/react/index.spec.tsx +2 -2
  254. package/src/react/index.tsx +1 -0
  255. package/src/types.ts +753 -245
  256. package/src/utils/authService/authService.spec.ts +7 -6
  257. package/src/utils/authService/authService.ts +4 -2
  258. package/src/utils/authService/tokenizedAuthService.ts +2 -1
  259. package/src/utils/graphql/answerService/answerService.ts +2 -4
  260. package/src/utils/logger.spec.ts +108 -0
  261. package/src/utils/logger.ts +88 -0
  262. package/src/utils/processData.ts +4 -1
  263. package/src/utils/processTrigger.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thoughtspot/visual-embed-sdk",
3
- "version": "1.26.6",
3
+ "version": "1.26.7",
4
4
  "description": "ThoughtSpot Embed SDK",
5
5
  "module": "lib/src/index.js",
6
6
  "main": "dist/tsembed.js",
package/src/auth.ts CHANGED
@@ -1,18 +1,19 @@
1
1
  import EventEmitter from 'eventemitter3';
2
+ import { getAuthenticationToken, resetCachedAuthToken } from './authToken';
2
3
  import { initMixpanel } from './mixpanel-service';
3
4
  import {
4
- AuthType, DOMSelector, EmbedConfig, EmbedEvent, Param,
5
+ AuthType, DOMSelector, EmbedConfig, EmbedEvent,
5
6
  } from './types';
6
7
  import { getDOMNode, getRedirectUrl } from './utils';
7
8
  import {
8
- fetchSessionInfoService,
9
+ EndPoints,
10
+ fetchAuthPostService,
9
11
  fetchAuthService,
10
12
  fetchBasicAuthService,
11
13
  fetchLogoutService,
12
- fetchAuthPostService,
13
- EndPoints,
14
+ fetchSessionInfoService,
14
15
  } from './utils/authService';
15
- import { getAuthenticationToken, resetCachedAuthToken } from './authToken';
16
+ import { logger } from './utils/logger';
16
17
 
17
18
  // eslint-disable-next-line import/no-mutable-exports
18
19
  export let loggedInStatus = false;
@@ -72,8 +73,8 @@ export enum AuthStatus {
72
73
  */
73
74
  LOGOUT = 'LOGOUT',
74
75
  /**
75
- * Emitted when inPopup: true in the SAMLRedirect flow.
76
- * And, we are waiting for popup to be triggered either programatically
76
+ * Emitted when inPopup is true in the SAMLRedirect flow and the
77
+ * popup is waiting to be triggered either programmatically
77
78
  * or by the trigger button.
78
79
  *
79
80
  * @version SDK: 1.19.0
@@ -126,8 +127,8 @@ export interface AuthEventEmitter {
126
127
  */
127
128
  export enum AuthEvent {
128
129
  /**
129
- * Manually trigger the SSO popup. This is useful with
130
- * authStatus: SAMLRedirect/OIDCRedicre and inPopup: true
130
+ * Manually trigger the SSO popup. This is useful when
131
+ * authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
131
132
  */
132
133
  TRIGGER_SSO_POPUP = 'TRIGGER_SSO_POPUP',
133
134
  }
@@ -154,7 +155,7 @@ export function setAuthEE(eventEmitter: EventEmitter<AuthStatus | AuthEvent>): v
154
155
  */
155
156
  export function notifyAuthSDKSuccess(): void {
156
157
  if (!authEE) {
157
- console.error('SDK not initialized');
158
+ logger.error('SDK not initialized');
158
159
  return;
159
160
  }
160
161
  authEE.emit(AuthStatus.SDK_SUCCESS);
@@ -165,7 +166,7 @@ export function notifyAuthSDKSuccess(): void {
165
166
  */
166
167
  export function notifyAuthSuccess(): void {
167
168
  if (!authEE) {
168
- console.error('SDK not initialized');
169
+ logger.error('SDK not initialized');
169
170
  return;
170
171
  }
171
172
  authEE.emit(AuthStatus.SUCCESS, sessionInfo);
@@ -177,7 +178,7 @@ export function notifyAuthSuccess(): void {
177
178
  */
178
179
  export function notifyAuthFailure(failureType: AuthFailureType): void {
179
180
  if (!authEE) {
180
- console.error('SDK not initialized');
181
+ logger.error('SDK not initialized');
181
182
  return;
182
183
  }
183
184
  authEE.emit(AuthStatus.FAILURE, failureType);
@@ -188,7 +189,7 @@ export function notifyAuthFailure(failureType: AuthFailureType): void {
188
189
  */
189
190
  export function notifyLogout(): void {
190
191
  if (!authEE) {
191
- console.error('SDK not initialized');
192
+ logger.error('SDK not initialized');
192
193
  return;
193
194
  }
194
195
  authEE.emit(AuthStatus.LOGOUT);
@@ -472,6 +473,12 @@ export const logout = async (embedConfig: EmbedConfig): Promise<boolean> => {
472
473
  const { thoughtSpotHost } = embedConfig;
473
474
  await fetchLogoutService(thoughtSpotHost);
474
475
  resetCachedAuthToken();
476
+ const thoughtspotIframes = document.querySelectorAll("[data-ts-iframe='true']");
477
+ if (thoughtspotIframes?.length) {
478
+ thoughtspotIframes.forEach((el) => {
479
+ el.parentElement.innerHTML = embedConfig.loginFailedMessage;
480
+ });
481
+ }
475
482
  loggedInStatus = false;
476
483
  return loggedInStatus;
477
484
  };
@@ -18,6 +18,7 @@ import {
18
18
  import { version } from '../../package.json';
19
19
  import * as config from '../config';
20
20
  import { TsEmbed, V1Embed } from './ts-embed';
21
+ import { logger } from '../utils/logger';
21
22
 
22
23
  const defaultViewConfig = {
23
24
  frameParams: {
@@ -463,15 +464,15 @@ describe('App embed tests', () => {
463
464
  },
464
465
  });
465
466
  await appEmbed.render();
466
- spyOn(console, 'warn');
467
+ spyOn(logger, 'warn');
467
468
  appEmbed.navigateToPage(-1);
468
- expect(console.warn).toHaveBeenCalledWith(
469
+ expect(logger.warn).toHaveBeenCalledWith(
469
470
  'Path can only by a string when triggered without noReload',
470
471
  );
471
472
  });
472
473
 
473
474
  test('navigateToPage function use before render', async () => {
474
- spyOn(console, 'log');
475
+ spyOn(logger, 'log');
475
476
  const appEmbed = new AppEmbed(getRootEl(), {
476
477
  frameParams: {
477
478
  width: '100%',
@@ -480,7 +481,7 @@ describe('App embed tests', () => {
480
481
  });
481
482
  appEmbed.navigateToPage(path);
482
483
  await appEmbed.render();
483
- expect(console.log).toHaveBeenCalledWith(
484
+ expect(logger.log).toHaveBeenCalledWith(
484
485
  'Please call render before invoking this method',
485
486
  );
486
487
  });
package/src/embed/app.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
10
10
  */
11
11
 
12
+ import { logger } from '../utils/logger';
12
13
  import { getQueryParamString } from '../utils';
13
14
  import {
14
15
  Param, DOMSelector, HostEvent, ViewConfig, EmbedEvent, MessagePayload,
@@ -57,43 +58,43 @@ export enum Page {
57
58
  */
58
59
  export interface AppViewConfig extends Omit<ViewConfig, 'visibleTabs'> {
59
60
  /**
60
- * If true, the main navigation bar within the ThoughtSpot app
61
+ * If true, the top navigation bar within the ThoughtSpot app
61
62
  * is displayed. By default, the navigation bar is hidden.
62
- * This flag also control the homepage left nav-bar.
63
+ * This flag also controls the homepage left navigation bar.
63
64
  */
64
65
  showPrimaryNavbar?: boolean;
65
66
  /**
66
- * Flag to control Homepage Left Nav Bar
67
- * If showPrimaryNavbar is true, ie navigation bar(Global nav-bar) and Homepage left
68
- * nav-bar is visible, this flag will only hide the homepage left nav.
69
- * Precedence of showPrimaryNavbar flag > hideHomepageLeftNav flag.
67
+ * Control the visibility of the left navigation bar on the Homepage.
68
+ * If showPrimaryNavbar is true, that is, if the Global and Homepage
69
+ * nav-bars are visible, this flag will only hide the homepage left nav-bar.
70
+ * The showPrimaryNavbar flag takes precedence over the hideHomepageLeftNav.
70
71
  *
71
72
  * @default false
72
73
  * @version SDK: 1.27.0 | Thoughtspot: 9.8.0.cl
73
74
  */
74
75
  hideHomepageLeftNav?: boolean;
75
76
  /**
76
- * If true, help and profile buttons will hide on NavBar. By default,
77
- * they are shown.
77
+ * Control the visibility of the help (?) and profile buttons on the
78
+ * Global nav-bar. By default, these buttons are visible on the nav-bar.
78
79
  */
79
80
  disableProfileAndHelp?: boolean;
80
81
  /**
81
- * If true, application switcher button will hide on NavBar. By default,
82
- * they are shown.
82
+ * Control the visibility of the application switcher button on the nav-bar.
83
+ * By default, the application switcher is shown.
83
84
  */
84
85
  hideApplicationSwitcher?: boolean;
85
86
  /**
86
- * If true, org switcher button will hide on NavBar. By default,
87
- * they are shown.
87
+ * Control the visibility of the Org switcher button on the nav-bar.
88
+ * By default, the Org switcher button is shown.
88
89
  */
89
90
  hideOrgSwitcher?: boolean;
90
91
  /**
91
- * A URL path within the app that is to be embedded.
92
+ * A URL path to the embedded application page
92
93
  * If both path and pageId attributes are defined, the path definition
93
94
  * takes precedence. This is the path post the `#/` in the URL of the standalone
94
95
  * ThoughtSpot app. Use this to open the embedded view to a specific path.
95
96
  *
96
- * For eg, if you want the component to open to a specific liveboard
97
+ * For eg, if you want the component to open to a specific Liveboard
97
98
  * you could set the path to `pinboard/<liveboardId>/tab/<tabId>`.
98
99
  *
99
100
  * @example
@@ -281,8 +282,10 @@ export class AppEmbed extends V1Embed {
281
282
  *
282
283
  * @param pageId The ID of the page to be embedded.
283
284
  */
284
- private getIFrameSrc() {
285
- const { pageId, path, modularHomeExperience } = this.viewConfig;
285
+ public getIFrameSrc(): string {
286
+ const {
287
+ pageId, path, modularHomeExperience,
288
+ } = this.viewConfig;
286
289
  const pageRoute = this.formatPath(path) || this.getPageRoute(pageId, modularHomeExperience);
287
290
  let url = `${this.getRootIframeSrc()}/${pageRoute}`;
288
291
 
@@ -300,7 +303,7 @@ export class AppEmbed extends V1Embed {
300
303
  */
301
304
  protected updateIFrameHeight = (data: MessagePayload) => {
302
305
  this.setIFrameHeight(Math.max(data.data, this.iFrame?.scrollHeight));
303
- }
306
+ };
304
307
 
305
308
  private embedIframeCenter = (data: MessagePayload, responder: any) => {
306
309
  const obj = this.getIframeCenter();
@@ -308,9 +311,7 @@ export class AppEmbed extends V1Embed {
308
311
  };
309
312
 
310
313
  private setIframeHeightForNonEmbedLiveboard = (data: MessagePayload) => {
311
- const {
312
- height: frameHeight, ...restParams
313
- } = this.viewConfig.frameParams || {};
314
+ const { height: frameHeight, ...restParams } = this.viewConfig.frameParams || {};
314
315
  if (!data.data.currentPath.startsWith('/pinboard/')) {
315
316
  this.setIFrameHeight(frameHeight || this.defaultHeight);
316
317
  }
@@ -375,14 +376,14 @@ export class AppEmbed extends V1Embed {
375
376
  */
376
377
  public navigateToPage(path: string | number, noReload = false): void {
377
378
  if (!this.iFrame) {
378
- console.log('Please call render before invoking this method');
379
+ logger.log('Please call render before invoking this method');
379
380
  return;
380
381
  }
381
382
  if (noReload) {
382
383
  this.trigger(HostEvent.Navigate, path);
383
384
  } else {
384
385
  if (typeof path !== 'string') {
385
- console.warn('Path can only by a string when triggered without noReload');
386
+ logger.warn('Path can only by a string when triggered without noReload');
386
387
  return;
387
388
  }
388
389
  const iframeSrc = this.iFrame.src;
@@ -1,11 +1,11 @@
1
1
  /* eslint-disable no-console */
2
2
  /* eslint-disable @typescript-eslint/no-shadow */
3
3
  import EventEmitter from 'eventemitter3';
4
- import { EmbedConfig } from '../index';
5
4
  import * as auth from '../auth';
6
- import * as authService from '../utils/authService/authService';
7
5
  import * as authTokenService from '../authToken';
8
6
  import * as index from '../index';
7
+ import { EmbedConfig } from '../index';
8
+ import * as authService from '../utils/authService/authService';
9
9
  import * as base from './base';
10
10
  import * as embedConfigInstance from './embedConfig';
11
11
 
@@ -13,10 +13,11 @@ import {
13
13
  executeAfterWait,
14
14
  getAllIframeEl,
15
15
  getDocumentBody,
16
- getRootEl,
17
16
  getIFrameSrc,
17
+ getRootEl,
18
18
  } from '../test/test-utils';
19
19
  import * as tokenizedFetchInstance from '../tokenizedFetch';
20
+ import { logger } from '../utils/logger';
20
21
 
21
22
  const thoughtSpotHost = 'tshost';
22
23
  let authEE: EventEmitter;
@@ -412,11 +413,11 @@ describe('Base TS Embed', () => {
412
413
  describe('Base without init', () => {
413
414
  test('notify should error when called without init', () => {
414
415
  base.reset();
415
- jest.spyOn(global.console, 'error').mockImplementation(() => undefined);
416
+ jest.spyOn(logger, 'error').mockImplementation(() => undefined);
416
417
  base.notifyAuthSuccess();
417
418
  base.notifyAuthFailure(auth.AuthFailureType.SDK);
418
419
  base.notifyLogout();
419
420
  base.notifyAuthSDKSuccess();
420
- expect(global.console.error).toHaveBeenCalledTimes(4);
421
+ expect(logger.error).toHaveBeenCalledTimes(4);
421
422
  });
422
423
  });
package/src/embed/base.ts CHANGED
@@ -10,30 +10,34 @@
10
10
  */
11
11
  import EventEmitter from 'eventemitter3';
12
12
  import uniq from 'lodash/uniq';
13
- import { tokenizedFetch } from '../tokenizedFetch';
14
- import { EndPoints } from '../utils/authService/authService';
15
- import { getThoughtSpotHost } from '../config';
16
- import { AuthType, EmbedConfig, PrefetchFeatures } from '../types';
17
13
  import {
18
- authenticate,
19
- logout as _logout,
14
+ AuthEvent,
15
+ AuthEventEmitter,
20
16
  AuthFailureType,
21
17
  AuthStatus,
22
- AuthEvent,
18
+ logout as _logout,
19
+ authenticate,
23
20
  notifyAuthFailure,
24
21
  notifyAuthSDKSuccess,
25
22
  notifyAuthSuccess,
26
23
  notifyLogout,
27
24
  setAuthEE,
28
- AuthEventEmitter,
29
25
  } from '../auth';
30
- import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
26
+ import { getThoughtSpotHost } from '../config';
27
+ import { MIXPANEL_EVENT, uploadMixpanelEvent } from '../mixpanel-service';
28
+ import { tokenizedFetch } from '../tokenizedFetch';
29
+ import {
30
+ AuthType, EmbedConfig, LogLevel, PrefetchFeatures,
31
+ } from '../types';
32
+ import { EndPoints } from '../utils/authService/authService';
33
+ import { logger, setGlobalLogLevelOverride } from '../utils/logger';
31
34
  import { getEmbedConfig, setEmbedConfig } from './embedConfig';
32
35
 
33
36
  const CONFIG_DEFAULTS: Partial<EmbedConfig> = {
34
37
  loginFailedMessage: 'Not logged in',
35
38
  authTriggerText: 'Authorize',
36
39
  authType: AuthType.None,
40
+ logLevel: LogLevel.ERROR,
37
41
  };
38
42
 
39
43
  export interface executeTMLInput {
@@ -100,7 +104,7 @@ const hostUrlToFeatureUrl = {
100
104
  export const prefetch = (url?: string, prefetchFeatures?: PrefetchFeatures[]): void => {
101
105
  if (url === '') {
102
106
  // eslint-disable-next-line no-console
103
- console.warn('The prefetch method does not have a valid URL');
107
+ logger.warn('The prefetch method does not have a valid URL');
104
108
  } else {
105
109
  const features = prefetchFeatures || [PrefetchFeatures.FullApp];
106
110
  let hostUrl = url || getEmbedConfig().thoughtSpotHost;
@@ -174,13 +178,16 @@ function backwardCompat(embedConfig: EmbedConfig): EmbedConfig {
174
178
  */
175
179
  export const init = (embedConfig: EmbedConfig): AuthEventEmitter => {
176
180
  sanity(embedConfig);
177
- setEmbedConfig(
181
+ embedConfig = setEmbedConfig(
178
182
  backwardCompat({
179
183
  ...CONFIG_DEFAULTS,
180
184
  ...embedConfig,
181
185
  thoughtSpotHost: getThoughtSpotHost(embedConfig),
182
186
  }),
183
187
  );
188
+
189
+ setGlobalLogLevelOverride(embedConfig.logLevel);
190
+
184
191
  const authEE = new EventEmitter<AuthStatus | AuthEvent>();
185
192
  setAuthEE(authEE);
186
193
  handleAuth();
@@ -1,3 +1,4 @@
1
+ import { logger } from '../utils/logger';
1
2
  import {
2
3
  init, AuthType, SearchEmbed, EmbedEvent,
3
4
  } from '../index';
@@ -51,7 +52,7 @@ describe('test view config', () => {
51
52
  });
52
53
 
53
54
  test('trying to register event handler after render should throw error', async () => {
54
- spyOn(console, 'error');
55
+ spyOn(logger, 'error');
55
56
  const onErrorSpy = jest.fn();
56
57
  const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
57
58
  searchEmbed
@@ -13,6 +13,7 @@ export const getEmbedConfig = (): EmbedConfig => config;
13
13
 
14
14
  /**
15
15
  * Sets the configuration embed was initialized with.
16
+ * And returns the new configuration.
16
17
  *
17
18
  * @param newConfig The configuration to set.
18
19
  * @version SDK: 1.27.0 | ThoughtSpot: *
@@ -20,4 +21,5 @@ export const getEmbedConfig = (): EmbedConfig => config;
20
21
  */
21
22
  export const setEmbedConfig = (newConfig: EmbedConfig) => {
22
23
  config = newConfig;
24
+ return newConfig;
23
25
  };
@@ -1,3 +1,4 @@
1
+ import { logger } from '../utils/logger';
1
2
  import {
2
3
  init,
3
4
  AuthType,
@@ -155,7 +156,7 @@ describe('test communication between host app and ThoughtSpot', () => {
155
156
  pinboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
156
157
  } as LiveboardViewConfig);
157
158
  liveboardEmbed.render();
158
- const spy1 = jest.spyOn(global.console, 'log');
159
+ const spy1 = jest.spyOn(logger, 'log');
159
160
 
160
161
  await executeAfterWait(() => {
161
162
  const iframe = getIFrameEl();
@@ -173,7 +174,7 @@ describe('test communication between host app and ThoughtSpot', () => {
173
174
  pinboardId: 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0',
174
175
  } as LiveboardViewConfig);
175
176
  pinboardEmbed.render();
176
- const spy1 = jest.spyOn(global.console, 'log');
177
+ const spy1 = jest.spyOn(logger, 'log');
177
178
 
178
179
  await executeAfterWait(() => {
179
180
  const iframe = getIFrameEl();
@@ -294,12 +294,13 @@ describe('Liveboard/viz embed tests', () => {
294
294
  liveboardV2: true,
295
295
  defaultHeight: 100,
296
296
  preventLiveboardFilterRemoval: true,
297
+ enableAskSage: true,
297
298
  } as LiveboardViewConfig);
298
299
  liveboardEmbed.render();
299
300
  await executeAfterWait(() => {
300
301
  expectUrlMatchesWithParams(
301
302
  getIFrameSrc(),
302
- `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&preventPinboardFilterRemoval=true&isLiveboardEmbed=true&isPinboardV2Enabled=true#/embed/viz/${liveboardId}/tab/${activeTabId}`,
303
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}&preventPinboardFilterRemoval=true&isLiveboardEmbed=true&isPinboardV2Enabled=true&enableAskSage=true#/embed/viz/${liveboardId}/tab/${activeTabId}`,
303
304
  );
304
305
  });
305
306
  });
@@ -28,7 +28,7 @@ import { V1Embed } from './ts-embed';
28
28
  *
29
29
  * @group Embed components
30
30
  */
31
- export interface LiveboardViewConfig extends Omit<ViewConfig, 'hiddenHomepageModules' | 'hiddenHomeLeftNavItems'| 'reorderedHomepageModules'> {
31
+ export interface LiveboardViewConfig extends Omit<ViewConfig, 'hiddenHomepageModules' | 'hiddenHomeLeftNavItems' | 'reorderedHomepageModules'> {
32
32
  /**
33
33
  * If set to true, the embedded object container dynamically resizes
34
34
  * according to the height of the Liveboard.
@@ -37,8 +37,8 @@ export interface LiveboardViewConfig extends Omit<ViewConfig, 'hiddenHomepageMod
37
37
  */
38
38
  fullHeight?: boolean;
39
39
  /**
40
- * This is the minimum height(in pixels) for a full height Liveboard.
41
- * Setting this height helps resolves issues with empty Liveboards and
40
+ * This is the minimum height(in pixels) for a full-height Liveboard.
41
+ * Setting this height helps resolve issues with empty Liveboards and
42
42
  * other screens navigable from a Liveboard.
43
43
  *
44
44
  * @version SDK: 1.5.0 | ThoughtSpot: ts7.oct.cl, 7.2.1
@@ -51,7 +51,7 @@ export interface LiveboardViewConfig extends Omit<ViewConfig, 'hiddenHomepageMod
51
51
  enableVizTransformations?: boolean;
52
52
  /**
53
53
  * The Liveboard to display in the embedded view.
54
- * Use either of liveboardId or pinboardId to reference the Liveboard to embed.
54
+ * Use either liveboardId or pinboardId to reference the Liveboard to embed.
55
55
  *
56
56
  * @version SDK: 1.3.0 | ThoughtSpot ts7.aug.cl, 7.2.1
57
57
  */
@@ -70,80 +70,92 @@ export interface LiveboardViewConfig extends Omit<ViewConfig, 'hiddenHomepageMod
70
70
  * If set to true, all filter chips from a
71
71
  * Liveboard page will be read-only (no X buttons)
72
72
  *
73
- * @version SDK: 1.3.0 | ThoughtSpot ts7.aug.cl, 7.2.1
73
+ * @version SDK: 1.3.0 | ThoughtSpot ts7.aug.cl, 7.2.1.sw
74
74
  */
75
75
  preventLiveboardFilterRemoval?: boolean;
76
76
  /**
77
- * Array of viz ids which should be visible when the liveboard
78
- * first renders. This can be changed by triggering the "SetVisibleVizs"
77
+ * Array of visualization IDs which should be visible when the Liveboard
78
+ * renders. This can be changed by triggering the `SetVisibleVizs`
79
79
  * event.
80
80
  *
81
81
  * @version SDK: 1.9.1 | ThoughtSpot: 8.1.0.cl, 8.4.1-sw
82
82
  */
83
83
  visibleVizs?: string[];
84
84
  /**
85
- * To support backward compatibilty
85
+ * To support backward compatibility
86
86
  *
87
87
  * @hidden
88
88
  */
89
89
  preventPinboardFilterRemoval?: boolean;
90
90
  /**
91
- * Render embedded Liveboards and visualizations in the new Liveboard experience mode
91
+ * Render embedded Liveboards and visualizations in the
92
+ * new Liveboard experience mode.
92
93
  *
93
94
  * @version SDK: 1.14.0 | ThoughtSpot: 8.6.0.cl, 8.8.1-sw
94
95
  */
95
96
  liveboardV2?: boolean;
96
97
  /**
97
- * Tab ID of the Liveboard that is supposed to be active
98
+ * Set a Liveboard tab as an active tab.
99
+ * Specify the tab ID.
98
100
  *
99
101
  * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl, 8.8.1-sw
100
102
  */
101
103
  activeTabId?: string;
102
104
  /**
103
- * Hide tab Panel of embedded LB
105
+ * Show or hide the tab panel of the embedded Liveboard.
104
106
  *
105
- * @version SDK: 1.25.0 | Thoughtspot: 9.6.0.cl
107
+ * @version SDK: 1.25.0 | Thoughtspot: 9.6.0.cl, 9.8.0.sw
106
108
  */
107
109
  hideTabPanel?: boolean;
108
110
  /**
109
- * Show or hide Liveboard header
111
+ * Show or hide the Liveboard header.
110
112
  *
111
- * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl
113
+ * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl, 9.8.0.sw
112
114
  * @default false
113
115
  */
114
116
  hideLiveboardHeader?: boolean;
115
117
  /**
116
- * Show or hide Liveboard title
118
+ * Show or hide the Liveboard title.
117
119
  *
118
- * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl
120
+ * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl, 9.8.0.sw
119
121
  * @default false
120
122
  */
121
123
  showLiveboardTitle?: boolean;
122
124
  /**
123
- * Show or hide Liveboard description
125
+ * Show or hide the Liveboard description.
124
126
  *
125
- * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl
127
+ * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl, 9.8.0.sw
126
128
  * @default false
127
129
  */
128
130
  showLiveboardDescription?: boolean;
129
131
  /**
130
- * Boolean for sticky Liveboard header.
132
+ * Control the position and visibility of
133
+ * the Liveboard header as the users scroll down the
134
+ * embedded Liveboard page.
131
135
  *
132
136
  * @example
133
137
  * ```js
134
138
  * const embed = new LiveboardEmbed('#embed', {
135
- * ... // other liveboard view config
139
+ * ... // other Liveboard view config
136
140
  * isLiveboardHeaderSticky: true,
137
141
  * });
138
142
  * ```
139
- * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl
143
+ * @version SDK: 1.26.0 | Thoughtspot: 9.7.0.cl, 9.8.0.sw
140
144
  */
141
145
  isLiveboardHeaderSticky?: boolean;
146
+ /**
147
+ * enable or disable ask sage
148
+ *
149
+ * @version SDK: 1.29.0 | Thoughtspot: 9.12.0.cl
150
+ * @default true
151
+ */
152
+ enableAskSage?: boolean;
142
153
  }
143
154
 
144
155
  /**
145
- * Embed a ThoughtSpot Liveboard or a Thoughtspot visualization. When rendered it already
146
- * waits for the authentication to complete, so no need to wait for AuthStatus.SUCCESS.
156
+ * Embed a ThoughtSpot Liveboard or visualization. When rendered it already
157
+ * waits for the authentication to complete, so you need not wait for
158
+ * `AuthStatus.SUCCESS`.
147
159
  *
148
160
  * @example
149
161
  * ```js
@@ -193,6 +205,7 @@ export class LiveboardEmbed extends V1Embed {
193
205
  showLiveboardDescription,
194
206
  showLiveboardTitle,
195
207
  isLiveboardHeaderSticky = true,
208
+ enableAskSage,
196
209
  } = this.viewConfig;
197
210
 
198
211
  const preventLiveboardFilterRemoval = this.viewConfig.preventLiveboardFilterRemoval
@@ -232,6 +245,9 @@ export class LiveboardEmbed extends V1Embed {
232
245
  if (showLiveboardTitle) {
233
246
  params[Param.ShowLiveboardTitle] = showLiveboardTitle;
234
247
  }
248
+ if (enableAskSage) {
249
+ params[Param.enableAskSage] = enableAskSage;
250
+ }
235
251
 
236
252
  params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
237
253
 
@@ -255,9 +271,9 @@ export class LiveboardEmbed extends V1Embed {
255
271
 
256
272
  /**
257
273
  * Construct the URL of the embedded ThoughtSpot Liveboard or visualization
258
- * to be loaded within the iframe.
274
+ * to be loaded within the iFrame.
259
275
  */
260
- private getIFrameSrc() {
276
+ private getIFrameSrc(): string {
261
277
  const { vizId, activeTabId } = this.viewConfig;
262
278
  const liveboardId = this.viewConfig.liveboardId ?? this.viewConfig.pinboardId;
263
279
 
@@ -306,7 +322,7 @@ export class LiveboardEmbed extends V1Embed {
306
322
  if (isUndefined(embedObj)) return;
307
323
 
308
324
  const showDifferentLib = this.viewConfig.liveboardId
309
- && embedObj.viewConfig.liveboardId !== this.viewConfig.liveboardId;
325
+ && embedObj.viewConfig.liveboardId !== this.viewConfig.liveboardId;
310
326
 
311
327
  if (showDifferentLib) {
312
328
  const libId = this.viewConfig.liveboardId;
@@ -373,4 +389,4 @@ export class LiveboardEmbed extends V1Embed {
373
389
  /**
374
390
  * @hidden
375
391
  */
376
- export class PinboardEmbed extends LiveboardEmbed {}
392
+ export class PinboardEmbed extends LiveboardEmbed { }
@@ -158,14 +158,14 @@ describe('Sage embed tests', () => {
158
158
  ...defaultConfig,
159
159
  dataSource: 'worksheet-id',
160
160
  searchOptions: {
161
- searchQuery: 'test-query',
161
+ searchQuery: 'test query', // also tests for query with spaces
162
162
  },
163
163
  });
164
164
  sageEmbed.render();
165
165
  await executeAfterWait(() => {
166
166
  expectUrlMatch(
167
167
  getIFrameSrc(),
168
- `http://${thoughtSpotHost}/?embedApp=true&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSearchBarTitle=false&hideSageAnswerHeader=false&hideAction=%5B"reportError","save","pin","editACopy","saveAsView","updateTSL","editTSL","onDeleteAnswer","share"%5D#/embed/eureka?worksheet=worksheet-id&query=test-query`,
168
+ `http://${thoughtSpotHost}/?embedApp=true&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSearchBarTitle=false&hideSageAnswerHeader=false&hideAction=%5B"reportError","save","pin","editACopy","saveAsView","updateTSL","editTSL","onDeleteAnswer","share"%5D#/embed/eureka?worksheet=worksheet-id&query=test%20query`,
169
169
  );
170
170
  });
171
171
  });
@@ -182,7 +182,7 @@ describe('Sage embed tests', () => {
182
182
  await executeAfterWait(() => {
183
183
  expectUrlMatch(
184
184
  getIFrameSrc(),
185
- `http://${thoughtSpotHost}/?embedApp=true&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&hideAction=%5B"reportError","save","pin","editACopy","saveAsView","updateTSL","editTSL","onDeleteAnswer","share"%5D#/embed/eureka?query=test-query&executeSearch=true`,
185
+ `http://${thoughtSpotHost}/?embedApp=true&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&hideAction=%5B"reportError","save","pin","editACopy","saveAsView","updateTSL","editTSL","onDeleteAnswer","share"%5D#/embed/eureka?executeSearch=true&query=test-query`,
186
186
  );
187
187
  });
188
188
  });