@thoughtspot/visual-embed-sdk 1.52.2-beta.2 → 1.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/package.json +1 -1
- package/cjs/src/css-variables.d.ts +373 -5
- package/cjs/src/css-variables.d.ts.map +1 -1
- package/cjs/src/embed/app.d.ts +14 -0
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +6 -3
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +28 -0
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/auto-frame-renderer.d.ts.map +1 -1
- package/cjs/src/embed/auto-frame-renderer.js +244 -4
- package/cjs/src/embed/auto-frame-renderer.js.map +1 -1
- package/cjs/src/embed/auto-frame-renderer.spec.js +389 -0
- package/cjs/src/embed/auto-frame-renderer.spec.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.js +1 -1
- package/cjs/src/embed/bodyless-conversation.js.map +1 -1
- package/cjs/src/embed/conversation.d.ts +15 -0
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +7 -3
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +66 -0
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/liveboard-override-utils.d.ts +59 -0
- package/cjs/src/embed/liveboard-override-utils.d.ts.map +1 -0
- package/cjs/src/embed/liveboard-override-utils.js +19 -0
- package/cjs/src/embed/liveboard-override-utils.js.map +1 -0
- package/cjs/src/embed/liveboard-override-utils.spec.d.ts +2 -0
- package/cjs/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
- package/cjs/src/embed/liveboard-override-utils.spec.js +34 -0
- package/cjs/src/embed/liveboard-override-utils.spec.js.map +1 -0
- package/cjs/src/embed/liveboard.d.ts +58 -13
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +11 -34
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +104 -79
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/search-bar.js +1 -1
- package/cjs/src/embed/search-bar.js.map +1 -1
- package/cjs/src/embed/search.js +1 -1
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/search.spec.js +20 -0
- package/cjs/src/embed/search.spec.js.map +1 -1
- package/cjs/src/embed/spotter-utils.d.ts +11 -0
- package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
- package/cjs/src/embed/spotter-utils.js +13 -1
- package/cjs/src/embed/spotter-utils.js.map +1 -1
- package/cjs/src/embed/spotter-viz-utils.d.ts +15 -0
- 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/spotter-viz-utils.spec.js +11 -0
- package/cjs/src/embed/spotter-viz-utils.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +27 -34
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +224 -102
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +543 -166
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +4 -2
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +4 -2
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/mixpanel-service.d.ts +1 -0
- package/cjs/src/mixpanel-service.d.ts.map +1 -1
- package/cjs/src/mixpanel-service.js +1 -0
- package/cjs/src/mixpanel-service.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/types.d.ts +182 -2
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +109 -0
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
- package/cjs/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
- package/cjs/src/utils/graphql/answerService/answer-queries.js +8 -1
- package/cjs/src/utils/graphql/answerService/answer-queries.js.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.d.ts +28 -4
- package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.js +39 -4
- package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.spec.js +124 -0
- package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
- package/dist/{index-CnHREfvN.js → index-CyDR8j_0.js} +1 -1
- package/dist/src/css-variables.d.ts +373 -5
- package/dist/src/css-variables.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +14 -0
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/auto-frame-renderer.d.ts.map +1 -1
- package/dist/src/embed/conversation.d.ts +15 -0
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/liveboard-override-utils.d.ts +59 -0
- package/dist/src/embed/liveboard-override-utils.d.ts.map +1 -0
- package/dist/src/embed/liveboard-override-utils.spec.d.ts +2 -0
- package/dist/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
- package/dist/src/embed/liveboard.d.ts +58 -13
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/spotter-utils.d.ts +11 -0
- package/dist/src/embed/spotter-utils.d.ts.map +1 -1
- package/dist/src/embed/spotter-viz-utils.d.ts +15 -0
- package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +27 -34
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/mixpanel-service.d.ts +1 -0
- package/dist/src/mixpanel-service.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/types.d.ts +182 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
- package/dist/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
- package/dist/src/utils/graphql/answerService/answerService.d.ts +28 -4
- package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +437 -191
- package/dist/tsembed-react.js +436 -190
- package/dist/tsembed.es.js +680 -196
- package/dist/tsembed.js +678 -194
- package/dist/visual-embed-sdk-react-full.d.ts +702 -56
- package/dist/visual-embed-sdk-react.d.ts +697 -56
- package/dist/visual-embed-sdk.d.ts +744 -57
- package/lib/package.json +1 -1
- package/lib/src/css-variables.d.ts +373 -5
- package/lib/src/css-variables.d.ts.map +1 -1
- package/lib/src/embed/app.d.ts +14 -0
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +7 -4
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +28 -0
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/auto-frame-renderer.d.ts.map +1 -1
- package/lib/src/embed/auto-frame-renderer.js +244 -4
- package/lib/src/embed/auto-frame-renderer.js.map +1 -1
- package/lib/src/embed/auto-frame-renderer.spec.js +389 -0
- package/lib/src/embed/auto-frame-renderer.spec.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.js +1 -1
- package/lib/src/embed/bodyless-conversation.js.map +1 -1
- package/lib/src/embed/conversation.d.ts +15 -0
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +8 -4
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +67 -1
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/liveboard-override-utils.d.ts +59 -0
- package/lib/src/embed/liveboard-override-utils.d.ts.map +1 -0
- package/lib/src/embed/liveboard-override-utils.js +15 -0
- package/lib/src/embed/liveboard-override-utils.js.map +1 -0
- package/lib/src/embed/liveboard-override-utils.spec.d.ts +2 -0
- package/lib/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
- package/lib/src/embed/liveboard-override-utils.spec.js +32 -0
- package/lib/src/embed/liveboard-override-utils.spec.js.map +1 -0
- package/lib/src/embed/liveboard.d.ts +58 -13
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +11 -33
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +104 -79
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/search-bar.js +1 -1
- package/lib/src/embed/search-bar.js.map +1 -1
- package/lib/src/embed/search.js +1 -1
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/search.spec.js +20 -0
- package/lib/src/embed/search.spec.js.map +1 -1
- package/lib/src/embed/spotter-utils.d.ts +11 -0
- package/lib/src/embed/spotter-utils.d.ts.map +1 -1
- package/lib/src/embed/spotter-utils.js +12 -0
- package/lib/src/embed/spotter-utils.js.map +1 -1
- package/lib/src/embed/spotter-viz-utils.d.ts +15 -0
- 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/spotter-viz-utils.spec.js +11 -0
- package/lib/src/embed/spotter-viz-utils.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +27 -34
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +224 -102
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +544 -167
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +4 -2
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +3 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/mixpanel-service.d.ts +1 -0
- package/lib/src/mixpanel-service.d.ts.map +1 -1
- package/lib/src/mixpanel-service.js +1 -0
- package/lib/src/mixpanel-service.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/types.d.ts +182 -2
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +109 -0
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
- package/lib/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
- package/lib/src/utils/graphql/answerService/answer-queries.js +7 -0
- package/lib/src/utils/graphql/answerService/answer-queries.js.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.d.ts +28 -4
- package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.js +39 -4
- package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.spec.js +125 -1
- package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +744 -57
- package/package.json +1 -1
- package/src/css-variables.ts +475 -26
- package/src/embed/app.spec.ts +32 -0
- package/src/embed/app.ts +28 -4
- package/src/embed/auto-frame-renderer.spec.ts +464 -0
- package/src/embed/auto-frame-renderer.ts +305 -6
- package/src/embed/bodyless-conversation.ts +1 -1
- package/src/embed/conversation.spec.ts +94 -1
- package/src/embed/conversation.ts +28 -3
- package/src/embed/liveboard-override-utils.spec.ts +38 -0
- package/src/embed/liveboard-override-utils.ts +71 -0
- package/src/embed/liveboard.spec.ts +119 -92
- package/src/embed/liveboard.ts +56 -40
- package/src/embed/search-bar.tsx +1 -1
- package/src/embed/search.spec.ts +23 -0
- package/src/embed/search.ts +1 -1
- package/src/embed/spotter-utils.ts +12 -0
- package/src/embed/spotter-viz-utils.spec.ts +11 -0
- package/src/embed/spotter-viz-utils.ts +15 -0
- package/src/embed/ts-embed.spec.ts +685 -207
- package/src/embed/ts-embed.ts +227 -97
- package/src/index.ts +16 -1
- package/src/mixpanel-service.ts +1 -0
- package/src/react/all-types-export.ts +6 -0
- package/src/types.ts +186 -5
- package/src/utils/graphql/answerService/answer-queries.ts +8 -0
- package/src/utils/graphql/answerService/answerService.spec.ts +145 -1
- package/src/utils/graphql/answerService/answerService.ts +65 -3
package/dist/tsembed.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @thoughtspot/visual-embed-sdk version 1.
|
|
1
|
+
/* @thoughtspot/visual-embed-sdk version 1.53.0 */
|
|
2
2
|
'use client';
|
|
3
3
|
function _mergeNamespaces(n, m) {
|
|
4
4
|
m.forEach(function (e) {
|
|
@@ -1208,6 +1208,36 @@ var EmbedEvent;
|
|
|
1208
1208
|
* ```
|
|
1209
1209
|
*/
|
|
1210
1210
|
EmbedEvent["Edit"] = "edit";
|
|
1211
|
+
/**
|
|
1212
|
+
* Emitted when a user clicks **Edit** on a Liveboard.
|
|
1213
|
+
*
|
|
1214
|
+
* Fired alongside {@link EmbedEvent.Edit} for backward compatibility;
|
|
1215
|
+
* listen to this instead of `Edit` to target the Liveboard surface only.
|
|
1216
|
+
* @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
|
|
1217
|
+
* @example
|
|
1218
|
+
* ```js
|
|
1219
|
+
* liveboardEmbed.on(EmbedEvent.EditLiveboard, payload => {
|
|
1220
|
+
* console.log('Liveboard edit', payload);
|
|
1221
|
+
* })
|
|
1222
|
+
* ```
|
|
1223
|
+
*/
|
|
1224
|
+
EmbedEvent["EditLiveboard"] = "editLiveboard";
|
|
1225
|
+
/**
|
|
1226
|
+
* Emitted when a user clicks **Edit** on a visualization inside a
|
|
1227
|
+
* Liveboard.
|
|
1228
|
+
*
|
|
1229
|
+
* Fired alongside {@link EmbedEvent.Edit} for backward compatibility;
|
|
1230
|
+
* listen to this instead of `Edit` to target the visualization surface
|
|
1231
|
+
* only.
|
|
1232
|
+
* @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
|
|
1233
|
+
* @example
|
|
1234
|
+
* ```js
|
|
1235
|
+
* liveboardEmbed.on(EmbedEvent.EditVisualization, payload => {
|
|
1236
|
+
* console.log('visualization edit', payload);
|
|
1237
|
+
* })
|
|
1238
|
+
* ```
|
|
1239
|
+
*/
|
|
1240
|
+
EmbedEvent["EditVisualization"] = "editVisualization";
|
|
1211
1241
|
/**
|
|
1212
1242
|
* Emitted when a user clicks *Make a copy* on a Liveboard
|
|
1213
1243
|
* @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl, 8.8.1.sw
|
|
@@ -3179,6 +3209,35 @@ var HostEvent;
|
|
|
3179
3209
|
* @version SDK: 1.15.0 | ThoughtSpot: 8.7.0.cl, 8.8.1.sw
|
|
3180
3210
|
*/
|
|
3181
3211
|
HostEvent["Edit"] = "edit";
|
|
3212
|
+
/**
|
|
3213
|
+
* Trigger the **Edit** action on a Liveboard only — does not affect a
|
|
3214
|
+
* visualization's edit surface.
|
|
3215
|
+
*
|
|
3216
|
+
* Behaves like {@link HostEvent.Edit} restricted to the Liveboard
|
|
3217
|
+
* surface. Use {@link HostEvent.EditVisualization} to target a
|
|
3218
|
+
* visualization instead, or `HostEvent.Edit` to control whichever
|
|
3219
|
+
* surface applies contextually (unchanged, existing behavior).
|
|
3220
|
+
* @example
|
|
3221
|
+
* ```js
|
|
3222
|
+
* liveboardEmbed.trigger(HostEvent.EditLiveboard)
|
|
3223
|
+
* ```
|
|
3224
|
+
* @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
|
|
3225
|
+
*/
|
|
3226
|
+
HostEvent["EditLiveboard"] = "editLiveboard";
|
|
3227
|
+
/**
|
|
3228
|
+
* Trigger the **Edit** action on a specific visualization inside a
|
|
3229
|
+
* Liveboard only — does not affect the Liveboard-level edit surface.
|
|
3230
|
+
* @param - Object parameter. Includes the following keys:
|
|
3231
|
+
* - `vizId`: **Required.** The visualization to edit.
|
|
3232
|
+
*
|
|
3233
|
+
* @example
|
|
3234
|
+
* ```js
|
|
3235
|
+
* liveboardEmbed.trigger(HostEvent.EditVisualization, {vizId:
|
|
3236
|
+
* '730496d6-6903-4601-937e-2c691821af3c'})
|
|
3237
|
+
* ```
|
|
3238
|
+
* @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
|
|
3239
|
+
*/
|
|
3240
|
+
HostEvent["EditVisualization"] = "editVisualization";
|
|
3182
3241
|
/**
|
|
3183
3242
|
* Trigger the **Copy link** action on a Liveboard or visualization
|
|
3184
3243
|
* Payload: {@link VizScopedRequest}.
|
|
@@ -4741,6 +4800,22 @@ var DataSourceVisualMode;
|
|
|
4741
4800
|
var Param;
|
|
4742
4801
|
(function (Param) {
|
|
4743
4802
|
Param["Tsmcp"] = "tsmcp";
|
|
4803
|
+
/**
|
|
4804
|
+
* Marker added by a host app replaying a stored conversation. Carries the
|
|
4805
|
+
* analytical session (conversation) identifier, from which the renderer
|
|
4806
|
+
* resolves the answer's current session parameters. Stripped before the
|
|
4807
|
+
* URL reaches the ThoughtSpot application.
|
|
4808
|
+
* @version SDK: 1.52.2 | ThoughtSpot Cloud: 26.9.0.cl
|
|
4809
|
+
*/
|
|
4810
|
+
Param["TsmcpConversationId"] = "tsmcpConversationId";
|
|
4811
|
+
/**
|
|
4812
|
+
* Zero-based position of the answer within the conversation, counting only
|
|
4813
|
+
* non-thinking answer items in message order. Accompanies
|
|
4814
|
+
* {@link TsmcpConversationId}; defaults to 0 when absent. Stripped before
|
|
4815
|
+
* the URL reaches the ThoughtSpot application.
|
|
4816
|
+
* @version SDK: 1.52.2 | ThoughtSpot Cloud: 26.9.0.cl
|
|
4817
|
+
*/
|
|
4818
|
+
Param["TsmcpAnswerIndex"] = "tsmcpAnswerIndex";
|
|
4744
4819
|
Param["EmbedApp"] = "embedApp";
|
|
4745
4820
|
Param["DataSources"] = "dataSources";
|
|
4746
4821
|
Param["DataSourceMode"] = "dataSourceMode";
|
|
@@ -4904,6 +4979,9 @@ var Param;
|
|
|
4904
4979
|
Param["SpotterDataSources"] = "spotterDataSources";
|
|
4905
4980
|
Param["OpenSpotterOnLiveboardByDefault"] = "openSpotterOnLiveboardByDefault";
|
|
4906
4981
|
Param["ShowAnswerEditPanel"] = "showAnswerEditPanel";
|
|
4982
|
+
Param["IsDarkMode"] = "isDarkMode";
|
|
4983
|
+
Param["RadiantThemeEnabled"] = "radiantThemeEnabled";
|
|
4984
|
+
Param["SpotterExperienceVersion"] = "spotterExperienceVersion";
|
|
4907
4985
|
})(Param || (Param = {}));
|
|
4908
4986
|
/**
|
|
4909
4987
|
* ThoughtSpot application pages include actions and menu commands
|
|
@@ -5358,12 +5436,43 @@ var Action;
|
|
|
5358
5436
|
* The *Edit* action on the Liveboard page and in the
|
|
5359
5437
|
* visualization menu.
|
|
5360
5438
|
* Opens a Liveboard or visualization in edit mode.
|
|
5439
|
+
*
|
|
5440
|
+
* Controls both surfaces together. To target one surface only, use
|
|
5441
|
+
* {@link Action.EditLiveboard} or {@link Action.EditVisualization}.
|
|
5361
5442
|
* @example
|
|
5362
5443
|
* ```js
|
|
5363
5444
|
* disabledActions: [Action.Edit]
|
|
5364
5445
|
* ```
|
|
5365
5446
|
*/
|
|
5366
5447
|
Action["Edit"] = "edit";
|
|
5448
|
+
/**
|
|
5449
|
+
* The *Edit* action on the Liveboard page only.
|
|
5450
|
+
* Opens a Liveboard in edit mode.
|
|
5451
|
+
*
|
|
5452
|
+
* Does not affect the *Edit* action in the visualization menu; use
|
|
5453
|
+
* {@link Action.EditVisualization} for that, or {@link Action.Edit} to
|
|
5454
|
+
* control both surfaces together.
|
|
5455
|
+
* @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
|
|
5456
|
+
* @example
|
|
5457
|
+
* ```js
|
|
5458
|
+
* disabledActions: [Action.EditLiveboard]
|
|
5459
|
+
* ```
|
|
5460
|
+
*/
|
|
5461
|
+
Action["EditLiveboard"] = "editLiveboard";
|
|
5462
|
+
/**
|
|
5463
|
+
* The *Edit* action in the visualization `...` menu only.
|
|
5464
|
+
* Opens a visualization in the editor.
|
|
5465
|
+
*
|
|
5466
|
+
* Does not affect the *Edit* action on the Liveboard page; use
|
|
5467
|
+
* {@link Action.EditLiveboard} for that, or {@link Action.Edit} to
|
|
5468
|
+
* control both surfaces together.
|
|
5469
|
+
* @version SDK: 1.54.0 | ThoughtSpot Cloud: 26.11.0.cl
|
|
5470
|
+
* @example
|
|
5471
|
+
* ```js
|
|
5472
|
+
* disabledActions: [Action.EditVisualization]
|
|
5473
|
+
* ```
|
|
5474
|
+
*/
|
|
5475
|
+
Action["EditVisualization"] = "editVisualization";
|
|
5367
5476
|
/**
|
|
5368
5477
|
* The text edit option for Liveboard and visualization titles.
|
|
5369
5478
|
* @example
|
|
@@ -7643,7 +7752,7 @@ var TableContentDensity;
|
|
|
7643
7752
|
TableContentDensity["Compact"] = "COMPACT";
|
|
7644
7753
|
})(TableContentDensity || (TableContentDensity = {}));
|
|
7645
7754
|
|
|
7646
|
-
var version$1="1.
|
|
7755
|
+
var version$1="1.53.0";var pkg = {version:version$1};
|
|
7647
7756
|
|
|
7648
7757
|
const { version } = pkg;
|
|
7649
7758
|
|
|
@@ -10311,6 +10420,13 @@ const addFilter = `
|
|
|
10311
10420
|
}
|
|
10312
10421
|
}
|
|
10313
10422
|
`;
|
|
10423
|
+
const updateSort = `
|
|
10424
|
+
mutation UpdateSort($session: BachSessionIdInput!, $sortOrder: [AnswerColumnSortInput!]!) {
|
|
10425
|
+
Answer__updateSort(session: $session, sortOrder: $sortOrder) {
|
|
10426
|
+
${bachSessionId}
|
|
10427
|
+
}
|
|
10428
|
+
}
|
|
10429
|
+
`;
|
|
10314
10430
|
const getAnswer = `
|
|
10315
10431
|
query GetAnswer($session: BachSessionIdInput!) {
|
|
10316
10432
|
getAnswer(session: $session) {
|
|
@@ -10615,6 +10731,26 @@ class AnswerService {
|
|
|
10615
10731
|
},
|
|
10616
10732
|
});
|
|
10617
10733
|
}
|
|
10734
|
+
/**
|
|
10735
|
+
* Adapt the sort options into the `updateSort` payload and send it.
|
|
10736
|
+
* @param sortOptions Columns to sort by, each with a direction.
|
|
10737
|
+
* @param sourceDetail
|
|
10738
|
+
*/
|
|
10739
|
+
async adaptSorting(sortOptions, sourceDetail) {
|
|
10740
|
+
const { answer } = await this.executeQuery(getAnswer, {});
|
|
10741
|
+
const guidToColumnId = getGuidToColumnIdMap(answer);
|
|
10742
|
+
const sortOrder = sortOptions.map((sort) => {
|
|
10743
|
+
const guid = getGuidsFromColumnNames(sourceDetail, [sort.columnName])
|
|
10744
|
+
.values().next().value;
|
|
10745
|
+
return {
|
|
10746
|
+
columnId: guidToColumnId.get(guid),
|
|
10747
|
+
sortType: sort.ascending ? 'ASCENDING' : 'DESCENDING',
|
|
10748
|
+
};
|
|
10749
|
+
});
|
|
10750
|
+
return this.executeQuery(updateSort, {
|
|
10751
|
+
sortOrder,
|
|
10752
|
+
});
|
|
10753
|
+
}
|
|
10618
10754
|
async updateDisplayMode(displayMode = "TABLE_MODE") {
|
|
10619
10755
|
return this.executeQuery(updateDisplayMode, {
|
|
10620
10756
|
displayMode,
|
|
@@ -10702,18 +10838,21 @@ class AnswerService {
|
|
|
10702
10838
|
* automatically passed.
|
|
10703
10839
|
* @param outputColumnNames
|
|
10704
10840
|
* @param selectedPoints
|
|
10841
|
+
* @param sortOptions Optional columns to sort the underlying data by.
|
|
10705
10842
|
* @example
|
|
10706
10843
|
* ```js
|
|
10707
10844
|
* embed.on(EmbedEvent.CustomAction, e => {
|
|
10708
|
-
* const underlying = await e.answerService.getUnderlyingDataForPoint(
|
|
10709
|
-
* 'col name 1' // The column should exist in the data source.
|
|
10710
|
-
*
|
|
10845
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint(
|
|
10846
|
+
* ['col name 1'], // The column should exist in the data source.
|
|
10847
|
+
* undefined,
|
|
10848
|
+
* [{ columnName: 'col name 1', ascending: true }],
|
|
10849
|
+
* );
|
|
10711
10850
|
* const data = await underlying.fetchData(0, 100);
|
|
10712
10851
|
* })
|
|
10713
10852
|
* ```
|
|
10714
10853
|
* @version SDK: 1.25.0 | ThoughtSpot: 9.10.0.cl
|
|
10715
10854
|
*/
|
|
10716
|
-
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
|
|
10855
|
+
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints, sortOptions) {
|
|
10717
10856
|
if (!selectedPoints && !this.selectedPoints) {
|
|
10718
10857
|
throw new Error('Needs to be triggered in context of a point');
|
|
10719
10858
|
}
|
|
@@ -10741,6 +10880,9 @@ class AnswerService {
|
|
|
10741
10880
|
if (columnsToRemove.length) {
|
|
10742
10881
|
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
10743
10882
|
}
|
|
10883
|
+
if (sortOptions === null || sortOptions === void 0 ? void 0 : sortOptions.length) {
|
|
10884
|
+
await unaggAnswerSession.adaptSorting(sortOptions, sourceDetail);
|
|
10885
|
+
}
|
|
10744
10886
|
return unaggAnswerSession;
|
|
10745
10887
|
}
|
|
10746
10888
|
/**
|
|
@@ -10779,7 +10921,7 @@ class AnswerService {
|
|
|
10779
10921
|
async getTML() {
|
|
10780
10922
|
const { object } = await this.executeQuery(getAnswerTML, {});
|
|
10781
10923
|
const edoc = object[0].edoc;
|
|
10782
|
-
const YAML = await import('./index-
|
|
10924
|
+
const YAML = await import('./index-CyDR8j_0.js');
|
|
10783
10925
|
const parsedDoc = YAML.parse(edoc);
|
|
10784
10926
|
return {
|
|
10785
10927
|
answer: {
|
|
@@ -10800,6 +10942,15 @@ class AnswerService {
|
|
|
10800
10942
|
this.tmlOverride = override;
|
|
10801
10943
|
}
|
|
10802
10944
|
}
|
|
10945
|
+
/**
|
|
10946
|
+
* Build a map from a source column guid to the answer's viz column id, using
|
|
10947
|
+
* the `referencedColumns` link on each viz column.
|
|
10948
|
+
* @param answer
|
|
10949
|
+
*/
|
|
10950
|
+
function getGuidToColumnIdMap(answer) {
|
|
10951
|
+
const tableViz = answer.visualizations.find((viz) => viz.columns);
|
|
10952
|
+
return new Map(tableViz.columns.map((col) => [col.column.referencedColumns[0].guid, col.column.id]));
|
|
10953
|
+
}
|
|
10803
10954
|
/**
|
|
10804
10955
|
*
|
|
10805
10956
|
* @param sourceDetail
|
|
@@ -19814,6 +19965,7 @@ let mixpanelInstance;
|
|
|
19814
19965
|
const MIXPANEL_EVENT = {
|
|
19815
19966
|
VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
|
|
19816
19967
|
VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
|
|
19968
|
+
VISUAL_SDK_INIT_ACTIONS: 'visual-sdk-init-actions',
|
|
19817
19969
|
VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
|
|
19818
19970
|
VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
|
|
19819
19971
|
VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
|
|
@@ -22196,9 +22348,6 @@ const TS_EMBED_ID = '_thoughtspot-embed';
|
|
|
22196
22348
|
*/
|
|
22197
22349
|
const PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY = 'tsEmbedOriginalPosition';
|
|
22198
22350
|
const PRERENDER_WRAPPER_ID_PREFIX = 'tsEmbed-pre-render-wrapper-';
|
|
22199
|
-
const PRERENDER_PARKED_TRANSFORM = 'translateY(-100%)';
|
|
22200
|
-
/** The height createPreRenderWrapper() seeds before anything is measured. */
|
|
22201
|
-
const UNMEASURED_WRAPPER_HEIGHT = '100vh';
|
|
22202
22351
|
// The container applies UpdateEmbedParams through React state, so a delivered
|
|
22203
22352
|
// post is not the same as the params being in effect.
|
|
22204
22353
|
const UPDATE_EMBED_PARAMS_SETTLE_MS = 200;
|
|
@@ -22206,6 +22355,97 @@ const UPDATE_EMBED_PARAMS_SETTLE_MS = 200;
|
|
|
22206
22355
|
// truthy, so null or '' leaves the previous embed's values in place. '&' is
|
|
22207
22356
|
// truthy and parses to {}.
|
|
22208
22357
|
const NO_RUNTIME_PARAMS = '&';
|
|
22358
|
+
/**
|
|
22359
|
+
* Params kept on the iframe `src` when `excludeConfigFromURL` is set. The rest
|
|
22360
|
+
* are sent in the APP_INIT payload.
|
|
22361
|
+
* @internal
|
|
22362
|
+
*/
|
|
22363
|
+
const BOOTSTRAP_URL_PARAMS = new Set([
|
|
22364
|
+
// Marks the app as embedded.
|
|
22365
|
+
Param.EmbedApp,
|
|
22366
|
+
// The host page URL, used to validate the postMessage origin.
|
|
22367
|
+
Param.HostAppUrl,
|
|
22368
|
+
// The SDK version.
|
|
22369
|
+
Param.Version,
|
|
22370
|
+
// The authentication type set in init.
|
|
22371
|
+
Param.AuthType,
|
|
22372
|
+
// Whether the app signs the user in automatically.
|
|
22373
|
+
Param.AutoLogin,
|
|
22374
|
+
// Stops the app from redirecting to its login page.
|
|
22375
|
+
Param.DisableLoginRedirect,
|
|
22376
|
+
// Forces the SAML redirect for EmbeddedSSO.
|
|
22377
|
+
Param.ForceSAMLAutoRedirect,
|
|
22378
|
+
// Set for cookieless trusted authentication.
|
|
22379
|
+
Param.cookieless,
|
|
22380
|
+
// Lets the app use the pre-fetched auth info.
|
|
22381
|
+
Param.preAuthCache,
|
|
22382
|
+
// Blocks access to the full app outside the embed.
|
|
22383
|
+
Param.blockNonEmbedFullAppAccess,
|
|
22384
|
+
// The org to load, which the auth info depends on.
|
|
22385
|
+
Param.OverrideOrgId,
|
|
22386
|
+
// The host window height when the iframe loads.
|
|
22387
|
+
Param.ViewPortHeight,
|
|
22388
|
+
// The host window width when the iframe loads.
|
|
22389
|
+
Param.ViewPortWidth,
|
|
22390
|
+
// The app's client log level.
|
|
22391
|
+
Param.ClientLogLevel,
|
|
22392
|
+
// Lets the app override the native console.
|
|
22393
|
+
Param.OverrideNativeConsole,
|
|
22394
|
+
// An extra Pendo tracking key.
|
|
22395
|
+
Param.PendoTrackingKey,
|
|
22396
|
+
// The locale for number formatting.
|
|
22397
|
+
Param.NumberFormatLocale,
|
|
22398
|
+
// The locale for date formatting.
|
|
22399
|
+
Param.DateFormatLocale,
|
|
22400
|
+
// The currency format.
|
|
22401
|
+
Param.CurrencyFormat,
|
|
22402
|
+
// The UI language.
|
|
22403
|
+
Param.Locale,
|
|
22404
|
+
// Turns on dark mode.
|
|
22405
|
+
Param.IsDarkMode,
|
|
22406
|
+
// Turns on the radiant theme that dark mode needs.
|
|
22407
|
+
Param.RadiantThemeEnabled,
|
|
22408
|
+
// Marks a SearchEmbed or SearchBarEmbed.
|
|
22409
|
+
Param.searchEmbed,
|
|
22410
|
+
// Marks a LiveboardEmbed.
|
|
22411
|
+
Param.livedBoardEmbed,
|
|
22412
|
+
// Marks a SpotterAgentEmbed.
|
|
22413
|
+
Param.isSpotterAgentEmbed,
|
|
22414
|
+
// Marks a SpotterEmbed.
|
|
22415
|
+
Param.SpotterEnabled,
|
|
22416
|
+
// Marks an AppEmbed.
|
|
22417
|
+
Param.IsFullAppEmbed,
|
|
22418
|
+
// Legacy flag for the onBeforeGetVizData API intercept.
|
|
22419
|
+
Param.IsOnBeforeGetVizDataInterceptEnabled,
|
|
22420
|
+
// Lets the host override links in the app.
|
|
22421
|
+
Param.LinkOverride,
|
|
22422
|
+
// Turns on version 2 of the link overrides.
|
|
22423
|
+
Param.EnableLinkOverridesV2,
|
|
22424
|
+
// Stops links from opening in a new tab.
|
|
22425
|
+
Param.DisableRedirectionLinksInNewTab,
|
|
22426
|
+
// Uses replaceState instead of pushState for app navigation.
|
|
22427
|
+
Param.OverrideHistoryState,
|
|
22428
|
+
// Shows search results as a table.
|
|
22429
|
+
Param.ForceTable,
|
|
22430
|
+
// The URL of the custom string IDs file.
|
|
22431
|
+
Param.StringIDsUrl,
|
|
22432
|
+
// The data sources that search opens with.
|
|
22433
|
+
Param.DataSources,
|
|
22434
|
+
// Exposes translation IDs in the app.
|
|
22435
|
+
Param.ExposeTranslationIDs,
|
|
22436
|
+
// The URL of the custom icon sprite.
|
|
22437
|
+
Param.IconSpriteUrl,
|
|
22438
|
+
// The tag that filters the metadata lists in an AppEmbed.
|
|
22439
|
+
Param.Tag,
|
|
22440
|
+
// Set when a Liveboard embed shows a single visualization (vizId).
|
|
22441
|
+
Param.vizEmbed,
|
|
22442
|
+
// Whether search opens with the last-selected data sources.
|
|
22443
|
+
Param.UseLastSelectedDataSource,
|
|
22444
|
+
// The query mode Spotter opens in.
|
|
22445
|
+
Param.DefaultQueryMode,
|
|
22446
|
+
// The initial search query. Omitted with excludeSearchTokenStringFromURL.
|
|
22447
|
+
Param.searchTokenString,
|
|
22448
|
+
]);
|
|
22209
22449
|
/**
|
|
22210
22450
|
* The event id map from v2 event names to v1 event id
|
|
22211
22451
|
* v1 events are the classic embed events implemented in Blink v1
|
|
@@ -22234,6 +22474,7 @@ class TsEmbed {
|
|
|
22234
22474
|
this.embedNodeKey = '__tsEmbed';
|
|
22235
22475
|
this.embedContainerLoadedKey = '__tsEmbedContainerLoaded';
|
|
22236
22476
|
this.isAppInitialized = false;
|
|
22477
|
+
this.initDataParams = {};
|
|
22237
22478
|
/**
|
|
22238
22479
|
* Should we encode URL Query Params using base64 encoding which ThoughtSpot
|
|
22239
22480
|
* will generate for embedding. This provides additional security to
|
|
@@ -22243,6 +22484,7 @@ class TsEmbed {
|
|
|
22243
22484
|
this.shouldEncodeUrlQueryParams = false;
|
|
22244
22485
|
this.defaultHiddenActions = [Action.ReportError];
|
|
22245
22486
|
this.preRenderContainerEl = document.body;
|
|
22487
|
+
this.containerScrollListener = null;
|
|
22246
22488
|
/**
|
|
22247
22489
|
* Handler for fullscreen change events
|
|
22248
22490
|
*/
|
|
@@ -22268,7 +22510,7 @@ class TsEmbed {
|
|
|
22268
22510
|
*/
|
|
22269
22511
|
this.appInitCb = async (_, responder) => {
|
|
22270
22512
|
try {
|
|
22271
|
-
const appInitData = await this.getAppInitData();
|
|
22513
|
+
const appInitData = this.withInitDataParams(await this.getAppInitData());
|
|
22272
22514
|
this.isAppInitialized = true;
|
|
22273
22515
|
responder({
|
|
22274
22516
|
type: EmbedEvent.APP_INIT,
|
|
@@ -22696,6 +22938,18 @@ class TsEmbed {
|
|
|
22696
22938
|
async getAppInitData() {
|
|
22697
22939
|
return this.getDefaultAppInitData();
|
|
22698
22940
|
}
|
|
22941
|
+
withInitDataParams(appInitData) {
|
|
22942
|
+
if (isEmpty_1(this.initDataParams)) {
|
|
22943
|
+
return appInitData;
|
|
22944
|
+
}
|
|
22945
|
+
return {
|
|
22946
|
+
...appInitData,
|
|
22947
|
+
embedParams: {
|
|
22948
|
+
...this.initDataParams,
|
|
22949
|
+
...(appInitData.embedParams || {}),
|
|
22950
|
+
},
|
|
22951
|
+
};
|
|
22952
|
+
}
|
|
22699
22953
|
/**
|
|
22700
22954
|
* Helper method to refresh/update auth token for TrustedAuthTokenCookieless auth type
|
|
22701
22955
|
* @param responder - Function to send response back
|
|
@@ -22755,7 +23009,7 @@ class TsEmbed {
|
|
|
22755
23009
|
* @returns queryParams
|
|
22756
23010
|
*/
|
|
22757
23011
|
getBaseQueryParams(queryParams = {}) {
|
|
22758
|
-
var _a, _b, _c, _d;
|
|
23012
|
+
var _a, _b, _c, _d, _e;
|
|
22759
23013
|
let hostAppUrl = ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '';
|
|
22760
23014
|
// The below check is needed because TS Cloud firewall, blocks
|
|
22761
23015
|
// localhost/127.0.0.1 in any url param.
|
|
@@ -22792,6 +23046,15 @@ class TsEmbed {
|
|
|
22792
23046
|
if (this.embedConfig.currencyFormat) {
|
|
22793
23047
|
queryParams[Param.CurrencyFormat] = this.embedConfig.currencyFormat;
|
|
22794
23048
|
}
|
|
23049
|
+
// The view config wins over init, so an embed can opt out of a dark
|
|
23050
|
+
// mode set in `init`. `??` and not `||`, so that an explicit `false`
|
|
23051
|
+
// overrides an init-level `true`.
|
|
23052
|
+
const isDarkMode = (_c = this.viewConfig.isDarkMode) !== null && _c !== void 0 ? _c : this.embedConfig.isDarkMode;
|
|
23053
|
+
setParamIfDefined(queryParams, Param.IsDarkMode, isDarkMode, true);
|
|
23054
|
+
// The app's dark mode lives in its radiant theme, so turn that on too.
|
|
23055
|
+
if (isDarkMode) {
|
|
23056
|
+
queryParams[Param.RadiantThemeEnabled] = true;
|
|
23057
|
+
}
|
|
22795
23058
|
const { disabledActions, disabledActionReason, hiddenActions, visibleActions, hiddenTabs, visibleTabs, showAlerts, additionalFlags: additionalFlagsFromView, locale, customizations, contextMenuTrigger, linkOverride, enableLinkOverridesV2, insertInToSlide, disableRedirectionLinksInNewTab, overrideOrgId, overrideHistoryState, exposeTranslationIDs, primaryAction, } = this.viewConfig;
|
|
22796
23059
|
const { additionalFlags: additionalFlagsFromInit } = this.embedConfig;
|
|
22797
23060
|
const additionalFlags = {
|
|
@@ -22857,7 +23120,7 @@ class TsEmbed {
|
|
|
22857
23120
|
if (spriteUrl) {
|
|
22858
23121
|
queryParams[Param.IconSpriteUrl] = spriteUrl.replace('https://', '');
|
|
22859
23122
|
}
|
|
22860
|
-
const stringIDsUrl = ((
|
|
23123
|
+
const stringIDsUrl = ((_d = customizations === null || customizations === void 0 ? void 0 : customizations.content) === null || _d === void 0 ? void 0 : _d.stringIDsUrl) || ((_e = embedCustomizations === null || embedCustomizations === void 0 ? void 0 : embedCustomizations.content) === null || _e === void 0 ? void 0 : _e.stringIDsUrl);
|
|
22861
23124
|
if (stringIDsUrl) {
|
|
22862
23125
|
queryParams[Param.StringIDsUrl] = stringIDsUrl;
|
|
22863
23126
|
}
|
|
@@ -22911,13 +23174,32 @@ class TsEmbed {
|
|
|
22911
23174
|
return path;
|
|
22912
23175
|
}
|
|
22913
23176
|
getEmbedParams() {
|
|
22914
|
-
const queryParams = this.
|
|
23177
|
+
const queryParams = this.getUrlQueryParamsObject();
|
|
22915
23178
|
return getQueryParamString(queryParams);
|
|
22916
23179
|
}
|
|
22917
23180
|
getEmbedParamsObject() {
|
|
22918
23181
|
const params = this.getBaseQueryParams();
|
|
22919
23182
|
return params;
|
|
22920
23183
|
}
|
|
23184
|
+
getUrlQueryParamsObject() {
|
|
23185
|
+
const queryParams = this.getEmbedParamsObject();
|
|
23186
|
+
if (!this.isConfigExcludedFromUrl()) {
|
|
23187
|
+
this.initDataParams = {};
|
|
23188
|
+
return queryParams;
|
|
23189
|
+
}
|
|
23190
|
+
const urlParams = {};
|
|
23191
|
+
const excludedParams = {};
|
|
23192
|
+
Object.entries(queryParams).forEach(([key, value]) => {
|
|
23193
|
+
if (BOOTSTRAP_URL_PARAMS.has(key)) {
|
|
23194
|
+
urlParams[key] = value;
|
|
23195
|
+
}
|
|
23196
|
+
else {
|
|
23197
|
+
excludedParams[key] = deserializeParam(value);
|
|
23198
|
+
}
|
|
23199
|
+
});
|
|
23200
|
+
this.initDataParams = excludedParams;
|
|
23201
|
+
return urlParams;
|
|
23202
|
+
}
|
|
22921
23203
|
getRootIframeSrc() {
|
|
22922
23204
|
const query = this.getEmbedParams();
|
|
22923
23205
|
return this.getEmbedBasePath(query);
|
|
@@ -23088,7 +23370,7 @@ class TsEmbed {
|
|
|
23088
23370
|
top: '0',
|
|
23089
23371
|
left: '0',
|
|
23090
23372
|
width: '100vw',
|
|
23091
|
-
height:
|
|
23373
|
+
height: '100vh',
|
|
23092
23374
|
};
|
|
23093
23375
|
setStyleProperties(preRenderWrapper, initialPreRenderWrapperStyle);
|
|
23094
23376
|
return preRenderWrapper;
|
|
@@ -23156,26 +23438,10 @@ class TsEmbed {
|
|
|
23156
23438
|
return placeholder;
|
|
23157
23439
|
}
|
|
23158
23440
|
/**
|
|
23159
|
-
* Resolves the configured preRenderContainer to a live element
|
|
23160
|
-
* selector is re-queried on every call so
|
|
23161
|
-
* replacing the node) resolves to the
|
|
23162
|
-
* directly cannot be re-resolved.
|
|
23163
|
-
*
|
|
23164
|
-
* With nothing configured the frame goes into the host element's nearest
|
|
23165
|
-
* scrolling ancestor, falling back to `document.body`.
|
|
23166
|
-
*
|
|
23167
|
-
* The wrapper is absolutely positioned, so it follows the page for free —
|
|
23168
|
-
* but only while it sits inside whatever scrolls. `document.body` is right
|
|
23169
|
-
* only when the document itself is the scroller; an app that scrolls an
|
|
23170
|
-
* inner element instead left the frame pinned to the viewport while the page
|
|
23171
|
-
* moved under it (SCAL-338563). Being inside the scroller also lets wheel
|
|
23172
|
-
* events chain out of the frame into it, which they cannot do from
|
|
23173
|
-
* `document.body`.
|
|
23174
|
-
*
|
|
23175
|
-
* A scrolling ancestor is layout chrome rather than route content, so it
|
|
23176
|
-
* outlives the embed in practice; and if it does go, the host element goes
|
|
23177
|
-
* with it and this instance is remounting anyway.
|
|
23178
|
-
* `reconcilePreRenderContainer` re-runs this on a detached container.
|
|
23441
|
+
* Resolves the configured preRenderContainer to a live element, falling
|
|
23442
|
+
* back to `document.body`. A string selector is re-queried on every call so
|
|
23443
|
+
* a remounted container (E.g.: React replacing the node) resolves to the
|
|
23444
|
+
* fresh element; an element passed directly cannot be re-resolved.
|
|
23179
23445
|
*/
|
|
23180
23446
|
resolvePreRenderContainerTarget() {
|
|
23181
23447
|
var _a;
|
|
@@ -23195,13 +23461,7 @@ class TsEmbed {
|
|
|
23195
23461
|
else if (containerConfig) {
|
|
23196
23462
|
container = containerConfig;
|
|
23197
23463
|
}
|
|
23198
|
-
|
|
23199
|
-
return container;
|
|
23200
|
-
}
|
|
23201
|
-
if (!this.hostElement) {
|
|
23202
|
-
return document.body;
|
|
23203
|
-
}
|
|
23204
|
-
return (_a = getScrollableAncestors(this.hostElement)[0]) !== null && _a !== void 0 ? _a : document.body;
|
|
23464
|
+
return (_a = container) !== null && _a !== void 0 ? _a : document.body;
|
|
23205
23465
|
}
|
|
23206
23466
|
inheritPreRenderContainer() {
|
|
23207
23467
|
var _a;
|
|
@@ -23246,9 +23506,8 @@ class TsEmbed {
|
|
|
23246
23506
|
* Re-attaches the wrapper to a live container when the previously resolved
|
|
23247
23507
|
* one has been detached or no longer holds the wrapper — e.g. the host app
|
|
23248
23508
|
* remounted a custom preRenderContainer, which would otherwise leave a stale
|
|
23249
|
-
* reference and collapse the wrapper.
|
|
23250
|
-
*
|
|
23251
|
-
* is left untouched, as there is nothing to re-query.
|
|
23509
|
+
* reference and collapse the wrapper. Only string selectors can be
|
|
23510
|
+
* re-resolved; a container passed as an element is left untouched.
|
|
23252
23511
|
*/
|
|
23253
23512
|
reconcilePreRenderContainer() {
|
|
23254
23513
|
const wrapper = this.preRenderWrapper;
|
|
@@ -23267,6 +23526,14 @@ class TsEmbed {
|
|
|
23267
23526
|
if (resolved === stored && stored.contains(wrapper)) {
|
|
23268
23527
|
return;
|
|
23269
23528
|
}
|
|
23529
|
+
if (this.containerScrollListener && stored !== resolved) {
|
|
23530
|
+
if (stored !== document.body) {
|
|
23531
|
+
stored.removeEventListener('scroll', this.containerScrollListener);
|
|
23532
|
+
}
|
|
23533
|
+
if (resolved !== document.body) {
|
|
23534
|
+
resolved.addEventListener('scroll', this.containerScrollListener);
|
|
23535
|
+
}
|
|
23536
|
+
}
|
|
23270
23537
|
this.preRenderContainerEl = resolved;
|
|
23271
23538
|
this.applyPreRenderContainerPositioning();
|
|
23272
23539
|
if (wrapper.parentNode !== resolved) {
|
|
@@ -23328,12 +23595,11 @@ class TsEmbed {
|
|
|
23328
23595
|
*/
|
|
23329
23596
|
setIFrameHeight(height) {
|
|
23330
23597
|
if (this.isPreRendered) {
|
|
23331
|
-
const next = getCssDimension(height);
|
|
23332
23598
|
if (this.insertedDomEl) {
|
|
23333
|
-
this.insertedDomEl.style.height =
|
|
23599
|
+
this.insertedDomEl.style.height = getCssDimension(height);
|
|
23334
23600
|
}
|
|
23335
23601
|
else if (this.preRenderWrapper) {
|
|
23336
|
-
this.preRenderWrapper.style.height =
|
|
23602
|
+
this.preRenderWrapper.style.height = getCssDimension(height);
|
|
23337
23603
|
}
|
|
23338
23604
|
}
|
|
23339
23605
|
else {
|
|
@@ -23617,9 +23883,16 @@ class TsEmbed {
|
|
|
23617
23883
|
* @param args
|
|
23618
23884
|
*/
|
|
23619
23885
|
async render() {
|
|
23886
|
+
var _a, _b, _c;
|
|
23620
23887
|
uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_RENDER_CALLED, {
|
|
23621
23888
|
embedComponentType: this.viewConfig.embedComponentType,
|
|
23622
23889
|
});
|
|
23890
|
+
uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_INIT_ACTIONS, {
|
|
23891
|
+
embedComponentType: this.viewConfig.embedComponentType,
|
|
23892
|
+
hiddenActions: (_a = this.viewConfig.hiddenActions) !== null && _a !== void 0 ? _a : [],
|
|
23893
|
+
visibleActions: (_b = this.viewConfig.visibleActions) !== null && _b !== void 0 ? _b : [],
|
|
23894
|
+
disabledActions: (_c = this.viewConfig.disabledActions) !== null && _c !== void 0 ? _c : [],
|
|
23895
|
+
});
|
|
23623
23896
|
if (!getIsInitCalled()) {
|
|
23624
23897
|
logger$3.error(ERROR_MESSAGE.RENDER_CALLED_BEFORE_INIT);
|
|
23625
23898
|
}
|
|
@@ -23768,47 +24041,34 @@ class TsEmbed {
|
|
|
23768
24041
|
delete container.dataset[PRERENDER_CONTAINER_ORIGINAL_POSITION_KEY];
|
|
23769
24042
|
}
|
|
23770
24043
|
/**
|
|
23771
|
-
*
|
|
23772
|
-
|
|
23773
|
-
|
|
23774
|
-
|
|
23775
|
-
* browser's job and costs nothing; repositioning it on scroll would mean a
|
|
23776
|
-
* layout read and a style write per frame to compensate for placing it in
|
|
23777
|
-
* the wrong box. Size is the one thing the browser will not do for us: the
|
|
23778
|
-
* placeholder grows when the embedded app reports a new height, and the
|
|
23779
|
-
* wrapper has to be told.
|
|
23780
|
-
*/
|
|
23781
|
-
observePreRenderSize() {
|
|
23782
|
-
var _a;
|
|
23783
|
-
if (this.getPreRenderConfig().doNotTrackSize || typeof ResizeObserver === 'undefined') {
|
|
23784
|
-
return;
|
|
23785
|
-
}
|
|
23786
|
-
const placeholder = this.getPreRenderPlaceHolderElement();
|
|
23787
|
-
if (!placeholder) {
|
|
24044
|
+
* Detaches and clears the container scroll listener, if one is attached.
|
|
24045
|
+
*/
|
|
24046
|
+
removeContainerScrollListener() {
|
|
24047
|
+
if (!this.containerScrollListener) {
|
|
23788
24048
|
return;
|
|
23789
24049
|
}
|
|
23790
|
-
|
|
23791
|
-
|
|
23792
|
-
this.
|
|
24050
|
+
const customContainer = this.getCustomPreRenderContainer();
|
|
24051
|
+
customContainer === null || customContainer === void 0 ? void 0 : customContainer.removeEventListener('scroll', this.containerScrollListener);
|
|
24052
|
+
this.containerScrollListener = null;
|
|
23793
24053
|
}
|
|
23794
24054
|
/**
|
|
23795
24055
|
* Destroys the ThoughtSpot embed, and remove any nodes from the DOM.
|
|
23796
24056
|
* @version SDK: 1.19.1 | ThoughtSpot: *
|
|
23797
24057
|
*/
|
|
23798
24058
|
destroy() {
|
|
23799
|
-
var _a, _b, _c
|
|
24059
|
+
var _a, _b, _c;
|
|
23800
24060
|
try {
|
|
23801
24061
|
this.removeFullscreenChangeHandler();
|
|
23802
|
-
|
|
24062
|
+
this.removeContainerScrollListener();
|
|
23803
24063
|
this.unsubscribeToEvents();
|
|
23804
|
-
(
|
|
24064
|
+
(_a = this.preRenderWrapper) === null || _a === void 0 ? void 0 : _a.remove();
|
|
23805
24065
|
this.restorePreRenderContainerPosition();
|
|
23806
24066
|
if (!this.isRendered) {
|
|
23807
24067
|
return;
|
|
23808
24068
|
}
|
|
23809
24069
|
if (!getEmbedConfig().waitForCleanupOnDestroy) {
|
|
23810
24070
|
this.trigger(HostEvent.DestroyEmbed);
|
|
23811
|
-
(
|
|
24071
|
+
(_c = (_b = this.insertedDomEl) === null || _b === void 0 ? void 0 : _b.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(this.insertedDomEl);
|
|
23812
24072
|
}
|
|
23813
24073
|
else {
|
|
23814
24074
|
const cleanupTimeout = getEmbedConfig().cleanupTimeout;
|
|
@@ -23854,6 +24114,26 @@ class TsEmbed {
|
|
|
23854
24114
|
this.isRendered = true;
|
|
23855
24115
|
return this.renderIFrame(prerenderFrameSrc);
|
|
23856
24116
|
}
|
|
24117
|
+
isConfigExcludedFromUrl() {
|
|
24118
|
+
var _a, _b, _c;
|
|
24119
|
+
const flag = (_b = (_a = this.viewConfig.additionalFlags) === null || _a === void 0 ? void 0 : _a.excludeConfigFromURL) !== null && _b !== void 0 ? _b : (_c = this.embedConfig.additionalFlags) === null || _c === void 0 ? void 0 : _c.excludeConfigFromURL;
|
|
24120
|
+
return flag === true || flag === 'true';
|
|
24121
|
+
}
|
|
24122
|
+
async triggerUpdateEmbedParams() {
|
|
24123
|
+
try {
|
|
24124
|
+
const params = await this.getUpdateEmbedParamsObject();
|
|
24125
|
+
this.trigger(HostEvent.UpdateEmbedParams, params);
|
|
24126
|
+
}
|
|
24127
|
+
catch (error) {
|
|
24128
|
+
logger$3.error(ERROR_MESSAGE.UPDATE_PARAMS_FAILED, error);
|
|
24129
|
+
this.handleError({
|
|
24130
|
+
errorType: ErrorDetailsTypes.API,
|
|
24131
|
+
message: (error === null || error === void 0 ? void 0 : error.message) || ERROR_MESSAGE.UPDATE_PARAMS_FAILED,
|
|
24132
|
+
code: EmbedErrorCodes.UPDATE_PARAMS_FAILED,
|
|
24133
|
+
error: (error === null || error === void 0 ? void 0 : error.message) || error,
|
|
24134
|
+
});
|
|
24135
|
+
}
|
|
24136
|
+
}
|
|
23857
24137
|
beforePrerenderVisible() {
|
|
23858
24138
|
// We can ignore this as its a bit expensive and the newer customers
|
|
23859
24139
|
// have moved on to UpdateEmbedParams supported clusters
|
|
@@ -23864,17 +24144,7 @@ class TsEmbed {
|
|
|
23864
24144
|
this.preRenderParamsApplied = new Promise((resolve) => {
|
|
23865
24145
|
this.executeAfterEmbedContainerLoaded(async () => {
|
|
23866
24146
|
try {
|
|
23867
|
-
|
|
23868
|
-
this.trigger(HostEvent.UpdateEmbedParams, params);
|
|
23869
|
-
}
|
|
23870
|
-
catch (error) {
|
|
23871
|
-
logger$3.error(ERROR_MESSAGE.UPDATE_PARAMS_FAILED, error);
|
|
23872
|
-
this.handleError({
|
|
23873
|
-
errorType: ErrorDetailsTypes.API,
|
|
23874
|
-
message: (error === null || error === void 0 ? void 0 : error.message) || ERROR_MESSAGE.UPDATE_PARAMS_FAILED,
|
|
23875
|
-
code: EmbedErrorCodes.UPDATE_PARAMS_FAILED,
|
|
23876
|
-
error: (error === null || error === void 0 ? void 0 : error.message) || error,
|
|
23877
|
-
});
|
|
24147
|
+
await this.triggerUpdateEmbedParams();
|
|
23878
24148
|
}
|
|
23879
24149
|
finally {
|
|
23880
24150
|
setTimeout(resolve, UPDATE_EMBED_PARAMS_SETTLE_MS);
|
|
@@ -23889,7 +24159,7 @@ class TsEmbed {
|
|
|
23889
24159
|
* wrapper to overlay it.
|
|
23890
24160
|
*/
|
|
23891
24161
|
async showPreRender() {
|
|
23892
|
-
var _a;
|
|
24162
|
+
var _a, _b;
|
|
23893
24163
|
uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_SHOW_PRE_RENDER, {
|
|
23894
24164
|
preRenderId: this.getPreRenderConfig().id,
|
|
23895
24165
|
embedComponentType: this.viewConfig.embedComponentType,
|
|
@@ -23908,16 +24178,14 @@ class TsEmbed {
|
|
|
23908
24178
|
this.beforePrerenderVisible();
|
|
23909
24179
|
if (this.hostElement) {
|
|
23910
24180
|
this.insertedDomEl = this.createPreRenderPlaceholder();
|
|
23911
|
-
|
|
23912
|
-
|
|
23913
|
-
|
|
23914
|
-
|
|
23915
|
-
|
|
23916
|
-
|
|
23917
|
-
|
|
23918
|
-
|
|
23919
|
-
&& wrapperHeight !== UNMEASURED_WRAPPER_HEIGHT) {
|
|
23920
|
-
this.insertedDomEl.style.height = wrapperHeight;
|
|
24181
|
+
if (this.viewConfig.fullHeight) {
|
|
24182
|
+
// If fullHeight has already sized the wrapper, seed the
|
|
24183
|
+
// placeholder with the same height so syncPreRenderStyle gets
|
|
24184
|
+
// an accurate rect.
|
|
24185
|
+
const existingHeight = this.preRenderWrapper.style.height;
|
|
24186
|
+
if (existingHeight) {
|
|
24187
|
+
this.insertedDomEl.style.height = existingHeight;
|
|
24188
|
+
}
|
|
23921
24189
|
}
|
|
23922
24190
|
const placeHolderId = this.getPreRenderIds().placeHolder;
|
|
23923
24191
|
// Remove any stale placeholder from a previous cycle. It is located
|
|
@@ -23931,19 +24199,29 @@ class TsEmbed {
|
|
|
23931
24199
|
(_a = this.hostElement.querySelector(`#${placeHolderId}`)) === null || _a === void 0 ? void 0 : _a.remove();
|
|
23932
24200
|
this.hostElement.appendChild(this.insertedDomEl);
|
|
23933
24201
|
this.syncPreRenderStyle();
|
|
23934
|
-
this.
|
|
24202
|
+
const customContainer = this.getCustomPreRenderContainer();
|
|
24203
|
+
if (customContainer && !this.containerScrollListener) {
|
|
24204
|
+
this.containerScrollListener = () => this.syncPreRenderStyle();
|
|
24205
|
+
customContainer.addEventListener('scroll', this.containerScrollListener);
|
|
24206
|
+
}
|
|
24207
|
+
if (!this.getPreRenderConfig().doNotTrackSize) {
|
|
24208
|
+
const observeTarget = (_b = this.insertedDomEl) !== null && _b !== void 0 ? _b : this.hostElement;
|
|
24209
|
+
this.resizeObserver = new ResizeObserver((entries) => {
|
|
24210
|
+
entries.forEach((entry) => {
|
|
24211
|
+
if (entry.target === observeTarget) {
|
|
24212
|
+
this.syncPreRenderStyle();
|
|
24213
|
+
}
|
|
24214
|
+
});
|
|
24215
|
+
});
|
|
24216
|
+
this.resizeObserver.observe(observeTarget);
|
|
24217
|
+
}
|
|
23935
24218
|
}
|
|
23936
24219
|
removeStyleProperties(this.preRenderWrapper, [
|
|
23937
24220
|
'z-index',
|
|
23938
24221
|
'opacity',
|
|
24222
|
+
'pointer-events',
|
|
23939
24223
|
'overflow',
|
|
23940
|
-
'transform',
|
|
23941
24224
|
]);
|
|
23942
|
-
// Set rather than removed: a container that carries `pointer-events:
|
|
23943
|
-
// none` — the usual styling for a parking root that must not swallow
|
|
23944
|
-
// clicks — passes it down, and dropping the property here would leave
|
|
23945
|
-
// the inherited `none` in force and the frame dead to input.
|
|
23946
|
-
setStyleProperties(this.preRenderWrapper, { pointerEvents: 'auto' });
|
|
23947
24225
|
this.subscribeToEvents();
|
|
23948
24226
|
// Setup fullscreen change handler for prerendered components
|
|
23949
24227
|
if (this.iFrame) {
|
|
@@ -23996,7 +24274,6 @@ class TsEmbed {
|
|
|
23996
24274
|
* If the component is not preRendered, it issues a warning.
|
|
23997
24275
|
*/
|
|
23998
24276
|
hidePreRender() {
|
|
23999
|
-
var _a;
|
|
24000
24277
|
uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_HIDE_PRE_RENDER, {
|
|
24001
24278
|
preRenderId: this.getPreRenderConfig().id,
|
|
24002
24279
|
embedComponentType: this.viewConfig.embedComponentType,
|
|
@@ -24016,15 +24293,12 @@ class TsEmbed {
|
|
|
24016
24293
|
top: '0',
|
|
24017
24294
|
left: '0',
|
|
24018
24295
|
overflow: 'hidden',
|
|
24019
|
-
// Keeps the measured size — so the next show needs no resize, which
|
|
24020
|
-
// is the point of pre-rendering — while lifting the box out of
|
|
24021
|
-
// the container's scrollable area. Overflow only extends
|
|
24022
|
-
// downwards, so a hidden frame parked above the top edge adds
|
|
24023
|
-
// none, where one left at full height shows as blank scroll space.
|
|
24024
|
-
transform: PRERENDER_PARKED_TRANSFORM,
|
|
24025
24296
|
};
|
|
24026
24297
|
setStyleProperties(this.preRenderWrapper, preRenderHideStyles);
|
|
24027
|
-
|
|
24298
|
+
this.removeContainerScrollListener();
|
|
24299
|
+
if (this.resizeObserver) {
|
|
24300
|
+
this.resizeObserver.disconnect();
|
|
24301
|
+
}
|
|
24028
24302
|
const placeHolderEle = this.getPreRenderPlaceHolderElement();
|
|
24029
24303
|
if (placeHolderEle) {
|
|
24030
24304
|
placeHolderEle.parentElement.removeChild(placeHolderEle);
|
|
@@ -24253,7 +24527,19 @@ function buildSpotterAnalystAppInitData(initData, viewConfig) {
|
|
|
24253
24527
|
spotterAnalystConfig,
|
|
24254
24528
|
},
|
|
24255
24529
|
};
|
|
24256
|
-
}
|
|
24530
|
+
}
|
|
24531
|
+
/**
|
|
24532
|
+
* The Spotter experience version to load in the embedded view.
|
|
24533
|
+
* @version SDK: 1.53.0 | ThoughtSpot Cloud: 26.11.0.cl
|
|
24534
|
+
* @group Embed components
|
|
24535
|
+
*/
|
|
24536
|
+
var SpotterExperienceVersion;
|
|
24537
|
+
(function (SpotterExperienceVersion) {
|
|
24538
|
+
/**
|
|
24539
|
+
* The Spotter experience version introduced in ThoughtSpot 26.11.
|
|
24540
|
+
*/
|
|
24541
|
+
SpotterExperienceVersion["SPOTTER_2026_11"] = "spotter_2026_11";
|
|
24542
|
+
})(SpotterExperienceVersion || (SpotterExperienceVersion = {}));
|
|
24257
24543
|
|
|
24258
24544
|
function buildSpotterVizAppInitData(initData, viewConfig) {
|
|
24259
24545
|
const { spotterViz } = viewConfig;
|
|
@@ -24450,12 +24736,12 @@ class AppEmbed extends V1Embed {
|
|
|
24450
24736
|
* embedded Liveboard or visualization.
|
|
24451
24737
|
*/
|
|
24452
24738
|
getEmbedParams() {
|
|
24453
|
-
const params = this.
|
|
24739
|
+
const params = this.getUrlQueryParamsObject();
|
|
24454
24740
|
return getQueryParamString(params, true);
|
|
24455
24741
|
}
|
|
24456
24742
|
getEmbedParamsObject() {
|
|
24457
24743
|
var _a;
|
|
24458
|
-
const { tag, hideTagFilterChips, hideObjects, liveboardV2, showPrimaryNavbar, disableProfileAndHelp, hideHamburger, hideObjectSearch, hideNotification, hideApplicationSwitcher, hideOrgSwitcher, enableSearchAssist, newConnectionsExperience, dataPanelV2 = true, updatedSpotterExperience, hideLiveboardHeader = false, showLiveboardTitle = true, showLiveboardDescription = true, showMaskedFilterChip = false, isLiveboardMasterpiecesEnabled, newChartsLibrary, hideHomepageLeftNav = false, modularHomeExperience, isLiveboardHeaderSticky = true, enableAskSage, collapseSearchBarInitially = false, enable2ColumnLayout, isLiveboardAlwaysOn12ColLayout, enableCustomColumnGroups = false, dataPanelCustomGroupsAccordionInitialState = DataPanelCustomColumnGroupsAccordionState$1.EXPAND_ALL, collapseSearchBar = true, isLiveboardCompactHeaderEnabled, showLiveboardVerifiedBadge = true, showLiveboardReverifyBanner = true, hideIrrelevantChipsInLiveboardTabs, isEnhancedFilterInteractivityEnabled, homePageSearchBarMode, isUnifiedSearchExperienceEnabled = true, enablePendoHelp = true, discoveryExperience, coverAndFilterOptionInPDF, isLiveboardStylingAndGroupingEnabled, liveboardGutter, isPNGInScheduledEmailsEnabled = false, isLiveboardXLSXCSVDownloadEnabled, isGranularXLSXCSVSchedulesEnabled, isCentralizedLiveboardFilterUXEnabled = false, isScopedLiveboardFilteringEnabled, isLinkParametersEnabled, updatedSpotterChatPrompt, showSpotterRadiance, defaultQueryMode, enableStopAnswerGenerationEmbed, spotterChatConfig, spotterDataSources, isThisPeriodInDateFiltersEnabled, enableHomepageAnnouncement = false, isContinuousLiveboardPDFEnabled, enableLiveboardDataCache, hideAnswerEditPanel, } = this.viewConfig;
|
|
24744
|
+
const { tag, hideTagFilterChips, hideObjects, liveboardV2, showPrimaryNavbar, disableProfileAndHelp, hideHamburger, hideObjectSearch, hideNotification, hideApplicationSwitcher, hideOrgSwitcher, enableSearchAssist, newConnectionsExperience, dataPanelV2 = true, updatedSpotterExperience, hideLiveboardHeader = false, showLiveboardTitle = true, showLiveboardDescription = true, showMaskedFilterChip = false, isLiveboardMasterpiecesEnabled, newChartsLibrary, hideHomepageLeftNav = false, modularHomeExperience, isLiveboardHeaderSticky = true, enableAskSage, collapseSearchBarInitially = false, enable2ColumnLayout, isLiveboardAlwaysOn12ColLayout, enableCustomColumnGroups = false, dataPanelCustomGroupsAccordionInitialState = DataPanelCustomColumnGroupsAccordionState$1.EXPAND_ALL, collapseSearchBar = true, isLiveboardCompactHeaderEnabled, showLiveboardVerifiedBadge = true, showLiveboardReverifyBanner = true, hideIrrelevantChipsInLiveboardTabs, isEnhancedFilterInteractivityEnabled, homePageSearchBarMode, isUnifiedSearchExperienceEnabled = true, enablePendoHelp = true, discoveryExperience, coverAndFilterOptionInPDF, isLiveboardStylingAndGroupingEnabled, liveboardGutter, isPNGInScheduledEmailsEnabled = false, isLiveboardXLSXCSVDownloadEnabled, isGranularXLSXCSVSchedulesEnabled, isCentralizedLiveboardFilterUXEnabled = false, isScopedLiveboardFilteringEnabled, isLinkParametersEnabled, updatedSpotterChatPrompt, showSpotterRadiance, defaultQueryMode, enableStopAnswerGenerationEmbed, spotterChatConfig, spotterDataSources, isThisPeriodInDateFiltersEnabled, enableHomepageAnnouncement = false, isContinuousLiveboardPDFEnabled, enableLiveboardDataCache, hideAnswerEditPanel, spotterExperienceVersion, } = this.viewConfig;
|
|
24459
24745
|
let params = {};
|
|
24460
24746
|
params[Param.PrimaryNavHidden] = !showPrimaryNavbar;
|
|
24461
24747
|
params[Param.HideProfleAndHelp] = !!disableProfileAndHelp;
|
|
@@ -24510,6 +24796,9 @@ class AppEmbed extends V1Embed {
|
|
|
24510
24796
|
if (spotterDataSources && spotterDataSources.length) {
|
|
24511
24797
|
params[Param.SpotterDataSources] = JSON.stringify(spotterDataSources);
|
|
24512
24798
|
}
|
|
24799
|
+
if (spotterExperienceVersion !== undefined) {
|
|
24800
|
+
params[Param.SpotterExperienceVersion] = spotterExperienceVersion;
|
|
24801
|
+
}
|
|
24513
24802
|
// Handle spotterChatConfig params
|
|
24514
24803
|
if (spotterChatConfig) {
|
|
24515
24804
|
const { hideToolResponseCardBranding, toolResponseCardBrandingLabel, spotterFileUploadEnabled, spotterFileUploadFileTypes, enableStarterPrompts, openSpotterOnLiveboardByDefault, } = spotterChatConfig;
|
|
@@ -24628,7 +24917,7 @@ class AppEmbed extends V1Embed {
|
|
|
24628
24917
|
}
|
|
24629
24918
|
// Navigation V1/V2 and home page V1/V2 are deprecated. V3 is now the
|
|
24630
24919
|
// default experience, Need to send navigationVersion=v3 and
|
|
24631
|
-
// homepageVersion=v3 even when the no discoveryExperience /
|
|
24920
|
+
// homepageVersion=v3 even when the no discoveryExperience /
|
|
24632
24921
|
// modularHomeExperience config is set. Without these
|
|
24633
24922
|
// params, older TSA versions (< 26.7) fall back to V2 for nav and
|
|
24634
24923
|
// home page, so the defaults must be sent explicitly from the SDK.
|
|
@@ -24767,46 +25056,6 @@ class AppEmbed extends V1Embed {
|
|
|
24767
25056
|
}
|
|
24768
25057
|
}
|
|
24769
25058
|
|
|
24770
|
-
/**
|
|
24771
|
-
* This method is like `_.isEqual` except that it accepts `customizer` which
|
|
24772
|
-
* is invoked to compare values. If `customizer` returns `undefined`, comparisons
|
|
24773
|
-
* are handled by the method instead. The `customizer` is invoked with up to
|
|
24774
|
-
* six arguments: (objValue, othValue [, index|key, object, other, stack]).
|
|
24775
|
-
*
|
|
24776
|
-
* @static
|
|
24777
|
-
* @memberOf _
|
|
24778
|
-
* @since 4.0.0
|
|
24779
|
-
* @category Lang
|
|
24780
|
-
* @param {*} value The value to compare.
|
|
24781
|
-
* @param {*} other The other value to compare.
|
|
24782
|
-
* @param {Function} [customizer] The function to customize comparisons.
|
|
24783
|
-
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
24784
|
-
* @example
|
|
24785
|
-
*
|
|
24786
|
-
* function isGreeting(value) {
|
|
24787
|
-
* return /^h(?:i|ello)$/.test(value);
|
|
24788
|
-
* }
|
|
24789
|
-
*
|
|
24790
|
-
* function customizer(objValue, othValue) {
|
|
24791
|
-
* if (isGreeting(objValue) && isGreeting(othValue)) {
|
|
24792
|
-
* return true;
|
|
24793
|
-
* }
|
|
24794
|
-
* }
|
|
24795
|
-
*
|
|
24796
|
-
* var array = ['hello', 'goodbye'];
|
|
24797
|
-
* var other = ['hi', 'goodbye'];
|
|
24798
|
-
*
|
|
24799
|
-
* _.isEqualWith(array, other, customizer);
|
|
24800
|
-
* // => true
|
|
24801
|
-
*/
|
|
24802
|
-
function isEqualWith(value, other, customizer) {
|
|
24803
|
-
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
24804
|
-
var result = customizer ? customizer(value, other) : undefined;
|
|
24805
|
-
return result === undefined ? _baseIsEqual(value, other, undefined, customizer) : !!result;
|
|
24806
|
-
}
|
|
24807
|
-
|
|
24808
|
-
var isEqualWith_1 = isEqualWith;
|
|
24809
|
-
|
|
24810
25059
|
const getPreviewQuery = `
|
|
24811
25060
|
query GetEurekaVizSnapshots(
|
|
24812
25061
|
$vizId: String!, $liveboardId: String!) {
|
|
@@ -24877,6 +25126,21 @@ const addPreviewStylesIfNotPresent = () => {
|
|
|
24877
25126
|
document.head.insertAdjacentHTML('beforeend', previewStyles);
|
|
24878
25127
|
};
|
|
24879
25128
|
|
|
25129
|
+
function buildLiveboardOverrideAppInitData(initData, viewConfig) {
|
|
25130
|
+
var _a;
|
|
25131
|
+
const { liveboardOverride } = viewConfig;
|
|
25132
|
+
// ThoughtSpot ignores an override with no data source entries; skip it.
|
|
25133
|
+
if (!((_a = liveboardOverride === null || liveboardOverride === void 0 ? void 0 : liveboardOverride.dataSourceOverride) === null || _a === void 0 ? void 0 : _a.length))
|
|
25134
|
+
return initData;
|
|
25135
|
+
return {
|
|
25136
|
+
...initData,
|
|
25137
|
+
embedParams: {
|
|
25138
|
+
...(initData.embedParams || {}),
|
|
25139
|
+
liveboardOverride,
|
|
25140
|
+
},
|
|
25141
|
+
};
|
|
25142
|
+
}
|
|
25143
|
+
|
|
24880
25144
|
/**
|
|
24881
25145
|
* Copyright (c) 2022
|
|
24882
25146
|
*
|
|
@@ -24906,11 +25170,6 @@ const HOME_SETTLE_MS = 200;
|
|
|
24906
25170
|
* })
|
|
24907
25171
|
* ```
|
|
24908
25172
|
*/
|
|
24909
|
-
/**
|
|
24910
|
-
* A shallow copy without the keys whose value is `undefined`, so a key that was
|
|
24911
|
-
* assigned `undefined` compares equal to one that was never set.
|
|
24912
|
-
*/
|
|
24913
|
-
const definedEntries = (config = {}) => Object.fromEntries(Object.entries(config).filter(([, value]) => value !== undefined));
|
|
24914
25173
|
class LiveboardEmbed extends V1Embed {
|
|
24915
25174
|
constructor(domSelector, viewConfig) {
|
|
24916
25175
|
viewConfig.embedComponentType = 'LiveboardEmbed';
|
|
@@ -24946,14 +25205,15 @@ class LiveboardEmbed extends V1Embed {
|
|
|
24946
25205
|
async getAppInitData() {
|
|
24947
25206
|
const defaultAppInitData = await super.getAppInitData();
|
|
24948
25207
|
const vizInitData = buildSpotterVizAppInitData(defaultAppInitData, this.viewConfig);
|
|
24949
|
-
|
|
25208
|
+
const starterPromptsInitData = buildStarterPromptsAppInitData(vizInitData, this.viewConfig);
|
|
25209
|
+
return buildLiveboardOverrideAppInitData(starterPromptsInitData, this.viewConfig);
|
|
24950
25210
|
}
|
|
24951
25211
|
/**
|
|
24952
25212
|
* Construct a map of params to be passed on to the
|
|
24953
25213
|
* embedded Liveboard or visualization.
|
|
24954
25214
|
*/
|
|
24955
25215
|
getEmbedParams() {
|
|
24956
|
-
const params = this.
|
|
25216
|
+
const params = this.getUrlQueryParamsObject();
|
|
24957
25217
|
const queryParams = getQueryParamString(params, true);
|
|
24958
25218
|
return queryParams;
|
|
24959
25219
|
}
|
|
@@ -24961,7 +25221,7 @@ class LiveboardEmbed extends V1Embed {
|
|
|
24961
25221
|
var _a;
|
|
24962
25222
|
let params = {};
|
|
24963
25223
|
params = this.getBaseQueryParams(params);
|
|
24964
|
-
const { enableVizTransformations, visibleVizs, liveboardV2, vizId, hideTabPanel, activeTabId, hideLiveboardHeader, showLiveboardDescription, showLiveboardTitle, isLiveboardHeaderSticky = true, isLiveboardCompactHeaderEnabled, showLiveboardVerifiedBadge = true, showLiveboardReverifyBanner = true, hideIrrelevantChipsInLiveboardTabs, showMaskedFilterChip = false, isLiveboardMasterpiecesEnabled, newChartsLibrary, isEnhancedFilterInteractivityEnabled, enableAskSage, enable2ColumnLayout, isLiveboardAlwaysOn12ColLayout, dataPanelV2 = true, updatedSpotterExperience, enableCustomColumnGroups = false, oAuthPollingInterval, isForceRedirect, dataSourceId, coverAndFilterOptionInPDF, isLiveboardStylingAndGroupingEnabled, liveboardGutter, isPNGInScheduledEmailsEnabled = false, isLiveboardXLSXCSVDownloadEnabled, isGranularXLSXCSVSchedulesEnabled, showSpotterLimitations, isCentralizedLiveboardFilterUXEnabled = false, isScopedLiveboardFilteringEnabled, isLinkParametersEnabled, updatedSpotterChatPrompt, showSpotterRadiance, enableStopAnswerGenerationEmbed, spotterChatConfig, isThisPeriodInDateFiltersEnabled, isContinuousLiveboardPDFEnabled, enableLiveboardDataCache, } = this.viewConfig;
|
|
25224
|
+
const { enableVizTransformations, visibleVizs, liveboardV2, vizId, hideTabPanel, activeTabId, hideLiveboardHeader, showLiveboardDescription, showLiveboardTitle, isLiveboardHeaderSticky = true, isLiveboardCompactHeaderEnabled, showLiveboardVerifiedBadge = true, showLiveboardReverifyBanner = true, hideIrrelevantChipsInLiveboardTabs, showMaskedFilterChip = false, isLiveboardMasterpiecesEnabled, newChartsLibrary, isEnhancedFilterInteractivityEnabled, enableAskSage, enable2ColumnLayout, isLiveboardAlwaysOn12ColLayout, dataPanelV2 = true, updatedSpotterExperience, enableCustomColumnGroups = false, oAuthPollingInterval, isForceRedirect, dataSourceId, coverAndFilterOptionInPDF, isLiveboardStylingAndGroupingEnabled, liveboardGutter, isPNGInScheduledEmailsEnabled = false, isLiveboardXLSXCSVDownloadEnabled, isGranularXLSXCSVSchedulesEnabled, showSpotterLimitations, isCentralizedLiveboardFilterUXEnabled = false, isScopedLiveboardFilteringEnabled, isLinkParametersEnabled, updatedSpotterChatPrompt, showSpotterRadiance, enableStopAnswerGenerationEmbed, spotterChatConfig, isThisPeriodInDateFiltersEnabled, isContinuousLiveboardPDFEnabled, enableLiveboardDataCache, spotterExperienceVersion, } = this.viewConfig;
|
|
24965
25225
|
const preventLiveboardFilterRemoval = this.viewConfig.preventLiveboardFilterRemoval
|
|
24966
25226
|
|| this.viewConfig.preventPinboardFilterRemoval;
|
|
24967
25227
|
(_a = this.fullHeightController) === null || _a === void 0 ? void 0 : _a.addQueryParams(params);
|
|
@@ -25023,6 +25283,9 @@ class LiveboardEmbed extends V1Embed {
|
|
|
25023
25283
|
if (isLiveboardStylingAndGroupingEnabled !== undefined) {
|
|
25024
25284
|
params[Param.IsLiveboardStylingAndGroupingEnabled] = isLiveboardStylingAndGroupingEnabled;
|
|
25025
25285
|
}
|
|
25286
|
+
if (spotterExperienceVersion !== undefined) {
|
|
25287
|
+
params[Param.SpotterExperienceVersion] = spotterExperienceVersion;
|
|
25288
|
+
}
|
|
25026
25289
|
if (liveboardGutter !== undefined) {
|
|
25027
25290
|
params[Param.LiveboardGutter] = liveboardGutter;
|
|
25028
25291
|
}
|
|
@@ -25192,12 +25455,10 @@ class LiveboardEmbed extends V1Embed {
|
|
|
25192
25455
|
beforePrerenderVisible() {
|
|
25193
25456
|
super.beforePrerenderVisible();
|
|
25194
25457
|
// Captured before showPreRender() hands the wrapper over to this
|
|
25195
|
-
// instance.
|
|
25196
|
-
//
|
|
25458
|
+
// instance. Itself means a hide/show, not a hand-over, so there is
|
|
25459
|
+
// nothing stale to clear.
|
|
25197
25460
|
const previous = this.getPreRenderObj();
|
|
25198
|
-
const showing = this.
|
|
25199
|
-
? undefined
|
|
25200
|
-
: previous === null || previous === void 0 ? void 0 : previous.currentLiveboardState;
|
|
25461
|
+
const showing = previous === this ? undefined : previous === null || previous === void 0 ? void 0 : previous.currentLiveboardState;
|
|
25201
25462
|
this.executeAfterEmbedContainerLoaded(async () => {
|
|
25202
25463
|
// Without this the params callback suspends on its await and
|
|
25203
25464
|
// Navigate goes out first, so the container loads with the previous
|
|
@@ -25224,25 +25485,6 @@ class LiveboardEmbed extends V1Embed {
|
|
|
25224
25485
|
};
|
|
25225
25486
|
});
|
|
25226
25487
|
}
|
|
25227
|
-
/**
|
|
25228
|
-
* Whether `previous` was showing what this instance is about to show.
|
|
25229
|
-
*
|
|
25230
|
-
* Undefined-valued keys are dropped before comparing. `navigateToLiveboard`
|
|
25231
|
-
* assigns `vizId`, `activeTabId` and `personalizedViewId` unconditionally,
|
|
25232
|
-
* so an instance that has been shown once carries those keys as `undefined`
|
|
25233
|
-
* while a freshly constructed one does not have them at all. `isEqual`
|
|
25234
|
-
* counts own keys, so without this the comparison can never be true after
|
|
25235
|
-
* the first show — which is the whole case this exists for.
|
|
25236
|
-
*
|
|
25237
|
-
* Callbacks compare as equal: React passes a fresh closure per render.
|
|
25238
|
-
*/
|
|
25239
|
-
isSameEmbedConfig(previous) {
|
|
25240
|
-
if (!previous)
|
|
25241
|
-
return false;
|
|
25242
|
-
if (previous === this)
|
|
25243
|
-
return true;
|
|
25244
|
-
return isEqualWith_1(definedEntries(previous.viewConfig), definedEntries(this.viewConfig), (a, b) => (typeof a === 'function' && typeof b === 'function' ? true : undefined));
|
|
25245
|
-
}
|
|
25246
25488
|
// The whole route, not just the liveboard id: the path is built from the
|
|
25247
25489
|
// viz, tab and view too, so a same-liveboard show onto another tab is a
|
|
25248
25490
|
// real navigation.
|
|
@@ -25505,7 +25747,7 @@ class SearchEmbed extends TsEmbed {
|
|
|
25505
25747
|
}
|
|
25506
25748
|
getEmbedParams() {
|
|
25507
25749
|
const { runtimeParameters, runtimeFilters, excludeRuntimeParametersfromURL, excludeRuntimeFiltersfromURL, } = this.viewConfig;
|
|
25508
|
-
const queryParams = this.
|
|
25750
|
+
const queryParams = this.getUrlQueryParamsObject();
|
|
25509
25751
|
let query = '';
|
|
25510
25752
|
const queryParamsString = getQueryParamString(queryParams, true);
|
|
25511
25753
|
if (queryParamsString) {
|
|
@@ -25593,7 +25835,7 @@ class SearchBarEmbed extends TsEmbed {
|
|
|
25593
25835
|
* @param dataSources A list of data source GUIDs
|
|
25594
25836
|
*/
|
|
25595
25837
|
getIFrameSrc() {
|
|
25596
|
-
const queryParams = this.
|
|
25838
|
+
const queryParams = this.getUrlQueryParamsObject();
|
|
25597
25839
|
const path = 'search-bar-embed';
|
|
25598
25840
|
let query = '';
|
|
25599
25841
|
const queryParamsString = getQueryParamString(queryParams, true);
|
|
@@ -26027,7 +26269,7 @@ class ConversationMessage extends TsEmbed {
|
|
|
26027
26269
|
getIframeSrc() {
|
|
26028
26270
|
const { sessionId, genNo, acSessionId, acGenNo, convId, messageId, } = this.viewConfig;
|
|
26029
26271
|
const path = 'conv-assist-answer';
|
|
26030
|
-
const queryParams = this.
|
|
26272
|
+
const queryParams = this.getUrlQueryParamsObject();
|
|
26031
26273
|
let query = '';
|
|
26032
26274
|
const queryParamsString = getQueryParamString(queryParams, true);
|
|
26033
26275
|
if (queryParamsString) {
|
|
@@ -26224,18 +26466,22 @@ class SpotterEmbed extends TsEmbed {
|
|
|
26224
26466
|
}
|
|
26225
26467
|
}
|
|
26226
26468
|
setParamIfDefined(queryParams, Param.UpdatedSpotterExperience, updatedSpotterExperience, true);
|
|
26469
|
+
setParamIfDefined(queryParams, Param.SpotterExperienceVersion, this.viewConfig.spotterExperienceVersion);
|
|
26227
26470
|
return queryParams;
|
|
26228
26471
|
}
|
|
26229
26472
|
getIframeSrc() {
|
|
26230
|
-
const { worksheetId, searchOptions, runtimeFilters, excludeRuntimeFiltersfromURL, runtimeParameters, excludeRuntimeParametersfromURL, sharedConversationId, dataSources, } = this.viewConfig;
|
|
26473
|
+
const { worksheetId, searchOptions, runtimeFilters, excludeRuntimeFiltersfromURL, runtimeParameters, excludeRuntimeParametersfromURL, sharedConversationId, dataSources, spotterExperienceVersion, } = this.viewConfig;
|
|
26231
26474
|
// Deep-link into the read-only shared-conversation reader view when a
|
|
26232
26475
|
// shared conversation id is supplied (e.g. a recipient landing from a
|
|
26233
26476
|
// host-configured CONVERSATION_URL share link); otherwise the normal
|
|
26234
26477
|
// Spotter conversation surface.
|
|
26235
|
-
|
|
26478
|
+
let path = sharedConversationId
|
|
26236
26479
|
? `insights/conv-assist/s/${encodeURIComponent(sharedConversationId)}`
|
|
26237
26480
|
: 'insights/conv-assist';
|
|
26238
|
-
|
|
26481
|
+
if (spotterExperienceVersion === SpotterExperienceVersion.SPOTTER_2026_11) {
|
|
26482
|
+
path = path.replace('insights/conv-assist', 'insights/spotter');
|
|
26483
|
+
}
|
|
26484
|
+
const queryParams = this.getUrlQueryParamsObject();
|
|
26239
26485
|
let query = '';
|
|
26240
26486
|
const queryParamsString = getQueryParamString(queryParams, true);
|
|
26241
26487
|
if (queryParamsString) {
|
|
@@ -27025,6 +27271,20 @@ function convertFilterChangedToUpdateFiltersPayload(filterChangedPayload) {
|
|
|
27025
27271
|
return { filters: [...liveboardFilterParams, ...runtimeFilterParams] };
|
|
27026
27272
|
}
|
|
27027
27273
|
|
|
27274
|
+
/**
|
|
27275
|
+
* Route the ThoughtSpot application uses to render a single conversational
|
|
27276
|
+
* answer. Used when a replayed frame carries no route of its own.
|
|
27277
|
+
*/
|
|
27278
|
+
const CONV_ASSIST_ANSWER_ROUTE = '/embed/conv-assist-answer';
|
|
27279
|
+
/**
|
|
27280
|
+
* Base path of the conversation service, proxied by the cluster's nginx as
|
|
27281
|
+
* the `convex` upstream. These are the same handlers the public
|
|
27282
|
+
* `/api/rest/2.0/ai/agent/conversations/...` endpoints proxy to, so the
|
|
27283
|
+
* response shapes are identical, but calling them directly skips the prism
|
|
27284
|
+
* hop and its error re-wrapping.
|
|
27285
|
+
*/
|
|
27286
|
+
const CONVERSATION_SERVICE_PATH = '/conversation/v2';
|
|
27287
|
+
const DEFAULT_STALE_ANSWER_NOTICE = 'This data may have changed since the last time you had a chat.';
|
|
27028
27288
|
/**
|
|
27029
27289
|
* Starts an automatic renderer that watches the DOM for iframes containing
|
|
27030
27290
|
* the `tsmcp=true` query parameter and replaces them with fully configured
|
|
@@ -27087,6 +27347,111 @@ function startAutoMCPFrameRenderer(viewConfig = {}) {
|
|
|
27087
27347
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
27088
27348
|
return observer;
|
|
27089
27349
|
}
|
|
27350
|
+
/**
|
|
27351
|
+
* Writes resolved session parameters into the route's hash query string,
|
|
27352
|
+
* preserving the route and any other hash params the source URL carried.
|
|
27353
|
+
*
|
|
27354
|
+
* @param sourceHash - The source URL's hash, with or without a leading `#`.
|
|
27355
|
+
* Falls back to the conversational-answer route when empty, so a host app
|
|
27356
|
+
* replaying a chat need only supply the conversation identifier.
|
|
27357
|
+
*/
|
|
27358
|
+
function buildAnswerHash(sourceHash, resolved) {
|
|
27359
|
+
const withoutHash = (sourceHash || '').replace('#', '');
|
|
27360
|
+
const [route, existingQuery] = withoutHash.split('?');
|
|
27361
|
+
const params = new URLSearchParams(existingQuery || '');
|
|
27362
|
+
Object.entries(resolved).forEach(([key, value]) => params.set(key, value));
|
|
27363
|
+
return `${route || CONV_ASSIST_ANSWER_ROUTE}?${params.toString()}`;
|
|
27364
|
+
}
|
|
27365
|
+
/**
|
|
27366
|
+
* Reads {@link Param.TsmcpAnswerIndex} as a whole, non-negative array index.
|
|
27367
|
+
*
|
|
27368
|
+
* Anything else - absent, malformed, fractional, negative - falls back to the
|
|
27369
|
+
* first answer rather than indexing with a value that can never match.
|
|
27370
|
+
*/
|
|
27371
|
+
function answerIndexFromParam(raw) {
|
|
27372
|
+
const parsed = Number(raw);
|
|
27373
|
+
return Number.isInteger(parsed) && parsed >= 0 ? parsed : 0;
|
|
27374
|
+
}
|
|
27375
|
+
/**
|
|
27376
|
+
* In-flight answer-id list requests, keyed by conversation-service URL.
|
|
27377
|
+
*
|
|
27378
|
+
* Replaying a stored chat mounts every one of its frames at once, and each
|
|
27379
|
+
* frame resolves on its own. Without this, N frames from one conversation make
|
|
27380
|
+
* N identical list calls. Sharing the in-flight request collapses them to one.
|
|
27381
|
+
*
|
|
27382
|
+
* Only the id list is shared, and only while its request is in flight: the
|
|
27383
|
+
* entry is dropped once the request settles, whether it succeeded or not. A
|
|
27384
|
+
* failed response is therefore never reused, and a frame mounted later always
|
|
27385
|
+
* reads a fresh list. The per-answer load call is never shared - it returns
|
|
27386
|
+
* live session state with its own expiry.
|
|
27387
|
+
*/
|
|
27388
|
+
const answerIdListRequests = new Map();
|
|
27389
|
+
/**
|
|
27390
|
+
* Lists a conversation's answer ids: its non-thinking `answer` items, in
|
|
27391
|
+
* message order. The host app counts answers the same way, so the Nth id here
|
|
27392
|
+
* is the Nth stored answer.
|
|
27393
|
+
*
|
|
27394
|
+
* @param conversationUrl - The conversation's base URL on the conversation
|
|
27395
|
+
* service, `{host}/conversation/v2/{encoded id}`.
|
|
27396
|
+
* @param conversationId - The conversation identifier, used in log messages.
|
|
27397
|
+
* @returns The ids, or `null` when the conversation cannot be read. Never
|
|
27398
|
+
* rejects, so callers sharing the request need no error handling of their own.
|
|
27399
|
+
*/
|
|
27400
|
+
async function fetchAnswerIds(conversationUrl, conversationId) {
|
|
27401
|
+
try {
|
|
27402
|
+
const messagesResponse = await tokenizedFetch(`${conversationUrl}/public`, {
|
|
27403
|
+
credentials: 'include',
|
|
27404
|
+
headers: { Accept: 'application/json' },
|
|
27405
|
+
});
|
|
27406
|
+
if (!messagesResponse.ok) {
|
|
27407
|
+
logger$3.warn(`[AutoFrameRenderer] Conversation fetch failed for ${conversationId}: ${messagesResponse.status}`);
|
|
27408
|
+
return null;
|
|
27409
|
+
}
|
|
27410
|
+
const messagesBody = await messagesResponse.json();
|
|
27411
|
+
const messages = messagesBody === null || messagesBody === void 0 ? void 0 : messagesBody.messages;
|
|
27412
|
+
const answerIds = [];
|
|
27413
|
+
for (const message of Array.isArray(messages) ? messages : []) {
|
|
27414
|
+
for (const item of (message === null || message === void 0 ? void 0 : message.response_items) || []) {
|
|
27415
|
+
if ((item === null || item === void 0 ? void 0 : item.type) === 'answer' && (item === null || item === void 0 ? void 0 : item.is_thinking) === false && (item === null || item === void 0 ? void 0 : item.answer_id)) {
|
|
27416
|
+
answerIds.push(item.answer_id);
|
|
27417
|
+
}
|
|
27418
|
+
}
|
|
27419
|
+
}
|
|
27420
|
+
return answerIds;
|
|
27421
|
+
}
|
|
27422
|
+
catch (e) {
|
|
27423
|
+
logger$3.warn(`[AutoFrameRenderer] Failed to list answers for ${conversationId}: ${e}`);
|
|
27424
|
+
return null;
|
|
27425
|
+
}
|
|
27426
|
+
}
|
|
27427
|
+
/**
|
|
27428
|
+
* The answer-id list for a conversation, joining a request already in flight
|
|
27429
|
+
* for it.
|
|
27430
|
+
*
|
|
27431
|
+
* @param conversationUrl - The conversation's base URL on the conversation
|
|
27432
|
+
* service. Also the key requests are shared under.
|
|
27433
|
+
* @param conversationId - The conversation identifier, used in log messages.
|
|
27434
|
+
* @param stale - A request the caller already read and found too short. It is
|
|
27435
|
+
* not reused; the first caller to pass it starts a new request, and the
|
|
27436
|
+
* others join that one.
|
|
27437
|
+
* @returns The shared request: the ids, or `null` when the conversation cannot
|
|
27438
|
+
* be read. Never rejects.
|
|
27439
|
+
*/
|
|
27440
|
+
function getAnswerIds(conversationUrl, conversationId, stale) {
|
|
27441
|
+
const inFlight = answerIdListRequests.get(conversationUrl);
|
|
27442
|
+
if (inFlight && inFlight !== stale) {
|
|
27443
|
+
return inFlight;
|
|
27444
|
+
}
|
|
27445
|
+
const request = fetchAnswerIds(conversationUrl, conversationId);
|
|
27446
|
+
answerIdListRequests.set(conversationUrl, request);
|
|
27447
|
+
const release = () => {
|
|
27448
|
+
if (answerIdListRequests.get(conversationUrl) === request) {
|
|
27449
|
+
answerIdListRequests.delete(conversationUrl);
|
|
27450
|
+
}
|
|
27451
|
+
};
|
|
27452
|
+
request.then(release, release);
|
|
27453
|
+
return request;
|
|
27454
|
+
}
|
|
27090
27455
|
function isTSMCPIframe(iframe) {
|
|
27091
27456
|
try {
|
|
27092
27457
|
const url = new URL(iframe.src);
|
|
@@ -27120,20 +27485,112 @@ class AutoFrameRenderer extends TsEmbed {
|
|
|
27120
27485
|
* ThoughtSpot application.
|
|
27121
27486
|
*
|
|
27122
27487
|
* @param sourceSrc - The original iframe's `src` URL string.
|
|
27488
|
+
* @param preserveSourceUrl - When true, return the source URL unchanged.
|
|
27123
27489
|
* @returns The constructed URL to use for the ThoughtSpot embed iframe.
|
|
27124
27490
|
*/
|
|
27125
|
-
getMCPIframeSrc(sourceSrc) {
|
|
27126
|
-
|
|
27491
|
+
getMCPIframeSrc(sourceSrc, resolved, preserveSourceUrl = false) {
|
|
27492
|
+
if (preserveSourceUrl) {
|
|
27493
|
+
return sourceSrc;
|
|
27494
|
+
}
|
|
27495
|
+
const queryParams = this.getUrlQueryParamsObject();
|
|
27127
27496
|
const sourceURL = new URL(sourceSrc);
|
|
27128
27497
|
const existingQueryParams = sourceURL.searchParams;
|
|
27129
27498
|
const existingQueryParamsObject = Object.fromEntries(existingQueryParams);
|
|
27130
27499
|
delete existingQueryParamsObject[Param.Tsmcp];
|
|
27500
|
+
// Replay markers address the SDK, not the ThoughtSpot application.
|
|
27501
|
+
delete existingQueryParamsObject[Param.TsmcpConversationId];
|
|
27502
|
+
delete existingQueryParamsObject[Param.TsmcpAnswerIndex];
|
|
27131
27503
|
const mergedQueryParams = { ...queryParams, ...existingQueryParamsObject };
|
|
27132
27504
|
const mergedQueryParamsString = getQueryParamString(mergedQueryParams, true);
|
|
27133
27505
|
const queryString = mergedQueryParamsString ? `?${mergedQueryParamsString}` : '';
|
|
27134
|
-
const
|
|
27506
|
+
const hash = resolved
|
|
27507
|
+
? buildAnswerHash(sourceURL.hash, resolved)
|
|
27508
|
+
: sourceURL.hash.replace('#', '');
|
|
27509
|
+
const frameSrc = `${this.getEmbedBasePath(queryString)}${hash}`;
|
|
27135
27510
|
return frameSrc;
|
|
27136
27511
|
}
|
|
27512
|
+
/**
|
|
27513
|
+
* Resolves the current session parameters for an answer stored only as a
|
|
27514
|
+
* conversation identifier plus an ordinal position.
|
|
27515
|
+
*
|
|
27516
|
+
* The answer object behind `sessionId`/`genNo` expires (roughly 8 hours),
|
|
27517
|
+
* so a host app replaying a stored chat cannot persist those values. It
|
|
27518
|
+
* persists the conversation identifier instead, and this walks the two
|
|
27519
|
+
* conversation-service APIs to rebuild them:
|
|
27520
|
+
*
|
|
27521
|
+
* 1. `GET {conv}/public` lists the conversation's messages; the
|
|
27522
|
+
* non-thinking `answer` items, in message order, give the answer ids.
|
|
27523
|
+
* Frames from the same conversation share one in-flight call - see
|
|
27524
|
+
* {@link getAnswerIds}.
|
|
27525
|
+
* 2. `POST {conv}/message/{id}/load/public` turns the answer id at
|
|
27526
|
+
* `answerIndex` into a live session identifier, generation number and
|
|
27527
|
+
* agent-context state.
|
|
27528
|
+
*
|
|
27529
|
+
* @returns The resolved parameters, or `null` when resolution fails - the
|
|
27530
|
+
* caller then falls back to whatever the source URL already carried.
|
|
27531
|
+
*/
|
|
27532
|
+
async resolveAnswerSessionParams(conversationId, answerIndex) {
|
|
27533
|
+
const base = `${this.thoughtSpotHost}${CONVERSATION_SERVICE_PATH}/${encodeURIComponent(conversationId)}`;
|
|
27534
|
+
try {
|
|
27535
|
+
const listRequest = getAnswerIds(base, conversationId);
|
|
27536
|
+
let answerIds = await listRequest;
|
|
27537
|
+
if (answerIds && !answerIds[answerIndex]) {
|
|
27538
|
+
// The list only grows, so a short one may predate this answer:
|
|
27539
|
+
// a frame that joined a request started before it was added.
|
|
27540
|
+
// Read the list once more before giving up.
|
|
27541
|
+
answerIds = await getAnswerIds(base, conversationId, listRequest);
|
|
27542
|
+
}
|
|
27543
|
+
if (!answerIds) {
|
|
27544
|
+
return null;
|
|
27545
|
+
}
|
|
27546
|
+
const answerId = answerIds[answerIndex];
|
|
27547
|
+
if (!answerId) {
|
|
27548
|
+
logger$3.warn(`[AutoFrameRenderer] No answer at index ${answerIndex} in conversation ${conversationId} (found ${answerIds.length}).`);
|
|
27549
|
+
return null;
|
|
27550
|
+
}
|
|
27551
|
+
// The load handler is a POST upstream; the public REST endpoint
|
|
27552
|
+
// exposed it as a GET and supplied this body on the caller's
|
|
27553
|
+
// behalf.
|
|
27554
|
+
const detailsResponse = await tokenizedFetch(`${base}/message/${encodeURIComponent(answerId)}/load/public`, {
|
|
27555
|
+
credentials: 'include',
|
|
27556
|
+
method: 'POST',
|
|
27557
|
+
headers: {
|
|
27558
|
+
Accept: 'application/json',
|
|
27559
|
+
'Content-Type': 'application/json',
|
|
27560
|
+
'x-requested-by': 'ThoughtSpot',
|
|
27561
|
+
},
|
|
27562
|
+
body: JSON.stringify({ type: 'TS_ANSWER' }),
|
|
27563
|
+
});
|
|
27564
|
+
if (!detailsResponse.ok) {
|
|
27565
|
+
logger$3.warn(`[AutoFrameRenderer] Answer load failed for ${answerId}: ${detailsResponse.status}`);
|
|
27566
|
+
return null;
|
|
27567
|
+
}
|
|
27568
|
+
const detailsBody = await detailsResponse.json();
|
|
27569
|
+
const answer = detailsBody === null || detailsBody === void 0 ? void 0 : detailsBody.answer;
|
|
27570
|
+
const acState = answer === null || answer === void 0 ? void 0 : answer.ac_state;
|
|
27571
|
+
// All four are nullable in the load-answer response. A missing
|
|
27572
|
+
// generation number is as unusable as a missing session id:
|
|
27573
|
+
// stringifying it would put a literal "null" in the hash. Fail
|
|
27574
|
+
// the resolve instead and let the caller fall back.
|
|
27575
|
+
if (!(answer === null || answer === void 0 ? void 0 : answer.session_identifier)
|
|
27576
|
+
|| !(acState === null || acState === void 0 ? void 0 : acState.transaction_identifier)
|
|
27577
|
+
|| !(Number.isInteger(answer.generation_number) && answer.generation_number > 0)
|
|
27578
|
+
|| !(Number.isInteger(acState.generation_number) && acState.generation_number > 0)) {
|
|
27579
|
+
logger$3.warn(`[AutoFrameRenderer] Answer load returned incomplete session state for ${answerId}.`);
|
|
27580
|
+
return null;
|
|
27581
|
+
}
|
|
27582
|
+
return {
|
|
27583
|
+
sessionId: answer.session_identifier,
|
|
27584
|
+
genNo: String(answer.generation_number),
|
|
27585
|
+
acSessionId: acState.transaction_identifier,
|
|
27586
|
+
acGenNo: String(acState.generation_number),
|
|
27587
|
+
};
|
|
27588
|
+
}
|
|
27589
|
+
catch (e) {
|
|
27590
|
+
logger$3.warn(`[AutoFrameRenderer] Failed to resolve stored answer: ${e}`);
|
|
27591
|
+
return null;
|
|
27592
|
+
}
|
|
27593
|
+
}
|
|
27137
27594
|
/**
|
|
27138
27595
|
* Overrides the base insertion behavior so the new embed iframe
|
|
27139
27596
|
* replaces the original iframe in-place rather than being appended
|
|
@@ -27162,10 +27619,37 @@ class AutoFrameRenderer extends TsEmbed {
|
|
|
27162
27619
|
if (this.shouldWaitForRenderPromise) {
|
|
27163
27620
|
await this.isReadyForRenderPromise;
|
|
27164
27621
|
}
|
|
27165
|
-
|
|
27622
|
+
// Only frames that ask for it take the replay path. A frame straight
|
|
27623
|
+
// from the MCP server carries its own session params and no
|
|
27624
|
+
// conversation id, so it renders exactly as it always has.
|
|
27625
|
+
const sourceParams = new URL(iframe.src).searchParams;
|
|
27626
|
+
const conversationId = sourceParams.get(Param.TsmcpConversationId);
|
|
27627
|
+
let resolved = null;
|
|
27628
|
+
if (conversationId) {
|
|
27629
|
+
resolved = await this.resolveAnswerSessionParams(conversationId, answerIndexFromParam(sourceParams.get(Param.TsmcpAnswerIndex)));
|
|
27630
|
+
}
|
|
27631
|
+
const src = this.getMCPIframeSrc(iframe.src, resolved !== null && resolved !== void 0 ? resolved : undefined, Boolean(conversationId) && !resolved);
|
|
27166
27632
|
await this.renderIFrame(src);
|
|
27633
|
+
// Mark only answers actually re-resolved: their numbers were computed
|
|
27634
|
+
// now, not when the conversation happened.
|
|
27635
|
+
if (resolved && !this.viewConfig.suppressStaleAnswerNotice) {
|
|
27636
|
+
this.markAsStaleAnswer();
|
|
27637
|
+
}
|
|
27167
27638
|
this.isRendered = true;
|
|
27168
27639
|
}
|
|
27640
|
+
/**
|
|
27641
|
+
* Adds the "data may have changed" notice to the rendered frame as a
|
|
27642
|
+
* native tooltip, so it needs no stylesheet and cannot disturb the host
|
|
27643
|
+
* app's layout.
|
|
27644
|
+
*/
|
|
27645
|
+
markAsStaleAnswer() {
|
|
27646
|
+
if (!this.iFrame) {
|
|
27647
|
+
return;
|
|
27648
|
+
}
|
|
27649
|
+
this.iFrame.title = this.viewConfig.staleAnswerNoticeText || DEFAULT_STALE_ANSWER_NOTICE;
|
|
27650
|
+
// Exposed so a host app can style or replace the native tooltip.
|
|
27651
|
+
this.iFrame.dataset.tsStaleAnswer = 'true';
|
|
27652
|
+
}
|
|
27169
27653
|
}
|
|
27170
27654
|
|
|
27171
|
-
export { Action, AnswerService, AppEmbed, ApplicabilityLevel, AuthEvent, AuthFailureType, AuthStatus, AuthType, BackgroundFormatType, BodylessConversation, ConditionalFormattingComparisonType, ConditionalFormattingOperator, ContextMenuTriggerOptions, ContextType, ConversationEmbed, CustomActionTarget, CustomActionsPosition, DataLabelFilterOperator, DataPanelCustomColumnGroupsAccordionState$1 as DataPanelCustomColumnGroupsAccordionState, DataSourceVisualMode, EmbedErrorCodes, EmbedErrorSeverity, EmbedEvent, ErrorDetailsTypes, HomeLeftNavItem, HomePage, HomePageSearchBarMode, HomepageModule, HostEvent, InterceptedApiType, LegendPosition, ListPage, ListPageColumns, LiveboardEmbed, LogLevel, MIXPANEL_EVENT, Page, PinboardEmbed, PrefetchFeatures, PrimaryNavbarVersion, RuntimeFilterOp, SearchBarEmbed, SearchEmbed, SpotterAgentEmbed, SpotterEmbed, SpotterQueryMode, TableContentDensity, TableTheme, UIPassthroughEvent, convertFilterChangedToUpdateFiltersPayload, createLiveboardWithAnswers, executeTML, exportTML, getAnswerFromQuery, getEmbedConfig as getInitConfig, getSessionInfo, init, logout, prefetch, reloadIframe, resetCachedAuthToken, startAutoMCPFrameRenderer, tokenizedFetch, uploadMixpanelEvent };
|
|
27655
|
+
export { Action, AnswerService, AppEmbed, ApplicabilityLevel, AuthEvent, AuthFailureType, AuthStatus, AuthType, BackgroundFormatType, BodylessConversation, ConditionalFormattingComparisonType, ConditionalFormattingOperator, ContextMenuTriggerOptions, ContextType, ConversationEmbed, CustomActionTarget, CustomActionsPosition, DataLabelFilterOperator, DataPanelCustomColumnGroupsAccordionState$1 as DataPanelCustomColumnGroupsAccordionState, DataSourceVisualMode, EmbedErrorCodes, EmbedErrorSeverity, EmbedEvent, ErrorDetailsTypes, HomeLeftNavItem, HomePage, HomePageSearchBarMode, HomepageModule, HostEvent, InterceptedApiType, LegendPosition, ListPage, ListPageColumns, LiveboardEmbed, LogLevel, MIXPANEL_EVENT, Page, PinboardEmbed, PrefetchFeatures, PrimaryNavbarVersion, RuntimeFilterOp, SearchBarEmbed, SearchEmbed, SpotterAgentEmbed, SpotterEmbed, SpotterExperienceVersion, SpotterQueryMode, TableContentDensity, TableTheme, UIPassthroughEvent, convertFilterChangedToUpdateFiltersPayload, createLiveboardWithAnswers, executeTML, exportTML, getAnswerFromQuery, getEmbedConfig as getInitConfig, getSessionInfo, init, logout, prefetch, reloadIframe, resetCachedAuthToken, startAutoMCPFrameRenderer, tokenizedFetch, uploadMixpanelEvent };
|