Skip to content

Commit adc3aa9

Browse files
committed
feat(spotter): add sidebar embed actions, events, params, and CSS variables
1 parent 504f01c commit adc3aa9

File tree

4 files changed

+4545
-2743
lines changed

4 files changed

+4545
-2743
lines changed

src/css-variables.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,4 +852,64 @@ export interface CustomCssVariables {
852852
* Width of the Spotter chat window.
853853
*/
854854
'--ts-var-spotter-chat-width'?: string;
855+
856+
/**
857+
* Border color for the saved chats sidebar container.
858+
*/
859+
'--ts-var-saved-chats-border-color'?: string;
860+
861+
/**
862+
* Background color for the saved chats sidebar container.
863+
*/
864+
'--ts-var-saved-chats-bg'?: string;
865+
866+
/**
867+
* Text color for the saved chats sidebar container.
868+
*/
869+
'--ts-var-saved-chats-text-color'?: string;
870+
871+
/**
872+
* Border color for the saved chats sidebar header.
873+
*/
874+
'--ts-var-saved-chats-header-border'?: string;
875+
876+
/**
877+
* Color for the saved chats sidebar title text.
878+
*/
879+
'--ts-var-saved-chats-title-color'?: string;
880+
881+
/**
882+
* Background color for buttons (new chat, toggle, footer) in the saved chats sidebar.
883+
*/
884+
'--ts-var-saved-chats-btn-bg'?: string;
885+
886+
/**
887+
* Hover background color for buttons in the saved chats sidebar.
888+
*/
889+
'--ts-var-saved-chats-btn-hover-bg'?: string;
890+
891+
/**
892+
* Text color for conversation items in the saved chats sidebar.
893+
*/
894+
'--ts-var-saved-chats-conv-text-color'?: string;
895+
896+
/**
897+
* Background color for conversation items on hover in the saved chats sidebar.
898+
*/
899+
'--ts-var-saved-chats-conv-hover-bg'?: string;
900+
901+
/**
902+
* Background color for the active/selected conversation in the saved chats sidebar.
903+
*/
904+
'--ts-var-saved-chats-conv-active-bg'?: string;
905+
906+
/**
907+
* Border color for the saved chats sidebar footer.
908+
*/
909+
'--ts-var-saved-chats-footer-border'?: string;
910+
911+
/**
912+
* Color for section title text (e.g., "Recent", "Older") in the saved chats sidebar.
913+
*/
914+
'--ts-var-saved-chats-section-title-color'?: string;
855915
}

src/embed/conversation.ts

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ import { Param, BaseViewConfig, RuntimeFilter, RuntimeParameter, ErrorDetailsTyp
44
import { TsEmbed } from './ts-embed';
55
import { getQueryParamString, getFilterQuery, getRuntimeParameters } from '../utils';
66

7+
/**
8+
* Validates that a URL uses only http: or https: protocols.
9+
* Returns true if valid, false otherwise.
10+
* @param url - The URL string to validate
11+
*/
12+
const isValidHttpUrl = (url: string): boolean => {
13+
try {
14+
const parsedUrl = new URL(url);
15+
return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
16+
} catch {
17+
return false;
18+
}
19+
};
20+
721
/**
822
* Configuration for search options
923
*/
@@ -200,6 +214,157 @@ export interface SpotterEmbedViewConfig extends Omit<BaseViewConfig, 'primaryAct
200214
* @version SDK: 1.45.0 | ThoughtSpot: 26.2.0.cl
201215
*/
202216
updatedSpotterChatPrompt?: boolean;
217+
/**
218+
* Custom title text for the sidebar header.
219+
* Defaults to translated "Spotter" text.
220+
*
221+
* Supported embed types: `SpotterEmbed`
222+
* @example
223+
* ```js
224+
* const embed = new SpotterEmbed('#tsEmbed', {
225+
* ... //other embed view config
226+
* spotterSidebarTitle: 'My Conversations',
227+
* })
228+
* ```
229+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
230+
*/
231+
spotterSidebarTitle?: string;
232+
/**
233+
* Boolean to set the default expanded state of the sidebar.
234+
*
235+
* Supported embed types: `SpotterEmbed`
236+
* @default false
237+
* @example
238+
* ```js
239+
* const embed = new SpotterEmbed('#tsEmbed', {
240+
* ... //other embed view config
241+
* spotterSidebarDefaultExpanded: true,
242+
* })
243+
* ```
244+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
245+
*/
246+
spotterSidebarDefaultExpanded?: boolean;
247+
/**
248+
* Custom label text for the rename action in the conversation edit menu.
249+
* Defaults to translated "Rename" text.
250+
*
251+
* Supported embed types: `SpotterEmbed`
252+
* @example
253+
* ```js
254+
* const embed = new SpotterEmbed('#tsEmbed', {
255+
* ... //other embed view config
256+
* spotterChatRenameLabel: 'Edit Name',
257+
* })
258+
* ```
259+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
260+
*/
261+
spotterChatRenameLabel?: string;
262+
/**
263+
* Custom label text for the delete action in the conversation edit menu.
264+
* Defaults to translated "DELETE" text.
265+
*
266+
* Supported embed types: `SpotterEmbed`
267+
* @example
268+
* ```js
269+
* const embed = new SpotterEmbed('#tsEmbed', {
270+
* ... //other embed view config
271+
* spotterChatDeleteLabel: 'Remove',
272+
* })
273+
* ```
274+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
275+
*/
276+
spotterChatDeleteLabel?: string;
277+
/**
278+
* Custom title text for the delete conversation confirmation modal.
279+
* Defaults to translated "Delete chat" text.
280+
*
281+
* Supported embed types: `SpotterEmbed`
282+
* @example
283+
* ```js
284+
* const embed = new SpotterEmbed('#tsEmbed', {
285+
* ... //other embed view config
286+
* spotterDeleteConversationModalTitle: 'Remove Conversation',
287+
* })
288+
* ```
289+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
290+
*/
291+
spotterDeleteConversationModalTitle?: string;
292+
/**
293+
* Custom message text for the past conversation banner alert.
294+
* Defaults to translated alert message.
295+
*
296+
* Supported embed types: `SpotterEmbed`
297+
* @example
298+
* ```js
299+
* const embed = new SpotterEmbed('#tsEmbed', {
300+
* ... //other embed view config
301+
* spotterPastConversationAlertMessage: 'You are viewing a past conversation',
302+
* })
303+
* ```
304+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
305+
*/
306+
spotterPastConversationAlertMessage?: string;
307+
/**
308+
* Custom URL for the documentation/best practices link.
309+
* Defaults to ThoughtSpot docs URL based on release version.
310+
* Note: URL must include the protocol (e.g., `https://www.example.com`).
311+
*
312+
* Supported embed types: `SpotterEmbed`
313+
* @example
314+
* ```js
315+
* const embed = new SpotterEmbed('#tsEmbed', {
316+
* ... //other embed view config
317+
* spotterDocumentationUrl: 'https://docs.example.com/spotter',
318+
* })
319+
* ```
320+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
321+
*/
322+
spotterDocumentationUrl?: string;
323+
/**
324+
* Custom label text for the best practices button in the footer.
325+
* Defaults to translated "Best Practices" text.
326+
*
327+
* Supported embed types: `SpotterEmbed`
328+
* @example
329+
* ```js
330+
* const embed = new SpotterEmbed('#tsEmbed', {
331+
* ... //other embed view config
332+
* spotterBestPracticesLabel: 'Help & Tips',
333+
* })
334+
* ```
335+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
336+
*/
337+
spotterBestPracticesLabel?: string;
338+
/**
339+
* Number of conversations to fetch per batch when loading conversation history.
340+
*
341+
* Supported embed types: `SpotterEmbed`
342+
* @default 30
343+
* @example
344+
* ```js
345+
* const embed = new SpotterEmbed('#tsEmbed', {
346+
* ... //other embed view config
347+
* spotterConversationsBatchSize: 50,
348+
* })
349+
* ```
350+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
351+
*/
352+
spotterConversationsBatchSize?: number;
353+
/**
354+
* Custom title text for the "New Chat" button in the sidebar.
355+
* Defaults to translated "New Chat" text.
356+
*
357+
* Supported embed types: `SpotterEmbed`
358+
* @example
359+
* ```js
360+
* const embed = new SpotterEmbed('#tsEmbed', {
361+
* ... //other embed view config
362+
* spotterNewChatButtonTitle: 'Start New Conversation',
363+
* })
364+
* ```
365+
* @version SDK: 1.46.0 | ThoughtSpot: 26.3.0.cl
366+
*/
367+
spotterNewChatButtonTitle?: string;
203368
}
204369

