@thoughtspot/visual-embed-sdk 1.24.0-alpha.6 → 1.24.0-dev

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 (119) hide show
  1. package/cjs/package.json +2 -2
  2. package/cjs/src/embed/app.d.ts +1 -0
  3. package/cjs/src/embed/app.d.ts.map +1 -1
  4. package/cjs/src/embed/app.js +1 -0
  5. package/cjs/src/embed/app.js.map +1 -1
  6. package/cjs/src/embed/liveboard.d.ts +6 -1
  7. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  8. package/cjs/src/embed/liveboard.js +10 -2
  9. package/cjs/src/embed/liveboard.js.map +1 -1
  10. package/cjs/src/embed/liveboard.spec.js +23 -7
  11. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  12. package/cjs/src/embed/search.d.ts +5 -1
  13. package/cjs/src/embed/search.d.ts.map +1 -1
  14. package/cjs/src/embed/search.js +4 -1
  15. package/cjs/src/embed/search.js.map +1 -1
  16. package/cjs/src/embed/search.spec.js +15 -0
  17. package/cjs/src/embed/search.spec.js.map +1 -1
  18. package/cjs/src/embed/ts-embed.d.ts +19 -0
  19. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  20. package/cjs/src/embed/ts-embed.js +136 -6
  21. package/cjs/src/embed/ts-embed.js.map +1 -1
  22. package/cjs/src/embed/ts-embed.spec.js +38 -1
  23. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  24. package/cjs/src/react/all-types-export.d.ts +1 -1
  25. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  26. package/cjs/src/react/all-types-export.js +2 -1
  27. package/cjs/src/react/all-types-export.js.map +1 -1
  28. package/cjs/src/react/index.d.ts +1 -0
  29. package/cjs/src/react/index.d.ts.map +1 -1
  30. package/cjs/src/react/index.js +18 -4
  31. package/cjs/src/react/index.js.map +1 -1
  32. package/cjs/src/types.d.ts +87 -7
  33. package/cjs/src/types.d.ts.map +1 -1
  34. package/cjs/src/types.js +60 -5
  35. package/cjs/src/types.js.map +1 -1
  36. package/cjs/src/utils.d.ts +9 -1
  37. package/cjs/src/utils.d.ts.map +1 -1
  38. package/cjs/src/utils.js +36 -1
  39. package/cjs/src/utils.js.map +1 -1
  40. package/cjs/src/utils.spec.js +24 -0
  41. package/cjs/src/utils.spec.js.map +1 -1
  42. package/dist/src/embed/app.d.ts +1 -0
  43. package/dist/src/embed/app.d.ts.map +1 -1
  44. package/dist/src/embed/liveboard.d.ts +6 -1
  45. package/dist/src/embed/liveboard.d.ts.map +1 -1
  46. package/dist/src/embed/search.d.ts +5 -1
  47. package/dist/src/embed/search.d.ts.map +1 -1
  48. package/dist/src/embed/ts-embed.d.ts +19 -0
  49. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  50. package/dist/src/react/all-types-export.d.ts +1 -1
  51. package/dist/src/react/all-types-export.d.ts.map +1 -1
  52. package/dist/src/react/index.d.ts +1 -0
  53. package/dist/src/react/index.d.ts.map +1 -1
  54. package/dist/src/types.d.ts +87 -7
  55. package/dist/src/types.d.ts.map +1 -1
  56. package/dist/src/utils.d.ts +9 -1
  57. package/dist/src/utils.d.ts.map +1 -1
  58. package/dist/tsembed-react.es.js +264 -21
  59. package/dist/tsembed-react.js +264 -20
  60. package/dist/tsembed.es.js +245 -16
  61. package/dist/tsembed.js +245 -16
  62. package/dist/visual-embed-sdk-react-full.d.ts +115 -7
  63. package/dist/visual-embed-sdk-react.d.ts +115 -7
  64. package/dist/visual-embed-sdk.d.ts +114 -7
  65. package/lib/package.json +2 -2
  66. package/lib/src/embed/app.d.ts +1 -0
  67. package/lib/src/embed/app.d.ts.map +1 -1
  68. package/lib/src/embed/app.js +1 -0
  69. package/lib/src/embed/app.js.map +1 -1
  70. package/lib/src/embed/liveboard.d.ts +6 -1
  71. package/lib/src/embed/liveboard.d.ts.map +1 -1
  72. package/lib/src/embed/liveboard.js +11 -3
  73. package/lib/src/embed/liveboard.js.map +1 -1
  74. package/lib/src/embed/liveboard.spec.js +23 -7
  75. package/lib/src/embed/liveboard.spec.js.map +1 -1
  76. package/lib/src/embed/search.d.ts +5 -1
  77. package/lib/src/embed/search.d.ts.map +1 -1
  78. package/lib/src/embed/search.js +5 -2
  79. package/lib/src/embed/search.js.map +1 -1
  80. package/lib/src/embed/search.spec.js +15 -0
  81. package/lib/src/embed/search.spec.js.map +1 -1
  82. package/lib/src/embed/ts-embed.d.ts +19 -0
  83. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  84. package/lib/src/embed/ts-embed.js +137 -7
  85. package/lib/src/embed/ts-embed.js.map +1 -1
  86. package/lib/src/embed/ts-embed.spec.js +38 -1
  87. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  88. package/lib/src/react/all-types-export.d.ts +1 -1
  89. package/lib/src/react/all-types-export.d.ts.map +1 -1
  90. package/lib/src/react/all-types-export.js +1 -1
  91. package/lib/src/react/all-types-export.js.map +1 -1
  92. package/lib/src/react/index.d.ts +1 -0
  93. package/lib/src/react/index.d.ts.map +1 -1
  94. package/lib/src/react/index.js +17 -3
  95. package/lib/src/react/index.js.map +1 -1
  96. package/lib/src/types.d.ts +87 -7
  97. package/lib/src/types.d.ts.map +1 -1
  98. package/lib/src/types.js +60 -5
  99. package/lib/src/types.js.map +1 -1
  100. package/lib/src/utils.d.ts +9 -1
  101. package/lib/src/utils.d.ts.map +1 -1
  102. package/lib/src/utils.js +32 -0
  103. package/lib/src/utils.js.map +1 -1
  104. package/lib/src/utils.spec.js +25 -1
  105. package/lib/src/utils.spec.js.map +1 -1
  106. package/lib/src/visual-embed-sdk.d.ts +116 -9
  107. package/package.json +5 -5
  108. package/src/embed/app.ts +1 -0
  109. package/src/embed/liveboard.spec.ts +29 -10
  110. package/src/embed/liveboard.ts +19 -2
  111. package/src/embed/search.spec.ts +18 -0
  112. package/src/embed/search.ts +16 -1
  113. package/src/embed/ts-embed.spec.ts +40 -1
  114. package/src/embed/ts-embed.ts +174 -14
  115. package/src/react/all-types-export.ts +1 -0
  116. package/src/react/index.tsx +25 -8
  117. package/src/types.ts +97 -16
  118. package/src/utils.spec.ts +31 -0
  119. package/src/utils.ts +43 -0
