UNPKG

@thoughtspot/visual-embed-sdk

Version:
437 lines 19.9 kB
"use strict"; /** * Copyright (c) 2022 * * Full application embedding * https://developers.thoughtspot.com/docs/?pageid=full-embed * @summary Full app embed * @module * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.AppEmbed = exports.ListPage = exports.HomePage = exports.PrimaryNavbarVersion = exports.HomePageSearchBarMode = exports.DataPanelCustomColumnGroupsAccordionState = exports.Page = void 0; const logger_1 = require("../utils/logger"); const utils_1 = require("../utils"); const types_1 = require("../types"); const ts_embed_1 = require("./ts-embed"); /** * Pages within the ThoughtSpot app that can be embedded. */ var Page; (function (Page) { /** * Home page */ Page["Home"] = "home"; /** * Search page */ Page["Search"] = "search"; /** * Saved answers listing page */ Page["Answers"] = "answers"; /** * Liveboards listing page */ Page["Liveboards"] = "liveboards"; /** * @hidden */ Page["Pinboards"] = "pinboards"; /** * Data management page */ Page["Data"] = "data"; /** * SpotIQ listing page */ Page["SpotIQ"] = "insights"; /** * Monitor Alerts Page */ Page["Monitor"] = "monitor"; })(Page = exports.Page || (exports.Page = {})); /** * Define the initial state os column custom group accordions * in data panel v2. */ var DataPanelCustomColumnGroupsAccordionState; (function (DataPanelCustomColumnGroupsAccordionState) { /** * Expand all the accordion initially in data panel v2. */ DataPanelCustomColumnGroupsAccordionState["EXPAND_ALL"] = "EXPAND_ALL"; /** * Collapse all the accordions initially in data panel v2. */ DataPanelCustomColumnGroupsAccordionState["COLLAPSE_ALL"] = "COLLAPSE_ALL"; /** * Expand the first accordion and collapse the rest. */ DataPanelCustomColumnGroupsAccordionState["EXPAND_FIRST"] = "EXPAND_FIRST"; })(DataPanelCustomColumnGroupsAccordionState = exports.DataPanelCustomColumnGroupsAccordionState || (exports.DataPanelCustomColumnGroupsAccordionState = {})); var HomePageSearchBarMode; (function (HomePageSearchBarMode) { HomePageSearchBarMode["OBJECT_SEARCH"] = "objectSearch"; HomePageSearchBarMode["AI_ANSWER"] = "aiAnswer"; HomePageSearchBarMode["NONE"] = "none"; })(HomePageSearchBarMode = exports.HomePageSearchBarMode || (exports.HomePageSearchBarMode = {})); /** * Define the version of the primary navbar * @version SDK: 1.40.0 | ThoughtSpot: 10.11.0.cl */ var PrimaryNavbarVersion; (function (PrimaryNavbarVersion) { /** * Sliding (v3) introduces a new left-side navigation hub featuring a tab switcher, * along with updates to the top navigation bar. * It serves as the foundational version of the PrimaryNavBar. */ PrimaryNavbarVersion["Sliding"] = "v3"; })(PrimaryNavbarVersion = exports.PrimaryNavbarVersion || (exports.PrimaryNavbarVersion = {})); /** * Define the version of the home page * @version SDK: 1.40.0 | ThoughtSpot: 10.11.0.cl */ var HomePage; (function (HomePage) { /** * Modular (v2) introduces the updated Modular Home Experience. * It serves as the foundational version of the home page. */ HomePage["Modular"] = "v2"; /** * ModularWithStylingChanges (v3) introduces Modular Home Experience * with styling changes. */ HomePage["ModularWithStylingChanges"] = "v3"; })(HomePage = exports.HomePage || (exports.HomePage = {})); /** * Define the version of the list page * @version SDK: 1.40.0 | ThoughtSpot: 10.12.0.cl */ var ListPage; (function (ListPage) { /** * List (v2) is the traditional List Experience. * It serves as the foundational version of the list page. */ ListPage["List"] = "v2"; /** * ListWithUXChanges (v3) introduces the new updated list page with UX changes. */ ListPage["ListWithUXChanges"] = "v3"; })(ListPage = exports.ListPage || (exports.ListPage = {})); /** * Embeds full ThoughtSpot experience in a host application. * @group Embed components */ class AppEmbed extends ts_embed_1.V1Embed { constructor(domSelector, viewConfig) { viewConfig.embedComponentType = 'AppEmbed'; super(domSelector, viewConfig); this.defaultHeight = '100%'; this.sendFullHeightLazyLoadData = () => { const data = (0, utils_1.calculateVisibleElementData)(this.iFrame); this.trigger(types_1.HostEvent.VisibleEmbedCoordinates, data); }; /** * This is a handler for the RequestVisibleEmbedCoordinates event. * It is used to send the visible coordinates data to the host application. * @param data The event payload * @param responder The responder function */ this.requestVisibleEmbedCoordinatesHandler = (data, responder) => { logger_1.logger.info('Sending RequestVisibleEmbedCoordinates', data); const visibleCoordinatesData = (0, utils_1.calculateVisibleElementData)(this.iFrame); responder({ type: types_1.EmbedEvent.RequestVisibleEmbedCoordinates, data: visibleCoordinatesData }); }; /** * Set the iframe height as per the computed height received * from the ThoughtSpot app. * @param data The event payload */ this.updateIFrameHeight = (data) => { var _a; this.setIFrameHeight(Math.max(data.data, (_a = this.iFrame) === null || _a === void 0 ? void 0 : _a.scrollHeight)); this.sendFullHeightLazyLoadData(); }; this.embedIframeCenter = (data, responder) => { const obj = this.getIframeCenter(); responder({ type: types_1.EmbedEvent.EmbedIframeCenter, data: obj }); }; this.setIframeHeightForNonEmbedLiveboard = (data) => { const { height: frameHeight } = this.viewConfig.frameParams || {}; const liveboardRelatedRoutes = [ '/pinboard/', '/insights/pinboard/', '/schedules/', '/embed/viz/', '/embed/insights/viz/', '/liveboard/', '/insights/liveboard/', '/tsl-editor/PINBOARD_ANSWER_BOOK/', '/import-tsl/PINBOARD_ANSWER_BOOK/', ]; if (liveboardRelatedRoutes.some((path) => data.data.currentPath.startsWith(path))) { // Ignore the height reset of the frame, if the navigation is // only within the liveboard page. return; } this.setIFrameHeight(frameHeight || this.defaultHeight); }; if (this.viewConfig.fullHeight === true) { this.on(types_1.EmbedEvent.RouteChange, this.setIframeHeightForNonEmbedLiveboard); this.on(types_1.EmbedEvent.EmbedHeight, this.updateIFrameHeight); this.on(types_1.EmbedEvent.EmbedIframeCenter, this.embedIframeCenter); this.on(types_1.EmbedEvent.RequestVisibleEmbedCoordinates, this.requestVisibleEmbedCoordinatesHandler); } } /** * Constructs a map of parameters to be passed on to the * embedded Liveboard or visualization. */ getEmbedParams() { const { tag, hideObjects, liveboardV2, showPrimaryNavbar, disableProfileAndHelp, hideHamburger, hideObjectSearch, hideNotification, hideApplicationSwitcher, hideOrgSwitcher, enableSearchAssist, fullHeight, dataPanelV2 = true, hideLiveboardHeader = false, showLiveboardTitle = true, showLiveboardDescription = true, hideHomepageLeftNav = false, modularHomeExperience = false, isLiveboardHeaderSticky = true, enableAskSage, collapseSearchBarInitially = false, enable2ColumnLayout, enableCustomColumnGroups = false, isOnBeforeGetVizDataInterceptEnabled = false, dataPanelCustomGroupsAccordionInitialState = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL, collapseSearchBar = true, isLiveboardCompactHeaderEnabled = false, showLiveboardVerifiedBadge = true, showLiveboardReverifyBanner = true, hideIrrelevantChipsInLiveboardTabs = false, homePageSearchBarMode, isUnifiedSearchExperienceEnabled = true, enablePendoHelp = true, discoveryExperience, coverAndFilterOptionInPDF = false, liveboardXLSXCSVDownload = false, isLiveboardStylingAndGroupingEnabled, isPNGInScheduledEmailsEnabled = false, } = this.viewConfig; let params = {}; params[types_1.Param.PrimaryNavHidden] = !showPrimaryNavbar; params[types_1.Param.HideProfleAndHelp] = !!disableProfileAndHelp; params[types_1.Param.HideApplicationSwitcher] = !!hideApplicationSwitcher; params[types_1.Param.HideOrgSwitcher] = !!hideOrgSwitcher; params[types_1.Param.HideLiveboardHeader] = hideLiveboardHeader; params[types_1.Param.ShowLiveboardTitle] = showLiveboardTitle; params[types_1.Param.ShowLiveboardDescription] = !!showLiveboardDescription; params[types_1.Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky; params[types_1.Param.IsFullAppEmbed] = true; params[types_1.Param.LiveboardHeaderV2] = isLiveboardCompactHeaderEnabled; params[types_1.Param.ShowLiveboardVerifiedBadge] = showLiveboardVerifiedBadge; params[types_1.Param.ShowLiveboardReverifyBanner] = showLiveboardReverifyBanner; params[types_1.Param.HideIrrelevantFiltersInTab] = hideIrrelevantChipsInLiveboardTabs; params[types_1.Param.IsUnifiedSearchExperienceEnabled] = isUnifiedSearchExperienceEnabled; params[types_1.Param.CoverAndFilterOptionInPDF] = !!coverAndFilterOptionInPDF; params[types_1.Param.LiveboardXLSXCSVDownload] = !!liveboardXLSXCSVDownload; params = this.getBaseQueryParams(params); if (hideObjectSearch) { params[types_1.Param.HideObjectSearch] = !!hideObjectSearch; } if (hideHamburger) { params[types_1.Param.HideHamburger] = !!hideHamburger; } if (hideNotification) { params[types_1.Param.HideNotification] = !!hideNotification; } if (fullHeight === true) { params[types_1.Param.fullHeight] = true; if (this.viewConfig.lazyLoadingForFullHeight) { params[types_1.Param.IsLazyLoadingForEmbedEnabled] = true; params[types_1.Param.RootMarginForLazyLoad] = this.viewConfig.lazyLoadingMargin; } } if (tag) { params[types_1.Param.Tag] = tag; } if (hideObjects && hideObjects.length) { params[types_1.Param.HideObjects] = JSON.stringify(hideObjects); } if (liveboardV2 !== undefined) { params[types_1.Param.LiveboardV2Enabled] = liveboardV2; } if (enableSearchAssist !== undefined) { params[types_1.Param.EnableSearchAssist] = enableSearchAssist; } if (enable2ColumnLayout !== undefined) { params[types_1.Param.Enable2ColumnLayout] = enable2ColumnLayout; } if (enableAskSage) { params[types_1.Param.enableAskSage] = enableAskSage; } if (isOnBeforeGetVizDataInterceptEnabled) { params[types_1.Param.IsOnBeforeGetVizDataInterceptEnabled] = isOnBeforeGetVizDataInterceptEnabled; } if (homePageSearchBarMode) { params[types_1.Param.HomePageSearchBarMode] = homePageSearchBarMode; } if (enablePendoHelp !== undefined) { params[types_1.Param.EnablePendoHelp] = enablePendoHelp; } if (isLiveboardStylingAndGroupingEnabled !== undefined) { params[types_1.Param.IsLiveboardStylingAndGroupingEnabled] = isLiveboardStylingAndGroupingEnabled; } if (isPNGInScheduledEmailsEnabled !== undefined) { params[types_1.Param.isPNGInScheduledEmailsEnabled] = isPNGInScheduledEmailsEnabled; } params[types_1.Param.DataPanelV2Enabled] = dataPanelV2; params[types_1.Param.HideHomepageLeftNav] = hideHomepageLeftNav; params[types_1.Param.ModularHomeExperienceEnabled] = modularHomeExperience; params[types_1.Param.CollapseSearchBarInitially] = collapseSearchBarInitially || collapseSearchBar; params[types_1.Param.EnableCustomColumnGroups] = enableCustomColumnGroups; if (dataPanelCustomGroupsAccordionInitialState === DataPanelCustomColumnGroupsAccordionState.COLLAPSE_ALL || dataPanelCustomGroupsAccordionInitialState === DataPanelCustomColumnGroupsAccordionState.EXPAND_FIRST) { params[types_1.Param.DataPanelCustomGroupsAccordionInitialState] = dataPanelCustomGroupsAccordionInitialState; } else { params[types_1.Param.DataPanelCustomGroupsAccordionInitialState] = DataPanelCustomColumnGroupsAccordionState.EXPAND_ALL; } // Set navigation to v2 by default to avoid problems like the app // switcher (9-dot menu) not showing when v3 navigation is turned on // at the cluster level. // To use v3 navigation, we must manually set the discoveryExperience // settings. params[types_1.Param.NavigationVersion] = 'v2'; // Set homePageVersion to v2 by default to reset the LD flag value // for the homepageVersion. params[types_1.Param.HomepageVersion] = 'v2'; // Set listpageVersion to v2 by default to reset the LD flag value // for the listpageVersion. params[types_1.Param.ListPageVersion] = ListPage.List; if (discoveryExperience) { // primaryNavbarVersion v3 will enabled the new left navigation if (discoveryExperience.primaryNavbarVersion === PrimaryNavbarVersion.Sliding) { params[types_1.Param.NavigationVersion] = discoveryExperience.primaryNavbarVersion; // Enable the modularHomeExperience when Sliding is enabled. params[types_1.Param.ModularHomeExperienceEnabled] = true; } // homePage v2 will enable the modular home page // and it will override the modularHomeExperience value if (discoveryExperience.homePage === HomePage.Modular) { params[types_1.Param.ModularHomeExperienceEnabled] = true; } // ModularWithStylingChanges (v3) introduces the styling changes // to the Modular Homepage. // v3 will be the base version of homePageVersion. if (discoveryExperience.homePage === HomePage.ModularWithStylingChanges) { params[types_1.Param.HomepageVersion] = HomePage.ModularWithStylingChanges; } // listPageVersion v3 will enable the new list page if (discoveryExperience.listPageVersion === ListPage.ListWithUXChanges) { params[types_1.Param.ListPageVersion] = discoveryExperience.listPageVersion; } } const queryParams = (0, utils_1.getQueryParamString)(params, true); return queryParams; } /** * Constructs the URL of the ThoughtSpot app page to be rendered. * @param pageId The ID of the page to be embedded. */ getIFrameSrc() { const { pageId, path, modularHomeExperience } = this.viewConfig; const pageRoute = this.formatPath(path) || this.getPageRoute(pageId, modularHomeExperience); let url = `${this.getRootIframeSrc()}/${pageRoute}`; const tsPostHashParams = this.getThoughtSpotPostUrlParams(); url = `${url}${tsPostHashParams}`; return url; } /** * Gets the ThoughtSpot route of the page for a particular page ID. * @param pageId The identifier for a page in the ThoughtSpot app. * @param modularHomeExperience */ getPageRoute(pageId, modularHomeExperience = false) { switch (pageId) { case Page.Search: return 'answer'; case Page.Answers: return modularHomeExperience ? 'home/answers' : 'answers'; case Page.Liveboards: return modularHomeExperience ? 'home/liveboards' : 'pinboards'; case Page.Pinboards: return modularHomeExperience ? 'home/liveboards' : 'pinboards'; case Page.Data: return 'data/tables'; case Page.SpotIQ: return modularHomeExperience ? 'home/spotiq-analysis' : 'insights/results'; case Page.Monitor: return modularHomeExperience ? 'home/monitor-alerts' : 'insights/monitor-alerts'; case Page.Home: default: return 'home'; } } /** * Formats the path provided by the user. * @param path The URL path. * @returns The URL path that the embedded app understands. */ formatPath(path) { if (!path) { return null; } // remove leading slash if (path.indexOf('/') === 0) { return path.substring(1); } return path; } /** * Navigate to particular page for app embed. eg:answers/pinboards/home * This is used for embedding answers, pinboards, visualizations and full application * only. * @param path string | number The string, set to iframe src and navigate to new page * eg: appEmbed.navigateToPage('pinboards') * When used with `noReload` (default: true) this can also be a number * like 1/-1 to go forward/back. * @param noReload boolean Trigger the navigation without reloading the page * @version SDK: 1.12.0 | ThoughtSpot: 8.4.0.cl, 8.4.1-sw */ navigateToPage(path, noReload = false) { if (!this.iFrame) { logger_1.logger.log('Please call render before invoking this method'); return; } if (noReload) { this.trigger(types_1.HostEvent.Navigate, path); } else { if (typeof path !== 'string') { logger_1.logger.warn('Path can only by a string when triggered without noReload'); return; } const iframeSrc = this.iFrame.src; const embedPath = '#/embed'; const currentPath = iframeSrc.includes(embedPath) ? embedPath : '#'; this.iFrame.src = `${iframeSrc.split(currentPath)[0]}${currentPath}/${path.replace(/^\/?#?\//, '')}`; } } /** * Destroys the ThoughtSpot embed, and remove any nodes from the DOM. * @version SDK: 1.39.0 | ThoughtSpot: 10.10.0.cl */ destroy() { super.destroy(); this.unregisterLazyLoadEvents(); } postRender() { this.registerLazyLoadEvents(); } registerLazyLoadEvents() { if (this.viewConfig.fullHeight && this.viewConfig.lazyLoadingForFullHeight) { // TODO: Use passive: true, install modernizr to check for passive window.addEventListener('resize', this.sendFullHeightLazyLoadData); window.addEventListener('scroll', this.sendFullHeightLazyLoadData, true); } } unregisterLazyLoadEvents() { if (this.viewConfig.fullHeight && this.viewConfig.lazyLoadingForFullHeight) { window.removeEventListener('resize', this.sendFullHeightLazyLoadData); window.removeEventListener('scroll', this.sendFullHeightLazyLoadData); } } /** * Renders the embedded application pages in the ThoughtSpot app. * @param renderOptions An object containing the page ID * to be embedded. */ async render() { await super.render(); const src = this.getIFrameSrc(); await this.renderV1Embed(src); this.postRender(); return this; } } exports.AppEmbed = AppEmbed; //# sourceMappingURL=app.js.map