@thoughtspot/visual-embed-sdk 1.10.0-alpha.2 → 1.10.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 (44) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/README.md +22 -3
  3. package/dist/src/embed/app.d.ts +9 -3
  4. package/dist/src/embed/search.d.ts +4 -0
  5. package/dist/src/embed/ts-embed.d.ts +18 -4
  6. package/dist/src/types.d.ts +139 -3
  7. package/dist/src/utils.d.ts +4 -0
  8. package/dist/tsembed.es.js +179 -21
  9. package/dist/tsembed.js +179 -21
  10. package/lib/package.json +2 -2
  11. package/lib/src/embed/app.d.ts +9 -3
  12. package/lib/src/embed/app.js +23 -7
  13. package/lib/src/embed/app.js.map +1 -1
  14. package/lib/src/embed/app.spec.js +36 -2
  15. package/lib/src/embed/app.spec.js.map +1 -1
  16. package/lib/src/embed/base.spec.js +13 -1
  17. package/lib/src/embed/base.spec.js.map +1 -1
  18. package/lib/src/embed/events.spec.js +30 -1
  19. package/lib/src/embed/events.spec.js.map +1 -1
  20. package/lib/src/embed/search.d.ts +4 -0
  21. package/lib/src/embed/search.js +1 -1
  22. package/lib/src/embed/search.js.map +1 -1
  23. package/lib/src/embed/ts-embed.d.ts +18 -4
  24. package/lib/src/embed/ts-embed.js +36 -14
  25. package/lib/src/embed/ts-embed.js.map +1 -1
  26. package/lib/src/embed/ts-embed.spec.js +123 -14
  27. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  28. package/lib/src/types.d.ts +139 -3
  29. package/lib/src/types.js +116 -0
  30. package/lib/src/types.js.map +1 -1
  31. package/lib/src/utils.d.ts +4 -0
  32. package/lib/src/utils.js +4 -0
  33. package/lib/src/utils.js.map +1 -1
  34. package/lib/src/visual-embed-sdk.d.ts +170 -10
  35. package/package.json +2 -2
  36. package/src/embed/app.spec.ts +49 -1
  37. package/src/embed/app.ts +24 -6
  38. package/src/embed/base.spec.ts +14 -0
  39. package/src/embed/events.spec.ts +32 -0
  40. package/src/embed/search.ts +5 -0
  41. package/src/embed/ts-embed.spec.ts +166 -14
  42. package/src/embed/ts-embed.ts +56 -16
  43. package/src/types.ts +148 -1
  44. package/src/utils.ts +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thoughtspot/visual-embed-sdk",
3
- "version": "1.10.0-alpha.2",
3
+ "version": "1.10.0",
4
4
  "description": "ThoughtSpot Embed SDK",
5
5
  "module": "lib/src/index.js",
6
6
  "main": "dist/tsembed.js",
@@ -32,7 +32,7 @@
32
32
  "test-sdk": "jest -c jest.config.sdk.js",
33
33
  "test-docs": "jest -c jest.config.docs.js",
34
34
  "test": "npm run test-sdk && npm run test-docs && npx istanbul-merge --out ./coverage/coverage.json ./coverage/docs/coverage-final.json ./coverage/sdk/coverage-final.json && npx istanbul report --include ./coverage/coverage.json --dir ./coverage lcov",
35
- "posttest": "cat ./coverage/lcov.info | coveralls",
35
+ "posttest": "cat ./coverage/sdk/lcov.info | coveralls",
36
36
  "prepublishOnly": "npm run test; npm run tsc; npm run bundle-dts; npm run build",
37
37
  "publish-dev": "npm publish --tag dev",
38
38
  "publish-prod": "npm publish --tag latest"
@@ -1,11 +1,12 @@
1
1
  import { AppEmbed, AppViewConfig, Page } from './app';
2
2
  import { init } from '../index';
3
- import { Action, AuthType, RuntimeFilterOp } from '../types';
3
+ import { Action, AuthType, HostEvent, RuntimeFilterOp } from '../types';
4
4
  import {
5
5
  executeAfterWait,
6
6
  getDocumentBody,
7
7
  getIFrameSrc,
8
8
  getRootEl,
9
+ getIFrameEl,
9
10
  } from '../test/test-utils';