@@ -18,6 +18,9 @@ import {
18
18
  getDOMNode,
19
19
  getFilterQuery,
20
20
  getQueryParamString,
21
+ getRuntimeParameters,
22
+ setStyleProperties,
23
+ removeStyleProperties,
21
24
  } from '../utils';
22
25
  import {
23
26
  getThoughtSpotHost,
@@ -272,11 +275,14 @@ export class TsEmbed {
272
275
  data: {
273
276
  customisations: getCustomisations(this.embedConfig, this.viewConfig),
274
277
  authToken,
275
- runtimeFilterParams: getRuntimeFilters(this.viewConfig.runtimeFilters),
278
+ runtimeFilterParams: this.viewConfig.excludeRuntimeFiltersfromURL
279
+ ? getRuntimeFilters(this.viewConfig.runtimeFilters)
280
+ : null,
276
281
  hiddenHomepageModules: this.viewConfig.hiddenHomepageModules || [],
277
282
  hostConfig: this.embedConfig.hostConfig,
278
283
  hiddenHomeLeftNavItems: this.viewConfig?.hiddenHomeLeftNavItems
279
- ? this.viewConfig?.hiddenHomeLeftNavItems : [],
284
+ ? this.viewConfig?.hiddenHomeLeftNavItems
285
+ : [],
280
286
  },
281
287
  });
282
288
  };
