@thoughtspot/visual-embed-sdk 1.33.9 → 1.33.10

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 (58) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/embed/liveboard.d.ts +36 -0
  3. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  4. package/cjs/src/embed/liveboard.js +10 -1
  5. package/cjs/src/embed/liveboard.js.map +1 -1
  6. package/cjs/src/embed/liveboard.spec.js +13 -0
  7. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  8. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  9. package/cjs/src/embed/ts-embed.js +5 -2
  10. package/cjs/src/embed/ts-embed.js.map +1 -1
  11. package/cjs/src/embed/ts-embed.spec.d.ts +2 -1
  12. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  13. package/cjs/src/embed/ts-embed.spec.js +158 -0
  14. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  15. package/cjs/src/types.d.ts +21 -2
  16. package/cjs/src/types.d.ts.map +1 -1
  17. package/cjs/src/types.js +12 -0
  18. package/cjs/src/types.js.map +1 -1
  19. package/dist/{index-BXczdQc7.js → index-HiSgAoIA.js} +1 -1
  20. package/dist/src/embed/liveboard.d.ts +36 -0
  21. package/dist/src/embed/liveboard.d.ts.map +1 -1
  22. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  23. package/dist/src/embed/ts-embed.spec.d.ts +2 -1
  24. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  25. package/dist/src/types.d.ts +21 -2
  26. package/dist/src/types.d.ts.map +1 -1
  27. package/dist/tsembed-react.es.js +30 -6
  28. package/dist/tsembed-react.js +29 -5
  29. package/dist/tsembed.es.js +30 -6
  30. package/dist/tsembed.js +29 -5
  31. package/dist/visual-embed-sdk-react-full.d.ts +57 -2
  32. package/dist/visual-embed-sdk-react.d.ts +57 -2
  33. package/dist/visual-embed-sdk.d.ts +57 -2
  34. package/lib/package.json +1 -1
  35. package/lib/src/embed/liveboard.d.ts +36 -0
  36. package/lib/src/embed/liveboard.d.ts.map +1 -1
  37. package/lib/src/embed/liveboard.js +10 -1
  38. package/lib/src/embed/liveboard.js.map +1 -1
  39. package/lib/src/embed/liveboard.spec.js +13 -0
  40. package/lib/src/embed/liveboard.spec.js.map +1 -1
  41. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  42. package/lib/src/embed/ts-embed.js +5 -2
  43. package/lib/src/embed/ts-embed.js.map +1 -1
  44. package/lib/src/embed/ts-embed.spec.d.ts +2 -1
  45. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  46. package/lib/src/embed/ts-embed.spec.js +159 -2
  47. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  48. package/lib/src/types.d.ts +21 -2
  49. package/lib/src/types.d.ts.map +1 -1
  50. package/lib/src/types.js +12 -0
  51. package/lib/src/types.js.map +1 -1
  52. package/lib/src/visual-embed-sdk.d.ts +57 -2
  53. package/package.json +1 -1
  54. package/src/embed/liveboard.spec.ts +17 -0
  55. package/src/embed/liveboard.ts +54 -0
  56. package/src/embed/ts-embed.spec.ts +219 -0
  57. package/src/embed/ts-embed.ts +6 -1
  58. package/src/types.ts +19 -0
@@ -338,6 +338,45 @@ export interface LiveboardViewConfig
338
338
  * ```
339
339
  */
340
340
  hideIrrelevantChipsInLiveboardTabs?: boolean;
341
+
342
+ /**
343
+ * The Liveboard to run on regular intervals to fetch the cdw token.
344
+ * @hidden
345
+ * @version SDK: 1.35.0 | ThoughtSpot:10.6.0.cl
346
+ * @example
347
+ * ```js
348
+ * const embed = new LiveboardEmbed('#embed-container', {
349
+ * ... // other options
350
+ * oAuthPollingInterval: value in milliseconds,
351
+ * })
352
+ */
353
+ oAuthPollingInterval?: number;
354
+
355
+ /**
356
+ * The Liveboard is set to force a token fetch during the initial load.
357
+ * @hidden
358
+ * @version SDK: 1.35.0 | ThoughtSpot:10.6.0.cl
359
+ * @example
360
+ * ```js
361
+ * const embed = new LiveboardEmbed('#embed-container', {
362
+ * ... // other options
363
+ * isForceRedirect: false,
364
+ * })
365
+ */
366
+ isForceRedirect?: boolean;
367
+
368
+ /**
369
+ * The source connection ID for authentication.
370
+ * @hidden
371
+ * @version SDK: 1.35.0 | ThoughtSpot:10.6.0.cl
372
+ * @example
373
+ * ```js
374
+ * const embed = new LiveboardEmbed('#embed-container', {
375
+ * ... // other options
376
+ * dataSourceId: '',
377
+ * })
378
+ */
379
+ dataSourceId?: string;
341
380
  }
