window.jsApiObjectName = 'yellowfin'; if(!window['yellowfin'] || (window['yellowfin'] && window['yellowfin'].loading)) { //We created a temp object for this, so lets overwrite it or we haven't created the object yet var loadPromise = window['yellowfin'] ? window['yellowfin'].load : null; if(!loadPromise) { loadPromise = new Promise(resolve => { resolve(); }); } window['yellowfin'] = { "load": loadPromise, "requests": [], "nextRequestId": 0, "apiLoadPromise": {}, "apiVersion": "3.0", "baseURL": "https://test.bi.adiqat.com/JsAPI/v3", "serverURL": "https://test.bi.adiqat.com", "showLoginPrompt": false, "scopeCss": true, "serverInfo": { "releaseVersion": "9.8", "buildVersion": "20230501", "javaVersion": "11.0.13", "operatingSystem": "Linux", "operatingSystemArch": "amd64", "operatingSystemVersion": "4.14.313-162.533.amzn1.x86_64", "schemaVersion": "20230501", "subVersion": "2.2", "base": ["dist/runtime.bundle.4e5607c3460a8d83f723.js?20230501","dist/vendor.chunk.1929e06f3478be99a48b.js?20230501","dist/common.chunk.e8cc2e80c0debc2570e3.js?20230501","dist/base_api.chunk.06f8ec55d9cc9788388a.js?20230501"], "loadedResources": {} }, "traceEnabled": false, "trace": function(name) { if (this.traceEnabled) { this.log('TRACE: ' + name); } }, "log": function(text) { if (window.console && console.log) { console.log(text); } }, "apiError": function(object) { this.trace('window[\'yellowfin\'].apiError()'); alert('${jsapi.error}: ' + object.errorDescription); }, "apiLoadError": function(object) { this.trace('window[\'yellowfin\'].apiLoadError()'); alert('${jsapi.error.load}: ' + object.errorDescription); }, "insertStyleSheetNode": function(css, scope) { if(scope === undefined) { scope = true; } if(scope && window['yellowfin'].scopeCss) { let href = css.href; //Find the last instance of "/" so we can grab the file name from that. And replace it with the JsAPICssCompress.i4?css=filename path let lastIndex = href.lastIndexOf('/'); let filename = href.substring(lastIndex + 1); let path = href.substring(0, lastIndex); let target = path + "/JsAPICssCompressor.i4?css=" + filename; //Get the path - this will be everything up to the final "/"; css.href = target; } var head = document.head; if (head.firstChild) { head.insertBefore(css, head.firstChild); } else { head.appendChild(css); } } , "insertStylesheet": function(url, scope) { this.trace('window[\'yellowfin\'].insertStylesheet()'); // Check if this link already exists in the head tag so we don't add duplicates var existingLinks = document.head.querySelectorAll('link[href="' + url + '"]'); if (existingLinks.length > 0) { return; } var css = document.createElement('link'); css.type = 'text/css'; css.rel = 'stylesheet'; css.href = url; css.media = 'screen'; css.classList.add('insertedCss'); window['yellowfin'].insertStyleSheetNode(css, scope); }, "_createScriptAndInsert": function(url) { var s = document.createElement('script'); s.type = 'text/javascript'; s.src = url; document.head.appendChild(s); return s; }, "insertScript": function(url, callback) { this.trace('window[\'yellowfin\'].insertScript()'); var s = this._createScriptAndInsert(url); s.onload = function() { if(callback) { callback(s); } } }, "getData": function(url, callback) { var s = this._createScriptAndInsert(url); s.onload = function() { var data = window['yellowfin'].result; window['yellowfin'].result = null; s.parentNode.removeChild(s); if(callback) { callback(data); } } }, "loadAPIResource": function(url, type, callback) { var promise = window['yellowfin'].serverInfo.loadedResources[url]; if(!promise) { promise = new Promise((resolve, reject) => { if(type === 'js') { window['yellowfin'].insertScript(url, () => { if(callback) { callback(); } resolve(); }); } else if(type === 'css') { window['yellowfin'].insertStylesheet(url, () => { resolve(); }); } }); window['yellowfin'].serverInfo.loadedResources[url] = promise; } return promise; }, "loadApi": function(apiName) { if(window['yellowfin'].apiLoadPromise[apiName]) return window['yellowfin'].apiLoadPromise[apiName]; /* IMPORTANT - Do not add any stylesheets before this. * window['yellowfin'].insertStyleSheet adds them in the reverse order in the DOM. * The first stylesheet is added last, and we need CustomCSS to be last. * loadSessionSpecificResources() loads CustomCSS. */ var promiseArr = this.loadSessionSpecificResources(); //Style sheet isn't required to be loaded before anything else can be, so just execute it window['yellowfin'].insertStylesheet(window['yellowfin'].serverURL + "/css/font-awesome/css/font-awesome.css"); var createScopedRequest = function(url) { if(window['yellowfin'].scopeCss) { url += "&scope=true"; } return url; } //This stylesheets should append the scope=true and not attempt to use the JsAPICompressor window['yellowfin'].insertStylesheet(createScopedRequest(window['yellowfin'].serverURL + '/css/YFCommonCompressor.i4?type=css&reportJsAPI=true'), false); window['yellowfin'].insertStylesheet(createScopedRequest(window['yellowfin'].serverURL + '/css/YFCommonCompressor.i4?type=css'), false); window['yellowfin'].insertStylesheet(window['yellowfin'].serverURL + '/SessionUtilJS.i4?type=fontTags', false); let loadPromise = new Promise((resolve, reject) => { let baseAPILoaded = function() { Promise.all(promiseArr).then(() => {window['yellowfin']._loadResources(window['yellowfin'].serverInfo[apiName]).then(() => { resolve(); }); }); } if(apiName === 'base') { baseAPILoaded(); } else { this.init().then(baseAPILoaded); } }); window['yellowfin'].apiLoadPromise[apiName] = loadPromise; return loadPromise }, "loadSessionSpecificResources": function() { let sessionResourcePromises = []; let sessionUtilURL = window['yellowfin'].serverURL + '/' + 'SessionUtilJS.i4?type=sessionUtil'; window['yellowfin'].serverInfo.loadedResources[sessionUtilURL] = null; let resourcesPromise = new Promise((resolve, reject) => { window['yellowfin'].loadAPIResource(sessionUtilURL, 'js', function() { var old = window.SessionUtil.getUrl; window.SessionUtil.getUrl = function(url) { var newUrl = old(url); return window.SessionUtil.getAbsoluteUrl(newUrl, window['yellowfin'].serverURL); }; }).then(() => { /** TextJS Should always be loaded after SessionUtil is loaded. Rather than concurrently. In a lot of cases this won't cause an issue, but if TextJSUrl is cached it can execute before the SessionUtil is added to the page, which will cause the text resources to not be usable by the page */ let textJSURL = window['yellowfin'].serverURL + '/' + 'SessionUtilJS.i4?type=text'; window['yellowfin'].serverInfo.loadedResources[textJSURL] = null; window['yellowfin'].loadAPIResource(textJSURL, 'js').then(() => { resolve(); }); if(window['yellowfin']._generateUser) { window['yellowfin']._generateUser(); } }); }); sessionResourcePromises.push(resourcesPromise); //Style sheet isn't required to be loaded before anything else can be, so just execute it /* IMPORTANT - Do not add any stylesheets before this. * window['yellowfin'].insertStyleSheet adds them in the reverse order in the DOM. * The first stylesheet is added last, and we need CustomCSS to be last. */ //Custom CSS is not scoped window['yellowfin'].insertStylesheet(window['yellowfin'].serverURL + '/css/CustomCSS.i4', false) return sessionResourcePromises; }, "loadReportAPI": function(element) { return new Promise((resolve, reject) => { window['yellowfin'].init().then(() => { window['yellowfin']._importReportsAPI(element).then(() => { resolve(); }) }) }); }, "loadDashboardAPI": function(element) { return new Promise((resolve, reject) => { window['yellowfin'].init().then(() => { window['yellowfin']._importDashboardAPI(element).then(() => { resolve(); }) }) }); }, "loadStoryAPI": function(element) { return new Promise((resolve, reject) => { window['yellowfin'].init().then(() => { window['yellowfin']._importStoryAPI(element).then(() => { resolve(); }) }) }); }, "loadNLQAPI": function() { return new Promise((resolve, reject) => { window['yellowfin'].init().then(() => { window['yellowfin']._importNLQAPI().then(() => { resolve(); }) }) }); }, "loadReport": function(options) { if(options.element && typeof options.element === 'string') { options.element = document.querySelector(options.element); } return new Promise((resolve, reject) => { window['yellowfin'].loadReportAPI(options.element).then(() => { window['yellowfin'].reports.loadReport(options).then(reportAPI => { resolve(reportAPI); }); }); }); }, "loadDashboard": function(options) { if(options.element && typeof options.element === 'string') { options.element = document.querySelector(options.element); } return new Promise((resolve, reject) => { window['yellowfin'].loadDashboardAPI(options.element).then(() => { window['yellowfin'].dashboards.loadDashboard(options).then(dashboardAPI => { resolve(dashboardAPI); }); }); }); }, "loadStory": function(options) { if(options.element && typeof options.element === 'string') { options.element = document.querySelector(options.element); } return new Promise((resolve, reject) => { window['yellowfin'].loadStoryAPI(options.element).then(() => { window['yellowfin'].stories.loadStory(options).then(storyAPI => { resolve(storyAPI); }); }); }); }, "loadNLQ": function(options) { if(!options) { options = {}; } if(options.element && typeof options.element === 'string') { options.element = document.querySelector(options.element); } return new Promise((resolve, reject) => { window['yellowfin'].loadNLQAPI().then(() => { window['yellowfin'].nlq.loadNLQ(options).then(nlqAPI => { resolve(nlqAPI); }); }); }); }, "_loadResources": function(resourceList) { return new Promise((resolve, reject) => { if (resourceList.length === 0) { // no resources to load, resolve immediately and return resolve(); return; } var counter = 0; var callbackFn = function() { counter++; if(counter >= resourceList.length) { resolve(); } } for(var i = 0; i < resourceList.length; i++) { var resource = resourceList[i]; if(window['yellowfin'].serverInfo.loadedResources[resource]) { callbackFn(); continue; } window['yellowfin'].serverInfo.loadedResources[resource] = true; window['yellowfin'].insertScript(window['yellowfin'].serverURL + "/" + resourceList[i], callbackFn); } }); }, "logoff": function(callback) { window['yellowfin'].trace('window[\'yellowfin\'].auth.logoffUser()'); var src = window['yellowfin'].baseURL + '?api=auth&cmd=logoff'; src += '&u=' + Math.floor(Math.random() * 1000000000); window['yellowfin'].insertScript(src, callback); }, "newSession": function(token, clientOrg) { return new Promise((resolve, reject) => { var src = window['yellowfin'].baseURL + '?api=auth&cmd=newSession&token=' + token + '&overwriteSession=true&clientOrg=' + clientOrg; src += '&u=' + Math.floor(Math.random() * 1000000000); var callbackFn = function(data) { window['yellowfin'].showLoginPrompt = data.showLoginPrompt; // We need to re-run all content in case the access rights, filters, etc of the newly logged // in user are different to the old user window['yellowfin'].refreshAll().then(() => { resolve(); }) } window['yellowfin'].getData(src, callbackFn); }); }, "exportContent": function(options) { options|| (options = {}); var data = { 'exportType': options.exportType, 'reportKey': options.reportKey }; var url = SessionUtil.getUrl('Dashboard.i4'); url += '?action=exportReport&subAction=' + encodeURIComponent(JSON.stringify(data)); window.location = url; }, /** * Initialises the base api, creates a promise that is resolved once the base api loads * @returns */ "init": function() { //We only want to store this once. As there are a number of other functions that call yelowfin.init() //We want to ensure that we have the $ object that existed the moment the page was included. if(!window['yellowfin'].existingJquery) { //Check if there is an existing $ on the page and if there is store it. window['yellowfin'].existingJquery = window.$; } return this.loadApi('base'); }, "isExternal": function() { return true; }, "cssScoping": true }; if (true) { window['yellowfin'].init(); } function getModifierKeys(event) { if(event == null) return {}; var modKeys = { ctrl : xor(event.metaKey, event.ctrlKey), shift : event.shiftKey }; return modKeys; } //Checks if one value is set but not both function xor(a,b) { return !a != !b; } }