@@ -305,12 +311,8 @@ export class TsEmbed {
305
311
  * Register APP_INIT event and sendback init payload
306
312
  */
307
313
  private registerAppInit = () => {
308
- this.on(
309
- EmbedEvent.APP_INIT, this.appInitCb, { start: false }, true,
310
- );
311
- this.on(
312
- EmbedEvent.AuthExpire, this.updateAuthToken, { start: false }, true,
313
- );
314
+ this.on(EmbedEvent.APP_INIT, this.appInitCb, { start: false }, true);
315
+ this.on(EmbedEvent.AuthExpire, this.updateAuthToken, { start: false }, true);
314
316
  };
315
317
 
316
318
  /**
@@ -510,8 +512,7 @@ export class TsEmbed {
510
512
  iFrame.allow = 'clipboard-read; clipboard-write';
511
513
 
512
514
  const {
513
- height: frameHeight,
514
- width: frameWidth, ...restParams
515
+ height: frameHeight, width: frameWidth, ...restParams
515
516
  } = this.viewConfig.frameParams || {};
516
517
  const width = getCssDimension(frameWidth || DEFAULT_EMBED_WIDTH);
517
518
  const height = getCssDimension(frameHeight || DEFAULT_EMBED_HEIGHT);
@@ -556,7 +557,11 @@ export class TsEmbed {
556
557
  return getAuthPromise()
557
558
  ?.then((isLoggedIn: boolean) => {
558
559
  if (!isLoggedIn) {
559
- this.insertIntoDOM(this.embedConfig.loginFailedMessage);
560
+ if (this.isPreRendered) {
561
+ this.insertIntoDOMForPreRender(this.embedConfig.loginFailedMessage);
562
+ } else {
563
+ this.insertIntoDOM(this.embedConfig.loginFailedMessage);
564
+ }
560
565
  return;
561
566
  }
562
567
 
@@ -579,7 +584,11 @@ export class TsEmbed {
579
584
  this.iFrame.addEventListener('error', () => {
580
585
  nextInQueue();
581
586
  });
582
- this.insertIntoDOM(this.iFrame);
587
+ if (this.isPreRendered) {
588
+ this.insertIntoDOMForPreRender(this.iFrame);
589
+ } else {
590
+ this.insertIntoDOM(this.iFrame);
591
+ }
583
592
  const prefetchIframe = document.querySelectorAll('.prefetchIframe');
584
593
  if (prefetchIframe.length) {
585
594
  prefetchIframe.forEach((el) => {
@@ -593,12 +602,150 @@ export class TsEmbed {
593
602
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_FAILED, {
594
603
  error: JSON.stringify(error),
595
604
  });
596
- this.insertIntoDOM(this.embedConfig.loginFailedMessage);
605
+ if (this.isPreRendered) {
606
+ this.insertIntoDOMForPreRender(this.embedConfig.loginFailedMessage);
607
+ } else {
608
+ this.insertIntoDOM(this.embedConfig.loginFailedMessage);
609
+ }
597
610
  this.handleError(error);
598
611
  });
599
612
  });
600
613
  }
601
614
 
615
+ public getPreRenderIds() {
616
+ return {
617
+ wrapper: `tsEmbed-pre-render-wrapper-${this.viewConfig.preRenderId}`,
618
+ shield: `tsEmbed-pre-render-shield-${this.viewConfig.preRenderId}`,
619
+ child: `tsEmbed-pre-render-child-${this.viewConfig.preRenderId}`,
620
+ };
621
+ }
622
+
623
+ protected createPreRenderWrapper(child: HTMLElement): HTMLDivElement {
624
+ if (!this.viewConfig.preRenderId) {
625
+ throw new Error('Pre render id is required');
626
+ }
627
+
628
+ const preRenderIds = this.getPreRenderIds();
629
+
630
+ const stalePreRenderWrapper = document.getElementById(preRenderIds.wrapper);
631
+ if (stalePreRenderWrapper) {
632
+ console.log('Found stale wrapper , removing');
633
+ stalePreRenderWrapper.remove();
634
+ }
635
+
636
+ const preRenderWrapper = document.createElement('div');
637
+ preRenderWrapper.id = preRenderIds.wrapper;
638
+ setStyleProperties(preRenderWrapper, { position: 'absolute', width: '100vw', height: '100vh' });
639
+
640
+ const preRenderShield = document.createElement('div');
641
+ preRenderShield.id = preRenderIds.shield;
642
+ setStyleProperties(preRenderShield, { position: 'absolute', width: '100%', height: '100%' });
643
+
644
+ child.id = preRenderIds.child;
645
+
646
+ preRenderWrapper.appendChild(child);
647
+ preRenderWrapper.appendChild(preRenderShield);
648
+
649
+ this.preRenderWrapper = preRenderWrapper;
650
+ this.preRenderShield = preRenderShield;
651
+ this.preRenderChild = child;
652
+
653
+ return preRenderWrapper;
654
+ }
655
+
656
+ protected preRenderWrapper: HTMLElement;
657
+
658
+ protected preRenderShield: HTMLElement;
659
+
660
+ protected preRenderChild: HTMLElement;
661
+
662
+ protected isPreRenderAvailable(): boolean {
663
+ const preRenderIds = this.getPreRenderIds();
664
+ this.preRenderWrapper = this.preRenderWrapper
665
+ || document.getElementById(preRenderIds.wrapper);
666
+ this.preRenderShield = this.preRenderShield
667
+ || document.getElementById(preRenderIds.shield);
668
+ this.preRenderChild = this.preRenderChild
669
+ || document.getElementById(preRenderIds.child);
670
+
671
+ return !!this.preRenderWrapper && !!this.preRenderShield
672
+ && !!this.preRenderChild;
673
+ }
674
+
675
+ protected insertIntoDOMForPreRender(child: string | HTMLElement): void {
676
+ let childNode: HTMLElement;
677
+ if (typeof child === 'string') {
678
+ const divChildNode = document.createElement('div');
679
+ divChildNode.innerHTML = child;
680
+ childNode = divChildNode;
681
+ } else {
682
+ childNode = child;
683
+ }
684
+
685
+ const preRenderWrapper = this.createPreRenderWrapper(childNode);
686
+
687
+ document.body.appendChild(preRenderWrapper);
688
+
689
+ this.hidePreRender();
690
+ }
691
+
692
+ public hidePreRender(): void {
693
+ if (!this.isPreRenderAvailable()) {
694
+ // if the embed component is not preRendered , nothing to hide
695
+ console.log('No preRender found, not hiding ');
696
+ return;
697
+ }
698
+
699
+ setStyleProperties(this.preRenderWrapper, {
700
+ opacity: '0',
701
+ pointerEvents: 'none',
702
+ zIndex: '-1000',
703
+ position: 'absolute ',
704
+ top: '0',
705
+ left: '0',
706
+ });
707
+
708
+ const childBoundingRect = this.preRenderChild.getBoundingClientRect();
709
+
710
+ setStyleProperties(this.preRenderShield, {
711
+ opacity: '0',
712
+ pointerEvents: 'none',
713
+ zIndex: '1',
714
+ width: `${childBoundingRect.width}px`,
715
+ height: `${childBoundingRect.height}px`,
716
+ position: 'absolute',
717
+ top: '0',
718
+ left: '0',
719
+ });
720
+ }
721
+
722
+ public showPreRender() {
723
+ if (!this.isPreRenderAvailable()) {
724
+ // if the Embed component is nor preRendered , Render it now and
725
+ // show it (hide is defalt behaviour)
726
+ console.log('No preRender found, creating new ');
727
+ this.render();
728
+ return;
729
+ }
730
+
731
+ this.syncPreRenderStyle();
732
+
733
+ removeStyleProperties(this.preRenderWrapper, ['z-index', 'opacity', 'pointer-events']);
734
+
735
+ setStyleProperties(this.preRenderShield, { zIndex: '-1' });
736
+ }
737
+
738
+ public syncPreRenderStyle() {
739
+ if (!this.el) {
740
+ throw new Error('Embed element is not defined');
741
+ }
742
+ const elBoundingClient = this.el.getBoundingClientRect();
743
+
744
+ setStyleProperties(this.preRenderWrapper, {
745
+ top: `${elBoundingClient.y}px`, left: `${elBoundingClient.x}px`, width: `${elBoundingClient.width}px`, height: `${elBoundingClient.height}px`,
746
+ });
747
+ }
748
+
602
749
  protected insertIntoDOM(child: string | Node): void {
603
750
  if (this.viewConfig.insertAsSibling) {
604
751
  if (typeof child === 'string') {
@@ -830,6 +977,16 @@ export class TsEmbed {
830
977
  return this;
831
978
  }
832
979
 
980
+ private isPreRendered: boolean;
981
+
982
+ /**
983
+ * Creates the preRender shell
984
+ */
985
+ public preRender(): TsEmbed {
986
+ this.isPreRendered = true;
987
+ return this;
988
+ }
989
+
833
990
  /**
834
991
  * Get the Post Url Params for THOUGHTSPOT from the current
835
992
  * host app URL.
@@ -920,8 +1077,11 @@ export class V1Embed extends TsEmbed {
920
1077
  let queryString = queryParams;
921
1078
  if (!this.viewConfig.excludeRuntimeFiltersfromURL) {
922
1079
  const runtimeFilters = this.viewConfig.runtimeFilters;
1080
+ const runtimeParameters = this.viewConfig.runtimeParameters;
1081
+
1082
+ const parameterQuery = getRuntimeParameters(runtimeParameters || []);
923
1083
  const filterQuery = getFilterQuery(runtimeFilters || []);
924
- queryString = [filterQuery, queryParams].filter(Boolean).join('&');
1084
+ queryString = [parameterQuery, filterQuery, queryParams].filter(Boolean).join('&');
925
1085
  }
926
1086
  return this.getV1EmbedBasePath(queryString);
927
1087
  }
@@ -5,6 +5,7 @@ export {
5
5
  AppEmbed,
6
6
  SageEmbed,
7
7
  useEmbedRef,
8
+ PreRenderedLiveboardEmbed,
8
9
  } from './index';
9
10
 
10
11
  export {
@@ -13,6 +13,7 @@ import { EmbedProps, getViewPropsAndListeners } from './util';
13
13
 
14
14
  const componentFactory = <T extends typeof TsEmbed, U extends EmbedProps, V extends ViewConfig>(
15
15
  EmbedConstructor: T,
16
+ isPreRenderedComponent = false,
16
17
  ) => React.forwardRef<InstanceType<T>, U>(
17
18
  (props: U, forwardedRef: React.MutableRefObject<InstanceType<T>>) => {
18
19
  const ref = React.useRef<HTMLDivElement>(null);
@@ -42,13 +43,24 @@ const componentFactory = <T extends typeof TsEmbed, U extends EmbedProps, V exte
42
43
  listeners[eventName as EmbedEvent],
43
44
  );
44
45
  });
45
- tsEmbed.render();
46
+
47
+ if (isPreRenderedComponent) {
48
+ tsEmbed.preRender();
49
+ } else if (props.preRenderId) {
50
+ tsEmbed.showPreRender();
51
+ } else {
52
+ tsEmbed.render();
53
+ }
54
+
46
55
  if (forwardedRef) {
47
56
  // eslint-disable-next-line no-param-reassign
48
57
  forwardedRef.current = tsEmbed;
49
58
  }
50
59
  return () => {
51
- tsEmbed.destroy();
60
+ if (!isPreRenderedComponent) {
61
+ if (props.preRenderId) tsEmbed.hidePreRender();
62
+ else tsEmbed.destroy();
63
+ }
52
64
  };
53
65
  }, [viewConfig, listeners]);
54
66
 
@@ -166,13 +178,12 @@ interface SageEmbedProps extends EmbedProps, SageViewConfig { }
166
178
  * }
167
179
  * ```
168
180
  */
169
- export const SageEmbed = componentFactory<
170
- typeof _SageEmbed,
171
- SageEmbedProps,
172
- SageViewConfig
173
- >(_SageEmbed);
181
+ export const SageEmbed = componentFactory<typeof _SageEmbed, SageEmbedProps, SageViewConfig>(
182
+ _SageEmbed,
183
+ );
174
184
 
175
- type EmbedComponent = typeof SearchEmbed
185
+ type EmbedComponent =
186
+ | typeof SearchEmbed
176
187
  | typeof AppEmbed
177
188
  | typeof LiveboardEmbed
178
189
  | typeof SearchBarEmbed
@@ -200,6 +211,12 @@ export function useEmbedRef<T extends EmbedComponent>():
200
211
  return React.useRef<React.ComponentRef<T>>(null);
201
212
  }
