@@ -4,6 +4,20 @@ import { Param, BaseViewConfig, RuntimeFilter, RuntimeParameter, ErrorDetailsTyp
44import { TsEmbed } from './ts-embed' ;
55import { 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