@thoughtspot/visual-embed-sdk 1.13.0-alpha.2 → 1.13.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 (103) hide show
  1. package/CHANGELOG.md +31 -6
  2. package/README.md +1 -1
  3. package/dist/src/auth.d.ts +4 -1
  4. package/dist/src/auth.spec.d.ts +1 -0
  5. package/dist/src/embed/app.d.ts +5 -0
  6. package/dist/src/embed/liveboard.d.ts +12 -1
  7. package/dist/src/embed/search.d.ts +5 -0
  8. package/dist/src/embed/searchEmbed-basic-auth.spec.d.ts +1 -0
  9. package/dist/src/embed/ts-embed.d.ts +12 -3
  10. package/dist/src/errors.d.ts +2 -0
  11. package/dist/src/test/test-utils.d.ts +6 -0
  12. package/dist/src/types.d.ts +211 -4
  13. package/dist/src/utils/processTrigger.d.ts +1 -1
  14. package/dist/src/utils.d.ts +3 -1
  15. package/dist/tsembed.es.js +292 -24
  16. package/dist/tsembed.js +292 -24
  17. package/lib/package.json +4 -2
  18. package/lib/src/auth.d.ts +4 -1
  19. package/lib/src/auth.js +11 -2
  20. package/lib/src/auth.js.map +1 -1
  21. package/lib/src/auth.spec.d.ts +1 -0
  22. package/lib/src/auth.spec.js +13 -1
  23. package/lib/src/auth.spec.js.map +1 -1
  24. package/lib/src/config.spec.js +7 -0
  25. package/lib/src/config.spec.js.map +1 -1
  26. package/lib/src/embed/app.d.ts +5 -0
  27. package/lib/src/embed/app.js +1 -1
  28. package/lib/src/embed/app.js.map +1 -1
  29. package/lib/src/embed/app.spec.js +18 -6
  30. package/lib/src/embed/app.spec.js.map +1 -1
  31. package/lib/src/embed/embed.spec.js +2 -0
  32. package/lib/src/embed/embed.spec.js.map +1 -1
  33. package/lib/src/embed/events.spec.js +3 -1
  34. package/lib/src/embed/events.spec.js.map +1 -1
  35. package/lib/src/embed/liveboard.d.ts +12 -1
  36. package/lib/src/embed/liveboard.js +22 -4
  37. package/lib/src/embed/liveboard.js.map +1 -1
  38. package/lib/src/embed/liveboard.spec.js +33 -6
  39. package/lib/src/embed/liveboard.spec.js.map +1 -1
  40. package/lib/src/embed/pinboard.spec.js +7 -5
  41. package/lib/src/embed/pinboard.spec.js.map +1 -1
  42. package/lib/src/embed/search.d.ts +5 -0
  43. package/lib/src/embed/search.js +10 -2
  44. package/lib/src/embed/search.js.map +1 -1
  45. package/lib/src/embed/search.spec.js +9 -1
  46. package/lib/src/embed/search.spec.js.map +1 -1
  47. package/lib/src/embed/searchEmbed-basic-auth.spec.d.ts +1 -0
  48. package/lib/src/embed/searchEmbed-basic-auth.spec.js +96 -0
  49. package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -0
  50. package/lib/src/embed/ts-embed.d.ts +12 -3
  51. package/lib/src/embed/ts-embed.js +29 -10
  52. package/lib/src/embed/ts-embed.js.map +1 -1
  53. package/lib/src/embed/ts-embed.spec.js +38 -5
  54. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  55. package/lib/src/errors.d.ts +2 -0
  56. package/lib/src/errors.js +2 -0
  57. package/lib/src/errors.js.map +1 -1
  58. package/lib/src/react/index.js +3 -2
  59. package/lib/src/react/index.js.map +1 -1
  60. package/lib/src/react/index.spec.js +6 -4
  61. package/lib/src/react/index.spec.js.map +1 -1
  62. package/lib/src/test/test-utils.d.ts +6 -0
  63. package/lib/src/test/test-utils.js +15 -0
  64. package/lib/src/test/test-utils.js.map +1 -1
  65. package/lib/src/types.d.ts +211 -4
  66. package/lib/src/types.js +176 -0
  67. package/lib/src/types.js.map +1 -1
  68. package/lib/src/utils/processTrigger.d.ts +1 -1
  69. package/lib/src/utils/processTrigger.js +28 -8
  70. package/lib/src/utils/processTrigger.js.map +1 -1
  71. package/lib/src/utils/processTrigger.spec.js +11 -1
  72. package/lib/src/utils/processTrigger.spec.js.map +1 -1
  73. package/lib/src/utils.d.ts +3 -1
  74. package/lib/src/utils.js +20 -0
  75. package/lib/src/utils.js.map +1 -1
  76. package/lib/src/utils.spec.js +22 -1
  77. package/lib/src/utils.spec.js.map +1 -1
  78. package/lib/src/visual-embed-sdk.d.ts +240 -9
  79. package/package.json +4 -2
  80. package/src/auth.spec.ts +20 -1
  81. package/src/auth.ts +12 -2
  82. package/src/config.spec.ts +11 -0
  83. package/src/embed/app.spec.ts +22 -3
  84. package/src/embed/app.ts +6 -0
  85. package/src/embed/embed.spec.ts +2 -0
  86. package/src/embed/events.spec.ts +3 -0
  87. package/src/embed/liveboard.spec.ts +46 -6
  88. package/src/embed/liveboard.ts +34 -2
  89. package/src/embed/pinboard.spec.ts +8 -6
  90. package/src/embed/search.spec.ts +11 -1
  91. package/src/embed/search.ts +20 -1
  92. package/src/embed/searchEmbed-basic-auth.spec.ts +115 -0
  93. package/src/embed/ts-embed.spec.ts +51 -5
  94. package/src/embed/ts-embed.ts +40 -12
  95. package/src/errors.ts +3 -0
  96. package/src/react/index.spec.tsx +7 -2
  97. package/src/react/index.tsx +3 -2
  98. package/src/test/test-utils.ts +16 -0
  99. package/src/types.ts +209 -0
  100. package/src/utils/processTrigger.spec.ts +11 -1
  101. package/src/utils/processTrigger.ts +36 -12
  102. package/src/utils.spec.ts +29 -0
  103. package/src/utils.ts +34 -1