202
213
 
214
+ export const PreRenderedLiveboardEmbed = componentFactory<
215
+ typeof _LiveboardEmbed,
216
+ LiveboardProps,
217
+ LiveboardViewConfig
218
+ >(_LiveboardEmbed, true);
219
+
203
220
  export {
204
221
  LiveboardViewConfig,
205
222
  SearchViewConfig,
package/src/types.ts CHANGED
@@ -520,7 +520,7 @@ export interface EmbedConfig {
520
520
  hostUserGuid: string;
521
521
  hostClusterId: string;
522
522
  hostClusterName: string;
523
- }
523
+ };
524
524
 
525
525
  /**
526
526
  * Pendo API key to enable Pendo tracking to your own subscription, the key
@@ -532,7 +532,7 @@ export interface EmbedConfig {
532
532
  }
533
533
 
534
534
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
535
- export interface LayoutConfig { }
535
+ export interface LayoutConfig {}
536
536
 
537
537
  /**
538
538
  * Embedded iFrame configuration
@@ -640,6 +640,11 @@ export interface ViewConfig {
640
640
  * visualization, or Liveboard.
641
641
  */
642
642
  runtimeFilters?: RuntimeFilter[];
643
+ /**
644
+ * The list of parameter override to apply to a search answer,
645
+ * visualization, or Liveboard.
646
+ */
647
+ runtimeParameters?: RuntimeParameter[];
643
648
  /**
644
649
  * The locale/language to use for the embedded view.
645
650
  *
@@ -747,6 +752,7 @@ export interface ViewConfig {
747
752
  /**
748
753
  * Hide the home page modules
749
754
  * eg: hiddenHomepageModules = [HomepageModule.MyLibrary]
755
+ *
750
756
  * @version SDK: 1.27.0 | Thoughtspot: 9.8.0.cl
751
757
  */