205370
/**
@@ -252,6 +417,16 @@ export class SpotterEmbed extends TsEmbed {
252417
runtimeParameters,
253418
excludeRuntimeParametersfromURL,
254419
updatedSpotterChatPrompt,
420+
spotterSidebarTitle,
421+
spotterSidebarDefaultExpanded,
422+
spotterChatRenameLabel,
423+
spotterChatDeleteLabel,
424+
spotterDeleteConversationModalTitle,
425+
spotterPastConversationAlertMessage,
426+
spotterDocumentationUrl,
427+
spotterBestPracticesLabel,
428+
spotterConversationsBatchSize,
429+
spotterNewChatButtonTitle,
255430
} = this.viewConfig;
256431

257432
if (!worksheetId) {
@@ -287,6 +462,35 @@ export class SpotterEmbed extends TsEmbed {
287462
queryParams[Param.UpdatedSpotterChatPrompt] = !!updatedSpotterChatPrompt;
288463
}
289464

465+
const sidebarParams: {
466+
key: keyof SpotterEmbedViewConfig;
467+
param: Param;
468+
isBoolean?: boolean;
469+
}[] = [
470+
{ key: 'spotterSidebarTitle', param: Param.SpotterSidebarTitle },
471+
{ key: 'spotterSidebarDefaultExpanded', param: Param.SpotterSidebarDefaultExpanded, isBoolean: true },
472+
{ key: 'spotterChatRenameLabel', param: Param.SpotterChatRenameLabel },
473+
{ key: 'spotterChatDeleteLabel', param: Param.SpotterChatDeleteLabel },
474+
{ key: 'spotterDeleteConversationModalTitle', param: Param.SpotterDeleteConversationModalTitle },
475+
{ key: 'spotterPastConversationAlertMessage', param: Param.SpotterPastConversationAlertMessage },
476+
{ key: 'spotterBestPracticesLabel', param: Param.SpotterBestPracticesLabel },
477+
{ key: 'spotterConversationsBatchSize', param: Param.SpotterConversationsBatchSize },
478+
{ key: 'spotterNewChatButtonTitle', param: Param.SpotterNewChatButtonTitle },
479+
];
480+
481+
sidebarParams.forEach(({ key, param, isBoolean }) => {
482+
const value = this.viewConfig[key];
483+
if (!isUndefined(value)) {
484+
queryParams[param] = isBoolean ? !!value : value;
485+
}
486+
});
487+
488+
if (!isUndefined(spotterDocumentationUrl)) {
489+
if (isValidHttpUrl(spotterDocumentationUrl)) {
490+
queryParams[Param.SpotterDocumentationUrl] = spotterDocumentationUrl;
491+
}
492+
}
493+
290494
return queryParams;
291495
}
292496

0 commit comments

Comments
 (0)