342
381
 
343
382
  /**
@@ -399,6 +438,9 @@ export class LiveboardEmbed extends V1Embed {
399
438
  enable2ColumnLayout,
400
439
  dataPanelV2 = false,
401
440
  enableCustomColumnGroups = false,
441
+ oAuthPollingInterval,
442
+ isForceRedirect,
443
+ dataSourceId,
402
444
  } = this.viewConfig;
403
445
 
404
446
  const preventLiveboardFilterRemoval = this.viewConfig.preventLiveboardFilterRemoval
@@ -445,6 +487,18 @@ export class LiveboardEmbed extends V1Embed {
445
487
  params[Param.enableAskSage] = enableAskSage;
446
488
  }
447
489
 
490
+ if (oAuthPollingInterval !== undefined) {
491
+ params[Param.OauthPollingInterval] = oAuthPollingInterval;
492
+ }
493
+
494
+ if (isForceRedirect) {
495
+ params[Param.IsForceRedirect] = isForceRedirect;
496
+ }
497
+
498
+ if (dataSourceId !== undefined) {
499
+ params[Param.DataSourceId] = dataSourceId;
500
+ }
501
+
448
502
  params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
449
503
  params[Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled;
450
504
  params[Param.ShowLiveboardVerifiedBadge] = showLiveboardVerifiedBadge;
@@ -9,6 +9,12 @@ import {
9
9
  LiveboardViewConfig,
10
10
  AppEmbed,
11
11
  LiveboardEmbed,
12
+ AppViewConfig,
13
+ SageEmbed,
14
+ SageViewConfig,
15
+ ConversationViewConfig,
16
+ ConversationEmbed,
17
+ SearchViewConfig,
12
18
  } from '../index';
13
19
  import {
14
20
  Action, HomeLeftNavItem, RuntimeFilter, RuntimeFilterOp, HomepageModule, HostEvent,
@@ -28,6 +34,8 @@ import {
28
34
  expectUrlToHaveParamsWithValues,
29
35
  mockMessageChannel,
30
36
  createRootEleForEmbed,
37
+ expectUrlMatch,
38
+ fixedEncodeURI,
31
39
  } from '../test/test-utils';
32
40
  import * as config from '../config';
33
41
  import * as embedConfig from './embedConfig';
@@ -38,6 +46,8 @@ import * as baseInstance from './base';
38
46
  import { MIXPANEL_EVENT } from '../mixpanel-service';
39
47
  import * as authService from '../utils/authService/authService';
40
48
  import { logger } from '../utils/logger';
49
+ import { version } from '../../package.json';
50
+ import { HiddenActionItemByDefaultForSearchEmbed } from './search';
41
51
 
42
52
  const defaultViewConfig = {
43
53
  frameParams: {
@@ -51,6 +61,12 @@ const tabId1 = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
51
61
  const tabId2 = 'eca215d4-0d2c-4a55-90e3-d81ef6848ae0';
52
62
  const thoughtSpotHost = 'tshost';
53
63
  const defaultParamsPost = '';
64
+ export const defaultParamsWithoutHiddenActions = `hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&authType=${AuthType.None}&blockNonEmbedFullAppAccess=true`;
65
+ export const defaultParams = `&${defaultParamsWithoutHiddenActions}&hideAction=[%22${Action.ReportError}%22]`;
66
+ const hideBydefault = `&hideAction=${fixedEncodeURI(
67
+ JSON.stringify([Action.ReportError, ...HiddenActionItemByDefaultForSearchEmbed]),
68
+ )}`;
69
+ const defaultParamsWithHiddenActions = defaultParamsWithoutHiddenActions + hideBydefault;
54
70
 
55
71
  beforeAll(() => {
56
72
  spyOn(window, 'alert');
@@ -89,6 +105,29 @@ describe('Unit test case for ts embed', () => {
89
105
  jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(true);
90
106
  });
91
107
 
108
+ describe('Vaidate iframe properties', () => {
109
+ beforeAll(() => {
110
+ init({
111
+ thoughtSpotHost: 'tshost',
112
+ authType: AuthType.None,
113
+ });
114
+ });
115
+
116
+ test('should set proper allow policies', async () => {
117
+ // we dont have origin specific policies so just checking if
118
+ // policies are ending with ;
119
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
120
+ searchEmbed.render();
121
+ await executeAfterWait(() => {
122
+ const iframe = getIFrameEl();
123
+ const policiesAdded = iframe.allow.split(' ');
124
+ policiesAdded.forEach((policy) => {
125
+ expect(policy.endsWith(';')).toBe(true);
126
+ });
127
+ });
128
+ });
129
+ });
130
+
92
131
  describe('AuthExpire embedEvent in cookieless authentication authType', () => {
93
132
  beforeAll(() => {
94
133
  jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
@@ -1454,6 +1493,186 @@ describe('Unit test case for ts embed', () => {
1454
1493
  orgId: overrideOrgId,
1455
1494
  });
1456
1495
  });
1496
+
1497
+ it('AppEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1498
+ const appEmbed = new AppEmbed(getRootEl(), {
1499
+ ...defaultViewConfig,
1500
+ enableFlipTooltipToContextMenu: true,
1501
+ } as AppViewConfig);
1502
+
1503
+ appEmbed.render();
1504
+ await executeAfterWait(() => {
1505
+ expectUrlMatchesWithParams(
1506
+ getIFrameSrc(),
1507
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&flipTooltipToContextMenuEnabled=true${defaultParams}${defaultParamsPost}#/home`,
1508
+ );
1509
+ });
1510
+ });
1511
+
1512
+ it('AppEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1513
+ const appEmbed = new AppEmbed(getRootEl(), {
1514
+ ...defaultViewConfig,
1515
+ enableFlipTooltipToContextMenu: false,
1516
+ } as AppViewConfig);
1517
+
1518
+ appEmbed.render();
1519
+ await executeAfterWait(() => {
1520
+ expectUrlMatchesWithParams(
1521
+ getIFrameSrc(),
1522
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
1523
+ );
1524
+ });
1525
+ });
1526
+
1527
+ it('LiveboardEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1528
+ const appEmbed = new LiveboardEmbed(getRootEl(), {
1529
+ ...defaultViewConfig,
1530
+ liveboardId,
1531
+ enableFlipTooltipToContextMenu: true,
1532
+ } as LiveboardViewConfig);
1533
+
1534
+ appEmbed.render();
1535
+ await executeAfterWait(() => {
1536
+ expectUrlMatchesWithParams(
1537
+ getIFrameSrc(),
1538
+ `http://${thoughtSpotHost}/?embedApp=true&flipTooltipToContextMenuEnabled=true${defaultParams}#/embed/viz/${liveboardId}`,
1539
+ );
1540
+ });
1541
+ });
1542
+
1543
+ it('LiveboardEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1544
+ const appEmbed = new LiveboardEmbed(getRootEl(), {
1545
+ ...defaultViewConfig,
1546
+ liveboardId,
1547
+ enableFlipTooltipToContextMenu: false,
1548
+ } as LiveboardViewConfig);
1549
+
1550
+ appEmbed.render();
1551
+ await executeAfterWait(() => {
1552
+ expectUrlMatchesWithParams(
1553
+ getIFrameSrc(),
1554
+ `http://${thoughtSpotHost}/?embedApp=true${defaultParams}#/embed/viz/${liveboardId}`,
1555
+ );
1556
+ });
1557
+ });
1558
+
1559
+ it('SageViewConfig: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1560
+ const defaultConfig: SageViewConfig = {
1561
+ disableWorksheetChange: false,
1562
+ hideWorksheetSelector: false,
1563
+ hideSageAnswerHeader: false,
1564
+ hideAutocompleteSuggestions: false,
1565
+ hideSampleQuestions: false,
1566
+ isProductTour: false,
1567
+ dataPanelV2: false,
1568
+ };
1569
+ const appEmbed = new SageEmbed(getRootEl(), {
1570
+ ...defaultConfig,
1571
+ enableFlipTooltipToContextMenu: true,
1572
+ } as SageViewConfig);
1573
+
1574
+ appEmbed.render();
1575
+ await executeAfterWait(() => {
1576
+ expectUrlMatch(
1577
+ getIFrameSrc(),
1578
+ `http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D&flipTooltipToContextMenuEnabled=true#/embed/eureka`,
1579
+ );
1580
+ });
1581
+ });
1582
+
1583
+ it('SageViewConfig: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1584
+ const defaultConfig: SageViewConfig = {
1585
+ disableWorksheetChange: false,
1586
+ hideWorksheetSelector: false,
1587
+ hideSageAnswerHeader: false,
1588
+ hideAutocompleteSuggestions: false,
1589
+ hideSampleQuestions: false,
1590
+ isProductTour: false,
1591
+ dataPanelV2: false,
1592
+ };
1593
+ const appEmbed = new SageEmbed(getRootEl(), {
1594
+ ...defaultConfig,
1595
+ enableFlipTooltipToContextMenu: false,
1596
+ } as SageViewConfig);
1597
+
1598
+ appEmbed.render();
1599
+ await executeAfterWait(() => {
1600
+ expectUrlMatch(
1601
+ getIFrameSrc(),
1602
+ `http://${thoughtSpotHost}/?embedApp=true&enableDataPanelV2=false&isSageEmbed=true&disableWorksheetChange=false&hideWorksheetSelector=false&hideEurekaSuggestions=false&isProductTour=false&hideSageAnswerHeader=false&hideAction=%5B%22reportError%22%5D#/embed/eureka`,
1603
+ );
1604
+ });
1605
+ });
1606
+
1607
+ it('ConversationEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1608
+ const appEmbed = new ConversationEmbed(getRootEl(), {
1609
+ worksheetId: 'worksheetId',
1610
+ searchOptions: {
1611
+ searchQuery: 'searchQuery',
1612
+ },
1613
+ enableFlipTooltipToContextMenu: true,
1614
+ } as ConversationViewConfig);
1615
+
1616
+ appEmbed.render();
1617
+ await executeAfterWait(() => {
1618
+ expectUrlMatchesWithParams(
1619
+ getIFrameSrc(),
1620
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&flipTooltipToContextMenuEnabled=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
1621
+ );
1622
+ });
1623
+ });
1624
+
1625
+ it('ConversationEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when flag is false', async () => {
1626
+ const appEmbed = new ConversationEmbed(getRootEl(), {
1627
+ worksheetId: 'worksheetId',
1628
+ searchOptions: {
1629
+ searchQuery: 'searchQuery',
1630
+ },
1631
+ enableFlipTooltipToContextMenu: false,
1632
+ } as ConversationViewConfig);
1633
+
1634
+ appEmbed.render();
1635
+ await executeAfterWait(() => {
1636
+ expectUrlMatchesWithParams(
1637
+ getIFrameSrc(),
1638
+ `http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
1639
+ );
1640
+ });
1641
+ });
1642
+
1643
+ it('SearchEmbed: Should add flipTooltipToContextMenuEnabled flag to the iframe src', async () => {
1644
+ const dataSources = ['data-source-1'];
1645
+ const appEmbed = new SearchEmbed(getRootEl(), {
1646
+ ...defaultViewConfig,
1647
+ dataSources,
1648
+ enableFlipTooltipToContextMenu: true,
1649
+ } as SearchViewConfig);
1650
+
1651
+ appEmbed.render();
1652
+ await executeAfterWait(() => {
1653
+ expectUrlMatchesWithParams(
1654
+ getIFrameSrc(),
1655
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSources=[%22data-source-1%22]&dataSourceMode=expand&useLastSelectedSources=false&flipTooltipToContextMenuEnabled=true#/embed/answer`,
1656
+ );
1657
+ });
1658
+ });
1659
+
1660
+ it('SearchEmbed: Should not add flipTooltipToContextMenuEnabled flag to the iframe src when if false', async () => {
1661
+ const dataSources = ['data-source-1'];
1662
+ const appEmbed = new SearchEmbed(getRootEl(), {
1663
+ ...defaultViewConfig,
1664
+ dataSources,
1665
+ enableFlipTooltipToContextMenu: false,
1666
+ } as SearchViewConfig);
1667
+
1668
+ appEmbed.render();
1669
+ await executeAfterWait(() => {
1670
+ expectUrlMatchesWithParams(
1671
+ getIFrameSrc(),
1672
+ `http://${thoughtSpotHost}/v2/?${defaultParamsWithHiddenActions}&dataSources=[%22data-source-1%22]&dataSourceMode=expand&useLastSelectedSources=false#/embed/answer`,
1673
+ );
1674
+ });
1675
+ });
1457
1676
  });
1458
1677
 
1459
1678
  describe('When destroyed', () => {
@@ -446,6 +446,7 @@ export class TsEmbed {
446
446
  insertInToSlide,
447
447
  disableRedirectionLinksInNewTab,
448
448
  overrideOrgId,
449
+ enableFlipTooltipToContextMenu = false,
449
450
  } = this.viewConfig;
450
451
 
451
452
  const { additionalFlags: additionalFlagsFromInit } = this.embedConfig;
@@ -455,6 +456,10 @@ export class TsEmbed {
455
456
  ...additionalFlagsFromView,
456
457
  };
457
458
 
459
+ if (enableFlipTooltipToContextMenu) {
460
+ queryParams[Param.EnableFlipTooltipToContextMenu] = enableFlipTooltipToContextMenu;
461
+ }
462
+
458
463
  if (Array.isArray(visibleActions) && Array.isArray(hiddenActions)) {
459
464
  this.handleError('You cannot have both hidden actions and visible actions');
460
465
  return queryParams;
@@ -576,7 +581,7 @@ export class TsEmbed {
576
581
  iFrame.mozallowfullscreen = true;
577
582
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
578
583
  // @ts-ignore
579
- iFrame.allow = 'clipboard-read; clipboard-write fullscreen';
584
+ iFrame.allow = 'clipboard-read; clipboard-write; fullscreen;';
580
585
 
581
586
  const {
582
587
  height: frameHeight,
package/src/types.ts CHANGED
@@ -1100,6 +1100,13 @@ export interface ViewConfig {
1100
1100
  * @version SDK: 1.35.0 | ThoughtSpot: 10.5.0.cl
1101
1101
  */