752
758
  hiddenHomepageModules?: HomepageModule[];
@@ -774,9 +780,15 @@ export interface ViewConfig {
774
780
  * There are 8 home nav list items, we will send those item as list
775
781
  * which we want to hide for TSE.
776
782
  * eg: hiddenHomeLeftNavItems = [HomeLeftNavItem.Home] to hide home.
783
+ *
777
784
  * @version SDK: 1.27.0 | Thoughtspot: 9.8.0.cl
778
785
  */
779
786
  hiddenHomeLeftNavItems?: HomeLeftNavItem[];
787
+ /**
788
+ * TBD
789
+ */
790
+
791
+ preRenderId?: string;
780
792
  }
781
793
 
782
794
  /**
@@ -952,6 +964,20 @@ export interface RuntimeFilter {
952
964
  */
953
965
  values: (number | boolean | string)[];
954
966
  }
967
+ /**
968
+ * A filter that can be applied to ThoughtSpot answers, Liveboards, or
969
+ * visualizations at runtime.
970
+ */
971
+ export interface RuntimeParameter {
972
+ /**
973
+ * The name of the runtime parameter to filter on (case-sensitive)
974
+ */
975
+ name: string;
976
+ /**
977
+ * Values
978
+ */
979
+ value: number | boolean | string;
980
+ }
955
981
 
