@thoughtspot/visual-embed-sdk 1.51.0 → 1.51.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.d.ts +1 -0
- package/cjs/src/config.d.ts.map +1 -1
- package/cjs/src/config.js +2 -1
- package/cjs/src/config.js.map +1 -1
- package/cjs/src/css-variables.d.ts +27 -0
- package/cjs/src/css-variables.d.ts.map +1 -1
- package/cjs/src/embed/app.d.ts +43 -12
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +29 -3
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +253 -1
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/base.d.ts +1 -1
- package/cjs/src/embed/base.js +1 -1
- package/cjs/src/embed/conversation.d.ts +171 -1
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +4 -2
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +125 -0
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/events.spec.js +3 -0
- package/cjs/src/embed/events.spec.js.map +1 -1
- package/cjs/src/embed/host-events.spec.js +36 -0
- package/cjs/src/embed/host-events.spec.js.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.d.ts +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/host-event-client.spec.js +18 -0
- package/cjs/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts +40 -13
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +25 -4
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +349 -2
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/search.spec.js +28 -0
- package/cjs/src/embed/search.spec.js.map +1 -1
- package/cjs/src/embed/spotter-utils.d.ts +8 -1
- package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
- package/cjs/src/embed/spotter-utils.js +15 -1
- package/cjs/src/embed/spotter-utils.js.map +1 -1
- package/cjs/src/embed/spotter-utils.spec.js +68 -0
- package/cjs/src/embed/spotter-utils.spec.js.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.d.ts +9 -10
- package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +97 -9
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +76 -35
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +537 -3
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +3 -3
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +3 -2
- 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 +2 -1
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/all-types-export.parity.spec.d.ts +2 -0
- package/cjs/src/react/all-types-export.parity.spec.d.ts.map +1 -0
- package/cjs/src/react/all-types-export.parity.spec.js +194 -0
- package/cjs/src/react/all-types-export.parity.spec.js.map +1 -0
- package/cjs/src/react/index.d.ts +66 -32
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +5 -3
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +101 -0
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +330 -18
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +182 -12
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils.d.ts +5 -0
- package/cjs/src/utils.d.ts.map +1 -1
- package/cjs/src/utils.js +19 -1
- package/cjs/src/utils.js.map +1 -1
- package/cjs/src/utils.spec.js +37 -0
- package/cjs/src/utils.spec.js.map +1 -1
- package/dist/{index-aBzH5ZwF.js → index-D8_Zs-Nr.js} +1 -1
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/css-variables.d.ts +27 -0
- package/dist/src/css-variables.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +43 -12
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts +1 -1
- package/dist/src/embed/conversation.d.ts +171 -1
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/host-event-client.d.ts +1 -1
- package/dist/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts +40 -13
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/spotter-utils.d.ts +8 -1
- package/dist/src/embed/spotter-utils.d.ts.map +1 -1
- package/dist/src/embed/spotter-viz-utils.d.ts +9 -10
- package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +97 -9
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -3
- 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/all-types-export.parity.spec.d.ts +2 -0
- package/dist/src/react/all-types-export.parity.spec.d.ts.map +1 -0
- package/dist/src/react/index.d.ts +66 -32
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +330 -18
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils.d.ts +5 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +354 -64
- package/dist/tsembed-react.js +353 -63
- package/dist/tsembed.es.js +414 -126
- package/dist/tsembed.js +416 -128
- package/dist/visual-embed-sdk-react-full.d.ts +777 -90
- package/dist/visual-embed-sdk-react.d.ts +773 -89
- package/dist/visual-embed-sdk.d.ts +713 -60
- package/lib/package.json +1 -1
- package/lib/src/config.d.ts +1 -0
- package/lib/src/config.d.ts.map +1 -1
- package/lib/src/config.js +1 -0
- package/lib/src/config.js.map +1 -1
- package/lib/src/css-variables.d.ts +27 -0
- package/lib/src/css-variables.d.ts.map +1 -1
- package/lib/src/embed/app.d.ts +43 -12
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +30 -4
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +253 -1
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts +1 -1
- package/lib/src/embed/base.js +1 -1
- package/lib/src/embed/conversation.d.ts +171 -1
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +5 -3
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +125 -0
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/events.spec.js +3 -0
- package/lib/src/embed/events.spec.js.map +1 -1
- package/lib/src/embed/host-events.spec.js +36 -0
- package/lib/src/embed/host-events.spec.js.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.d.ts +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/host-event-client.spec.js +18 -0
- package/lib/src/embed/hostEventClient/host-event-client.spec.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts +40 -13
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +25 -4
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +349 -2
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/search.spec.js +28 -0
- package/lib/src/embed/search.spec.js.map +1 -1
- package/lib/src/embed/spotter-utils.d.ts +8 -1
- package/lib/src/embed/spotter-utils.d.ts.map +1 -1
- package/lib/src/embed/spotter-utils.js +13 -0
- package/lib/src/embed/spotter-utils.js.map +1 -1
- package/lib/src/embed/spotter-utils.spec.js +69 -1
- package/lib/src/embed/spotter-utils.spec.js.map +1 -1
- package/lib/src/embed/spotter-viz-utils.d.ts +9 -10
- package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/lib/src/embed/spotter-viz-utils.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +97 -9
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +77 -36
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +537 -3
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +3 -3
- 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/all-types-export.parity.spec.d.ts +2 -0
- package/lib/src/react/all-types-export.parity.spec.d.ts.map +1 -0
- package/lib/src/react/all-types-export.parity.spec.js +191 -0
- package/lib/src/react/all-types-export.parity.spec.js.map +1 -0
- package/lib/src/react/index.d.ts +66 -32
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +5 -3
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +102 -1
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +330 -18
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +182 -12
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils.d.ts +5 -0
- package/lib/src/utils.d.ts.map +1 -1
- package/lib/src/utils.js +17 -0
- package/lib/src/utils.js.map +1 -1
- package/lib/src/utils.spec.js +38 -1
- package/lib/src/utils.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +713 -60
- package/package.json +1 -1
- package/src/config.ts +1 -0
- package/src/css-variables.ts +32 -0
- package/src/embed/app.spec.ts +335 -1
- package/src/embed/app.ts +71 -13
- package/src/embed/base.ts +1 -1
- package/src/embed/conversation.spec.ts +136 -0
- package/src/embed/conversation.ts +181 -3
- package/src/embed/events.spec.ts +4 -0
- package/src/embed/host-events.spec.ts +48 -0
- package/src/embed/hostEventClient/host-event-client.spec.ts +34 -0
- package/src/embed/hostEventClient/host-event-client.ts +2 -2
- package/src/embed/liveboard.spec.ts +457 -2
- package/src/embed/liveboard.ts +74 -15
- package/src/embed/search.spec.ts +31 -0
- package/src/embed/spotter-utils.spec.ts +72 -0
- package/src/embed/spotter-utils.ts +21 -1
- package/src/embed/spotter-viz-utils.ts +9 -10
- package/src/embed/ts-embed.spec.ts +699 -3
- package/src/embed/ts-embed.ts +91 -41
- package/src/index.ts +43 -2
- package/src/react/all-types-export.parity.spec.ts +208 -0
- package/src/react/all-types-export.ts +22 -0
- package/src/react/index.spec.tsx +158 -0
- package/src/react/index.tsx +70 -33
- package/src/types.ts +329 -16
- package/src/utils.spec.ts +49 -0
- package/src/utils.ts +16 -0
package/src/embed/base.ts
CHANGED
|
@@ -233,7 +233,7 @@ export const getIsInitCalled = (): boolean => !!getValueFromWindow(initFlagKey)?
|
|
|
233
233
|
/**
|
|
234
234
|
* Initializes the Visual Embed SDK globally and perform
|
|
235
235
|
* authentication if applicable. This function needs to be called before any ThoughtSpot
|
|
236
|
-
* component like Liveboard etc can be embedded. But need not wait for
|
|
236
|
+
* component like Liveboard etc can be embedded. But need not wait for AuthStatus.SUCCESS
|
|
237
237
|
* to actually embed. That is handled internally.
|
|
238
238
|
* @param embedConfig The configuration object containing ThoughtSpot host,
|
|
239
239
|
* authentication mechanism and so on.
|
|
@@ -537,6 +537,49 @@ describe('ConversationEmbed', () => {
|
|
|
537
537
|
);
|
|
538
538
|
});
|
|
539
539
|
|
|
540
|
+
it('should render the conversation embed with spotterAnalystConfig.analystId in the url', async () => {
|
|
541
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
542
|
+
worksheetId: 'worksheetId',
|
|
543
|
+
searchOptions: {
|
|
544
|
+
searchQuery: 'searchQuery',
|
|
545
|
+
},
|
|
546
|
+
spotterAnalystConfig: {
|
|
547
|
+
analystId: 'analyst-id-1234',
|
|
548
|
+
},
|
|
549
|
+
};
|
|
550
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
551
|
+
await conversationEmbed.render();
|
|
552
|
+
expectUrlMatchesWithParams(
|
|
553
|
+
getIFrameSrc(),
|
|
554
|
+
`http://${thoughtSpotHost}/v2/?${defaultParams}&isSpotterExperienceEnabled=true&analystId=analyst-id-1234#/embed/insights/conv-assist?worksheet=worksheetId&query=searchQuery`,
|
|
555
|
+
);
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
it('should not add analystId to the url when spotterAnalystConfig is not provided', async () => {
|
|
559
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
560
|
+
worksheetId: 'worksheetId',
|
|
561
|
+
searchOptions: {
|
|
562
|
+
searchQuery: 'searchQuery',
|
|
563
|
+
},
|
|
564
|
+
};
|
|
565
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
566
|
+
await conversationEmbed.render();
|
|
567
|
+
expect(getIFrameSrc()).not.toContain('analystId');
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
it('should not add analystId to the url when spotterAnalystConfig is empty', async () => {
|
|
571
|
+
const viewConfig: SpotterEmbedViewConfig = {
|
|
572
|
+
worksheetId: 'worksheetId',
|
|
573
|
+
searchOptions: {
|
|
574
|
+
searchQuery: 'searchQuery',
|
|
575
|
+
},
|
|
576
|
+
spotterAnalystConfig: {},
|
|
577
|
+
};
|
|
578
|
+
const conversationEmbed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
579
|
+
await conversationEmbed.render();
|
|
580
|
+
expect(getIFrameSrc()).not.toContain('analystId');
|
|
581
|
+
});
|
|
582
|
+
|
|
540
583
|
describe('spotter chat hiddenActions', () => {
|
|
541
584
|
it.each([
|
|
542
585
|
['SpotterChatConnectorResources', Action.SpotterChatConnectorResources],
|
|
@@ -548,6 +591,8 @@ describe('ConversationEmbed', () => {
|
|
|
548
591
|
['SpotterAnalystDelete', Action.SpotterAnalystDelete],
|
|
549
592
|
['SpotterAnalystMakeACopy', Action.SpotterAnalystMakeACopy],
|
|
550
593
|
['SpotterAnalystSidebar', Action.SpotterAnalystSidebar],
|
|
594
|
+
['SpotterAnalystList', Action.SpotterAnalystList],
|
|
595
|
+
['SpotterDefaultAnalyst', Action.SpotterDefaultAnalyst],
|
|
551
596
|
])('should render with hiddenActions for %s', async (_, action) => {
|
|
552
597
|
const viewConfig: SpotterEmbedViewConfig = {
|
|
553
598
|
worksheetId: 'worksheetId',
|
|
@@ -592,6 +637,8 @@ describe('ConversationEmbed', () => {
|
|
|
592
637
|
['SpotterAnalystDelete', Action.SpotterAnalystDelete],
|
|
593
638
|
['SpotterAnalystMakeACopy', Action.SpotterAnalystMakeACopy],
|
|
594
639
|
['SpotterAnalystSidebar', Action.SpotterAnalystSidebar],
|
|
640
|
+
['SpotterAnalystList', Action.SpotterAnalystList],
|
|
641
|
+
['SpotterDefaultAnalyst', Action.SpotterDefaultAnalyst],
|
|
595
642
|
])('should render with disabledActions for %s', async (_, action) => {
|
|
596
643
|
const disabledReason = 'testing disabled reason';
|
|
597
644
|
const viewConfig: SpotterEmbedViewConfig = {
|
|
@@ -922,3 +969,92 @@ describe('SpotterEmbed updatedSpotterExperience', () => {
|
|
|
922
969
|
);
|
|
923
970
|
});
|
|
924
971
|
});
|
|
972
|
+
|
|
973
|
+
describe('SpotterEmbed APP_INIT starterPrompts', () => {
|
|
974
|
+
const mockEmbedEventPayload = { type: EmbedEvent.APP_INIT, data: {} };
|
|
975
|
+
|
|
976
|
+
async function getAppInitResponse(viewConfig: SpotterEmbedViewConfig) {
|
|
977
|
+
const embed = new SpotterEmbed(getRootEl(), viewConfig);
|
|
978
|
+
embed.render();
|
|
979
|
+
const mockPort: any = { postMessage: jest.fn() };
|
|
980
|
+
await executeAfterWait(() => {
|
|
981
|
+
postMessageToParent(getIFrameEl().contentWindow, mockEmbedEventPayload, mockPort);
|
|
982
|
+
});
|
|
983
|
+
await executeAfterWait(() => {});
|
|
984
|
+
return mockPort.postMessage.mock.calls[0]?.[0];
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
it('should include starterPrompts in embedParams when configured', async () => {
|
|
988
|
+
const response = await getAppInitResponse({
|
|
989
|
+
worksheetId: 'ws1',
|
|
990
|
+
spotterChatConfig: {
|
|
991
|
+
starterPrompts: {
|
|
992
|
+
enable: true,
|
|
993
|
+
quick: {
|
|
994
|
+
label: 'Quick',
|
|
995
|
+
questions: [{ label: 'Q1', prompt: 'P1' }],
|
|
996
|
+
},
|
|
997
|
+
research: { label: 'Research' },
|
|
998
|
+
previewData: { label: 'Explore' },
|
|
999
|
+
},
|
|
1000
|
+
},
|
|
1001
|
+
});
|
|
1002
|
+
expect(response.data.embedParams.starterPrompts).toEqual({
|
|
1003
|
+
enable: true,
|
|
1004
|
+
quick: {
|
|
1005
|
+
label: 'Quick',
|
|
1006
|
+
questions: [{ label: 'Q1', prompt: 'P1' }],
|
|
1007
|
+
},
|
|
1008
|
+
research: { label: 'Research' },
|
|
1009
|
+
previewData: { label: 'Explore' },
|
|
1010
|
+
});
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
it('should forward the config as is, the app enforces the limits', async () => {
|
|
1014
|
+
const starterPrompts = {
|
|
1015
|
+
quick: {
|
|
1016
|
+
label: 'L'.repeat(50),
|
|
1017
|
+
questions: [
|
|
1018
|
+
{ label: 'Q'.repeat(100), prompt: 'P'.repeat(400) },
|
|
1019
|
+
{ label: 'Q2', prompt: 'P2' },
|
|
1020
|
+
{ label: 'Q3', prompt: 'P3' },
|
|
1021
|
+
{ label: 'Q4', prompt: 'P4' },
|
|
1022
|
+
{ label: 'Q5', prompt: 'P5' },
|
|
1023
|
+
],
|
|
1024
|
+
},
|
|
1025
|
+
previewData: { label: 'L'.repeat(50) },
|
|
1026
|
+
};
|
|
1027
|
+
const response = await getAppInitResponse({
|
|
1028
|
+
worksheetId: 'ws1',
|
|
1029
|
+
spotterChatConfig: { starterPrompts },
|
|
1030
|
+
});
|
|
1031
|
+
expect(response.data.embedParams.starterPrompts).toEqual(starterPrompts);
|
|
1032
|
+
});
|
|
1033
|
+
|
|
1034
|
+
it('should not include starterPrompts in embedParams when not configured', async () => {
|
|
1035
|
+
const response = await getAppInitResponse({ worksheetId: 'ws1' });
|
|
1036
|
+
expect(response.data.embedParams?.starterPrompts).toBeUndefined();
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
it('exposes per-pill starter-prompt actions with the strings the app gates on', () => {
|
|
1040
|
+
expect(Action.QuickSearchPill).toBe('quickSearchPill');
|
|
1041
|
+
expect(Action.DeepAnalysisPill).toBe('deepAnalysisPill');
|
|
1042
|
+
expect(Action.DataLiteracyPill).toBe('dataLiteracyPill');
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
it('forwards the enable feature flag when disabled', async () => {
|
|
1046
|
+
const response = await getAppInitResponse({
|
|
1047
|
+
worksheetId: 'ws1',
|
|
1048
|
+
spotterChatConfig: {
|
|
1049
|
+
starterPrompts: {
|
|
1050
|
+
enable: false,
|
|
1051
|
+
quick: { questions: [{ label: 'Q1', prompt: 'P1' }] },
|
|
1052
|
+
},
|
|
1053
|
+
},
|
|
1054
|
+
});
|
|
1055
|
+
expect(response.data.embedParams.starterPrompts).toEqual({
|
|
1056
|
+
enable: false,
|
|
1057
|
+
quick: { questions: [{ label: 'Q1', prompt: 'P1' }] },
|
|
1058
|
+
});
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Param, BaseViewConfig, RuntimeFilter, RuntimeParameter, ErrorDetailsTypes, EmbedErrorCodes, DefaultAppInitData, VisualizationOverrides, SpotterFileUploadFileTypes } from '../types';
|
|
2
2
|
import { TsEmbed } from './ts-embed';
|
|
3
|
-
import { buildSpotterSidebarAppInitData, buildSpotterShareConversationAppInitData } from './spotter-utils';
|
|
3
|
+
import { buildSpotterSidebarAppInitData, buildSpotterShareConversationAppInitData, buildStarterPromptsAppInitData } from './spotter-utils';
|
|
4
4
|
import { getQueryParamString, getFilterQuery, getRuntimeParameters, setParamIfDefined } from '../utils';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -227,6 +227,91 @@ export interface SpotterShareConversationConfig {
|
|
|
227
227
|
spotterSharedConversationExitLabel?: string;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
/**
|
|
231
|
+
* A single starter prompt question shown under a category pill.
|
|
232
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
233
|
+
* @group Embed components
|
|
234
|
+
*/
|
|
235
|
+
export interface StarterPromptQuestion {
|
|
236
|
+
/**
|
|
237
|
+
* Short label shown as a clickable suggestion. Falls back to `prompt` when
|
|
238
|
+
* omitted. ThoughtSpot truncates it beyond 80 characters.
|
|
239
|
+
*/
|
|
240
|
+
label?: string;
|
|
241
|
+
/**
|
|
242
|
+
* Prompt text sent to Spotter on click. ThoughtSpot truncates it beyond
|
|
243
|
+
* 300 characters.
|
|
244
|
+
*/
|
|
245
|
+
prompt: string;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Configuration for a starter prompt category with questions
|
|
250
|
+
* (`quick` and `research`).
|
|
251
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
252
|
+
* @group Embed components
|
|
253
|
+
*/
|
|
254
|
+
export interface StarterPromptCategory {
|
|
255
|
+
/**
|
|
256
|
+
* Overrides the default category pill label. ThoughtSpot truncates it
|
|
257
|
+
* beyond 30 characters.
|
|
258
|
+
*/
|
|
259
|
+
label?: string;
|
|
260
|
+
/**
|
|
261
|
+
* Replaces the backend-generated prompts. ThoughtSpot renders the first 4
|
|
262
|
+
* and drops any entry without a `prompt`.
|
|
263
|
+
*/
|
|
264
|
+
questions?: StarterPromptQuestion[];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Configuration for the Data Literacy starter prompt category.
|
|
269
|
+
* Only the label is customizable; the prompt text comes from the backend.
|
|
270
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
271
|
+
* @group Embed components
|
|
272
|
+
*/
|
|
273
|
+
export interface StarterPreviewDataCategory {
|
|
274
|
+
/**
|
|
275
|
+
* Overrides the default category pill label. ThoughtSpot truncates it
|
|
276
|
+
* beyond 30 characters.
|
|
277
|
+
*/
|
|
278
|
+
label?: string;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Content configuration for the Spotter starter prompts.
|
|
283
|
+
* Keys are fixed: `quick` (Basic Search), `research` (Deep Analysis),
|
|
284
|
+
* `previewData` (Data Literacy) and `liveboard` (Liveboard chat panel).
|
|
285
|
+
*
|
|
286
|
+
* Note: this controls the Spotter chat interface only. The starter prompts on
|
|
287
|
+
* the Liveboard SpotterViz surface are configured separately through
|
|
288
|
+
* {@link SpotterVizConfig.customStarterPrompts}.
|
|
289
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
290
|
+
* @group Embed components
|
|
291
|
+
*/
|
|
292
|
+
export interface StarterPromptsConfig {
|
|
293
|
+
/**
|
|
294
|
+
* Turns the starter prompts surface on. Must be set explicitly, an
|
|
295
|
+
* unset flag leaves the surface off.
|
|
296
|
+
*
|
|
297
|
+
* Either this or `enableStarterPrompts` turns the surface on, so `false`
|
|
298
|
+
* here does not switch it off while `enableStarterPrompts` is `true`.
|
|
299
|
+
* @default false
|
|
300
|
+
*/
|
|
301
|
+
enable?: boolean;
|
|
302
|
+
/** Basic Search category configuration. */
|
|
303
|
+
quick?: StarterPromptCategory;
|
|
304
|
+
/** Deep Analysis category configuration. */
|
|
305
|
+
research?: StarterPromptCategory;
|
|
306
|
+
/** Data Literacy category configuration. */
|
|
307
|
+
previewData?: StarterPreviewDataCategory;
|
|
308
|
+
/**
|
|
309
|
+
* Starter prompts for the Spotter chat panel on a Liveboard.
|
|
310
|
+
* @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
|
|
311
|
+
*/
|
|
312
|
+
liveboard?: StarterPromptQuestion[];
|
|
313
|
+
}
|
|
314
|
+
|
|
230
315
|
/**
|
|
231
316
|
* Configuration for customizing Spotter chat UI branding.
|
|
232
317
|
* @version SDK: 1.46.0 | ThoughtSpot: 26.4.0.cl
|
|
@@ -267,11 +352,84 @@ export interface SpotterChatViewConfig {
|
|
|
267
352
|
/**
|
|
268
353
|
* Enables starter prompts in the Spotter chat interface.
|
|
269
354
|
*
|
|
270
|
-
*
|
|
355
|
+
* Either this or `starterPrompts.enable` turns the surface on, so it stays
|
|
356
|
+
* on while this is `true` even if `starterPrompts.enable` is `false`.
|
|
357
|
+
*
|
|
358
|
+
* Supported embed types: `SpotterEmbed`, `LiveboardEmbed`, `AppEmbed`
|
|
271
359
|
* @version SDK: 1.51.0 | ThoughtSpot: 26.8.0.cl
|
|
272
360
|
* @default false
|
|
273
361
|
*/
|
|
274
362
|
enableStarterPrompts?: boolean;
|
|
363
|
+
/**
|
|
364
|
+
* Customizes the labels and questions of the Spotter starter prompts.
|
|
365
|
+
* Individual pills are hidden or shown with `hiddenActions` /
|
|
366
|
+
* `visibleActions` using `Action.QuickSearchPill`,
|
|
367
|
+
* `Action.DeepAnalysisPill` and `Action.DataLiteracyPill`.
|
|
368
|
+
*
|
|
369
|
+
* Supported embed types: `SpotterEmbed`, `LiveboardEmbed`, `AppEmbed`
|
|
370
|
+
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
371
|
+
* @example
|
|
372
|
+
* ```js
|
|
373
|
+
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
374
|
+
* worksheetId: 'worksheet-id',
|
|
375
|
+
* hiddenActions: [Action.DeepAnalysisPill],
|
|
376
|
+
* spotterChatConfig: {
|
|
377
|
+
* starterPrompts: {
|
|
378
|
+
* enable: true,
|
|
379
|
+
* quick: {
|
|
380
|
+
* label: 'Quick questions',
|
|
381
|
+
* questions: [
|
|
382
|
+
* { label: 'Top products', prompt: 'What are the top products by revenue?' },
|
|
383
|
+
* ],
|
|
384
|
+
* },
|
|
385
|
+
* previewData: { label: 'Explore your data' },
|
|
386
|
+
* },
|
|
387
|
+
* },
|
|
388
|
+
* })
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
starterPrompts?: StarterPromptsConfig;
|
|
392
|
+
/**
|
|
393
|
+
* Opens the Spotter chat panel when the Liveboard loads.
|
|
394
|
+
*
|
|
395
|
+
* Supported embed types: `LiveboardEmbed`, `AppEmbed`
|
|
396
|
+
* @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
|
|
397
|
+
* @default true
|
|
398
|
+
* @example
|
|
399
|
+
* ```js
|
|
400
|
+
* const embed = new LiveboardEmbed('#tsEmbed', {
|
|
401
|
+
* liveboardId: 'liveboard-id',
|
|
402
|
+
* spotterChatConfig: {
|
|
403
|
+
* openSpotterOnLiveboardByDefault: false,
|
|
404
|
+
* },
|
|
405
|
+
* })
|
|
406
|
+
* ```
|
|
407
|
+
*/
|
|
408
|
+
openSpotterOnLiveboardByDefault?: boolean;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Configuration for the Spotter Analyst experience.
|
|
413
|
+
* Can be used in SpotterEmbed.
|
|
414
|
+
* @group Embed components
|
|
415
|
+
* @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
|
|
416
|
+
* @example
|
|
417
|
+
* ```js
|
|
418
|
+
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
419
|
+
* ... //other embed view config
|
|
420
|
+
* spotterAnalystConfig: {
|
|
421
|
+
* analystId: 'analyst-id-1234',
|
|
422
|
+
* },
|
|
423
|
+
* })
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
export interface SpotterAnalystConfig {
|
|
427
|
+
/**
|
|
428
|
+
* Pins the embed to a single spotter analyst. Implies no default Spotter
|
|
429
|
+
* and no "Show all".
|
|
430
|
+
* @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
|
|
431
|
+
*/
|
|
432
|
+
analystId?: string;
|
|
275
433
|
}
|
|
276
434
|
|
|
277
435
|
/**
|
|
@@ -303,6 +461,22 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
|
|
|
303
461
|
* @version SDK: 1.52.0 | ThoughtSpot Cloud: 26.9.0.cl
|
|
304
462
|
*/
|
|
305
463
|
dataSources?: string[];
|
|
464
|
+
/**
|
|
465
|
+
* Configuration for the Spotter Analyst experience.
|
|
466
|
+
*
|
|
467
|
+
* Supported embed types: `SpotterEmbed`
|
|
468
|
+
* @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.10.0.cl
|
|
469
|
+
* @example
|
|
470
|
+
* ```js
|
|
471
|
+
* const embed = new SpotterEmbed('#tsEmbed', {
|
|
472
|
+
* ... //other embed view config
|
|
473
|
+
* spotterAnalystConfig: {
|
|
474
|
+
* analystId: 'analyst-id-1234',
|
|
475
|
+
* },
|
|
476
|
+
* })
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
spotterAnalystConfig?: SpotterAnalystConfig;
|
|
306
480
|
/**
|
|
307
481
|
* Ability to pass a starting search query to the conversation.
|
|
308
482
|
*/
|
|
@@ -626,6 +800,7 @@ export interface SpotterAppInitData extends DefaultAppInitData {
|
|
|
626
800
|
spotterSidebarConfig?: SpotterSidebarViewConfig;
|
|
627
801
|
spotterShareConversationConfig?: SpotterShareConversationConfig;
|
|
628
802
|
visualOverridesParams?: VisualizationOverrides | null;
|
|
803
|
+
starterPrompts?: StarterPromptsConfig;
|
|
629
804
|
};
|
|
630
805
|
}
|
|
631
806
|
|
|
@@ -674,7 +849,8 @@ export class SpotterEmbed extends TsEmbed {
|
|
|
674
849
|
this.viewConfig,
|
|
675
850
|
this.handleError.bind(this),
|
|
676
851
|
);
|
|
677
|
-
|
|
852
|
+
const shareInitData = buildSpotterShareConversationAppInitData(sidebarInitData, this.viewConfig);
|
|
853
|
+
return buildStarterPromptsAppInitData(shareInitData, this.viewConfig);
|
|
678
854
|
}
|
|
679
855
|
|
|
680
856
|
protected getEmbedParamsObject() {
|
|
@@ -695,6 +871,7 @@ export class SpotterEmbed extends TsEmbed {
|
|
|
695
871
|
defaultQueryMode,
|
|
696
872
|
enableStopAnswerGenerationEmbed,
|
|
697
873
|
spotterChatConfig,
|
|
874
|
+
spotterAnalystConfig,
|
|
698
875
|
} = this.viewConfig;
|
|
699
876
|
|
|
700
877
|
const queryParams = this.getBaseQueryParams();
|
|
@@ -710,6 +887,7 @@ export class SpotterEmbed extends TsEmbed {
|
|
|
710
887
|
setParamIfDefined(queryParams, Param.ShowSpotterRadiance, showSpotterRadiance, true);
|
|
711
888
|
setParamIfDefined(queryParams, Param.DefaultQueryMode, defaultQueryMode);
|
|
712
889
|
setParamIfDefined(queryParams, Param.EnableStopAnswerGenerationEmbed, enableStopAnswerGenerationEmbed, true);
|
|
890
|
+
setParamIfDefined(queryParams, Param.AnalystId, spotterAnalystConfig?.analystId);
|
|
713
891
|
|
|
714
892
|
// Handle spotterChatConfig params
|
|
715
893
|
if (spotterChatConfig) {
|
package/src/embed/events.spec.ts
CHANGED
|
@@ -474,6 +474,10 @@ describe('Action enum values', () => {
|
|
|
474
474
|
test('RemoveFromFavorites should resolve to its string value', () => {
|
|
475
475
|
expect(Action.RemoveFromFavorites).toBe('removeFromFavorites');
|
|
476
476
|
});
|
|
477
|
+
|
|
478
|
+
test('EditInputTable should resolve to its string value', () => {
|
|
479
|
+
expect(Action.EditInputTable).toBe('editInputTable');
|
|
480
|
+
});
|
|
477
481
|
});
|
|
478
482
|
|
|
479
483
|
describe('EmbedEvent basic routing', () => {
|
|
@@ -180,6 +180,54 @@ describe('HostEvent.OpenParameter', () => {
|
|
|
180
180
|
});
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
// 10c – OpenAddFilterModal
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
describe('HostEvent.OpenAddFilterModal', () => {
|
|
187
|
+
test('postMessage type is openAddFilterModal (camelCase, no payload)', async () => {
|
|
188
|
+
mockMessageChannel();
|
|
189
|
+
const { lb, iframe } = await renderLiveboard();
|
|
190
|
+
await executeAfterWait(() => {
|
|
191
|
+
lb.trigger(HostEvent.OpenAddFilterModal);
|
|
192
|
+
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
|
|
193
|
+
expect.objectContaining({ type: 'openAddFilterModal' }),
|
|
194
|
+
thoughtSpotHost,
|
|
195
|
+
expect.anything(),
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('returns null when !isRendered', async () => {
|
|
201
|
+
const lb = unrenderedLiveboard();
|
|
202
|
+
const result = await lb.trigger(HostEvent.OpenAddFilterModal);
|
|
203
|
+
expect(result).toBeNull();
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
// 10d – OpenAddParameterModal
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
describe('HostEvent.OpenAddParameterModal', () => {
|
|
211
|
+
test('postMessage type is openAddParameterModal (camelCase, no payload)', async () => {
|
|
212
|
+
mockMessageChannel();
|
|
213
|
+
const { lb, iframe } = await renderLiveboard();
|
|
214
|
+
await executeAfterWait(() => {
|
|
215
|
+
lb.trigger(HostEvent.OpenAddParameterModal);
|
|
216
|
+
expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(
|
|
217
|
+
expect.objectContaining({ type: 'openAddParameterModal' }),
|
|
218
|
+
thoughtSpotHost,
|
|
219
|
+
expect.anything(),
|
|
220
|
+
);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('returns null when !isRendered', async () => {
|
|
225
|
+
const lb = unrenderedLiveboard();
|
|
226
|
+
const result = await lb.trigger(HostEvent.OpenAddParameterModal);
|
|
227
|
+
expect(result).toBeNull();
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
183
231
|
// ---------------------------------------------------------------------------
|
|
184
232
|
// 11 – AddColumns
|
|
185
233
|
// ---------------------------------------------------------------------------
|
|
@@ -1154,4 +1154,38 @@ describe('HostEventClient', () => {
|
|
|
1154
1154
|
expect(result.answerId).toBeUndefined();
|
|
1155
1155
|
});
|
|
1156
1156
|
});
|
|
1157
|
+
|
|
1158
|
+
describe('trigger typing contracts (compile-time)', () => {
|
|
1159
|
+
// These assertions are enforced by ts-jest at compile time; the runtime
|
|
1160
|
+
// expect() is trivial. They lock the PayloadT default on
|
|
1161
|
+
// triggerHostEvent: no-payload calls must infer the contract response
|
|
1162
|
+
// instead of collapsing to `any`.
|
|
1163
|
+
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
1164
|
+
type Extends<A, B> = A extends B ? true : false;
|
|
1165
|
+
|
|
1166
|
+
it('infers typed response for no-payload contracted events and keeps any for uncontracted', () => {
|
|
1167
|
+
const { client } = createHostEventClient();
|
|
1168
|
+
|
|
1169
|
+
// Contracted event, called with no payload — the fixed case.
|
|
1170
|
+
const getTabs = () => client.triggerHostEvent(HostEvent.GetTabs);
|
|
1171
|
+
type TabsResponse = Awaited<ReturnType<typeof getTabs>>;
|
|
1172
|
+
const tabsIsTyped: IsAny<TabsResponse> = false;
|
|
1173
|
+
const tabsHasContractFields: Extends<
|
|
1174
|
+
TabsResponse,
|
|
1175
|
+
{ numberOfTabs: number; orderedTabIds: string[] }
|
|
1176
|
+
> = true;
|
|
1177
|
+
const probeUnknownField = (r: TabsResponse) =>
|
|
1178
|
+
// @ts-expect-error — field not on the GetTabs contract (was silent when `any`)
|
|
1179
|
+
r.tabCount;
|
|
1180
|
+
void probeUnknownField;
|
|
1181
|
+
|
|
1182
|
+
// Uncontracted event — must remain `any` with or without payload.
|
|
1183
|
+
const reload = () => client.triggerHostEvent(HostEvent.Reload);
|
|
1184
|
+
type ReloadResponse = Awaited<ReturnType<typeof reload>>;
|
|
1185
|
+
const reloadStaysAny: IsAny<ReloadResponse> = true;
|
|
1186
|
+
|
|
1187
|
+
expect([tabsIsTyped, tabsHasContractFields, reloadStaysAny])
|
|
1188
|
+
.toEqual([false, true, true]);
|
|
1189
|
+
});
|
|
1190
|
+
});
|
|
1157
1191
|
});
|
|
@@ -281,8 +281,8 @@ export class HostEventClient {
|
|
|
281
281
|
*/
|
|
282
282
|
public async triggerHostEvent<
|
|
283
283
|
HostEventT extends HostEvent,
|
|
284
|
-
PayloadT
|
|
285
|
-
ContextT extends ContextType,
|
|
284
|
+
PayloadT = HostEventRequest<HostEventT>,
|
|
285
|
+
ContextT extends ContextType = ContextType,
|
|
286
286
|
>(
|
|
287
287
|
hostEvent: HostEventT,
|
|
288
288
|
payload?: TriggerPayload<PayloadT, HostEventT>,
|