@thoughtspot/visual-embed-sdk 1.37.1 → 1.38.0-alpha.1
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/README.md +1 -1
- package/cjs/package.json +1 -1
- package/cjs/src/embed/app.js +1 -1
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.d.ts +44 -9
- package/cjs/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/cjs/src/embed/bodyless-conversation.js +35 -5
- package/cjs/src/embed/bodyless-conversation.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.spec.js +290 -5
- package/cjs/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +40 -11
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +29 -4
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +7 -7
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +21 -10
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +4 -4
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +5 -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 -1
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/index.d.ts +53 -5
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +73 -4
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +94 -0
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +2 -1
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +1 -0
- package/cjs/src/types.js.map +1 -1
- package/dist/{index-m9UtENc9.js → index-DeFzsyFF.js} +1 -1
- package/dist/index-NZYq1Tu3.js +7370 -0
- package/dist/src/embed/bodyless-conversation.d.ts +44 -9
- package/dist/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +40 -11
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -4
- 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 +53 -5
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +2 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +583 -21
- package/dist/tsembed-react.js +583 -19
- package/dist/tsembed.es.js +86 -22
- package/dist/tsembed.js +92 -26
- package/dist/visual-embed-sdk-react-full.d.ts +184 -72
- package/dist/visual-embed-sdk-react.d.ts +184 -72
- package/dist/visual-embed-sdk.d.ts +87 -22
- package/lib/package.json +1 -1
- package/lib/src/embed/app.js +1 -1
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.d.ts +44 -9
- package/lib/src/embed/bodyless-conversation.d.ts.map +1 -1
- package/lib/src/embed/bodyless-conversation.js +33 -4
- package/lib/src/embed/bodyless-conversation.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.spec.js +292 -7
- package/lib/src/embed/bodyless-conversation.spec.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +40 -11
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +27 -3
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +8 -8
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +21 -10
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +4 -4
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +4 -4
- 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 +53 -5
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +73 -4
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +96 -2
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +2 -1
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +1 -0
- package/lib/src/types.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +90 -25
- package/package.json +1 -1
- package/src/embed/app.ts +1 -1
- package/src/embed/bodyless-conversation.spec.ts +314 -7
- package/src/embed/bodyless-conversation.ts +53 -8
- package/src/embed/conversation.spec.ts +16 -16
- package/src/embed/conversation.ts +44 -11
- package/src/embed/liveboard.ts +25 -10
- package/src/embed/ts-embed.spec.ts +0 -2
- package/src/index.ts +16 -5
- package/src/react/all-types-export.ts +2 -0
- package/src/react/index.spec.tsx +157 -1
- package/src/react/index.tsx +98 -11
- package/src/types.ts +1 -0
|
@@ -8,14 +8,28 @@ import { getQueryParamString } from '../utils';
|
|
|
8
8
|
* Configuration for bodyless conversation options.
|
|
9
9
|
* @group Embed components
|
|
10
10
|
*/
|
|
11
|
-
export interface
|
|
11
|
+
export interface SpotterAgentEmbedViewConfig extends ViewConfig {
|
|
12
12
|
/**
|
|
13
13
|
* The ID of the worksheet to use for the conversation.
|
|
14
14
|
*/
|
|
15
15
|
worksheetId: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Optional CSS class name to add to the container div.
|
|
19
|
+
*/
|
|
20
|
+
containerClassName?: string;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for conversation options.
|
|
25
|
+
* @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
|
|
26
|
+
* Use {@link SpotterAgentEmbedViewConfig} instead
|
|
27
|
+
* @group Embed components
|
|
28
|
+
*/
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
30
|
+
export interface BodylessConversationViewConfig extends SpotterAgentEmbedViewConfig {}
|
|
31
|
+
|
|
32
|
+
interface SpotterAgentMessageViewConfig extends SpotterAgentEmbedViewConfig {
|
|
19
33
|
sessionId: string;
|
|
20
34
|
genNo: number;
|
|
21
35
|
acSessionId: string;
|
|
@@ -23,7 +37,7 @@ interface ConversationMessageViewConfig extends BodylessConversationViewConfig {
|
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
class ConversationMessage extends TsEmbed {
|
|
26
|
-
constructor(container: HTMLElement, protected viewConfig:
|
|
40
|
+
constructor(container: HTMLElement, protected viewConfig: SpotterAgentMessageViewConfig) {
|
|
27
41
|
viewConfig.embedComponentType = 'bodyless-conversation';
|
|
28
42
|
super(container, viewConfig);
|
|
29
43
|
}
|
|
@@ -39,6 +53,7 @@ class ConversationMessage extends TsEmbed {
|
|
|
39
53
|
const queryParams = this.getBaseQueryParams();
|
|
40
54
|
|
|
41
55
|
queryParams[Param.HideActions] = [...(queryParams[Param.HideActions] ?? [])];
|
|
56
|
+
queryParams[Param.isSpotterAgentEmbed] = true;
|
|
42
57
|
let query = '';
|
|
43
58
|
const queryParamsString = getQueryParamString(queryParams, true);
|
|
44
59
|
if (queryParamsString) {
|
|
@@ -68,9 +83,9 @@ class ConversationMessage extends TsEmbed {
|
|
|
68
83
|
* chatbots or other conversational interfaces.
|
|
69
84
|
* @example
|
|
70
85
|
* ```js
|
|
71
|
-
* import {
|
|
86
|
+
* import { SpotterAgentEmbed } from '@thoughtspot/visual-embed-sdk';
|
|
72
87
|
*
|
|
73
|
-
* const conversation = new
|
|
88
|
+
* const conversation = new SpotterAgentEmbed({
|
|
74
89
|
* worksheetId: 'worksheetId',
|
|
75
90
|
* });
|
|
76
91
|
*
|
|
@@ -80,12 +95,12 @@ class ConversationMessage extends TsEmbed {
|
|
|
80
95
|
* document.body.appendChild(container); // or to any other element
|
|
81
96
|
* ```
|
|
82
97
|
* @group Embed components
|
|
83
|
-
* @version SDK: 1.
|
|
98
|
+
* @version SDK: 1.37.0 | ThoughtSpot: 10.9.0.cl
|
|
84
99
|
*/
|
|
85
|
-
export class
|
|
100
|
+
export class SpotterAgentEmbed {
|
|
86
101
|
private conversationService: ConversationService;
|
|
87
102
|
|
|
88
|
-
constructor(private viewConfig:
|
|
103
|
+
constructor(private viewConfig: SpotterAgentEmbedViewConfig) {
|
|
89
104
|
const embedConfig = getEmbedConfig();
|
|
90
105
|
|
|
91
106
|
this.conversationService = new ConversationService(
|
|
@@ -101,6 +116,10 @@ export class BodylessConversation {
|
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
const container = document.createElement('div');
|
|
119
|
+
if (this.viewConfig.containerClassName) {
|
|
120
|
+
container.className = this.viewConfig.containerClassName;
|
|
121
|
+
}
|
|
122
|
+
|
|
104
123
|
const embed = new ConversationMessage(container, {
|
|
105
124
|
...this.viewConfig,
|
|
106
125
|
sessionId: data.sessionId,
|
|
@@ -112,3 +131,29 @@ export class BodylessConversation {
|
|
|
112
131
|
return { container, viz: embed };
|
|
113
132
|
}
|
|
114
133
|
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Create a conversation embed, which can be integrated inside
|
|
137
|
+
* chatbots or other conversational interfaces.
|
|
138
|
+
* @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
|
|
139
|
+
* Use {@link SpotterAgentEmbed} instead
|
|
140
|
+
* @example
|
|
141
|
+
* ```js
|
|
142
|
+
* import { SpotterAgentEmbed } from '@thoughtspot/visual-embed-sdk';
|
|
143
|
+
*
|
|
144
|
+
* const conversation = new SpotterAgentEmbed({
|
|
145
|
+
* worksheetId: 'worksheetId',
|
|
146
|
+
* });
|
|
147
|
+
*
|
|
148
|
+
* const { container, error } = await conversation.sendMessage('show me sales by region');
|
|
149
|
+
*
|
|
150
|
+
* // append the container to the DOM
|
|
151
|
+
* document.body.appendChild(container); // or to any other element
|
|
152
|
+
* ```
|
|
153
|
+
* @group Embed components
|
|
154
|
+
*/
|
|
155
|
+
export class BodylessConversation extends SpotterAgentEmbed {
|
|
156
|
+
constructor(viewConfig: BodylessConversationViewConfig) {
|
|
157
|
+
super(viewConfig);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
SpotterEmbed,
|
|
3
|
+
SpotterEmbedViewConfig,
|
|
4
4
|
} from './conversation';
|
|
5
5
|
import * as authInstance from '../auth';
|
|
6
6
|
import { init } from '../index';
|
|
@@ -28,14 +28,14 @@ beforeAll(() => {
|
|
|
28
28
|
|
|
29
29
|
describe('ConversationEmbed', () => {
|
|
30
30
|
it('should render the conversation embed', async () => {
|
|
31
|
-
const viewConfig:
|
|
31
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
32
32
|
worksheetId: 'worksheetId',
|
|
33
33
|
searchOptions: {
|
|
34
34
|
searchQuery: 'searchQuery',
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
const conversationEmbed = new
|
|
38
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
39
39
|
await conversationEmbed.render();
|
|
40
40
|
expectUrlMatchesWithParams(
|
|
41
41
|
getIFrameSrc(),
|
|
@@ -44,7 +44,7 @@ describe('ConversationEmbed', () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
it('should render the conversation embed with worksheets disabled', async () => {
|
|
47
|
-
const viewConfig:
|
|
47
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
48
48
|
worksheetId: 'worksheetId',
|
|
49
49
|
searchOptions: {
|
|
50
50
|
searchQuery: 'searchQuery',
|
|
@@ -52,7 +52,7 @@ describe('ConversationEmbed', () => {
|
|
|
52
52
|
disableSourceSelection: true,
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
const conversationEmbed = new
|
|
55
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
56
56
|
await conversationEmbed.render();
|
|
57
57
|
expectUrlMatchesWithParams(
|
|
58
58
|
getIFrameSrc(),
|
|
@@ -61,7 +61,7 @@ describe('ConversationEmbed', () => {
|
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
it('should render the conversation embed with spotter limitations text if flag is set', async () => {
|
|
64
|
-
const viewConfig:
|
|
64
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
65
65
|
worksheetId: 'worksheetId',
|
|
66
66
|
searchOptions: {
|
|
67
67
|
searchQuery: 'searchQuery',
|
|
@@ -69,7 +69,7 @@ describe('ConversationEmbed', () => {
|
|
|
69
69
|
showSpotterLimitations: true,
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
const conversationEmbed = new
|
|
72
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
73
73
|
await conversationEmbed.render();
|
|
74
74
|
expectUrlMatchesWithParams(
|
|
75
75
|
getIFrameSrc(),
|
|
@@ -78,7 +78,7 @@ describe('ConversationEmbed', () => {
|
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
it('should render the conversation embed with sample questions hidden', async () => {
|
|
81
|
-
const viewConfig:
|
|
81
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
82
82
|
worksheetId: 'worksheetId',
|
|
83
83
|
searchOptions: {
|
|
84
84
|
searchQuery: 'searchQuery',
|
|
@@ -86,7 +86,7 @@ describe('ConversationEmbed', () => {
|
|
|
86
86
|
hideSampleQuestions: true,
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
const conversationEmbed = new
|
|
89
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
90
90
|
await conversationEmbed.render();
|
|
91
91
|
expectUrlMatchesWithParams(
|
|
92
92
|
getIFrameSrc(),
|
|
@@ -95,7 +95,7 @@ describe('ConversationEmbed', () => {
|
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
it('should render the conversation embed with worksheets hidden', async () => {
|
|
98
|
-
const viewConfig:
|
|
98
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
99
99
|
worksheetId: 'worksheetId',
|
|
100
100
|
searchOptions: {
|
|
101
101
|
searchQuery: 'searchQuery',
|
|
@@ -103,7 +103,7 @@ describe('ConversationEmbed', () => {
|
|
|
103
103
|
hideSourceSelection: true,
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
-
const conversationEmbed = new
|
|
106
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
107
107
|
await conversationEmbed.render();
|
|
108
108
|
expectUrlMatchesWithParams(
|
|
109
109
|
getIFrameSrc(),
|
|
@@ -112,13 +112,13 @@ describe('ConversationEmbed', () => {
|
|
|
112
112
|
});
|
|
113
113
|
|
|
114
114
|
it('should handle error when worksheetId is not provided', async () => {
|
|
115
|
-
const viewConfig:
|
|
115
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
116
116
|
worksheetId: '',
|
|
117
117
|
searchOptions: {
|
|
118
118
|
searchQuery: 'searchQuery',
|
|
119
119
|
},
|
|
120
120
|
};
|
|
121
|
-
const conversationEmbed = new
|
|
121
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
122
122
|
(conversationEmbed as any).handleError = jest.fn();
|
|
123
123
|
await conversationEmbed.render();
|
|
124
124
|
expect((conversationEmbed as any).handleError).toHaveBeenCalledWith(
|
|
@@ -127,7 +127,7 @@ describe('ConversationEmbed', () => {
|
|
|
127
127
|
});
|
|
128
128
|
|
|
129
129
|
it('should render the conversation embed if data panel v2 flag is true', async () => {
|
|
130
|
-
const viewConfig:
|
|
130
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
131
131
|
worksheetId: 'worksheetId',
|
|
132
132
|
searchOptions: {
|
|
133
133
|
searchQuery: 'searchQuery',
|
|
@@ -135,7 +135,7 @@ describe('ConversationEmbed', () => {
|
|
|
135
135
|
dataPanelV2: true,
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
-
const conversationEmbed = new
|
|
138
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
139
139
|
await conversationEmbed.render();
|
|
140
140
|
expectUrlMatchesWithParams(
|
|
141
141
|
getIFrameSrc(),
|
|
@@ -15,10 +15,10 @@ export interface SearchOptions {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* The configuration for the embedded
|
|
18
|
+
* The configuration for the embedded spotterEmbed options.
|
|
19
19
|
* @group Embed components
|
|
20
20
|
*/
|
|
21
|
-
export interface
|
|
21
|
+
export interface SpotterEmbedViewConfig extends ViewConfig {
|
|
22
22
|
/**
|
|
23
23
|
* The ID of the worksheet to use for the conversation.
|
|
24
24
|
*/
|
|
@@ -32,7 +32,7 @@ export interface ConversationViewConfig extends ViewConfig {
|
|
|
32
32
|
* but still display the selected data source.
|
|
33
33
|
* @example
|
|
34
34
|
* ```js
|
|
35
|
-
* const embed = new
|
|
35
|
+
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
36
36
|
* ... // other options
|
|
37
37
|
* disableSourceSelection : true,
|
|
38
38
|
* })
|
|
@@ -44,7 +44,7 @@ export interface ConversationViewConfig extends ViewConfig {
|
|
|
44
44
|
* hideSourceSelection : Hide data source selection
|
|
45
45
|
* @example
|
|
46
46
|
* ```js
|
|
47
|
-
* const embed = new
|
|
47
|
+
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
48
48
|
* ... // other options
|
|
49
49
|
* hideSourceSelection : true,
|
|
50
50
|
* })
|
|
@@ -71,7 +71,7 @@ export interface ConversationViewConfig extends ViewConfig {
|
|
|
71
71
|
* default is false.
|
|
72
72
|
* @example
|
|
73
73
|
* ```js
|
|
74
|
-
* const embed = new
|
|
74
|
+
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
75
75
|
* ... // other options
|
|
76
76
|
* showSpotterLimitations : true,
|
|
77
77
|
* })
|
|
@@ -84,7 +84,7 @@ export interface ConversationViewConfig extends ViewConfig {
|
|
|
84
84
|
* the initial screen of the conversation.
|
|
85
85
|
* @example
|
|
86
86
|
* ```js
|
|
87
|
-
* const embed = new
|
|
87
|
+
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
88
88
|
* ... // other options
|
|
89
89
|
* hideSampleQuestions : true,
|
|
90
90
|
* })
|
|
@@ -94,12 +94,21 @@ export interface ConversationViewConfig extends ViewConfig {
|
|
|
94
94
|
hideSampleQuestions?: boolean;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* The configuration for the embedded spotterEmbed options.
|
|
99
|
+
* @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
|
|
100
|
+
* Use {@link SpotterEmbedViewConfig} instead
|
|
101
|
+
* @group Embed components
|
|
102
|
+
*/
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
104
|
+
export interface ConversationViewConfig extends SpotterEmbedViewConfig {}
|
|
105
|
+
|
|
97
106
|
/**
|
|
98
107
|
* Embed ThoughtSpot AI Conversation.
|
|
99
108
|
* @group Embed components
|
|
100
109
|
* @example
|
|
101
110
|
* ```js
|
|
102
|
-
* const conversation = new
|
|
111
|
+
* const conversation = new SpotterEmbed('#tsEmbed', {
|
|
103
112
|
* worksheetId: 'worksheetId',
|
|
104
113
|
* searchOptions: {
|
|
105
114
|
* searchQuery: 'searchQuery',
|
|
@@ -107,10 +116,10 @@ export interface ConversationViewConfig extends ViewConfig {
|
|
|
107
116
|
* });
|
|
108
117
|
* conversation.render();
|
|
109
118
|
* ```
|
|
110
|
-
* @version SDK: 1.
|
|
119
|
+
* @version SDK: 1.37.0 | ThoughtSpot: 10.9.0.cl
|
|
111
120
|
*/
|
|
112
|
-
export class
|
|
113
|
-
constructor(container: HTMLElement, protected viewConfig:
|
|
121
|
+
export class SpotterEmbed extends TsEmbed {
|
|
122
|
+
constructor(container: HTMLElement, protected viewConfig: SpotterEmbedViewConfig) {
|
|
114
123
|
viewConfig.embedComponentType = 'conversation';
|
|
115
124
|
super(container, viewConfig);
|
|
116
125
|
}
|
|
@@ -163,7 +172,7 @@ export class ConversationEmbed extends TsEmbed {
|
|
|
163
172
|
return `${this.getEmbedBasePath(query)}/embed/${path}${tsPostHashParams}`;
|
|
164
173
|
}
|
|
165
174
|
|
|
166
|
-
public async render(): Promise<
|
|
175
|
+
public async render(): Promise<SpotterEmbed> {
|
|
167
176
|
await super.render();
|
|
168
177
|
|
|
169
178
|
const src = this.getIframeSrc();
|
|
@@ -171,3 +180,27 @@ export class ConversationEmbed extends TsEmbed {
|
|
|
171
180
|
return this;
|
|
172
181
|
}
|
|
173
182
|
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Embed ThoughtSpot AI Conversation.
|
|
186
|
+
* @deprecated from SDK: 1.38.0 | ThoughtSpot: 10.10.0.cl
|
|
187
|
+
* Use {@link SpotterEmbed} instead
|
|
188
|
+
* @group Embed components
|
|
189
|
+
* @example
|
|
190
|
+
* ```js
|
|
191
|
+
* const conversation = new SpotterEmbed('#tsEmbed', {
|
|
192
|
+
* worksheetId: 'worksheetId',
|
|
193
|
+
* searchOptions: {
|
|
194
|
+
* searchQuery: 'searchQuery',
|
|
195
|
+
* },
|
|
196
|
+
* });
|
|
197
|
+
* conversation.render();
|
|
198
|
+
* ```
|
|
199
|
+
* @version SDK: 1.37.0 | ThoughtSpot: 10.9.0.cl
|
|
200
|
+
*/
|
|
201
|
+
export class ConversationEmbed extends SpotterEmbed {
|
|
202
|
+
constructor(container: HTMLElement, protected viewConfig: ConversationViewConfig) {
|
|
203
|
+
viewConfig.embedComponentType = 'conversation';
|
|
204
|
+
super(container, viewConfig);
|
|
205
|
+
}
|
|
206
|
+
}
|
package/src/embed/liveboard.ts
CHANGED
|
@@ -24,13 +24,8 @@ import { getAuthPromise } from './base';
|
|
|
24
24
|
import { TsEmbed, V1Embed } from './ts-embed';
|
|
25
25
|
import { addPreviewStylesIfNotPresent } from '../utils/global-styles';
|
|
26
26
|
import { TriggerPayload, TriggerResponse } from './hostEventClient/contracts';
|
|
27
|
+
import { logger } from '../utils/logger';
|
|
27
28
|
|
|
28
|
-
const liveboardHeightWhitelistedRoutes = [
|
|
29
|
-
'/embed/viz/',
|
|
30
|
-
'/embed/insights/viz/',
|
|
31
|
-
'/tsl-editor/PINBOARD_ANSWER_BOOK/',
|
|
32
|
-
'/import-tsl/PINBOARD_ANSWER_BOOK/',
|
|
33
|
-
];
|
|
34
29
|
|
|
35
30
|
/**
|
|
36
31
|
* The configuration for the embedded Liveboard or visualization page view.
|
|
@@ -429,11 +424,16 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
429
424
|
|
|
430
425
|
private defaultHeight = 500;
|
|
431
426
|
|
|
432
|
-
|
|
427
|
+
|
|
433
428
|
constructor(domSelector: DOMSelector, viewConfig: LiveboardViewConfig) {
|
|
434
429
|
viewConfig.embedComponentType = 'LiveboardEmbed';
|
|
435
430
|
super(domSelector, viewConfig);
|
|
436
431
|
if (this.viewConfig.fullHeight === true) {
|
|
432
|
+
if (this.viewConfig.vizId) {
|
|
433
|
+
logger.warn('Full height is currently only supported for Liveboard embeds.' +
|
|
434
|
+
'Using full height with vizId might lead to unexpected behavior.');
|
|
435
|
+
}
|
|
436
|
+
|
|
437
437
|
this.on(EmbedEvent.RouteChange, this.setIframeHeightForNonEmbedLiveboard);
|
|
438
438
|
this.on(EmbedEvent.EmbedHeight, this.updateIFrameHeight);
|
|
439
439
|
this.on(EmbedEvent.EmbedIframeCenter, this.embedIframeCenter);
|
|
@@ -592,11 +592,26 @@ export class LiveboardEmbed extends V1Embed {
|
|
|
592
592
|
};
|
|
593
593
|
|
|
594
594
|
private setIframeHeightForNonEmbedLiveboard = (data: MessagePayload) => {
|
|
595
|
-
const
|
|
596
|
-
|
|
595
|
+
const { height: frameHeight } = this.viewConfig.frameParams || {};
|
|
596
|
+
|
|
597
|
+
const liveboardRelatedRoutes = [
|
|
598
|
+
'/pinboard/',
|
|
599
|
+
'/insights/pinboard/',
|
|
600
|
+
'/schedules/',
|
|
601
|
+
'/embed/viz/',
|
|
602
|
+
'/embed/insights/viz/',
|
|
603
|
+
'/liveboard/',
|
|
604
|
+
'/insights/liveboard/',
|
|
605
|
+
'/tsl-editor/PINBOARD_ANSWER_BOOK/',
|
|
606
|
+
'/import-tsl/PINBOARD_ANSWER_BOOK/',
|
|
607
|
+
];
|
|
608
|
+
|
|
609
|
+
if (liveboardRelatedRoutes.some((path) => data.data.currentPath.startsWith(path))) {
|
|
610
|
+
// Ignore the height reset of the frame, if the navigation is
|
|
611
|
+
// only within the liveboard page.
|
|
597
612
|
return;
|
|
598
613
|
}
|
|
599
|
-
this.setIFrameHeight(this.defaultHeight);
|
|
614
|
+
this.setIFrameHeight(frameHeight || this.defaultHeight);
|
|
600
615
|
};
|
|
601
616
|
|
|
602
617
|
private setActiveTab(data: { tabId: string }) {
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
* @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
|
|
10
10
|
*/
|
|
11
11
|
import {
|
|
12
|
-
AppEmbed,
|
|
12
|
+
AppEmbed,
|
|
13
|
+
Page,
|
|
14
|
+
AppViewConfig,
|
|
15
|
+
HomePageSearchBarMode,
|
|
16
|
+
PrimaryNavbarVersion,
|
|
17
|
+
HomePage,
|
|
13
18
|
} from './embed/app';
|
|
14
19
|
import {
|
|
15
20
|
init,
|
|
@@ -23,8 +28,8 @@ import {
|
|
|
23
28
|
import { PinboardEmbed, LiveboardViewConfig, LiveboardEmbed } from './embed/liveboard';
|
|
24
29
|
import { SearchEmbed, SearchViewConfig } from './embed/search';
|
|
25
30
|
import { SearchBarEmbed, SearchBarViewConfig } from './embed/search-bar';
|
|
26
|
-
import { BodylessConversation, BodylessConversationViewConfig
|
|
27
|
-
import { ConversationEmbed, ConversationViewConfig } from './embed/conversation';
|
|
31
|
+
import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig, BodylessConversation, BodylessConversationViewConfig} from './embed/bodyless-conversation';
|
|
32
|
+
import { SpotterEmbed, SpotterEmbedViewConfig, ConversationEmbed, ConversationViewConfig } from './embed/conversation';
|
|
28
33
|
import {
|
|
29
34
|
AuthFailureType, AuthStatus, AuthEvent, AuthEventEmitter,
|
|
30
35
|
} from './auth';
|
|
@@ -85,10 +90,14 @@ export {
|
|
|
85
90
|
LiveboardEmbed,
|
|
86
91
|
SageEmbed,
|
|
87
92
|
AppEmbed,
|
|
88
|
-
|
|
93
|
+
SpotterAgentEmbed,
|
|
94
|
+
SpotterAgentEmbedViewConfig,
|
|
89
95
|
BodylessConversationViewConfig,
|
|
90
|
-
|
|
96
|
+
BodylessConversation,
|
|
97
|
+
SpotterEmbed,
|
|
98
|
+
SpotterEmbedViewConfig,
|
|
91
99
|
ConversationViewConfig,
|
|
100
|
+
ConversationEmbed,
|
|
92
101
|
AuthFailureType,
|
|
93
102
|
AuthStatus,
|
|
94
103
|
AuthEvent,
|
|
@@ -129,6 +138,8 @@ export {
|
|
|
129
138
|
uploadMixpanelEvent,
|
|
130
139
|
MIXPANEL_EVENT,
|
|
131
140
|
HomePageSearchBarMode,
|
|
141
|
+
PrimaryNavbarVersion,
|
|
142
|
+
HomePage,
|
|
132
143
|
VizPoint,
|
|
133
144
|
CustomActionPayload,
|
|
134
145
|
UIPassthroughEvent,
|
package/src/react/index.spec.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from '../test/test-utils';
|
|
17
17
|
import {
|
|
18
18
|
SearchEmbed, AppEmbed, LiveboardEmbed, useEmbedRef, SearchBarEmbed, PreRenderedLiveboardEmbed,
|
|
19
|
+
SpotterAgentEmbed
|
|
19
20
|
} from './index';
|
|
20
21
|
import * as allExports from './index';
|
|
21
22
|
import {
|
|
@@ -235,6 +236,161 @@ describe('React Components', () => {
|
|
|
235
236
|
});
|
|
236
237
|
});
|
|
237
238
|
|
|
239
|
+
describe('SpotterAgentEmbed', () => {
|
|
240
|
+
it('Should work as a React component integrating BodylessConversation', async () => {
|
|
241
|
+
const mockDiv = document.createElement('div');
|
|
242
|
+
|
|
243
|
+
let conversationService: any = null;
|
|
244
|
+
|
|
245
|
+
render(
|
|
246
|
+
<SpotterAgentEmbed
|
|
247
|
+
ref={(instance: any) => {
|
|
248
|
+
conversationService = instance;
|
|
249
|
+
|
|
250
|
+
if (instance) {
|
|
251
|
+
instance.sendMessage = jest.fn().mockResolvedValue({
|
|
252
|
+
container: mockDiv
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}}
|
|
256
|
+
worksheetId="test-worksheet-id"
|
|
257
|
+
/>
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
expect(conversationService).not.toBeNull();
|
|
261
|
+
|
|
262
|
+
if (conversationService) {
|
|
263
|
+
expect(typeof conversationService.sendMessage).toBe('function');
|
|
264
|
+
|
|
265
|
+
const response = await conversationService.sendMessage("What are my sales this month?");
|
|
266
|
+
expect(response.container).toBe(mockDiv);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('Should work as a React component with ref support', () => {
|
|
271
|
+
const mockSendMessage = jest.fn().mockResolvedValue({
|
|
272
|
+
container: document.createElement('div'),
|
|
273
|
+
viz: {}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const TestComponent = () => {
|
|
277
|
+
const conversationRef = React.useRef(null);
|
|
278
|
+
|
|
279
|
+
const handleClick = () => {
|
|
280
|
+
if (conversationRef.current) {
|
|
281
|
+
conversationRef.current.sendMessage = mockSendMessage;
|
|
282
|
+
|
|
283
|
+
conversationRef.current.sendMessage("Test message");
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
<>
|
|
289
|
+
<SpotterAgentEmbed
|
|
290
|
+
ref={conversationRef}
|
|
291
|
+
worksheetId="test-worksheet-id"
|
|
292
|
+
/>
|
|
293
|
+
<button data-testid="test-button" onClick={handleClick}>
|
|
294
|
+
Send Message
|
|
295
|
+
</button>
|
|
296
|
+
</>
|
|
297
|
+
);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const { getByTestId } = render(<TestComponent />);
|
|
301
|
+
|
|
302
|
+
fireEvent.click(getByTestId('test-button'));
|
|
303
|
+
|
|
304
|
+
expect(mockSendMessage).toHaveBeenCalledWith("Test message");
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('Should work with the useEmbedRef hook', () => {
|
|
308
|
+
const mockSendMessage = jest.fn().mockResolvedValue({
|
|
309
|
+
container: document.createElement('div'),
|
|
310
|
+
viz: {}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const TestComponent = () => {
|
|
314
|
+
const embedRef = useEmbedRef<typeof SpotterAgentEmbed>();
|
|
315
|
+
|
|
316
|
+
const handleClick = () => {
|
|
317
|
+
if (embedRef.current) {
|
|
318
|
+
const service = embedRef.current as unknown as {
|
|
319
|
+
sendMessage: typeof mockSendMessage
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
service.sendMessage = mockSendMessage;
|
|
323
|
+
|
|
324
|
+
service.sendMessage("Test with useEmbedRef");
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
return (
|
|
329
|
+
<>
|
|
330
|
+
<SpotterAgentEmbed
|
|
331
|
+
ref={embedRef}
|
|
332
|
+
worksheetId="test-worksheet-id"
|
|
333
|
+
/>
|
|
334
|
+
<button data-testid="use-embed-ref-button" onClick={handleClick}>
|
|
335
|
+
Send with useEmbedRef
|
|
336
|
+
</button>
|
|
337
|
+
</>
|
|
338
|
+
);
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const { getByTestId } = render(<TestComponent />);
|
|
342
|
+
|
|
343
|
+
fireEvent.click(getByTestId('use-embed-ref-button'));
|
|
344
|
+
|
|
345
|
+
expect(mockSendMessage).toHaveBeenCalledWith("Test with useEmbedRef");
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('Should work with the className prop', async () => {
|
|
349
|
+
let capturedInstance: any = null;
|
|
350
|
+
|
|
351
|
+
const TestComponent = () => {
|
|
352
|
+
const embedRef = useEmbedRef<typeof SpotterAgentEmbed>();
|
|
353
|
+
|
|
354
|
+
React.useEffect(() => {
|
|
355
|
+
capturedInstance = embedRef.current;
|
|
356
|
+
|
|
357
|
+
if (capturedInstance) {
|
|
358
|
+
const mockConversationService = {
|
|
359
|
+
sendMessage: jest.fn().mockResolvedValue({
|
|
360
|
+
data: {
|
|
361
|
+
sessionId: 'test-session',
|
|
362
|
+
genNo: 1,
|
|
363
|
+
stateKey: {
|
|
364
|
+
transactionId: 'test-transaction',
|
|
365
|
+
generationNumber: 1
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
})
|
|
369
|
+
};
|
|
370
|
+
(capturedInstance as any).conversationService = mockConversationService;
|
|
371
|
+
}
|
|
372
|
+
}, []);
|
|
373
|
+
|
|
374
|
+
return (
|
|
375
|
+
<SpotterAgentEmbed
|
|
376
|
+
ref={embedRef}
|
|
377
|
+
worksheetId="test-worksheet-id"
|
|
378
|
+
className="embedClass"
|
|
379
|
+
/>
|
|
380
|
+
);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
render(<TestComponent />);
|
|
384
|
+
|
|
385
|
+
expect(capturedInstance).not.toBeNull();
|
|
386
|
+
|
|
387
|
+
if (capturedInstance) {
|
|
388
|
+
const result = await capturedInstance.sendMessage("test");
|
|
389
|
+
expect(result.container.className).toBe("embedClass");
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
|
|
238
394
|
describe('PreRenderedLiveboardEmbed', () => {
|
|
239
395
|
it('should preRender the liveboard ', async () => {
|
|
240
396
|
const preRenderId = 'tsEmbed-pre-render-wrapper-test';
|
|
@@ -285,7 +441,7 @@ describe('allExports', () => {
|
|
|
285
441
|
it('should not have undefined exports', () => {
|
|
286
442
|
Object.keys(allExports).forEach(
|
|
287
443
|
(exportKey) => expect(
|
|
288
|
-
Boolean(allExports[exportKey]),
|
|
444
|
+
Boolean(allExports[exportKey as keyof typeof allExports]),
|
|
289
445
|
)
|
|
290
446
|
.toBe(true),
|
|
291
447
|
);
|