956
982
  /**
957
983
  * Event types emitted by the embedded ThoughtSpot application.
@@ -1378,21 +1404,21 @@ export enum EmbedEvent {
1378
1404
  */
1379
1405
  InsertIntoSlide = 'insertInToSlide',
1380
1406
  /**
1407
+ * @hidden
1381
1408
  * Emitted when a user changes any filter on a Liveboard.
1382
- *
1383
1409
  * @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
1384
1410
  */
1385
1411
  FilterChanged = 'filterChanged',
1386
1412
  /**
1387
1413
  * Emitted when a user click on Go button in Sage Embed
1388
1414
  *
1389
- * @version SDK : 1.27.0 | Thoughtspot: 9.7.0.cl
1415
+ * @version SDK : 1.26.0 | Thoughtspot: 9.7.0.cl
1390
1416
  */
1391
1417
  SageEmbedQuery = 'sageEmbedQuery',
1392
1418
  /**
1393
1419
  * Emitten when a user select data source in Sage Embed
1394
1420
  *
1395
- * @version SDK : 1.27.0 | Thoughtspot: 9.7.0.cl
1421
+ * @version SDK : 1.26.0 | Thoughtspot: 9.7.0.cl
1396
1422
  */
1397
1423
  SageWorksheetUpdated = 'sageWorksheetUpdated',
