Skip to content

Commit

Permalink
SCAL-228730 - Added option to send additionalFlags in prefetch (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbhanu-thoughtspot authored Oct 31, 2024
1 parent c6a3f13 commit 389bc36
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 23 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@thoughtspot/visual-embed-sdk",
"version": "1.33.4",
"version": "1.33.5",
"description": "ThoughtSpot Embed SDK",
"module": "lib/src/index.js",
"main": "dist/tsembed.js",
Expand Down
1 change: 0 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export const getThoughtSpotHost = (config: EmbedConfig): string => {
}
// const urlParams = urlParts[7];
// const hash = urlParts[8];

return `${protocol}//${host}${path}`;
};

Expand Down
1 change: 0 additions & 1 deletion src/embed/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,6 @@ export class AppEmbed extends V1Embed {
} = this.viewConfig;

let params = {};
params[Param.EmbedApp] = true;
params[Param.PrimaryNavHidden] = !showPrimaryNavbar;
params[Param.HideProfleAndHelp] = !!disableProfileAndHelp;
params[Param.HideApplicationSwitcher] = !!hideApplicationSwitcher;
Expand Down
51 changes: 48 additions & 3 deletions src/embed/base.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ describe('Base TS Embed', () => {
});

test('Should add the prefetch iframe when prefetch is called. Should remove it once init is called.', async () => {
const url = 'https://10.87.90.95/';
const url = 'https://10.87.90.95/?embedApp=true';
index.init({
thoughtSpotHost: url,
authType: index.AuthType.None,
Expand All @@ -266,8 +266,8 @@ describe('Base TS Embed', () => {

test('Should add the prefetch iframe when prefetch is called with multiple options', async () => {
const url = 'https://10.87.90.95/';
const searchUrl = `${url}v2/#/embed/answer`;
const liveboardUrl = url;
const searchUrl = `${url}v2/?embedApp=true#/embed/answer`;
const liveboardUrl = `${url}?embedApp=true`;
index.prefetch(url, [
index.PrefetchFeatures.SearchEmbed,
index.PrefetchFeatures.LiveboardEmbed,
Expand All @@ -281,6 +281,51 @@ describe('Base TS Embed', () => {
expect(secondIframe.src).toBe(liveboardUrl);
});

test('Should add the prefetch iframe with additionalFlags', async () => {
const url = 'https://10.87.90.95/';
const searchUrl = `${url}v2/?embedApp=true&flag2=bool&flag3=block&flag1=true#/embed/answer`;
const liveboardUrl = `${url}?embedApp=true&flag2=bool&flag3=block&flag1=true`;
base.init({
thoughtSpotHost: url,
authType: index.AuthType.None,
additionalFlags: {
flag2: 'bar',
flag3: 'block',
},
});
index.prefetch(url, [
index.PrefetchFeatures.SearchEmbed,
index.PrefetchFeatures.LiveboardEmbed,
],
{ flag1: true, flag2: 'bool' });
expect(getAllIframeEl().length).toBe(2);
const prefetchIframe = document.querySelectorAll<HTMLIFrameElement>('.prefetchIframe');
expect(prefetchIframe.length).toBe(2);
const firstIframe = <HTMLIFrameElement>prefetchIframe[0];
expect(firstIframe.src).toBe(searchUrl);
const secondIframe = <HTMLIFrameElement>prefetchIframe[1];
expect(secondIframe.src).toBe(liveboardUrl);
});

test('Should add the prefetch iframe with additionalFlags for prefetch from init', async () => {
const url = 'https://10.87.90.95/';
const prefetchUrl = `${url}?embedApp=true&flag2=bar&flag3=block`;
base.init({
thoughtSpotHost: url,
authType: index.AuthType.None,
additionalFlags: {
flag2: 'bar',
flag3: 'block',
},
callPrefetch: true,
});
expect(getAllIframeEl().length).toBe(1);
const prefetchIframe = document.querySelectorAll<HTMLIFrameElement>('.prefetchIframe');
expect(prefetchIframe.length).toBe(1);
const firstIframe = <HTMLIFrameElement>prefetchIframe[0];
expect(firstIframe.src).toBe(prefetchUrl);
});

test('Should not generate a prefetch iframe when url is empty string', async () => {
const url = '';
index.prefetch(url);
Expand Down
28 changes: 21 additions & 7 deletions src/embed/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { tokenizedFetch } from '../tokenizedFetch';
import { EndPoints } from '../utils/authService/authService';
import { getThoughtSpotHost } from '../config';
import {
AuthType, EmbedConfig, LogLevel, PrefetchFeatures,
AuthType, EmbedConfig, LogLevel, Param, PrefetchFeatures,
} from '../types';
import {
authenticate,
Expand All @@ -33,6 +33,7 @@ import {
} from '../auth';
import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
import { getEmbedConfig, setEmbedConfig } from './embedConfig';
import { getQueryParamString } from '../utils';

const CONFIG_DEFAULTS: Partial<EmbedConfig> = {
loginFailedMessage: 'Not logged in',
Expand Down Expand Up @@ -88,10 +89,10 @@ export const handleAuth = (): Promise<boolean> => {
};

const hostUrlToFeatureUrl = {
[PrefetchFeatures.SearchEmbed]: (url: string) => `${url}v2/#/embed/answer`,
[PrefetchFeatures.LiveboardEmbed]: (url: string) => url,
[PrefetchFeatures.FullApp]: (url: string) => url,
[PrefetchFeatures.VizEmbed]: (url: string) => url,
[PrefetchFeatures.SearchEmbed]: (url: string, flags: string) => `${url}v2/?${flags}#/embed/answer`,
[PrefetchFeatures.LiveboardEmbed]: (url: string, flags: string) => `${url}?${flags}`,
[PrefetchFeatures.FullApp]: (url: string, flags: string) => `${url}?${flags}`,
[PrefetchFeatures.VizEmbed]: (url: string, flags: string) => `${url}?${flags}`,
};

/**
Expand All @@ -100,20 +101,33 @@ const hostUrlToFeatureUrl = {
* to your app.
* @param url The URL provided for prefetch
* @param prefetchFeatures Specify features which needs to be prefetched.
* @param additionalFlags This can be used to add any URL flag.
* @version SDK: 1.4.0 | ThoughtSpot: ts7.sep.cl, 7.2.1
* @group Global methods
*/
export const prefetch = (url?: string, prefetchFeatures?: PrefetchFeatures[]): void => {
export const prefetch = (
url?: string,
prefetchFeatures?: PrefetchFeatures[],
additionalFlags?: { [key: string]: string | number | boolean },
): void => {
if (url === '') {
// eslint-disable-next-line no-console
logger.warn('The prefetch method does not have a valid URL');
} else {
const features = prefetchFeatures || [PrefetchFeatures.FullApp];
let hostUrl = url || getEmbedConfig().thoughtSpotHost;
const prefetchFlags = {
[Param.EmbedApp]: true,
...getEmbedConfig()?.additionalFlags,
...additionalFlags,
};
hostUrl = hostUrl[hostUrl.length - 1] === '/' ? hostUrl : `${hostUrl}/`;
Array.from(
new Set(features
.map((feature) => hostUrlToFeatureUrl[feature](hostUrl))),
.map((feature) => hostUrlToFeatureUrl[feature](
hostUrl,
getQueryParamString(prefetchFlags),
))),
)
.forEach(
(prefetchUrl, index) => {
Expand Down
1 change: 0 additions & 1 deletion src/embed/liveboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ export class LiveboardEmbed extends V1Embed {
*/
protected getEmbedParams() {
let params = {};
params[Param.EmbedApp] = true;
params = this.getBaseQueryParams(params);
const {
enableVizTransformations,
Expand Down
1 change: 0 additions & 1 deletion src/embed/sage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ export class SageEmbed extends V1Embed {
} = this.viewConfig;

const params = this.getBaseQueryParams();
params[Param.EmbedApp] = true;
params[Param.IsSageEmbed] = true;
params[Param.DisableWorksheetChange] = !!disableWorksheetChange;
params[Param.HideWorksheetSelector] = !!hideWorksheetSelector;
Expand Down
31 changes: 31 additions & 0 deletions src/embed/ts-embed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
createRootEleForEmbed,
} from '../test/test-utils';
import * as config from '../config';
import * as embedConfig from './embedConfig';
import * as tsEmbedInstance from './ts-embed';
import * as mixpanelInstance from '../mixpanel-service';
import * as authInstance from '../auth';
Expand Down Expand Up @@ -1276,6 +1277,36 @@ describe('Unit test case for ts embed', () => {
);
});

it('should set the additional flags correctly on the iframe src from init and view config', async () => {
init({
thoughtSpotHost: 'http://tshost',
authType: AuthType.None,
additionalFlags: {
foo: 'bar1',
foo2: 'bar2',
foo3: false,
},
});
const appEmbed = new AppEmbed(getRootEl(), {
frameParams: {
width: '100%',
height: '100%',
},
additionalFlags: {
foo: 'bar',
baz: 1,
bool: true,
},
});
await appEmbed.render();
console.log('val ', getIFrameSrc());
expectUrlMatchesWithParams(
getIFrameSrc(),
`http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false&${defaultParamsForPinboardEmbed}`
+ `&foo=bar&foo2=bar2&foo3=false&baz=1&bool=true${defaultParamsPost}#/home`,
);
});

it('Sets the showAlerts param', async () => {
const appEmbed = new AppEmbed(getRootEl(), {
frameParams: {
Expand Down
14 changes: 12 additions & 2 deletions src/embed/ts-embed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/

import isEqual from 'lodash/isEqual';
import isEmpty from 'lodash/isEmpty';
import isObject from 'lodash/isObject';
import { logger } from '../utils/logger';
import { getAuthenticationToken } from '../authToken';
import { AnswerService } from '../utils/graphql/answerService/answerService';
Expand Down Expand Up @@ -398,6 +400,7 @@ export class TsEmbed {
if (hostAppUrl.includes('localhost') || hostAppUrl.includes('127.0.0.1')) {
hostAppUrl = 'local-host';
}
queryParams[Param.EmbedApp] = true;
queryParams[Param.HostAppUrl] = encodeURIComponent(hostAppUrl);
queryParams[Param.ViewPortHeight] = window.innerHeight;
queryParams[Param.ViewPortWidth] = window.innerWidth;
Expand Down Expand Up @@ -435,7 +438,7 @@ export class TsEmbed {
hiddenTabs,
visibleTabs,
showAlerts,
additionalFlags,
additionalFlags: additionalFlagsFromView,
locale,
customizations,
contextMenuTrigger,
Expand All @@ -445,6 +448,13 @@ export class TsEmbed {
overrideOrgId,
} = this.viewConfig;

const { additionalFlags: additionalFlagsFromInit } = this.embedConfig;

const additionalFlags = {
...additionalFlagsFromInit,
...additionalFlagsFromView,
};

if (Array.isArray(visibleActions) && Array.isArray(hiddenActions)) {
this.handleError('You cannot have both hidden actions and visible actions');
return queryParams;
Expand Down Expand Up @@ -511,7 +521,7 @@ export class TsEmbed {
queryParams[Param.OverrideNativeConsole] = true;
queryParams[Param.ClientLogLevel] = this.embedConfig.logLevel;

if (additionalFlags && additionalFlags.constructor.name === 'Object') {
if (isObject(additionalFlags) && !isEmpty(additionalFlags)) {
Object.assign(queryParams, additionalFlags);
}

Expand Down
4 changes: 2 additions & 2 deletions src/react/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('React Components', () => {
),
).toBe(true);
expect(getIFrameSrc(container)).toBe(
`http://${thoughtSpotHost}/?hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&authType=None&blockNonEmbedFullAppAccess=true&hideAction=[%22${Action.ReportError}%22,%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&overrideConsoleLogs=true&clientLogLevel=ERROR&enableDataPanelV2=false&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true&collapseSearchBarInitially=true&enableCustomColumnGroups=false&dataPanelCustomGroupsAccordionInitialState=EXPAND_ALL#/embed/answer`,
`http://${thoughtSpotHost}/?embedApp=true&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&authType=None&blockNonEmbedFullAppAccess=true&hideAction=[%22${Action.ReportError}%22,%22editACopy%22,%22saveAsView%22,%22updateTSL%22,%22editTSL%22,%22onDeleteAnswer%22]&overrideConsoleLogs=true&clientLogLevel=ERROR&enableDataPanelV2=false&dataSourceMode=hide&useLastSelectedSources=false&isSearchEmbed=true&collapseSearchBarInitially=true&enableCustomColumnGroups=false&dataPanelCustomGroupsAccordionInitialState=EXPAND_ALL#/embed/answer`,
);
});

Expand Down Expand Up @@ -230,7 +230,7 @@ describe('React Components', () => {
),
).toBe(true);
expect(getIFrameSrc(container)).toBe(
`http://${thoughtSpotHost}/?hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&authType=None&blockNonEmbedFullAppAccess=true&hideAction=[%22${Action.ReportError}%22]&overrideConsoleLogs=true&clientLogLevel=ERROR&dataSources=[%22test%22]&searchTokenString=%5Brevenue%5D&executeSearch=true&useLastSelectedSources=false&isSearchEmbed=true#/embed/search-bar-embed`,
`http://${thoughtSpotHost}/?embedApp=true&hostAppUrl=local-host&viewPortHeight=768&viewPortWidth=1024&sdkVersion=${version}&authType=None&blockNonEmbedFullAppAccess=true&hideAction=[%22${Action.ReportError}%22]&overrideConsoleLogs=true&clientLogLevel=ERROR&dataSources=[%22test%22]&searchTokenString=%5Brevenue%5D&executeSearch=true&useLastSelectedSources=false&isSearchEmbed=true#/embed/search-bar-embed`,
);
});
});
Expand Down
30 changes: 26 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,26 @@ export interface EmbedConfig {
* @version SDK 1.32.3 | Thoughtspot: *
*/
disableLoginFailurePage?: boolean;
/**
* This is an object (key/val) of override flags which will be applied
* to the internal embedded object. This can be used to add any
* URL flag.
* Warning: This option is for advanced use only and is used internally
* to control embed behavior in non-regular ways. We do not publish the
* list of supported keys and values associated with each.
* @example
* ```js
* const embed = new LiveboardEmbed('#embed', {
* ... // other liveboard view config
* additionalFlags: {
* flag1: 'value1',
* flag2: 'value2'
* }
* });
* ```
* @version SDK: 1.33.5 | ThoughtSpot: *
*/
additionalFlags?: { [key: string]: string | number | boolean };
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
Expand Down Expand Up @@ -779,6 +799,7 @@ export interface ViewConfig {
* This is an object (key/val) of override flags which will be applied
* to the internal embedded object. This can be used to add any
* URL flag.
* If the same flags are passed in init, they will be overriden by the values here.
* Warning: This option is for advanced use only and is used internally
* to control embed behavior in non-regular ways. We do not publish the
* list of supported keys and values associated with each.
Expand Down Expand Up @@ -1134,7 +1155,7 @@ export type MessageCallbackObj = {
export type GenericCallbackFn = (...args: any[]) => any;

export type QueryParams = {
[key: string]: string;
[key: string]: string | boolean | number;
};

/**
Expand Down Expand Up @@ -2978,12 +2999,13 @@ export enum HostEvent {
* see link:https://developers.thoughtspot.com/docs/runtime-filters#rtOperator[Developer Documentation].
*
* `values` - An array of one or several values. The value definition on the
* data type you choose to filter on. For a complete list of supported data types, see
* link:https://developers.thoughtspot.com/docs/runtime-filters#_supported_data_types[Supported data types].
* data type you choose to filter on. For a complete list of supported data types,
* see
* link:https://developers.thoughtspot.com/docs/runtime-filters#_supported_data_types[Supported
* data types].
*
* `type` - To update filters for date time, specify the date format type.
* For more information and examples, see link:https://developers.thoughtspot.com/docs/embed-liveboard#_date_filters[Date filters].
*
* @example
* ```js
*
Expand Down

0 comments on commit 389bc36

Please sign in to comment.