@thoughtspot/visual-embed-sdk 1.39.2-alpha.1 → 1.39.2-alpha.2
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.
- package/cjs/package.json +1 -1
- package/cjs/src/config.spec.js +9 -0
- package/cjs/src/config.spec.js.map +1 -1
- package/cjs/src/embed/app.d.ts +75 -15
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +68 -9
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +356 -4
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.d.ts +19 -7
- package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/cjs/src/embed/bodyless-conversation.js +24 -4
- package/cjs/src/embed/bodyless-conversation.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.spec.js +8 -190
- package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +2 -60
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +1 -9
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +0 -102
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts +56 -0
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +46 -0
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +203 -0
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/errors.d.ts +1 -0
- package/cjs/src/errors.d.ts.map +1 -1
- package/cjs/src/errors.js +1 -0
- package/cjs/src/errors.js.map +1 -1
- package/cjs/src/index.d.ts +2 -2
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +2 -1
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/react/all-types-export.d.ts +1 -1
- package/cjs/src/react/all-types-export.d.ts.map +1 -1
- package/cjs/src/react/all-types-export.js +3 -2
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/index.d.ts +71 -20
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +79 -42
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +436 -100
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +46 -4
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +28 -0
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/cjs/src/utils/graphql/nlsService/conversation-service.js +2 -0
- package/cjs/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
- package/cjs/src/utils/processTrigger.js +2 -1
- package/cjs/src/utils/processTrigger.js.map +1 -1
- package/cjs/src/utils.d.ts +6 -0
- package/cjs/src/utils.d.ts.map +1 -1
- package/cjs/src/utils.js +23 -3
- package/cjs/src/utils.js.map +1 -1
- package/cjs/src/utils.spec.js +237 -1
- package/cjs/src/utils.spec.js.map +1 -1
- package/dist/index-e3Uw3YFO.js +7371 -0
- package/dist/src/embed/app.d.ts +75 -15
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/bodyless-conversation.d.ts +19 -7
- package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +2 -60
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +56 -0
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/errors.d.ts +1 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/react/all-types-export.d.ts +1 -1
- package/dist/src/react/all-types-export.d.ts.map +1 -1
- package/dist/src/react/index.d.ts +71 -20
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +46 -4
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/dist/src/utils.d.ts +6 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +276 -74
- package/dist/tsembed-react.js +276 -72
- package/dist/tsembed.es.js +194 -27
- package/dist/tsembed.js +192 -25
- package/dist/visual-embed-sdk-react-full.d.ts +246 -105
- package/dist/visual-embed-sdk-react.d.ts +246 -105
- package/dist/visual-embed-sdk.d.ts +176 -86
- package/lib/package.json +1 -1
- package/lib/src/config.spec.js +9 -0
- package/lib/src/config.spec.js.map +1 -1
- package/lib/src/embed/app.d.ts +75 -15
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +68 -9
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +357 -5
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.d.ts +19 -7
- package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/lib/src/embed/bodyless-conversation.js +23 -4
- package/lib/src/embed/bodyless-conversation.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.spec.js +9 -191
- package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +2 -60
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +2 -10
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +2 -104
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +56 -0
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +47 -1
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +203 -0
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/errors.d.ts +1 -0
- package/lib/src/errors.d.ts.map +1 -1
- package/lib/src/errors.js +1 -0
- package/lib/src/errors.js.map +1 -1
- package/lib/src/index.d.ts +2 -2
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/react/all-types-export.d.ts +1 -1
- package/lib/src/react/all-types-export.d.ts.map +1 -1
- package/lib/src/react/all-types-export.js +1 -1
- package/lib/src/react/all-types-export.js.map +1 -1
- package/lib/src/react/index.d.ts +71 -20
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +79 -43
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +439 -103
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +46 -4
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +28 -0
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/graphql/nlsService/conversation-service.d.ts.map +1 -1
- package/lib/src/utils/graphql/nlsService/conversation-service.js +2 -0
- package/lib/src/utils/graphql/nlsService/conversation-service.js.map +1 -1
- package/lib/src/utils/processTrigger.js +2 -1
- package/lib/src/utils/processTrigger.js.map +1 -1
- package/lib/src/utils.d.ts +6 -0
- package/lib/src/utils.d.ts.map +1 -1
- package/lib/src/utils.js +21 -2
- package/lib/src/utils.js.map +1 -1
- package/lib/src/utils.spec.js +238 -2
- package/lib/src/utils.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +178 -88
- package/package.json +1 -1
- package/src/config.spec.ts +11 -0
- package/src/embed/app.spec.ts +444 -4
- package/src/embed/app.ts +131 -27
- package/src/embed/bodyless-conversation.spec.ts +9 -203
- package/src/embed/bodyless-conversation.ts +24 -10
- package/src/embed/conversation.spec.ts +5 -131
- package/src/embed/conversation.ts +10 -82
- package/src/embed/liveboard.spec.ts +251 -1
- package/src/embed/liveboard.ts +97 -5
- package/src/errors.ts +1 -0
- package/src/index.ts +2 -0
- package/src/react/all-types-export.ts +2 -1
- package/src/react/index.spec.tsx +556 -157
- package/src/react/index.tsx +117 -51
- package/src/types.ts +42 -0
- package/src/utils/graphql/nlsService/conversation-service.ts +2 -0
- package/src/utils/processTrigger.ts +1 -1
- package/src/utils.spec.ts +279 -2
- package/src/utils.ts +28 -2
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
SpotterEmbed,
|
|
3
|
+
SpotterEmbedViewConfig,
|
|
4
|
+
} from './conversation';
|
|
3
5
|
import * as authInstance from '../auth';
|
|
4
6
|
import { Action, init } from '../index';
|
|
5
|
-
import { AuthType, Param
|
|
7
|
+
import { AuthType, Param } from '../types';
|
|
6
8
|
import {
|
|
7
9
|
getDocumentBody,
|
|
8
10
|
getIFrameSrc,
|
|
@@ -178,132 +180,4 @@ describe('ConversationEmbed', () => {
|
|
|
178
180
|
`http://${thoughtSpotHost}/v2/?${defaultParams}&${Param.DisableActions}=[%22${Action.InConversationTraining}%22]&${Param.DisableActionReason}=${disabledReason}&isSpotterExperienceEnabled=true&enableDataPanelV2=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
|
|
179
181
|
);
|
|
180
182
|
});
|
|
181
|
-
|
|
182
|
-
it('should render the conversation embed with runtime filters', async () => {
|
|
183
|
-
const viewConfig: SpotterEmbedViewConfig = {
|
|
184
|
-
worksheetId: 'worksheetId',
|
|
185
|
-
searchOptions: {
|
|
186
|
-
searchQuery: 'searchQuery',
|
|
187
|
-
},
|
|
188
|
-
runtimeFilters: [
|
|
189
|
-
{
|
|
190
|
-
columnName: 'revenue',
|
|
191
|
-
operator: RuntimeFilterOp.EQ,
|
|
192
|
-
values: [1000],
|
|
193
|
-
},
|
|
194
|
-
],
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
198
|
-
await conversationEmbed.render();
|
|
199
|
-
expectUrlMatchesWithParams(
|
|
200
|
-
getIFrameSrc(),
|
|
201
|
-
`http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&col1=revenue&op1=EQ&val1=1000#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
|
|
202
|
-
);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('should render the conversation embed with runtime parameters', async () => {
|
|
206
|
-
const viewConfig: SpotterEmbedViewConfig = {
|
|
207
|
-
worksheetId: 'worksheetId',
|
|
208
|
-
searchOptions: {
|
|
209
|
-
searchQuery: 'searchQuery',
|
|
210
|
-
},
|
|
211
|
-
runtimeParameters: [
|
|
212
|
-
{
|
|
213
|
-
name: 'Date Range',
|
|
214
|
-
value: '30',
|
|
215
|
-
},
|
|
216
|
-
],
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
220
|
-
await conversationEmbed.render();
|
|
221
|
-
expectUrlMatchesWithParams(
|
|
222
|
-
getIFrameSrc(),
|
|
223
|
-
`http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true¶m1=Date%20Range¶mVal1=30#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
|
|
224
|
-
);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it('should render the conversation embed with runtime parameters excluded from URL', async () => {
|
|
228
|
-
const viewConfig: SpotterEmbedViewConfig = {
|
|
229
|
-
worksheetId: 'worksheetId',
|
|
230
|
-
searchOptions: {
|
|
231
|
-
searchQuery: 'searchQuery',
|
|
232
|
-
},
|
|
233
|
-
runtimeParameters: [
|
|
234
|
-
{
|
|
235
|
-
name: 'Date Range',
|
|
236
|
-
value: '30',
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
name: 'Region',
|
|
240
|
-
value: 'North America',
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
excludeRuntimeParametersfromURL: true,
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
247
|
-
await conversationEmbed.render();
|
|
248
|
-
expectUrlMatchesWithParams(
|
|
249
|
-
getIFrameSrc(),
|
|
250
|
-
`http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
|
|
251
|
-
);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it('should render the conversation embed with both runtime filters and parameters', async () => {
|
|
255
|
-
const viewConfig: SpotterEmbedViewConfig = {
|
|
256
|
-
worksheetId: 'worksheetId',
|
|
257
|
-
searchOptions: {
|
|
258
|
-
searchQuery: 'searchQuery',
|
|
259
|
-
},
|
|
260
|
-
runtimeParameters: [
|
|
261
|
-
{
|
|
262
|
-
name: 'Date Range',
|
|
263
|
-
value: '30',
|
|
264
|
-
},
|
|
265
|
-
],
|
|
266
|
-
runtimeFilters: [
|
|
267
|
-
{
|
|
268
|
-
columnName: 'revenue',
|
|
269
|
-
operator: RuntimeFilterOp.EQ,
|
|
270
|
-
values: [1000],
|
|
271
|
-
},
|
|
272
|
-
],
|
|
273
|
-
excludeRuntimeParametersfromURL: false,
|
|
274
|
-
excludeRuntimeFiltersfromURL: false,
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
278
|
-
await conversationEmbed.render();
|
|
279
|
-
expectUrlMatchesWithParams(
|
|
280
|
-
getIFrameSrc(),
|
|
281
|
-
`http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&col1=revenue&op1=EQ&val1=1000¶m1=Date%20Range¶mVal1=30#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
|
|
282
|
-
);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it('should ensure deprecated ConversationEmbed class maintains same functionality as SpotterEmbed', async () => {
|
|
286
|
-
const viewConfig: SpotterEmbedViewConfig = {
|
|
287
|
-
worksheetId: 'worksheetId',
|
|
288
|
-
searchOptions: {
|
|
289
|
-
searchQuery: 'searchQuery',
|
|
290
|
-
},
|
|
291
|
-
runtimeParameters: [
|
|
292
|
-
{
|
|
293
|
-
name: 'Date Range',
|
|
294
|
-
value: '30',
|
|
295
|
-
},
|
|
296
|
-
],
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
// Test with deprecated class
|
|
300
|
-
const conversationEmbed = new ConversationEmbed(getRootEl(), viewConfig);
|
|
301
|
-
await conversationEmbed.render();
|
|
302
|
-
|
|
303
|
-
// Verify it generates the same URL structure as SpotterEmbed
|
|
304
|
-
expectUrlMatchesWithParams(
|
|
305
|
-
getIFrameSrc(),
|
|
306
|
-
`http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true¶m1=Date%20Range¶mVal1=30#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
|
|
307
|
-
);
|
|
308
|
-
});
|
|
309
183
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import isUndefined from 'lodash/isUndefined';
|
|
2
2
|
import { ERROR_MESSAGE } from '../errors';
|
|
3
|
-
import { Param, BaseViewConfig
|
|
3
|
+
import { Param, BaseViewConfig } from '../types';
|
|
4
4
|
import { TsEmbed } from './ts-embed';
|
|
5
|
-
import { getQueryParamString
|
|
5
|
+
import { getQueryParamString } from '../utils';
|
|
6
6
|
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
8
|
* Configuration for search options
|
|
9
9
|
*/
|
|
10
10
|
export interface SearchOptions {
|
|
@@ -20,8 +20,7 @@ export interface SearchOptions {
|
|
|
20
20
|
*/
|
|
21
21
|
export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAction'> {
|
|
22
22
|
/**
|
|
23
|
-
* The ID of the data source object. For example, Model, View, or Table. Spotter uses
|
|
24
|
-
* this object to query data and generate Answers.
|
|
23
|
+
* The ID of the data source object. For example, Model, View, or Table. Spotter uses this object to query data and generate Answers.
|
|
25
24
|
*/
|
|
26
25
|
worksheetId: string;
|
|
27
26
|
/**
|
|
@@ -31,7 +30,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
|
|
|
31
30
|
/**
|
|
32
31
|
* disableSourceSelection : Disables data source selection
|
|
33
32
|
* but still display the selected data source.
|
|
34
|
-
*
|
|
33
|
+
*
|
|
35
34
|
* Supported embed types: `SpotterEmbed`
|
|
36
35
|
* @example
|
|
37
36
|
* ```js
|
|
@@ -45,7 +44,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
|
|
|
45
44
|
disableSourceSelection?: boolean;
|
|
46
45
|
/**
|
|
47
46
|
* hideSourceSelection : Hide data source selection
|
|
48
|
-
*
|
|
47
|
+
*
|
|
49
48
|
* Supported embed types: `SpotterEmbed`
|
|
50
49
|
* @example
|
|
51
50
|
* ```js
|
|
@@ -59,7 +58,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
|
|
|
59
58
|
hideSourceSelection?: boolean;
|
|
60
59
|
/**
|
|
61
60
|
* Flag to control Data panel experience
|
|
62
|
-
*
|
|
61
|
+
*
|
|
63
62
|
* Supported embed types: `SageEmbed`, `AppEmbed`, `SearchBarEmbed`, `LiveboardEmbed`, `SearchEmbed`
|
|
64
63
|
* @default false
|
|
65
64
|
* @version SDK: 1.36.0 | ThoughtSpot Cloud: 10.4.0.cl
|
|
@@ -77,7 +76,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
|
|
|
77
76
|
* showSpotterLimitations : show limitation text
|
|
78
77
|
* of the spotter underneath the chat input.
|
|
79
78
|
* default is false.
|
|
80
|
-
*
|
|
79
|
+
*
|
|
81
80
|
* Supported embed types: `SpotterEmbed`
|
|
82
81
|
* @example
|
|
83
82
|
* ```js
|
|
@@ -92,7 +91,7 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
|
|
|
92
91
|
/**
|
|
93
92
|
* hideSampleQuestions : Hide sample questions on
|
|
94
93
|
* the initial screen of the conversation.
|
|
95
|
-
*
|
|
94
|
+
*
|
|
96
95
|
* Supported embed types: `SpotterEmbed`
|
|
97
96
|
* @example
|
|
98
97
|
* ```js
|
|
@@ -104,63 +103,6 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
|
|
|
104
103
|
* @version SDK: 1.36.0 | ThoughtSpot: 10.6.0.cl
|
|
105
104
|
*/
|
|
106
105
|
hideSampleQuestions?: boolean;
|
|
107
|
-
/**
|
|
108
|
-
* The list of runtime filters to apply to a search Answer,
|
|
109
|
-
* visualization, or Liveboard.
|
|
110
|
-
*
|
|
111
|
-
* Supported embed types: `SpotterEmbed`
|
|
112
|
-
* @example
|
|
113
|
-
* ```js
|
|
114
|
-
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
115
|
-
* ... // other embed view config
|
|
116
|
-
* runtimeFilters: [
|
|
117
|
-
* {
|
|
118
|
-
* columnName: 'value',
|
|
119
|
-
* operator: RuntimeFilterOp.EQ,
|
|
120
|
-
* values: ['string' | 123 | true],
|
|
121
|
-
* },
|
|
122
|
-
* ],
|
|
123
|
-
* })
|
|
124
|
-
* ```
|
|
125
|
-
*/
|
|
126
|
-
runtimeFilters?: RuntimeFilter[];
|
|
127
|
-
/**
|
|
128
|
-
* Flag to control whether runtime filters should be included in the URL.
|
|
129
|
-
* If true, filters will be passed via app initialization payload instead.
|
|
130
|
-
* If false/undefined, filters will be added to URL (default behavior).
|
|
131
|
-
*
|
|
132
|
-
* Supported embed types: `SpotterEmbed`
|
|
133
|
-
* @default false
|
|
134
|
-
*/
|
|
135
|
-
excludeRuntimeFiltersfromURL?: boolean;
|
|
136
|
-
/**
|
|
137
|
-
* The list of runtime parameters to apply to the conversation.
|
|
138
|
-
*
|
|
139
|
-
* Supported embed types: `SpotterEmbed`
|
|
140
|
-
* @example
|
|
141
|
-
* ```js
|
|
142
|
-
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
143
|
-
* ... // other embed view config
|
|
144
|
-
* runtimeParameters: [
|
|
145
|
-
* {
|
|
146
|
-
* name: 'Parameter Name',
|
|
147
|
-
* value: 'Parameter Value',
|
|
148
|
-
* },
|
|
149
|
-
* ],
|
|
150
|
-
* })
|
|
151
|
-
* ```
|
|
152
|
-
*/
|
|
153
|
-
runtimeParameters?: RuntimeParameter[];
|
|
154
|
-
/**
|
|
155
|
-
* Flag to control whether runtime parameters should be included in the URL.
|
|
156
|
-
* If true, parameters will be passed via app initialization payload instead.
|
|
157
|
-
* If false/undefined, parameters will be added to URL (default behavior).
|
|
158
|
-
*
|
|
159
|
-
* Supported embed types: `SpotterEmbed`
|
|
160
|
-
* @default false
|
|
161
|
-
*
|
|
162
|
-
*/
|
|
163
|
-
excludeRuntimeParametersfromURL?: boolean;
|
|
164
106
|
}
|
|
165
107
|
|
|
166
108
|
/**
|
|
@@ -202,10 +144,6 @@ export class SpotterEmbed extends TsEmbed {
|
|
|
202
144
|
dataPanelV2,
|
|
203
145
|
showSpotterLimitations,
|
|
204
146
|
hideSampleQuestions,
|
|
205
|
-
runtimeFilters,
|
|
206
|
-
excludeRuntimeFiltersfromURL,
|
|
207
|
-
runtimeParameters,
|
|
208
|
-
excludeRuntimeParametersfromURL,
|
|
209
147
|
} = this.viewConfig;
|
|
210
148
|
const path = 'insights/conv-assist';
|
|
211
149
|
if (!worksheetId) {
|
|
@@ -237,21 +175,11 @@ export class SpotterEmbed extends TsEmbed {
|
|
|
237
175
|
if (queryParamsString) {
|
|
238
176
|
query = `?${queryParamsString}`;
|
|
239
177
|
}
|
|
240
|
-
|
|
241
|
-
const filterQuery = getFilterQuery(runtimeFilters || []);
|
|
242
|
-
if (filterQuery && !excludeRuntimeFiltersfromURL) {
|
|
243
|
-
query += `&${filterQuery}`;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const parameterQuery = getRuntimeParameters(runtimeParameters || []);
|
|
247
|
-
if (parameterQuery && !excludeRuntimeParametersfromURL) {
|
|
248
|
-
query += `&${parameterQuery}`;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
178
|
const tsPostHashParams = this.getThoughtSpotPostUrlParams({
|
|
252
179
|
worksheet: worksheetId,
|
|
253
180
|
query: searchOptions?.searchQuery || '',
|
|
254
181
|
});
|
|
182
|
+
|
|
255
183
|
return `${this.getEmbedBasePath(query)}/embed/${path}${tsPostHashParams}`;
|
|
256
184
|
}
|
|
257
185
|
|
|
@@ -786,7 +786,7 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
786
786
|
await waitFor(() => !!getIFrameEl());
|
|
787
787
|
|
|
788
788
|
const ts = '__tsEmbed';
|
|
789
|
-
expect(document.getElementById(libEmbed.getPreRenderIds().wrapper)[ts]).toEqual(
|
|
789
|
+
expect((document.getElementById(libEmbed.getPreRenderIds().wrapper) as any)[ts]).toEqual(
|
|
790
790
|
libEmbed,
|
|
791
791
|
);
|
|
792
792
|
|
|
@@ -814,6 +814,256 @@ describe('Liveboard/viz embed tests', () => {
|
|
|
814
814
|
});
|
|
815
815
|
});
|
|
816
816
|
|
|
817
|
+
describe('LazyLoadingForFullHeight functionality', () => {
|
|
818
|
+
let mockIFrame: HTMLIFrameElement;
|
|
819
|
+
|
|
820
|
+
beforeEach(() => {
|
|
821
|
+
mockIFrame = document.createElement('iframe');
|
|
822
|
+
mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
|
|
823
|
+
top: 100,
|
|
824
|
+
left: 150,
|
|
825
|
+
bottom: 600,
|
|
826
|
+
right: 800,
|
|
827
|
+
width: 650,
|
|
828
|
+
height: 500,
|
|
829
|
+
});
|
|
830
|
+
jest.spyOn(document, 'createElement').mockImplementation((tagName) => {
|
|
831
|
+
if (tagName === 'iframe') {
|
|
832
|
+
return mockIFrame;
|
|
833
|
+
}
|
|
834
|
+
return document.createElement(tagName);
|
|
835
|
+
});
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
afterEach(() => {
|
|
839
|
+
jest.restoreAllMocks();
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
test('should set lazyLoadingMargin parameter when provided', async () => {
|
|
843
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
844
|
+
...defaultViewConfig,
|
|
845
|
+
liveboardId,
|
|
846
|
+
fullHeight: true,
|
|
847
|
+
lazyLoadingForFullHeight: true,
|
|
848
|
+
lazyLoadingMargin: '100px 0px',
|
|
849
|
+
} as LiveboardViewConfig);
|
|
850
|
+
|
|
851
|
+
await liveboardEmbed.render();
|
|
852
|
+
|
|
853
|
+
await executeAfterWait(() => {
|
|
854
|
+
const iframeSrc = getIFrameSrc();
|
|
855
|
+
expect(iframeSrc).toContain('isLazyLoadingForEmbedEnabled=true');
|
|
856
|
+
expect(iframeSrc).toContain('isFullHeightPinboard=true');
|
|
857
|
+
expect(iframeSrc).toContain('rootMarginForLazyLoad=100px%200px');
|
|
858
|
+
}, 100);
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
test('should set isLazyLoadingForEmbedEnabled=true when both fullHeight and lazyLoadingForFullHeight are enabled', async () => {
|
|
862
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
863
|
+
...defaultViewConfig,
|
|
864
|
+
liveboardId,
|
|
865
|
+
fullHeight: true,
|
|
866
|
+
lazyLoadingForFullHeight: true,
|
|
867
|
+
} as LiveboardViewConfig);
|
|
868
|
+
|
|
869
|
+
await liveboardEmbed.render();
|
|
870
|
+
|
|
871
|
+
await executeAfterWait(() => {
|
|
872
|
+
const iframeSrc = getIFrameSrc();
|
|
873
|
+
expect(iframeSrc).toContain('isLazyLoadingForEmbedEnabled=true');
|
|
874
|
+
expect(iframeSrc).toContain('isFullHeightPinboard=true');
|
|
875
|
+
}, 100);
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
test('should not set lazyLoadingForEmbed when lazyLoadingForFullHeight is enabled but fullHeight is false', async () => {
|
|
879
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
880
|
+
...defaultViewConfig,
|
|
881
|
+
liveboardId,
|
|
882
|
+
fullHeight: false,
|
|
883
|
+
lazyLoadingForFullHeight: true,
|
|
884
|
+
} as LiveboardViewConfig);
|
|
885
|
+
|
|
886
|
+
await liveboardEmbed.render();
|
|
887
|
+
|
|
888
|
+
await executeAfterWait(() => {
|
|
889
|
+
const iframeSrc = getIFrameSrc();
|
|
890
|
+
expect(iframeSrc).not.toContain('isLazyLoadingForEmbedEnabled=true');
|
|
891
|
+
expect(iframeSrc).not.toContain('isFullHeightPinboard=true');
|
|
892
|
+
}, 100);
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
test('should not set isLazyLoadingForEmbedEnabled when fullHeight is true but lazyLoadingForFullHeight is false', async () => {
|
|
896
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
897
|
+
...defaultViewConfig,
|
|
898
|
+
liveboardId,
|
|
899
|
+
fullHeight: true,
|
|
900
|
+
lazyLoadingForFullHeight: false,
|
|
901
|
+
} as LiveboardViewConfig);
|
|
902
|
+
|
|
903
|
+
await liveboardEmbed.render();
|
|
904
|
+
|
|
905
|
+
await executeAfterWait(() => {
|
|
906
|
+
const iframeSrc = getIFrameSrc();
|
|
907
|
+
expect(iframeSrc).not.toContain('isLazyLoadingForEmbedEnabled=true');
|
|
908
|
+
expect(iframeSrc).toContain('isFullHeightPinboard=true');
|
|
909
|
+
}, 100);
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
test('should register event handlers to adjust iframe height', async () => {
|
|
913
|
+
const onSpy = jest.spyOn(LiveboardEmbed.prototype, 'on');
|
|
914
|
+
|
|
915
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
916
|
+
...defaultViewConfig,
|
|
917
|
+
liveboardId,
|
|
918
|
+
fullHeight: true,
|
|
919
|
+
lazyLoadingForFullHeight: true,
|
|
920
|
+
} as LiveboardViewConfig);
|
|
921
|
+
|
|
922
|
+
await liveboardEmbed.render();
|
|
923
|
+
|
|
924
|
+
await executeAfterWait(() => {
|
|
925
|
+
expect(onSpy).toHaveBeenCalledWith(EmbedEvent.EmbedHeight, expect.anything());
|
|
926
|
+
expect(onSpy).toHaveBeenCalledWith(EmbedEvent.RouteChange, expect.anything());
|
|
927
|
+
expect(onSpy).toHaveBeenCalledWith(EmbedEvent.EmbedIframeCenter, expect.anything());
|
|
928
|
+
expect(onSpy).toHaveBeenCalledWith(EmbedEvent.RequestVisibleEmbedCoordinates, expect.anything());
|
|
929
|
+
}, 100);
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
test('should send correct visible data when RequestVisibleEmbedCoordinates is triggered', async () => {
|
|
933
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
934
|
+
...defaultViewConfig,
|
|
935
|
+
liveboardId,
|
|
936
|
+
fullHeight: true,
|
|
937
|
+
lazyLoadingForFullHeight: true,
|
|
938
|
+
} as LiveboardViewConfig);
|
|
939
|
+
|
|
940
|
+
const mockTrigger = jest.spyOn(liveboardEmbed, 'trigger');
|
|
941
|
+
|
|
942
|
+
await liveboardEmbed.render();
|
|
943
|
+
|
|
944
|
+
// Trigger the lazy load data calculation
|
|
945
|
+
(liveboardEmbed as any).sendFullHeightLazyLoadData();
|
|
946
|
+
|
|
947
|
+
expect(mockTrigger).toHaveBeenCalledWith(HostEvent.VisibleEmbedCoordinates, {
|
|
948
|
+
top: 0,
|
|
949
|
+
height: 500,
|
|
950
|
+
left: 0,
|
|
951
|
+
width: 650,
|
|
952
|
+
});
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
test('should calculate correct visible data for partially visible full height element', async () => {
|
|
956
|
+
mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
|
|
957
|
+
top: -50,
|
|
958
|
+
left: -30,
|
|
959
|
+
bottom: 700,
|
|
960
|
+
right: 1024,
|
|
961
|
+
width: 1054,
|
|
962
|
+
height: 750,
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
966
|
+
...defaultViewConfig,
|
|
967
|
+
liveboardId,
|
|
968
|
+
fullHeight: true,
|
|
969
|
+
lazyLoadingForFullHeight: true,
|
|
970
|
+
} as LiveboardViewConfig);
|
|
971
|
+
|
|
972
|
+
const mockTrigger = jest.spyOn(liveboardEmbed, 'trigger');
|
|
973
|
+
|
|
974
|
+
await liveboardEmbed.render();
|
|
975
|
+
|
|
976
|
+
// Trigger the lazy load data calculation
|
|
977
|
+
(liveboardEmbed as any).sendFullHeightLazyLoadData();
|
|
978
|
+
|
|
979
|
+
expect(mockTrigger).toHaveBeenCalledWith(HostEvent.VisibleEmbedCoordinates, {
|
|
980
|
+
top: 50,
|
|
981
|
+
height: 700,
|
|
982
|
+
left: 30,
|
|
983
|
+
width: 1024,
|
|
984
|
+
});
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
test('should add window event listeners for resize and scroll when fullHeight and lazyLoadingForFullHeight are enabled', async () => {
|
|
988
|
+
const addEventListenerSpy = jest.spyOn(window, 'addEventListener');
|
|
989
|
+
|
|
990
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
991
|
+
...defaultViewConfig,
|
|
992
|
+
liveboardId,
|
|
993
|
+
fullHeight: true,
|
|
994
|
+
lazyLoadingForFullHeight: true,
|
|
995
|
+
} as LiveboardViewConfig);
|
|
996
|
+
|
|
997
|
+
await liveboardEmbed.render();
|
|
998
|
+
|
|
999
|
+
expect(addEventListenerSpy).toHaveBeenCalledWith('resize', expect.anything());
|
|
1000
|
+
expect(addEventListenerSpy).toHaveBeenCalledWith('scroll', expect.anything());
|
|
1001
|
+
|
|
1002
|
+
addEventListenerSpy.mockRestore();
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
test('should remove window event listeners on destroy when fullHeight and lazyLoadingForFullHeight are enabled', async () => {
|
|
1006
|
+
const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener');
|
|
1007
|
+
|
|
1008
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
1009
|
+
...defaultViewConfig,
|
|
1010
|
+
liveboardId,
|
|
1011
|
+
fullHeight: true,
|
|
1012
|
+
lazyLoadingForFullHeight: true,
|
|
1013
|
+
} as LiveboardViewConfig);
|
|
1014
|
+
|
|
1015
|
+
await liveboardEmbed.render();
|
|
1016
|
+
liveboardEmbed.destroy();
|
|
1017
|
+
|
|
1018
|
+
expect(removeEventListenerSpy).toHaveBeenCalledWith('resize', expect.anything());
|
|
1019
|
+
expect(removeEventListenerSpy).toHaveBeenCalledWith('scroll', expect.anything());
|
|
1020
|
+
|
|
1021
|
+
removeEventListenerSpy.mockRestore();
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
test('should handle RequestVisibleEmbedCoordinates event and respond with correct data', async () => {
|
|
1025
|
+
// Mock the iframe element
|
|
1026
|
+
mockIFrame.getBoundingClientRect = jest.fn().mockReturnValue({
|
|
1027
|
+
top: 100,
|
|
1028
|
+
left: 150,
|
|
1029
|
+
bottom: 600,
|
|
1030
|
+
right: 800,
|
|
1031
|
+
width: 650,
|
|
1032
|
+
height: 500,
|
|
1033
|
+
});
|
|
1034
|
+
Object.defineProperty(mockIFrame, 'scrollHeight', { value: 500 });
|
|
1035
|
+
|
|
1036
|
+
const liveboardEmbed = new LiveboardEmbed(getRootEl(), {
|
|
1037
|
+
...defaultViewConfig,
|
|
1038
|
+
liveboardId,
|
|
1039
|
+
fullHeight: true,
|
|
1040
|
+
lazyLoadingForFullHeight: true,
|
|
1041
|
+
} as LiveboardViewConfig);
|
|
1042
|
+
|
|
1043
|
+
// Set the iframe before render
|
|
1044
|
+
(liveboardEmbed as any).iFrame = mockIFrame;
|
|
1045
|
+
|
|
1046
|
+
await liveboardEmbed.render();
|
|
1047
|
+
|
|
1048
|
+
// Create a mock responder function
|
|
1049
|
+
const mockResponder = jest.fn();
|
|
1050
|
+
|
|
1051
|
+
// Trigger the handler directly
|
|
1052
|
+
(liveboardEmbed as any).requestVisibleEmbedCoordinatesHandler({}, mockResponder);
|
|
1053
|
+
|
|
1054
|
+
// Verify the responder was called with the correct data
|
|
1055
|
+
expect(mockResponder).toHaveBeenCalledWith({
|
|
1056
|
+
type: EmbedEvent.RequestVisibleEmbedCoordinates,
|
|
1057
|
+
data: {
|
|
1058
|
+
top: 0,
|
|
1059
|
+
height: 500,
|
|
1060
|
+
left: 0,
|
|
1061
|
+
width: 650,
|
|
1062
|
+
},
|
|
1063
|
+
});
|
|
1064
|
+
});
|
|
1065
|
+
});
|
|
1066
|
+
|
|
817
1067
|
describe('Host events for liveborad', () => {
|
|
818
1068
|
test('Host event with empty param', async () => {
|
|
819
1069
|
const mockProcessTrigger = jest.spyOn(tsEmbed.TsEmbed.prototype, 'trigger');
|