1398
1424
  /**
@@ -1401,6 +1427,51 @@ export enum EmbedEvent {
1401
1427
  * @version SDK : 1.27.0 | Thoughtspot: 9.8.0.cl
1402
1428
  */
1403
1429
  UpdateConnection = 'updateConnection',
1430
+ /**
1431
+ * Emitted when name, status (private or public) or filter values of a
1432
+ * PersonalisedView is updated.
1433
+ *
1434
+ * @returns viewName: string
1435
+ * @returns viewId: string
1436
+ * @returns liveboardId: string
1437
+ * @returns isPublic: boolean
1438
+ * @version SDK : 1.26.0 | Thoughtspot: 9.7.0.cl
1439
+ */
1440
+ UpdatePersonalisedView = 'updatePersonalisedView',
1441
+ /**
1442
+ * Emitted when a PersonalisedView is saved.
1443
+ *
1444
+ * @returns viewName: string
1445
+ * @returns viewId: string
1446
+ * @returns liveboardId: string
1447
+ * @returns isPublic: boolean
1448
+ * @version SDK : 1.26.0 | Thoughtspot: 9.7.0.cl
1449
+ */
1450
+ SavePersonalisedView = 'savePersonalisedView',
1451
+ /**
1452
+ * Emitted when a Liveboard is reset.
1453
+ *
1454
+ * @returns viewName: string
1455
+ * @returns viewId: string
1456
+ * @returns liveboardId: string
1457
+ * @returns isPublic: boolean
1458
+ * @version SDK : 1.26.0 | Thoughtspot: 9.7.0.cl
1459
+ */
1460
+ ResetLiveboard = 'resetLiveboard',
1461
+ /**
1462
+ * Emitted when a PersonalisedView is deleted.
1463
+ *
1464
+ * @returns views: string[]
1465
+ * @returns liveboardId: string
1466
+ * @version SDK : 1.26.0 | Thoughtspot: 9.7.0.cl
1467
+ */
1468
+ DeletePersonalisedView = 'deletePersonalisedView',
1469
+ /**
1470
+ * Emitten when a user creates a new worksheet
1471
+ *
1472
+ * @version SDK : 1.27.0 | Thoughtspot: 9.8.0.cl
1473
+ */
1474
+ CreateWorksheet = 'createWorksheet',
1404
1475
  }
1405
1476
 
1406
1477
  /**
@@ -2045,16 +2116,16 @@ export enum HostEvent {
2045
2116
  */
2046
2117
  ResetSearch = 'resetSearch',
2047
2118
  /**
2119
+ * @hidden
2048
2120
  * Gets the currents visible and runtime filters applied on a Liveboard
2049
- *
2050
2121
  * @example
2051
2122
  * liveboardEmbed.trigger(HostEvent.GetFilters)
2052
2123
  * @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
2053
2124
  */
2054
2125
  GetFilters = 'getFilters',
2055
2126
  /**
2127
+ * @hidden
2056
2128
  * Updates the visible filters on the Liveboard.
2057
- *
2058
2129
  * @param - filter: filter object containing column name and filter operation and values
2059
2130
  * @example
2060
2131
  *
@@ -2710,15 +2781,15 @@ export enum Action {
2710
2781
  * ```
2711
2782
  */
2712
2783
  RequestAccess = 'requestAccess',
2713
- /**
2714
- * The **Query visualizer** and **Query SQL** buttons in Query details panel
2715
- * of the Answer page
2716
- *
2717
- * @example
2718
- * ```js
2719
- * disabledActions: [Action.QueryDetailsButtons]
2720
- * ```
2721
- */
2784
+ /**
2785
+ * The **Query visualizer** and **Query SQL** buttons in Query details panel
2786
+ * of the Answer page
2787
+ *
2788
+ * @example
2789
+ * ```js
2790
+ * disabledActions: [Action.QueryDetailsButtons]
2791
+ * ```
2792
+ */
2722
2793
  QueryDetailsButtons = 'queryDetailsButtons',
2723
2794
  /**
2724
2795
  * The **Delete** action for Answers.
@@ -3043,6 +3114,16 @@ export enum Action {
3043
3114
  * ```
3044
3115
  */
3045
3116
  ManageMonitor = 'ManageMonitor',