10
11
  import { version } from '../../package.json';
11
12
  import * as config from '../config';
@@ -82,6 +83,7 @@ describe('App embed tests', () => {
82
83
  [Page.Liveboards]: 'pinboards',
83
84
  [Page.Data]: 'data/tables',
84
85
  [Page.Home]: 'home',
86
+ [Page.SpotIQ]: 'insights/results',
85
87
  };
86
88
 
87
89
  const pageIds = Object.keys(pageRouteMap);
@@ -194,6 +196,52 @@ describe('App embed tests', () => {
194
196
  );
195
197
  });
196
198
 
199
+ test('navigateToPage with noReload should trigger the appropriate event', async () => {
200
+ const appEmbed = new AppEmbed(getRootEl(), {
201
+ frameParams: {
202
+ width: '100%',
203
+ height: '100%',
204
+ },
205
+ });
206
+ await appEmbed.render();
207
+
208
+ const iframe = getIFrameEl();
209
+ iframe.contentWindow.postMessage = jest.fn();
210
+ appEmbed.navigateToPage(path, true);
211
+
212
+ expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
213
+ expect.objectContaining({
214
+ type: HostEvent.Navigate,
215
+ data: path,
216
+ }),
217
+ `http://${thoughtSpotHost}`,
218
+ );
219
+
220
+ appEmbed.navigateToPage(-1, true);
221
+ expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
222
+ expect.objectContaining({
223
+ type: HostEvent.Navigate,
224
+ data: -1,
225
+ }),
226
+ `http://${thoughtSpotHost}`,
227
+ );
228
+ });
229
+
230
+ test('Do not allow number path without noReload in navigateToPage', async () => {
231
+ const appEmbed = new AppEmbed(getRootEl(), {
232
+ frameParams: {
233
+ width: '100%',
234
+ height: '100%',
235
+ },
236
+ });
237
+ await appEmbed.render();
238
+ spyOn(console, 'warn');
239
+ appEmbed.navigateToPage(-1);
240
+ expect(console.warn).toHaveBeenCalledWith(
241
+ 'Path can only by a string when triggered without noReload',
242
+ );
243
+ });
244
+
197
245
  test('navigateToPage function use before render', async () => {
198
246
  spyOn(console, 'log');
199
247
  const appEmbed = new AppEmbed(getRootEl(), {
package/src/embed/app.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { getFilterQuery, getQueryParamString } from '../utils';
13
- import { Param, RuntimeFilter, DOMSelector } from '../types';
13
+ import { Param, RuntimeFilter, DOMSelector, HostEvent } from '../types';
14
14
  import { V1Embed, ViewConfig } from './ts-embed';
15
15
 
16
16
  /**
@@ -42,6 +42,10 @@ export enum Page {
42
42
  * Data management page
43
43
  */
44
44
  Data = 'data',
45
+ /**
46
+ * SpotIQ listing page
47
+ */
48
+ SpotIQ = 'spotiq',
45
49
  }
46
50
 
47
51
  /**
@@ -161,6 +165,8 @@ export class AppEmbed extends V1Embed {
161
165
  return 'pinboards';
162
166
  case Page.Data:
163
167
  return 'data/tables';
168
+ case Page.SpotIQ:
169
+ return 'insights/results';
164
170
  case Page.Home:
165
171
  default:
166
172
  return 'home';
@@ -188,19 +194,31 @@ export class AppEmbed extends V1Embed {
188
194
  /**
189
195
  * Navigate to particular page for app embed. eg:answers/pinboards/home
190
196
  * This is used for embedding answers, pinboards, visualizations and full application only.
191
- * @param path The string, set to iframe src and navigate to new page
197
+ * @param path string | number The string, set to iframe src and navigate to new page
192
198
  * eg: appEmbed.navigateToPage('pinboards')
199
+ * When used with `noReload` this can also be a number like 1/-1 to go forward/back.
200
+ * @param noReload boolean Trigger the navigation without reloading the page (version: 1.12.0 | 8.4.0.cl)
193
201
  */
194
- public navigateToPage(path: string): void {
195
- if (this.iFrame) {
202
+ public navigateToPage(path: string | number, noReload = false): void {
203
+ if (!this.iFrame) {
204
+ console.log('Please call render before invoking this method');
205
+ return;
206
+ }
207
+ if (noReload) {
208
+ this.trigger(HostEvent.Navigate, path);
209
+ } else {
210
+ if (typeof path !== 'string') {
211
+ console.warn(
212
+ 'Path can only by a string when triggered without noReload',
213
+ );
214
+ return;
215
+ }
196
216
  const iframeSrc = this.iFrame.src;
197
217
  const embedPath = '#/embed';
198
218
  const currentPath = iframeSrc.includes(embedPath) ? embedPath : '#';
199
219
  this.iFrame.src = `${
200
220
  iframeSrc.split(currentPath)[0]
201
221
  }${currentPath}/${path.replace(/^\/?#?\//, '')}`;
202
- } else {
203
- console.log('Please call render before invoking this method');
204
222
  }
205
223
  }
206
224
 
@@ -5,6 +5,7 @@ import {
5
5
  getDocumentBody,
6
6
  getRootEl,
7
7
  getRootEl2,
8
+ getIFrameSrc,
8
9
  } from '../test/test-utils';
9
10
 
10
11
  const thoughtSpotHost = 'tshost';
@@ -78,4 +79,17 @@ describe('Base TS Embed', () => {
78
79
 
79
80
  expect(prefetch).toHaveBeenCalledTimes(0);
80
81
  });
82
+
83
+ test('Sets the disableLoginRedirect param when autoLogin is true', async () => {
84
+ index.init({
85
+ thoughtSpotHost,
86
+ authType: index.AuthType.None,
87
+ autoLogin: true,
88
+ });
89
+ const tsEmbed = new index.AppEmbed(getRootEl(), {});
90
+ await tsEmbed.render();
91
+ await executeAfterWait(() => {
92
+ expect(getIFrameSrc()).toContain('disableLoginRedirect=true');
93
+ });
94
+ });
81
95
  });
@@ -5,6 +5,7 @@ import {
5
5
  SearchEmbed,
6
6
  PinboardEmbed,
7
7
  LiveboardEmbed,
8
+ AppEmbed,
8
9
  HostEvent,
9
10
  } from '../index';
10
11
  import {
@@ -247,4 +248,35 @@ describe('test communication between host app and ThoughtSpot', () => {
247
248
  };
248
249
  expect(mockPort.postMessage).toHaveBeenCalledWith(heightObj);
249
250
  });
251
+ test('ALL event listener should fire for all events with the event type set correctly', async () => {
252
+ const embed = new AppEmbed(getRootEl(), defaultViewConfig);
253
+ const spy = jest.fn();
254
+ embed.on(EmbedEvent.ALL, spy);
255
+ embed.render();
256
+
257
+ await executeAfterWait(() => {
258
+ const iframe = getIFrameEl();
259
+ postMessageToParent(iframe.contentWindow, {
260
+ type: EmbedEvent.CustomAction,
261
+ data: PAYLOAD,
262
+ });
263
+ postMessageToParent(iframe.contentWindow, {
264
+ type: EmbedEvent.DialogOpen,
265
+ });
266
+ });
267
+
268
+ await executeAfterWait(() => {
269
+ expect(spy).toHaveBeenCalledTimes(3);
270
+ expect(spy.mock.calls[0][0]).toMatchObject({
271
+ type: EmbedEvent.Init,
272
+ });
273
+ expect(spy.mock.calls[1][0]).toMatchObject({
274
+ type: EmbedEvent.CustomAction,
275
+ data: PAYLOAD,
276
+ });
277
+ expect(spy.mock.calls[2][0]).toMatchObject({
278
+ type: EmbedEvent.DialogOpen,
279
+ });
280
+ }, EVENT_WAIT_TIME);
281
+ });
250
282
  });
@@ -49,6 +49,10 @@ export interface SearchViewConfig extends ViewConfig {
49
49
  * using raw answer data.
50
50
  */
51
51
  hideResults?: boolean;
52
+ /**
53
+ * If set to true, expands all the data sources panel.
54
+ */
55
+ expandAllDataSource?: boolean;
52
56
  /**
53
57
  * If set to true, the Search Assist feature is enabled.
54
58
  */
@@ -126,6 +130,7 @@ export class SearchEmbed extends TsEmbed {
126
130
  private getIFrameSrc(answerId: string, dataSources?: string[]) {
127
131
  const {
128
132
  hideResults,
133
+ expandAllDataSource,
129
134
  enableSearchAssist,
130
135
  forceTable,
131
136
  searchOptions,
@@ -11,10 +11,12 @@ import {
11
11
  } from '../index';
12
12
  import { Action } from '../types';
13
13
  import {
14
+ executeAfterWait,
14
15
  getDocumentBody,
15
16
  getIFrameEl,
16
17
  getIFrameSrc,
17
18
  getRootEl,
19
+ postMessageToParent,
18
20
  } from '../test/test-utils';
19
21
  import * as config from '../config';
20
22
  import * as tsEmbedInstance from './ts-embed';
@@ -43,6 +45,126 @@ describe('Unit test case for ts embed', () => {
43
45
  beforeEach(() => {
44
46
  document.body.innerHTML = getDocumentBody();
45
47
  });
48
+
49
+ afterEach(() => {
50
+ jest.clearAllMocks();
51
+ });
52
+
53
+ describe('Called Embed event status for start and end', () => {
54
+ beforeAll(() => {
55
+ init({
56
+ thoughtSpotHost: 'tshost',
57
+ authType: AuthType.None,
58
+ });
59
+ });
60
+
61
+ test('when Embed event status have start status', (done) => {
62
+ const mockEmbedEventPayload = {
63
+ type: EmbedEvent.Save,
64
+ data: { answerId: '123' },
65
+ status: 'start',
66
+ };
67
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
68
+ searchEmbed
69
+ .on(
70
+ EmbedEvent.Save,
71
+ (payload) => {
72
+ expect(payload).toEqual(mockEmbedEventPayload);
73
+ done();
74
+ },
75
+ { start: true },
76
+ )
77
+ .render();
78
+
79
+ executeAfterWait(() => {
80
+ const iframe = getIFrameEl();
81
+ postMessageToParent(
82
+ iframe.contentWindow,
83
+ mockEmbedEventPayload,
84
+ );
85
+ });
86
+ });
87
+
88
+ test('should not called post message, when Embed event status have start and start option as false', () => {
89
+ const mockEmbedEventPayload = {
90
+ type: EmbedEvent.Save,
91
+ data: { answerId: '123' },
92
+ status: 'start',
93
+ };
94
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
95
+ searchEmbed
96
+ .on(EmbedEvent.Save, () => {
97
+ console.log('non callable');
98
+ })
99
+ .render();
100
+
101
+ executeAfterWait(() => {
102
+ const iframe = getIFrameEl();
103
+ iframe.contentWindow.postMessage = jest.fn();
104
+ postMessageToParent(
105
+ iframe.contentWindow,
106
+ mockEmbedEventPayload,
107
+ );
108
+ expect(iframe.contentWindow.postMessage).toHaveBeenCalledTimes(
109
+ 0,
110
+ );
111
+ });
112
+ });
113
+
114
+ test('when Embed event status have end status', (done) => {
115
+ const mockEmbedEventPayload = {
116
+ type: EmbedEvent.Save,
117
+ data: { answerId: '123' },
118
+ status: 'end',
119
+ };
120
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
121
+ searchEmbed
122
+ .on(EmbedEvent.Save, (payload) => {
123
+ expect(payload).toEqual(mockEmbedEventPayload);
124
+ done();
125
+ })
126
+ .render();
127
+
128
+ executeAfterWait(() => {
129
+ const iframe = getIFrameEl();
130
+ postMessageToParent(
131
+ iframe.contentWindow,
132
+ mockEmbedEventPayload,
133
+ );
134
+ }, 1000);
135
+ });
136
+
137
+ test('should not called post message, when Embed event status have end status and start is true', () => {
138
+ const mockEmbedEventPayload = {
139
+ type: EmbedEvent.Save,
140
+ data: { answerId: '123' },
141
+ status: 'end',
142
+ };
143
+ const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
144
+ searchEmbed
145
+ .on(
146
+ EmbedEvent.Save,
147
+ () => {
148
+ console.log('non callable');
149
+ },
150
+ { start: true },
151
+ )
152
+ .render();
153
+
154
+ executeAfterWait(() => {
155
+ const iframe = getIFrameEl();
156
+ iframe.contentWindow.postMessage = jest.fn();
157
+ postMessageToParent(
158
+ iframe.contentWindow,
159
+ mockEmbedEventPayload,
160
+ );
161
+ expect(iframe.contentWindow.postMessage).toHaveBeenCalledTimes(
162
+ 0,
163
+ );
164
+ }, 1000);
165
+ });
166
+ });
167
+
46
168
  describe('when thoughtSpotHost have value and authPromise return success response', () => {
47
169
  beforeAll(() => {
48
170
  init({
@@ -266,19 +388,6 @@ describe('Unit test case for ts embed', () => {
266
388
  );
267
389
  });
268
390
 
269
- test('Set Frame params to the iframe as attributes', async () => {
270
- const appEmbed = new AppEmbed(getRootEl(), {
271
- frameParams: {
272
- width: '100%',
273
- height: '100%',
274
- allowtransparency: true,
275
- },
276
- });
277
- await appEmbed.render();
278
- const iframe = getIFrameEl();
279
- expect(iframe.getAttribute('allowtransparency')).toBe('true');
280
- });
281
-
282
391
  test('navigateToPage function use before render', async () => {
283
392
  spyOn(console, 'log');
284
393
  const appEmbed = new AppEmbed(getRootEl(), {
@@ -317,12 +426,26 @@ describe('Unit test case for ts embed', () => {
317
426
  });
318
427
  });
319
428
 
320
- describe('additionalFlags config', () => {
429
+ describe('Iframe flags', () => {
321
430
  beforeEach(() => {
322
431
  jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(
323
432
  () => 'http://tshost',
324
433
  );
325
434
  });
435
+
436
+ test('Set Frame params to the iframe as attributes', async () => {
437
+ const appEmbed = new AppEmbed(getRootEl(), {
438
+ frameParams: {
439
+ width: '100%',
440
+ height: '100%',
441
+ allowtransparency: true,
442
+ },
443
+ });
444
+ await appEmbed.render();
445
+ const iframe = getIFrameEl();
446
+ expect(iframe.getAttribute('allowtransparency')).toBe('true');
447
+ });
448
+
326
449
  it('should set the additional flags correctly on the iframe src', async () => {
327
450
  const appEmbed = new AppEmbed(getRootEl(), {
328
451
  frameParams: {
@@ -341,6 +464,35 @@ describe('Unit test case for ts embed', () => {
341
464
  `&foo=bar&baz=1&bool=true${defaultParamsPost}#/home`,
342
465
  );
343
466
  });
467
+
468
+ it('Sets the showAlerts param', async () => {
469
+ const appEmbed = new AppEmbed(getRootEl(), {
470
+ frameParams: {
471
+ width: '100%',
472
+ height: '100%',
473
+ },
474
+ showAlerts: true,
475
+ });
476
+ await appEmbed.render();
477
+ expect(getIFrameSrc()).toBe(
478
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}` +
479
+ `&showAlerts=true${defaultParamsPost}#/home`,
480
+ );
481
+ });
482
+ it('Sets the locale param', async () => {
483
+ const appEmbed = new AppEmbed(getRootEl(), {
484
+ frameParams: {
485
+ width: '100%',
486
+ height: '100%',
487
+ },
488
+ locale: 'ja-JP',
489
+ });
490
+ await appEmbed.render();
491
+ expect(getIFrameSrc()).toBe(
492
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}` +
493
+ `&locale=ja-JP${defaultParamsPost}#/home`,
494
+ );
495
+ });
344
496
  });
345
497
 
346
498
  describe('validate getThoughtSpotPostUrlParams', () => {
@@ -11,6 +11,7 @@ import {
11
11
  getEncodedQueryParamsString,
12
12
  getCssDimension,
13
13
  getOffsetTop,
14
+ embedEventStatus,
14
15
  setAttributes,
15
16
  } from '../utils';
16
17
  import {
@@ -29,6 +30,8 @@ import {
29
30
  RuntimeFilter,
30
31
  Param,
31
32
  EmbedConfig,
33
+ MessageOptions,
34
+ MessageCallbackObj,
32
35
  } from '../types';
33
36
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
34
37
  import { getProcessData } from '../utils/processData';
@@ -116,15 +119,28 @@ export interface ViewConfig {
116
119
  * @version 1.6.0 or later
117
120
  */
118
121
  visibleActions?: Action[];
122
+ /**
123
+ * Show alert messages and toast messages in the embedded view.
124
+ * @version 1.11.0 | ThoughtSpot: 8.3.0.cl
125
+ */
126
+ showAlerts?: boolean;
119
127
  /**
120
128
  * The list of runtime filters to apply to a search answer,
121
129
  * visualization, or Liveboard.
122
130
  */
123
131
  runtimeFilters?: RuntimeFilter[];
132
+ /**
133
+ * The locale/language to use for the embedded view.
134
+ * @version 1.9.4 or later
135
+ */
136
+ locale?: string;
124
137
  /**
125
138
  * This is an object (key/val) of override flags which will be applied
126
139
  * to the internal embedded object. This can be used to add any
127
140
  * URL flag.
141
+ * Warning: This option is for advanced use only and is used internally
142
+ * to control embed behavior in non-regular ways. We do not publish the
143
+ * list of supported keys and values associated with each.
128
144
  * @version SDK: 1.9.0 | ThoughtSpot: 8.1.0.cl
129
145
  */
130
146
  additionalFlags?: { [key: string]: string | number | boolean };
@@ -166,7 +182,7 @@ export class TsEmbed {
166
182
  * by the embedded app; multiple event handlers can be registered
167
183
  * against a particular message type.
168
184
  */
169
- private eventHandlerMap: Map<string, MessageCallback[]>;
185
+ private eventHandlerMap: Map<string, MessageCallbackObj[]>;
170
186
 
171
187
  /**
172
188
  * A flag that is set to true post render.
@@ -263,9 +279,10 @@ export class TsEmbed {
263
279
  * will be removed for ts7.oct.cl
264
280
  * @hidden
265
281
  */
266
- private formatEventData(event: MessageEvent) {
282
+ private formatEventData(event: MessageEvent, eventType: string) {
267
283
  const eventData = {
268
284
  ...event.data,
285
+ type: eventType,
269
286
  };
270
287
  if (!eventData.data) {
271
288
  eventData.data = event.data.payload;
@@ -283,7 +300,7 @@ export class TsEmbed {
283
300
  window.addEventListener('message', (event) => {
284
301
  const eventType = this.getEventType(event);
285
302
  const eventPort = this.getEventPort(event);
286
- const eventData = this.formatEventData(event);
303
+ const eventData = this.formatEventData(event, eventType);
287
304
  if (event.source === this.iFrame.contentWindow) {
288
305
  this.executeCallbacks(
289
306
  eventType,
@@ -335,10 +352,11 @@ export class TsEmbed {
335
352
  queryParams[Param.ViewPortHeight] = window.innerHeight;
336
353
  queryParams[Param.ViewPortWidth] = window.innerWidth;
337
354
  queryParams[Param.Version] = version;
338
- if (this.embedConfig.disableLoginRedirect === true) {
339
- queryParams[
340
- Param.DisableLoginRedirect
341
- ] = this.embedConfig.disableLoginRedirect;
355
+ if (
356
+ this.embedConfig.disableLoginRedirect === true ||
357
+ this.embedConfig.autoLogin === true
358
+ ) {
359
+ queryParams[Param.DisableLoginRedirect] = true;
342
360
  }
343
361
  if (this.embedConfig.customCssUrl) {
344
362
  queryParams[Param.CustomCSSUrl] = this.embedConfig.customCssUrl;
@@ -349,7 +367,9 @@ export class TsEmbed {
349
367
  disabledActionReason,
350
368
  hiddenActions,
351
369
  visibleActions,
370
+ showAlerts,
352
371
  additionalFlags,
372
+ locale,
353
373
  } = this.viewConfig;
354
374
 
355
375
  if (Array.isArray(visibleActions) && Array.isArray(hiddenActions)) {
@@ -371,6 +391,12 @@ export class TsEmbed {
371
391
  if (Array.isArray(visibleActions)) {
372
392
  queryParams[Param.VisibleActions] = visibleActions;
373
393
  }
394
+ if (showAlerts !== undefined) {
395
+ queryParams[Param.ShowAlerts] = showAlerts;
396
+ }
397
+ if (locale !== undefined) {
398
+ queryParams[Param.Locale] = locale;
399
+ }
374
400
  if (additionalFlags && additionalFlags.constructor.name === 'Object') {
375
401
  Object.assign(queryParams, additionalFlags);
376
402
  }
@@ -432,6 +458,7 @@ export class TsEmbed {
432
458
  data: {
433
459
  timestamp: initTimestamp,
434
460
  },
461
+ type: EmbedEvent.Init,
435
462
  });
436
463
 
437
464
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_START);
@@ -480,6 +507,7 @@ export class TsEmbed {
480
507
  data: {
481
508
  timestamp: loadTimestamp,
482
509
  },
510
+ type: EmbedEvent.Load,
483
511
  });
484
512
  uploadMixpanelEvent(
485
513
  MIXPANEL_EVENT.VISUAL_SDK_IFRAME_LOAD_PERFORMANCE,
@@ -533,11 +561,21 @@ export class TsEmbed {
533
561
  eventPort?: MessagePort | void,
534
562
  ): void {
535
563
  const callbacks = this.eventHandlerMap.get(eventType) || [];
536
- callbacks.forEach((callback) =>
537
- callback(data, (payload) => {
538
- this.triggerEventOnPort(eventPort, payload);
539
- }),
540
- );
564
+ const allHandlers = this.eventHandlerMap.get(EmbedEvent.ALL) || [];
565
+ callbacks.push(...allHandlers);
566
+ const dataStatus = data?.status || embedEventStatus.END;
567
+ callbacks.forEach((callbackObj) => {
568
+ if (
569
+ (callbackObj.options.start &&
570
+ dataStatus === embedEventStatus.START) || // When start status is true it trigger only start releated payload
571
+ (!callbackObj.options.start &&
572
+ dataStatus === embedEventStatus.END) // When start status is false it trigger only end releated payload
573
+ ) {
574
+ callbackObj.callback(data, (payload) => {
575
+ this.triggerEventOnPort(eventPort, payload);
576
+ });
577
+ }
578
+ });
541
579
  }
542
580
 
543
581
  /**
@@ -604,20 +642,21 @@ export class TsEmbed {
604
642
  * sends an event of a particular message type to the host application.
605
643
  *
606
644
  * @param messageType The message type
607
- * @param callback A callback function
645
+ * @param callback A callback as a function
646
+ * @param options The message options
608
647
  */
609
648
  public on(
610
649
  messageType: EmbedEvent,
611
650
  callback: MessageCallback,
651
+ options: MessageOptions = { start: false },
612
652
  ): typeof TsEmbed.prototype {
613
653
  if (this.isRendered) {
614
654
  this.handleError(
615
655
  'Please register event handlers before calling render',
616
656
  );
617
657
  }
618
-
619
658
  const callbacks = this.eventHandlerMap.get(messageType) || [];
620
- callbacks.push(callback);
659
+ callbacks.push({ options, callback });
621
660
  this.eventHandlerMap.set(messageType, callbacks);
622
661
  return this;
623
662
  }
@@ -726,9 +765,10 @@ export class V1Embed extends TsEmbed {
726
765
  public on(
727
766
  messageType: EmbedEvent,
728
767
  callback: MessageCallback,
768
+ options: MessageOptions = { start: false },
729
769
  ): typeof TsEmbed.prototype {
730
770
  const eventType = this.getCompatibleEventType(messageType);
731
771
 
732
- return super.on(eventType, callback);
772
+ return super.on(eventType, callback, options);
733
773
  }
734
774
  }