@@ -13,6 +13,7 @@ import {
13
13
  getOffsetTop,
14
14
  embedEventStatus,
15
15
  setAttributes,
16
+ getCustomisations,
16
17
  } from '../utils';
17
18
  import {
18
19
  getThoughtSpotHost,
@@ -31,6 +32,7 @@ import {
31
32
  Param,
32
33
  EmbedConfig,
33
34
  MessageOptions,
35
+ MessagePayload,
34
36
  MessageCallbackObj,
35
37
  } from '../types';
36
38
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
@@ -75,7 +77,7 @@ export interface FrameParams {
75
77
  * This parameters will be passed on the iframe
76
78
  * as is.
77
79
  */
78
- [key: string]: string | number | boolean;
80
+ [key: string]: string | number | boolean | undefined;
79
81
  }
80
82
 
81
83
  /**
@@ -202,6 +204,8 @@ export class TsEmbed {
202
204
  */
203
205
  private shouldEncodeUrlQueryParams = false;
204
206
 
207
+ private defaultHiddenActions = [Action.ReportError];
208
+
205
209
  constructor(domSelector: DOMSelector, viewConfig?: ViewConfig) {
206
210
  this.el = this.getDOMNode(domSelector);
207
211
  // TODO: handle error
@@ -212,6 +216,7 @@ export class TsEmbed {
212
216
  this.isError = false;
213
217
  this.viewConfig = viewConfig;
214
218
  this.shouldEncodeUrlQueryParams = this.embedConfig.shouldEncodeUrlQueryParams;
219
+ this.registerAppInit();
215
220
  }
216
221
 
217
222
  /**
@@ -242,7 +247,7 @@ export class TsEmbed {
242
247
  error,
243
248
  });
244
249
  // Log error
245
- console.log(error);
250
+ console.error(error);
246
251
  }
247
252
 
248
253
  /**
@@ -308,6 +313,23 @@ export class TsEmbed {
308
313
  });
309
314
  }
310
315
 
316
+ /**
317
+ * Send Custom style as part of payload of APP_INIT
318
+ */
319
+ private appInitCb = (_: any, responder: any) => {
320
+ responder({
321
+ type: EmbedEvent.APP_INIT,
322
+ data: { customisations: getCustomisations(this.embedConfig) },
323
+ });
324
+ };
325
+
326
+ /**
327
+ * Register APP_INIT event and sendback init payload
328
+ */
329
+ private registerAppInit = () => {
330
+ this.on(EmbedEvent.APP_INIT, this.appInitCb);
331
+ };
332
+
311
333
  /**
312
334
  * Constructs the base URL string to load the ThoughtSpot app.
313
335
  */
@@ -355,6 +377,7 @@ export class TsEmbed {
355
377
  ) {
356
378
  queryParams[Param.DisableLoginRedirect] = true;
357
379
  }
380
+ // TODO remove this
358
381
  if (this.embedConfig.customCssUrl) {
359
382
  queryParams[Param.CustomCSSUrl] = this.embedConfig.customCssUrl;
360
383
  }
@@ -382,9 +405,10 @@ export class TsEmbed {
382
405
  if (disabledActionReason) {
383
406
  queryParams[Param.DisableActionReason] = disabledActionReason;
384
407
  }
385
- if (hiddenActions?.length) {
386
- queryParams[Param.HideActions] = hiddenActions;
387
- }
408
+ queryParams[Param.HideActions] = [
409
+ ...this.defaultHiddenActions,
410
+ ...(hiddenActions ?? []),
411
+ ];
388
412
  if (Array.isArray(visibleActions)) {
389
413
  queryParams[Param.VisibleActions] = visibleActions;
390
414
  }
@@ -412,12 +436,16 @@ export class TsEmbed {
412
436
  showPrimaryNavbar = false,
413
437
  disableProfileAndHelp = false,
414
438
  isAppEmbed = false,
439
+ enableSearchAssist = false,
415
440
  ): string {
416
441
  const queryStringFrag = queryString ? `&${queryString}` : '';
417
442
  const primaryNavParam = `&primaryNavHidden=${!showPrimaryNavbar}`;
418
443
  const disableProfileAndHelpParam = `&profileAndHelpInNavBarHidden=${disableProfileAndHelp}`;
444
+ const enableSearchAssistParam = `&${Param.EnableSearchAssist}=${enableSearchAssist}`;
419
445
  let queryParams = `?embedApp=true${isAppEmbed ? primaryNavParam : ''}${
420
446
  isAppEmbed ? disableProfileAndHelpParam : ''
447
+ }${
448
+ enableSearchAssist ? enableSearchAssistParam : ''
421
449
  }${queryStringFrag}`;
422
450
  if (this.shouldEncodeUrlQueryParams) {
423
451
  queryParams = `?base64UrlEncodedFlags=${getEncodedQueryParamsString(
@@ -459,7 +487,6 @@ export class TsEmbed {
459
487
  });
460
488
 
461
489
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_START);
462
-
463
490
  getAuthPromise()
464
491
  ?.then((isLoggedIn: boolean) => {
465
492
  if (!isLoggedIn) {
@@ -691,15 +718,16 @@ export class TsEmbed {
691
718
  * @param messageType The event type
692
719
  * @param data The payload to send with the message
693
720
  */
694
- public trigger(
695
- messageType: HostEvent,
696
- data: any,
697
- ): typeof TsEmbed.prototype {
698
- processTrigger(this.iFrame, messageType, this.thoughtSpotHost, data);
721
+ public trigger(messageType: HostEvent, data: any): Promise<any> {
699
722
  uploadMixpanelEvent(
700
723
  `${MIXPANEL_EVENT.VISUAL_SDK_TRIGGER}-${messageType}`,
701
724
  );
702
- return this;
725
+ return processTrigger(
726
+ this.iFrame,
727
+ messageType,
728
+ this.thoughtSpotHost,
729
+ data,
730
+ );
703
731
  }
704
732
 
705
733
  /**
package/src/errors.ts CHANGED
@@ -3,4 +3,7 @@ export const ERROR_MESSAGE = {
3
3
  'Error parsing ThoughtSpot host. Please provide a valid URL.',
4
4
  LIVEBOARD_VIZ_ID_VALIDATION:
5
5
  'Please provide either liveboardId or pinboardId',
6
+ TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
7
+ SEARCHEMBED_BETA_WRANING_MESSAGE:
8
+ 'Search Embed is in Beta in this release.',
6
9
  };
@@ -2,15 +2,17 @@ import React from 'react';
2
2
  import '@testing-library/jest-dom';
3
3
  import '@testing-library/jest-dom/extend-expect';
4
4
  import { cleanup, fireEvent, render, waitFor } from '@testing-library/react';
5
+ import { Action, EmbedEvent, HostEvent } from '../types';
5
6
  import {
6
7
  executeAfterWait,
7
8
  getIFrameEl,
8
9
  getIFrameSrc,
9
10
  postMessageToParent,
11
+ mockMessageChannel,
10
12
  } from '../test/test-utils';
11
13
  import { SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef } from './index';
12
14
  import { AuthType, init } from '../index';
13
- import { EmbedEvent, HostEvent } from '../types';
15
+
14
16
  import { version } from '../../package.json';
15
17
 
16
18
  const thoughtSpotHost = 'localhost';
@@ -20,6 +22,7 @@ beforeAll(() => {
20
22
  thoughtSpotHost,
21
23
  authType: AuthType.None,
22
24
  });
25
+ spyOn(window, 'alert');
23
26
  });
24
27
 
25
28
  describe('React Components', () => {
@@ -37,7 +40,7 @@ describe('React Components', () => {
37
40
  ),
38
41
  ).toBe(true);
39
42
  expect(getIFrameSrc(container)).toBe(
40
- `http://${thoughtSpotHost}/?hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&hideAction=[%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true#/embed/answer`,
43
+ `http://${thoughtSpotHost}/?hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&hideAction=[%22${Action.ReportError}%22,%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true#/embed/answer`,
41
44
  );
42
45
  });
43
46
 
@@ -73,6 +76,7 @@ describe('React Components', () => {
73
76
  describe('LiveboardEmbed', () => {
74
77
  //
75
78
  it('Should be able to trigger events on the embed using refs', async () => {
79
+ mockMessageChannel();
76
80
  const TestComponent = () => {
77
81
  const embedRef = useEmbedRef();
78
82
  const onLiveboardRendered = () => {
@@ -109,6 +113,7 @@ describe('React Components', () => {
109
113
  data: ['viz1', 'viz2'],
110
114
  },
111
115
  `http://${thoughtSpotHost}`,
116
+ expect.anything(),
112
117
  );
113
118
  });
114
119
  });
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import useDeepCompareEffect from 'use-deep-compare-effect';
2
3
  import { SearchEmbed as _SearchEmbed, SearchViewConfig } from '../embed/search';
3
4
  import { AppEmbed as _AppEmbed, AppViewConfig } from '../embed/app';
4
5
  import {
@@ -25,7 +26,7 @@ const componentFactory = <
25
26
  Omit<U, 'className'>,
26
27
  V
27
28
  >(embedProps);
28
- React.useEffect(() => {
29
+ useDeepCompareEffect(() => {
29
30
  const tsEmbed = new EmbedConstructor(ref!.current, {
30
31
  ...viewConfig,
31
32
  });
@@ -40,7 +41,7 @@ const componentFactory = <
40
41
  // eslint-disable-next-line no-param-reassign
41
42
  forwardedRef.current = tsEmbed;
42
43
  }
43
- }, [embedProps]);
44
+ }, [viewConfig, listeners]);
44
45
 
45
46
  return (
46
47
  <div
@@ -70,3 +70,19 @@ export const EVENT_WAIT_TIME = 1000;
70
70
  export function fixedEncodeURI(str: string) {
71
71
  return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']');
72
72
  }
73
+
74
+ /**
75
+ * MessageChannel is available in Node > 15.0.0. Since the current node environment's
76
+ * used for github actions is not above 14, we are mocking this for the current unit tests.
77
+ */
78
+ export const messageChannelMock: any = {
79
+ port1: {},
80
+ port2: {},
81
+ };
82
+ export const mockMessageChannel = () => {
83
+ messageChannelMock.port1.close = jest.fn();
84
+ messageChannelMock.port2.onmessage = jest.fn();
85
+ window.MessageChannel = function MessageChannelMock() {
86
+ return messageChannelMock;
87
+ } as any;
88
+ };
package/src/types.ts CHANGED
@@ -19,8 +19,13 @@ export enum AuthType {
19
19
  None = 'None',
20
20
  /**
21
21
  * SSO using SAML
22
+ * @deprecated Use {@link SAML} instead
22
23
  */
23
24
  SSO = 'SSO_SAML',
25
+ /**
26
+ * SSO using SAML
27
+ */
28
+ SAML = 'SSO_SAML',
24
29
  /**
25
30
  * SSO using OIDC
26
31
  */
@@ -40,6 +45,28 @@ export enum AuthType {
40
45
 
41
46
  export type DOMSelector = string | HTMLElement;
42
47
 
48
+ interface customCssInterface {
49
+ variables?: {
50
+ [variableName: string]: string;
51
+ };
52
+ // eslint-disable-next-line camelcase
53
+ rules_UNSTABLE?: {
54
+ [selector: string]: {
55
+ [declaration: string]: string;
56
+ };
57
+ };
58
+ }
59
+ interface CustomStyles {
60
+ customCSSUrl?: string;
61
+ customCss?: customCssInterface;
62
+ }
63
+ export interface CustomisationsInterface {
64
+ style: CustomStyles;
65
+ content: {
66
+ [key: string]: string;
67
+ };
68
+ }
69
+
43
70
  /**
44
71
  * The configuration object for embedding ThoughtSpot content.
45
72
  * It includes the ThoughtSpot hostname or IP address,
@@ -177,6 +204,17 @@ export interface EmbedConfig {
177
204
  * @version SDK: 1.10.4 | ThoughtSpot: *
178
205
  */
179
206
  detectCookieAccessSlow?: boolean;
207
+ /**
208
+ * Hide beta alert warning message for SearchEmbed.
209
+ *
210
+ * @version SDK: 1.12.0 | ThoughtSpot: *
211
+ */
212
+ suppressSearchEmbedBetaWarning?: boolean;
213
+
214
+ /**
215
+ * Custom style params for embed Config
216
+ */
217
+ customisations?: CustomisationsInterface;
180
218
  }
181
219
 
182
220
  /**
@@ -551,6 +589,65 @@ export enum EmbedEvent {
551
589
  * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl
552
590
  */
553
591
  AnswerChartSwitcher = 'answerChartSwitcher',
592
+ /**
593
+ *
594
+ */
595
+ APP_INIT = 'appInit',
596
+ /**
597
+ * Emitted when a user clicks Show Liveboard details on a Liveboard
598
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
599
+ */
600
+ LiveboardInfo = 'pinboardInfo',
601
+ /**
602
+ * Emitted when a user clicks on the Favorite icon on a Liveboard
603
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
604
+ */
605
+ AddToFavorites = 'addToFavorites',
606
+ /**
607
+ * Emitted when a user clicks Schedule on a Liveboard
608
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
609
+ */
610
+ Schedule = 'subscription',
611
+ /**
612
+ * Emitted when a user clicks Edit on a Liveboard or visualization
613
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
614
+ */
615
+ Edit = 'edit',
616
+ /**
617
+ * Emitted when a user clicks Make a copy on a Liveboard
618
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
619
+ */
620
+ MakeACopy = 'makeACopy',
621
+ /**
622
+ * Emitted when a user clicks Present on a Liveboard or visualization
623
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
624
+ */
625
+ Present = 'present',
626
+ /**
627
+ * Emitted when a user clicks Delete on a Liveboard
628
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
629
+ */
630
+ Delete = 'delete',
631
+ /**
632
+ * Emitted when a user clicks Manage schedules on a Liveboard
633
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
634
+ */
635
+ SchedulesList = 'schedule-list',
636
+ /**
637
+ * Emitted when a user clicks Cancel in edit mode on a Liveboard
638
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
639
+ */
640
+ Cancel = 'cancel',
641
+ /**
642
+ * Emitted when a user clicks Explore on a visualization
643
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
644
+ */
645
+ Explore = 'explore',
646
+ /**
647
+ * Emitted when a user clicks Copy link action on a visualization
648
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
649
+ */
650
+ CopyLink = 'embedDocument',
554
651
  }
555
652
 
556
653
  /**
@@ -608,6 +705,112 @@ export enum HostEvent {
608
705
  * @version SDK: 1.12.0 | ThoughtSpot: 8.4.0.cl
609
706
  */
610
707
  Navigate = 'Navigate',
708
+ /**
709
+ * Gets the current pinboard content.
710
+ * @version SDK: 1.13.0 | ThoughtSpot: 8.5.0.cl
711
+ */
712
+ getExportRequestForCurrentPinboard = 'getExportRequestForCurrentPinboard',
713
+ /**
714
+ * Triggers the Pin action on an embedded object
715
+ * @param - incase of Liveboard embed, takes in an object with vizId as a key
716
+ * can be left empty for search and visualization embeds
717
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
718
+ */
719
+ Pin = 'pin',
720
+ /**
721
+ * Triggers the Show Liveboard details action on a Liveboard
722
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
723
+ */
724
+ LiveboardInfo = 'pinboardInfo',
725
+ /**
726
+ * Triggers the Schedule action on a Liveboard
727
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
728
+ */
729
+ Schedule = 'subscription',
730
+ /**
731
+ * Triggers the Manage schedule action on a Liveboard
732
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
733
+ */
734
+ SchedulesList = 'schedule-list',
735
+ /**
736
+ * Triggers the Export TML action on a Liveboard
737
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
738
+ */
739
+ ExportTML = 'exportTSL',
740
+ /**
741
+ * Triggers the Edit TML action on a Liveboard
742
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
743
+ */
744
+ EditTML = 'editTSL',
745
+ /**
746
+ * Triggers the Update TML action on a Liveboard
747
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
748
+ */
749
+ UpdateTML = 'updateTSL',
750
+ /**
751
+ * Triggers the Download PDF action on a Liveboard
752
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
753
+ */
754
+ DownloadAsPdf = 'downloadAsPdf',
755
+ /**
756
+ * Triggers the Make a copy action on a Liveboard
757
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
758
+ */
759
+ MakeACopy = 'makeACopy',
760
+ /**
761
+ * Triggers the Delete action on a Liveboard
762
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
763
+ */
764
+ Remove = 'delete',
765
+ /**
766
+ * Triggers the Explore action on a visualization
767
+ * @param - an object with vizId as a key
768
+ * eg: {vizId: '730496d6-6903-4601-937e-2c691821af3c'}
769
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
770
+ */
771
+ Explore = 'explore',
772
+ /**
773
+ * Triggers the Create alert action on a visualization
774
+ * @param - an object with vizId as a key
775
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
776
+ */
777
+ CreateMonitor = 'createMonitor',
778
+ /**
779
+ * Triggers the Manage alert action on a visualization
780
+ * @param - an object with vizId as a key
781
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
782
+ */
783
+ ManageMonitor = 'manageMonitor',
784
+ /**
785
+ * Triggers the Edit action on a Liveboard or visualization
786
+ * @param - object - to trigger the action for a specfic visualization in Liveboard embed, pass in vizId as a key
787
+ * @example
788
+ * liveboardEmbed.trigger(HostEvent.Edit)
789
+ * liveboardEmbed.trigger(HostEvent.Edit, {vizId: '730496d6-6903-4601-937e-2c691821af3c'})
790
+ * vizEmbed.trigger((HostEvent.Edit)
791
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
792
+ */
793
+ Edit = 'edit',
794
+ /**
795
+ * Triggers the Copy link action on a Liveboard or visualization
796
+ * @param - object - to trigger the action for a specfic visualization in Liveboard embed, pass in vizId as a key
797
+ * @example
798
+ * liveboardEmbed.trigger(HostEvent.CopyLink)
799
+ * liveboardEmbed.trigger(HostEvent.CopyLink, {vizId: '730496d6-6903-4601-937e-2c691821af3c'})
800
+ * vizEmbed.trigger((HostEvent.CopyLink)
801
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
802
+ */
803
+ CopyLink = 'embedDocument',
804
+ /**
805
+ * Triggers the Present action on a Liveboard or visualization
806
+ * @param - object - to trigger the action for a specfic visualization in Liveboard embed, pass in vizId as a key
807
+ * @example
808
+ * liveboardEmbed.trigger(HostEvent.Present)
809
+ * liveboardEmbed.trigger(HostEvent.Present, {vizId: '730496d6-6903-4601-937e-2c691821af3c'})
810
+ * vizEmbed.trigger((HostEvent.Present)
811
+ * @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl
812
+ */
813
+ Present = 'present',
611
814
  }
612
815
 
613
816
  /**
@@ -656,6 +859,7 @@ export enum Param {
656
859
  fullHeight = 'isFullHeightPinboard',
657
860
  livedBoardEmbed = 'isLiveboardEmbed',
658
861
  searchEmbed = 'isSearchEmbed',
862
+ vizEmbed = 'isVizEmbed',
659
863
  Version = 'sdkVersion',
660
864
  ViewPortHeight = 'viewPortHeight',
661
865
  ViewPortWidth = 'viewPortWidth',
@@ -666,6 +870,7 @@ export enum Param {
666
870
  LiveboardV2Enabled = 'isPinboardV2Enabled',
667
871
  ShowAlerts = 'showAlerts',
668
872
  Locale = 'locale',
873
+ CustomStyle = 'customStyle',
669
874
  }
670
875
 
671
876
  /**
@@ -808,6 +1013,10 @@ export enum Action {
808
1013
  * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl
809
1014
  */
810
1015
  CreateMonitor = 'createMonitor',
1016
+ /**
1017
+ * @version SDK: 1.11.1 | ThoughtSpot: 8.3.0.cl
1018
+ */
1019
+ ReportError = 'reportError',
811
1020
  }
812
1021
 
813
1022
  export interface SessionInterface {
@@ -1,5 +1,6 @@
1
1
  import * as _processTriggerInstance from './processTrigger';
2
2
  import { HostEvent } from '../types';
3
+ import { messageChannelMock, mockMessageChannel } from '../test/test-utils';
3
4
 
4
5
  describe('Unit test for processTrigger', () => {
5
6
  const iFrame: any = {
@@ -29,12 +30,21 @@ describe('Unit test for processTrigger', () => {
29
30
  const messageType = HostEvent.Search;
30
31
  const thoughtSpotHost = 'http://localhost:3000';
31
32
  const data = {};
32
- _processTriggerInstance.processTrigger(
33
+ mockMessageChannel();
34
+ const triggerPromise = _processTriggerInstance.processTrigger(
33
35
  iFrame,
34
36
  messageType,
35
37
  thoughtSpotHost,
36
38
  data,
37
39
  );
38
40
  expect(iFrame.contentWindow.postMessage).toBeCalled();
41
+ const res = {
42
+ data: {
43
+ test: '123',
44
+ },
45
+ };
46
+ messageChannelMock.port1.onmessage(res);
47
+ expect(messageChannelMock.port1.close).toBeCalled();
48
+ expect(triggerPromise).resolves.toEqual(res.data);
39
49
  });
40
50
  });
@@ -1,3 +1,4 @@
1
+ import { ERROR_MESSAGE } from '../errors';
1
2
  import { HostEvent } from '../types';
2
3
 
3
4
  /**
@@ -17,24 +18,47 @@ function postIframeMessage(
17
18
  iFrame: HTMLIFrameElement,
18
19
  message: { type: HostEvent; data: any },
19
20
  thoughtSpotHost: string,
21
+ channel?: MessageChannel,
20
22
  ) {
21
- return iFrame.contentWindow.postMessage(message, thoughtSpotHost);
23
+ return iFrame.contentWindow.postMessage(message, thoughtSpotHost, [
24
+ channel?.port2,
25
+ ]);
22
26
  }
23
27
 
28
+ const TRIGGER_TIMEOUT = 30000;
29
+
24
30
  export function processTrigger(
25
31
  iFrame: HTMLIFrameElement,
26
32
  messageType: HostEvent,
27
33
  thoughtSpotHost: string,
28
34
  data: any,
29
- ) {
30
- switch (messageType) {
31
- case HostEvent.Reload:
32
- return reload(iFrame);
33
- default:
34
- return postIframeMessage(
35
- iFrame,
36
- { type: messageType, data },
37
- thoughtSpotHost,
38
- );
39
- }
35
+ ): Promise<any> {
36
+ return new Promise<any>((res, rej) => {
37
+ if (messageType === HostEvent.Reload) {
38
+ reload(iFrame);
39
+ return res(null);
40
+ }
41
+ const channel = new MessageChannel();
42
+ channel.port1.onmessage = ({ data: responseData }) => {
43
+ channel.port1.close();
44
+ if (responseData.error) {
45
+ rej(responseData.error);
46
+ } else {
47
+ res(responseData);
48
+ }
49
+ };
50
+
51
+ // Close the messageChannel and resolve the promise if timeout.
52
+ setTimeout(() => {
53
+ channel.port1.close();
54
+ res(new Error(ERROR_MESSAGE.TRIGGER_TIMED_OUT));
55
+ }, TRIGGER_TIMEOUT);
56
+
57
+ return postIframeMessage(
58
+ iFrame,
59
+ { type: messageType, data },
60
+ thoughtSpotHost,
61
+ channel,
62
+ );
63
+ });
40
64
  }
package/src/utils.spec.ts CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  getEncodedQueryParamsString,
10
10
  appendToUrlHash,
11
11
  getRedirectUrl,
12
+ checkReleaseVersionInBeta,
12
13
  } from './utils';
13
14
  import { RuntimeFilterOp } from './types';
14
15
 
@@ -110,4 +111,32 @@ describe('unit test for utils', () => {
110
111
  expect(getEncodedQueryParamsString('')).toBe('');
111
112
  expect(getEncodedQueryParamsString('test')).toBe('dGVzdA');
112
113
  });
114
+
115
+ test('when ReleaseVersion is empty ', () => {
116
+ expect(checkReleaseVersionInBeta('', false)).toBe(false);
117
+ });
118
+
119
+ test('when ReleaseVersion is 7.0.1.cl ', () => {
120
+ expect(checkReleaseVersionInBeta('7.0.1.cl', false)).toBe(false);
121
+ });
122
+
123
+ test('when cluster has dev version', () => {
124
+ expect(checkReleaseVersionInBeta('dev', false)).toBe(false);
125
+ });
126
+
127
+ test('when cluster is above 8.4.0.cl-11 software version', () => {
128
+ expect(checkReleaseVersionInBeta('8.4.0.cl-117', false)).toBe(false);
129
+ });
130
+
131
+ test('when cluster is bellow 8.0.0.sw software version', () => {
132
+ expect(checkReleaseVersionInBeta('7.2.1.sw', false)).toBe(true);
133
+ });
134
+
135
+ test('when suppressBetaWarning is true and ReleaseVersion is 7.0.1', () => {
136
+ expect(checkReleaseVersionInBeta('7.0.1', true)).toBe(false);
137
+ });
138
+
139
+ test('when suppressBetaWarning is false ReleaseVersion is 7.0.1', () => {
140
+ expect(checkReleaseVersionInBeta('7.0.1', false)).toBe(true);
141
+ });
113
142
  });
package/src/utils.ts CHANGED
@@ -7,7 +7,12 @@
7
7
  * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
8
8
  */
9
9
 
10
- import { QueryParams, RuntimeFilter } from './types';
10
+ import {
11
+ EmbedConfig,
12
+ QueryParams,
13
+ RuntimeFilter,
14
+ CustomisationsInterface,
15
+ } from './types';
11
16
 
12
17
  /**
13
18
  * Construct a runtime filters query string from the given filters.
@@ -154,3 +159,31 @@ export const setAttributes = (
154
159
  element.setAttribute(key, attributes[key].toString());
155
160
  });
156
161
  };
162
+
163
+ const isCloudRelease = (version: string) => version.endsWith('.cl');
164
+
165
+ /* For Search Embed: ReleaseVersionInBeta */
166
+ export const checkReleaseVersionInBeta = (
167
+ releaseVersion: string,
168
+ suppressBetaWarning: boolean,
169
+ ): boolean => {
170
+ if (releaseVersion !== '' && !isCloudRelease(releaseVersion)) {
171
+ const splittedReleaseVersion = releaseVersion.split('.');
172
+ const majorVersion = Number(splittedReleaseVersion[0]);
173
+ const isBetaVersion = majorVersion < 8;
174
+ return !suppressBetaWarning && isBetaVersion;
175
+ }
176
+ return false;
177
+ };
178
+
179
+ export const getCustomisations = (
180
+ embedConfig: EmbedConfig,
181
+ ): CustomisationsInterface => {
182
+ const { customCssUrl } = embedConfig;
183
+ let { customisations } = embedConfig;
184
+ customisations = customisations || ({} as CustomisationsInterface);
185
+ customisations.style = customisations.style || {};
186
+ customisations.style.customCSSUrl =
187
+ customisations.style.customCSSUrl || customCssUrl;
188
+ return customisations;
189
+ };