3117
+ /**
3118
+ * Action ID for Liveboard Personalised Views dropdown
3119
+ *
3120
+ * @example
3121
+ * ```js
3122
+ * disabledActions: [Action.PersonalisedViewsDropdown]
3123
+ * ```
3124
+ * @version SDK : 1.26.0 | Thoughtspot: 9.7.0.cl
3125
+ */
3126
+ PersonalisedViewsDropdown = 'personalisedViewsDropdown',
3046
3127
  }
3047
3128
 
3048
3129
  export interface SessionInterface {
package/src/utils.spec.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  appendToUrlHash,
11
11
  getRedirectUrl,
12
12
  checkReleaseVersionInBeta,
13
+ getRuntimeParameters,
13
14
  } from './utils';
14
15
  import { RuntimeFilterOp } from './types';
15
16
 
@@ -65,6 +66,36 @@ describe('unit test for utils', () => {
65
66
  'col1=foo&op1=EQ&val1=42&col2=bar&op2=BW_INC&val2=1&val2=10&col3=baz&op3=CONTAINS&val3=abc',
66
67
  );
67
68
  });
69
+ test('getParameterOverride', () => {
70
+ expect(getRuntimeParameters([])).toBe(null);
71
+
72
+ expect(
73
+ getRuntimeParameters([
74
+ {
75
+ name: 'foo',
76
+ value: 'bar',
77
+ },
78
+ ]),
79
+ ).toBe('param1=foo&paramVal1=bar');
80
+
81
+ const params = [
82
+ {
83
+ name: 'foo',
84
+ value: 42,
85
+ },
86
+ {
87
+ name: 'bar',
88
+ value: 'abc',
89
+ },
90
+ {
91
+ name: 'baz',
92
+ value: true,
93
+ },
94
+ ];
95
+ expect(getRuntimeParameters(params)).toBe(
96
+ 'param1=foo&paramVal1=42&param2=bar&paramVal2=abc&param3=baz&paramVal3=true',
97
+ );
98
+ });
68
99
 
69
100
  test('getCssDimension', () => {
70
101
  expect(getCssDimension(100)).toBe('100px');
package/src/utils.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  CustomisationsInterface,
16
16
  DOMSelector,
17
17
  ViewConfig,
18
+ RuntimeParameter,
18
19
  } from './types';
19
20
 
20
21
  /**
@@ -43,6 +44,28 @@ export const getFilterQuery = (runtimeFilters: RuntimeFilter[]): string => {
43
44
  return null;
44
45
  };
45
46
 
47
+ /**
48
+ * Construct a runtime parameter override query string from the given option.
49
+ *
50
+ * @param runtimeParameters
51
+ */
52
+ export const getRuntimeParameters = (runtimeParameters: RuntimeParameter[]): string => {
53
+ if (runtimeParameters && runtimeParameters.length) {
54
+ const params = runtimeParameters.map((param, valueIndex) => {
55
+ const index = valueIndex + 1;
56
+ const filterExpr = [];
57
+ filterExpr.push(`param${index}=${encodeURIComponent(param.name)}`);
58
+ filterExpr.push(`paramVal${index}=${encodeURIComponent(param.value)}`);
59
+
60
+ return filterExpr.join('&');
61
+ });
62
+
63
+ return `${params.join('&')}`;
64
+ }
65
+
66
+ return null;
67
+ };
68
+
46
69
  /**
47
70
  * Convert a value to a string representation to be sent as a query
48
71
  * parameter to the ThoughtSpot app.
@@ -225,3 +248,23 @@ export function getDOMNode(domSelector: DOMSelector): HTMLElement {
225
248
  }
226
249
 
227
250
  export const deepMerge = (target: any, source: any) => merge(target, source);
251
+
252
+ export const setStyleProperties = (
253
+ element: HTMLElement,
254
+ styleProperties: Partial<CSSStyleDeclaration>,
255
+ ): void => {
256
+ if (!element || !styleProperties) return;
257
+ Object.keys(styleProperties).forEach((styleProperty) => {
258
+ element.style[styleProperty] = styleProperties[styleProperty].toString();
259
+ });
260
+ };
261
+
262
+ export const removeStyleProperties = (
263
+ element: HTMLElement,
264
+ styleProperties: string[],
265
+ ): void => {
266
+ if (!element || !styleProperties) return;
267
+ styleProperties.forEach((styleProperty) => {
268
+ element.style.removeProperty(styleProperty);
269
+ });
270
+ };