1102
1102
  overrideOrgId?: number;
1103
+ /**
1104
+ * Flag to control new flip tooltip context menu experience
1105
+ *
1106
+ * @default false
1107
+ * @version SDK: 1.36.0 | Thoughtspot: 10.6.0.cl
1108
+ */
1109
+ enableFlipTooltipToContextMenu?: boolean;
1103
1110
  }
1104
1111
 
1105
1112
  /**
@@ -3187,6 +3194,14 @@ export enum HostEvent {
3187
3194
  * @version SDK: 1.29.0 | Thoughtspot: 10.1.0.cl
3188
3195
  */
3189
3196
  GetParameters = 'GetParameters',
3197
+ /**
3198
+ * Triggers update of persoanlised view for a liveboard
3199
+ * ```js
3200
+ * liveboardEmbed.trigger(HostEvent.UpdatePersonalisedView, {viewId: '1234'})
3201
+ * ```
3202
+ * @version SDK: 1.36.0 | Thoughtspot: 10.6.0.cl
3203
+ */
3204
+ UpdatePersonalisedView = 'UpdatePersonalisedView',
3190
3205
  }
3191
3206
 
3192
3207
  /**
@@ -3308,6 +3323,10 @@ export enum Param {
3308
3323
  SpotterEnabled = 'isSpotterExperienceEnabled',
3309
3324
  IsUnifiedSearchExperienceEnabled = 'isUnifiedSearchExperienceEnabled',
3310
3325
  OverrideOrgId = 'orgId',
3326
+ EnableFlipTooltipToContextMenu = 'flipTooltipToContextMenuEnabled',
3327
+ OauthPollingInterval = 'oAuthPollingInterval',
3328
+ IsForceRedirect = 'isForceRedirect',
3329
+ DataSourceId = 'dataSourceId',
3311
3330
  }
3312
3331
 
3313
3332
  /**