// src/pages/ThoughtSpot/NewsletterLiveboard.tsx import React, { useEffect, useState, useRef, useCallback } from 'react'; import { init, LiveboardEmbed, AuthType, EmbedEvent, RuntimeFilterOp, type MessagePayload, } from '@thoughtspot/visual-embed-sdk'; import styles from './NewsletterLiveboard.module.scss'; import { thoughtSpotAuthService } from '@/services/thoughtspot'; import { appConfig } from '@/config/appConfig'; import { DynamicTabs, Tab } from '@fourkites/elemental-tabs'; import { Spinner } from '@fourkites/elemental-loading-indicator'; import { useAppSelector } from '@/store/redux/hooks'; import { UsersStateModule } from '@/store/redux/slices/usersSlice'; const liveboardConfigs = [ { id: '18d4cc6a-e356-4988-b3fa-c5314b365144', name: 'Ocean Newsletter' }, ]; const NewsletterLiveboard: React.FC = () => { const [isLoading, setIsLoading] = useState(true); const [errorMessage, setErrorMessage] = useState(null); const [activeLiveboardId, setActiveLiveboardId] = useState(liveboardConfigs[0]?.id || ''); const embedContainerRef = useRef(null); const sdkInitializedRef = useRef(false); const companyId = useAppSelector(UsersStateModule.selectors.getCompanyId); console.log(`--- NewsletterLiveboard Rendering --- companyId from Redux: ${companyId}`); const getAuthTokenCallback = useCallback(async (): Promise => { try { const token = await thoughtSpotAuthService.getThoughtSpotToken(); if (!token) throw new Error('Received an empty token from auth service.'); return token; } catch (e: any) { throw new Error(e.message || 'Failed to fetch auth token.'); } }, []); useEffect(() => { if (sdkInitializedRef.current || !appConfig.thoughtspotHost) return; init({ thoughtSpotHost: appConfig.thoughtspotHost, authType: AuthType.TrustedAuthToken, autoLogin: true, getAuthToken: getAuthTokenCallback, }); sdkInitializedRef.current = true; }, [appConfig.thoughtspotHost, getAuthTokenCallback]); useEffect(() => { let isMounted = true; let embedInstance: LiveboardEmbed | null = null; const embedLiveboard = async () => { if (!sdkInitializedRef.current || !embedContainerRef.current || !companyId) { setIsLoading(false); return; } setIsLoading(true); setErrorMessage(null); embedContainerRef.current.innerHTML = ''; try { const runtimeFilters = [{ columnName: 'Shipper ID', operator: RuntimeFilterOp.EQ, values: [companyId], }]; console.log(`%cCreating new LiveboardEmbed with filter:`, 'color: blue; font-weight: bold;', runtimeFilters); embedInstance = new LiveboardEmbed(embedContainerRef.current, { liveboardId: activeLiveboardId, runtimeFilters: runtimeFilters, frameParams: { width: '100%', height: '100%' }, fullHeight: true, }); embedInstance .on(EmbedEvent.Load, () => { if (isMounted) setIsLoading(false); }) .on(EmbedEvent.Error, (errorData: MessagePayload) => { /* ... error handling ... */ }); await embedInstance.render(); console.log('%cLiveboard render command sent.', 'color: green;'); } catch (error: any) { if (isMounted) { setErrorMessage(`Embedding Error: ${String(error.message || error)}`); setIsLoading(false); } } }; embedLiveboard(); return () => { isMounted = false; console.log(`%c<<< Effect CLEANUP for company: ${companyId}. Destroying instance.`, 'color: red;'); if (embedInstance) { embedInstance.destroy(); } }; }, [activeLiveboardId, companyId]); return (
setActiveLiveboardId(tabId)} selectedTab={activeLiveboardId} variant="flat"> {liveboardConfigs.map((lb) => ({lb.name}))}
{isLoading && !errorMessage && (

Loading Liveboard...

)} {errorMessage && (

Could not load Liveboard

{errorMessage}

)}
); }; export default NewsletterLiveboard;