/* IBM Confidential OCO Source Materials IBM Cognos Products: rs (C) Copyright IBM Corp. 2003, 2021 The source code for this program is not published or otherwise divested of its trade secrets, irrespective of what has been deposited with the U.S. Copyright Office. */ define([ 'jquery', 'q', 'bi/authoring/utils/rsIFrameManager', 'bi/authoring/utils/rsCommon', 'bi/authoring/nls/StringResource', 'bi/commons/utils/LegacyUtils', 'bi/authoring/utils/pat/rsLaunchParameters', 'bi/authoring/utils/pat/rsPromptParameters' ], function($, Q, rsIFrameManager, rsCommon, StringResource, LegacyUtils, rsLaunchParameters, rsPromptParameters){ 'use strict'; var legacyUtils = null; /** * This method extends LegacyUtils by adding the method we need * Once LegacyUtils in ba-core-client is updated we can remove this method and * use LegacyUtils directly */ function getLegacyUtils() { if (!legacyUtils) { legacyUtils = LegacyUtils; if (!legacyUtils.getLegacyLaunchUrl) { legacyUtils.getLegacyLaunchUrl = function(glassContext, tool, object, action) { var qParms = this._getLaunchParms(glassContext, tool, object); qParms['ui.action'] = action; return this._getUrl(qParms); }.bind(LegacyUtils); } } return legacyUtils; } /** * Retrieve the URL that will launch the legacy application * Reject if unable to retrieve URL */ function getLegacyLaunchUrl( oOpenSpec ) { var tool = oOpenSpec.cmProperties.type == 'query' ? 'QueryStudio' : 'AnalysisStudio'; var searchPath = 'storeID("' + oOpenSpec.cmProperties.id + '")'; var v_sLaunchURL = getLegacyUtils().getLegacyLaunchUrl( oOpenSpec.glassContext, tool, searchPath, 'edit' ); if (oOpenSpec.urlMap.prompt != undefined) { v_sLaunchURL = v_sLaunchURL + '&prompt=' + (oOpenSpec.urlMap.prompt ? 'true' : 'false'); } // TODO add content and product locale to URL var v_sParameterValuesXML = oOpenSpec.urlMap.parameterValuesXML; if (!v_sParameterValuesXML && oOpenSpec.urlMap.parameterValuesJSON) { v_sParameterValuesXML = rsPromptParameters.rsBuildPromptParameters(null, oOpenSpec.urlMap.parameterValuesJSON, "parameters"); } if (v_sParameterValuesXML) { v_sLaunchURL = v_sLaunchURL + '&ui.drillThroughTargetParameterValues=' + encodeURIComponent(v_sParameterValuesXML); } return v_sLaunchURL; } function runActiveReportInNewWindow( urlMap ) { //console.log('rsOpenHelper.runActiveReportInNewWindow ...'); var deferred = Q.defer(); var v_sCmPath = 'storeID("' + urlMap.id + '")'; var v_sA11y = urlMap.a11y ? '&' + encodeURIComponent('system.http://developer.cognos.com/ceba/constants/systemOptionEnum#accessibilityFeatures') + '=true' : ''; var v_sBidi = urlMap.bidi ? '&' + encodeURIComponent('biDirectional.http://developer.cognos.com/ceba/constants/biDirectionalOptionEnum#biDirectionalFeaturesEnabled') + '=true' : ''; var v_sPrompt = urlMap.prompt != undefined ? ('&run.prompt=' + urlMap.prompt) : ''; var v_sUri = 'v1/disp?b_action=cognosViewer&ui.action=run&ui.object='+ v_sCmPath + v_sPrompt + v_sA11y + v_sBidi; try { var v_oWin = window.open( v_sUri, '', ''); v_oWin.focus(); //console.log('rsOpenHelper.runActiveReportInNewWindow ... succeeded'); deferred.resolve(v_oWin); } catch(e) { rsCommon.reject( deferred, 'Failed to opend window: ' + e.toString(), 'rsOpenHelper.runActiveReportInNewWindow' ); } finally { return deferred.promise; } } function isActiveReport( cmProperties ) { return rsCommon.isObjectOfType( cmProperties, 'interactiveReport' ); } function isDataSet2( cmProperties ) { return rsCommon.isObjectOfType( cmProperties, 'dataSet2' ); } function isReport_ish( cmProperties ) { return rsCommon.isObjectOfType( cmProperties, ['report', 'reportView', 'reportTemplate', 'interactiveReport', 'dataSet2', 'query', 'analysis'] ); } function loadCmProperties( v_oUrlMap, v_oCmProperties ) { if (v_oCmProperties) { // The id identifies the content-view. // By convention we are using the store-id to uniquely identify loaded content views. v_oUrlMap.cmProperties = v_oCmProperties; v_oUrlMap.id = v_oCmProperties.id; v_oUrlMap.type = v_oCmProperties.type; } } function getType(v_sId, glassContext) { var v_sSearchPathUrl = "v1/search_path?searchPath=" + encodeURIComponent("storeID('" + v_sId + "')") + "&fields=type"; return glassContext.services.fetch.get(v_sSearchPathUrl) .then( function(v_oCmInfoResponse) { return v_oCmInfoResponse.data.data[0].type; }); } /** * Return the default action based on the action ID and the CM properties. * null means no action is allowed. * undefined means we can't determine the default action. */ function determineDefaultAction(v_sActionId, v_oCmProperties, glassContext, urlMap) { if (urlMap && (urlMap.m_oPromptContext || (urlMap.m_oLaunchParameters && urlMap.m_oLaunchParameters.promptContext))) { // If we have a prompt context then we are handling prompting so the action is run // The classic and authoring perspectives load the prompt context differently hence the || in the condition. return glassContext.hasCapability('canUseCognosViewer') ? 'run' : 'none'; } var v_sAction; // = undefined; if (v_oCmProperties && v_oCmProperties.defaultPortalAction) { var v_bDefault = true; v_sAction = v_oCmProperties.defaultPortalAction; var v_sType = v_oCmProperties.type; switch (v_sActionId) { case 'com.ibm.bi.authoring.run': case 'com.ibm.bi.contentApps.action.runAs': case 'com.ibm.bi.authoringContrib.runBtn': v_sAction = 'run'; v_bDefault = false; break; default: if (v_sActionId && v_sActionId.indexOf('com.ibm.bi.contentApps.defaultAction.') == -1) { // A non-default action id was specified that is not one of the values above // Assume edit. v_sAction = 'edit'; v_bDefault = false; } } switch (v_sType) { case 'dataSet2': // Can only edit datasets. Switch action to edit if allowed. v_sAction = (v_oCmProperties.permissions.indexOf("read") != -1 && glassContext.hasCapability( 'canUseMyDataSets' )) ? 'edit' : null; break; case 'reportTemplate': // Can only edit report templates. Switch action to edit if allowed. v_sAction = (v_oCmProperties.permissions.indexOf("read") != -1 && glassContext.hasCapability( 'canUseReportStudio' )) ? 'edit' : null; break; case 'reportView': if (v_sAction == 'edit') { // Can't edit report views. Switch action to run instead. v_sAction = v_bDefault ? 'run' : null; } // fall through to default case default: var v_sStudioCapability; var v_bIsLegacy = false; switch (v_sType) { case 'query': v_sStudioCapability = 'canUseQueryStudio'; v_bIsLegacy = true; break; case 'analysis': v_sStudioCapability = 'canUseAnalysisStudio'; v_bIsLegacy = true; break; default: v_sStudioCapability = 'canUseReportStudio'; } if (v_bIsLegacy && v_sAction == 'edit') { var v_bTool = LegacyUtils.canUseLegacyTool( glassContext, v_sType == 'query' ? 'QueryStudio' : 'AnalysisStudio'); // Change edit to legacy if it is supported (e.g. Chrome does not support Query Studio) else run v_sAction = v_bTool ? 'legacy' : 'run'; } switch (v_sAction) { case 'edit': case 'legacy': if (v_oCmProperties.permissions.indexOf("read") == -1 || !glassContext.hasCapability( v_sStudioCapability )) { // Can't edit object without read access or the appropriate capability. Switch action to run if allowed. v_sAction = (v_oCmProperties.permissions.indexOf("execute") != -1 && v_bDefault) ? 'run' : null; } break; case 'run': if (v_oCmProperties.permissions.indexOf("execute") == -1) { // Can't execute report. Switch action to view if allowed. v_sAction = (v_oCmProperties.permissions.indexOf("read") != -1 && v_bDefault) ? 'viewOutput' : null; } break; case 'viewOutput': if (v_oCmProperties.permissions.indexOf("read") == -1) { // Can't view report. Switch action to run if allowed. v_sAction = (v_oCmProperties.permissions.indexOf("execute") != -1 && v_bDefault) ? 'run' : null; } break; default: v_sAction = null; } if ((v_sAction == 'run' || v_sAction == 'viewOutput') && !glassContext.hasCapability('canUseCognosViewer')) { v_sAction = null; } break; } } else if (urlMap && urlMap.isNew) { // No object available so either creating something new or we have an inline spec if (urlMap.isViewer) { v_sAction = glassContext.hasCapability('canUseCognosViewer') ? 'run' : 'none'; } else if (urlMap.perspective == 'authoring') { v_sAction = glassContext.hasCapability('canUseReportStudio') ? 'edit' : 'none'; } else if (urlMap.perspective == 'datasets') { v_sAction = glassContext.hasCapability('canUseMyDataSets') ? 'edit' : 'none'; } else { v_sAction = 'none'; } } return v_sAction; } function determineAction(v_oOpenSpec) { var v_sAction; var v_bAllowLegacy = true; var v_sCreateType; switch (v_oOpenSpec.actionId) { case "com.ibm.bi.authoring.run": case "com.ibm.bi.contentApps.action.runAs": v_sAction = 'run'; break; case "com.ibm.bi.authoring.createReportFromModule": case "com.ibm.bi.authoring.createReportFromPackage": v_sCreateType = "report"; v_sAction = 'edit'; break; case "com.ibm.bi.datasets.createDataSetFromModule": case "com.ibm.bi.datasets.createDataSetFromPackage": v_sCreateType = "dataSet2"; v_sAction = 'edit'; break; case 'com.ibm.bi.authoring.convertToReport': v_sAction = 'edit'; v_bAllowLegacy = false; // force edit break; default: v_sAction = v_oOpenSpec.urlMap.action; } var sObjectType = v_oOpenSpec.urlMap.cmProperties ? v_oOpenSpec.urlMap.cmProperties.type : undefined; switch (sObjectType) { case 'reportVersion': case 'output': // reportVersion and output objects can only be viewed v_sAction = v_oOpenSpec.glassContext.hasCapability('canUseCognosViewer') ? 'viewOutput' : 'none'; break; default: switch (v_sAction) { case 'run': case 'edit': case 'viewOutput': if (v_oOpenSpec.urlMap.isNew || !isReport_ish( v_oOpenSpec.urlMap.cmProperties )) { v_sAction = v_oOpenSpec.glassContext.hasCapability(v_sCreateType == 'dataSet2' ? 'canUseMyDataSets' : 'canUseReportStudio') ? 'edit' : 'none'; } if (v_sAction == 'edit' && (sObjectType == 'query' || sObjectType == 'analysis') && v_bAllowLegacy) { // edit on query and analysis means run the corresponding studio, not RS // But if the tool is not allowed, switch to run v_sAction = (LegacyUtils.canUseLegacyTool( v_oOpenSpec.glassContext, sObjectType == 'query' ? 'QueryStudio' : 'AnalysisStudio')) ? 'legacy' : 'run'; } break; case 'default': // classic viewer sends this case undefined: // Action unspecified, determine default from object v_sAction = determineDefaultAction(v_oOpenSpec.actionId, v_oOpenSpec.urlMap.cmProperties, v_oOpenSpec.glassContext, v_oOpenSpec.urlMap); v_oOpenSpec.defaultAction = true; break; default: // Unexpected action, change to null v_sAction = null; } } v_oOpenSpec.urlMap.action = v_sAction; } /** * Initialize the urlMap in the given open spec * @return the updated open spec */ function prepareUrlMap(v_oOpenSpec, v_oCmProperties) { // console.log('rsOpenHelper.prepareUrlMap'); var urlMap = v_oOpenSpec.urlMap || {}; rsCommon.convertStringQSToValues(urlMap, v_oOpenSpec.glassContext, v_oOpenSpec.trimURLParameterValues); var dataset = false; switch (v_oOpenSpec.actionId) { case "com.ibm.bi.datasets.createDataSetFromModule": case "com.ibm.bi.datasets.createDataSetFromPackage": urlMap.startingTemplate = "DatasetList"; dataset = true; urlMap.isNew = true; break; case "com.ibm.bi.contentApps.defaultAction.dataSet2": case "com.ibm.bi.datasets.editDataset": dataset = true; break; case "com.ibm.bi.authoring.createReportFromModule": case "com.ibm.bi.authoring.createReportFromPackage": urlMap.isNew = true; break; default: // In case there is no CM object and somehow the perspective was specified, use it to determine if we are dealing with a dataset dataset = isDataSet2(v_oCmProperties) || (!v_oCmProperties && urlMap.perspective == 'datasets'); // If object type is not one of the report-ish types, assume we are doing a new and the CM object is the metadata source object (package/module) urlMap.isNew = !isReport_ish( v_oCmProperties ); break; } loadCmProperties( urlMap, v_oCmProperties ); urlMap.isApplication = isActiveReport(v_oCmProperties); if (!urlMap.perspective && dataset) { // perspective not specified but we know we are dealing with a dataset // so only option is the dataset perspective urlMap.perspective = 'datasets'; } urlMap.UIProfile = urlMap.perspective == 'datasets' ? "TitanDataset" : "Titan"; rsCommon.decodeAndMoveRSOptions(urlMap); v_oOpenSpec.urlMap = urlMap; determineAction(v_oOpenSpec); return v_oOpenSpec; } // CM Options are an array like: // [ // 0: {name: optionName1, value: optionValue1, type: cmOptionType } // 1: {name: optionName2, value: optionValue2, type: cmOptionType } // 2: {name: optionName1, value: optionValue3, type: cmOptionType } // ... // ] // // convert into a regular object // { // optionName1: [optionValue1, optionValue3], // optionName2: optionValue2 // ... // } function convertToObjectFromCmOptionsArray(aCmOptions) { if (!aCmOptions || !Array.isArray(aCmOptions)) { return aCmOptions; } var oReturn = {}; aCmOptions.forEach(function(oOption){ if (typeof oReturn[oOption.name] === 'undefined') { oReturn[oOption.name] = oOption.value; } else if (Array.isArray(oReturn[oOption.name])) { oReturn[oOption.name].push( oOption.value); } else { // we already have value and it's not an array // add existing value AND the new value into an array // replace the whole value with the new array oReturn[oOption.name] = [oReturn[oOption.name], oOption.value]; } }); return oReturn; } function convertCmOptionsToSimpleArray(cmProperties) { // convert options cmProperties.options = convertToObjectFromCmOptionsArray(cmProperties.options); // convert options in base if any if (cmProperties.base && cmProperties.base.length > 0 && cmProperties.base[0]) { cmProperties.base[0].options = convertToObjectFromCmOptionsArray( cmProperties.base[0].options ); } } function getCMInfoForOpen( cmProperties, v_aProperties, glassContext ) { // console.log('rsOpenHelper.getCMInfoForOpen ...'); var deferred = Q.defer(); var v_sReportViewUrl = 'v1/objects/' + cmProperties.id; var v_aFields = []; v_aProperties.forEach(function(v_sField){ v_aFields.push(v_sField); }); v_aFields.join(','); var v_sReportViewPropsUrl = v_sReportViewUrl.concat('?fields=', v_aFields.join(',')); glassContext.services.ajax.ajax({ url: v_sReportViewPropsUrl, type: 'GET', dataType: 'json' }) .fail( function(err){ console.log('rsOpenHelper.getCMInfo ... FAILED'); deferred.reject(err); }) .done( function(resp){ if (! resp || ! resp.data || resp.data.length <= 0 ) { rsCommon.reject( deferred, 'unexpected response', 'rsOpenHelper.getCMInfoForOpen' ); return; } var v_oData = resp.data[0]; convertCmOptionsToSimpleArray(v_oData); convertCmOptionsToSimpleArray(cmProperties); // Extend new cm properties with the ones we already have var v_oCurrentCmProperties = cmProperties; for (var v_sProperty in v_oCurrentCmProperties) { if (v_oCurrentCmProperties.hasOwnProperty(v_sProperty) && v_oData[v_sProperty] == undefined) { v_oData[v_sProperty] = v_oCurrentCmProperties[v_sProperty]; } } //console.log('rsOpenHelper.getCMInfo ... succeeded'); deferred.resolve( v_oData ); }); return deferred.promise; } function f_determineMissingProperties( v_aProperties, v_oCmProperties ) { var v_aMissingProperties= []; // Check if we are missing any of the required properties var len = v_aProperties.length; for ( var i = 0; i < len; ++i ) { var v_sProperty = v_aProperties[i]; if (typeof v_oCmProperties[v_sProperty] == 'undefined') { v_aMissingProperties.push( v_sProperty ); } } return v_aMissingProperties; } // The list of CM properties required by rs (all scenarios including edit, viewer, share etc.) var m_aProperties = [ 'ancestors', 'defaultDescription', 'defaultName', 'defaultPortalAction', 'id', 'modificationTime', 'options', 'owner', 'parent', 'permissions', 'routingServerGroup', 'runInAdvancedViewer', 'searchPath', 'format', 'type' ]; var m_aOutputProperties = [ 'ancestors', 'dataDescriptor', 'defaultName', 'burstKey', 'id', 'modificationTime', 'owner', 'parent', 'permissions', 'searchPath', 'type', 'format', 'locale', 'lastPage' ]; var m_aReportVersionProperties = [ 'decoratedSpecification', 'id', 'parent' ]; function extractProperties( v_aPropertiesSpec, type ) { var v_aProperties; if (v_aPropertiesSpec) { v_aProperties = []; for (var idx = 0; idx < v_aPropertiesSpec.length; ++idx) { if (!type || !v_aPropertiesSpec[idx].type || v_aPropertiesSpec[idx].type.includes(type)) { v_aProperties.push(v_aPropertiesSpec[idx].property); } } } return v_aProperties; } /** * Get the cm object with all the necessary properties. * @param v_oCmProperties Current know properties. * @param glassContext The glass context. * @param v_aPropertiesSpec Set of properties to be retrieved. This is optional and if unspecified, * the complete set of properties needed by authoring will be retrieved. * This is an array of objects { property, type } where prop is the property and type is an optional array of types * to which the property applies. * @return The requested cm properties. */ function retreiveCMInfo(v_oCmProperties, glassContext, v_aPropertiesSpec) { //console.log('rsOpenHelper.retreiveCMInfo ...'); var deferred = Q.defer(); if (v_oCmProperties && v_oCmProperties.id && !v_oCmProperties.type) { // deal with situation where we were given an id but no type (URL with perspective and objRef) return getType(v_oCmProperties.id, glassContext) .then(function(v_sType){ v_oCmProperties.type = v_sType; return retreiveCMInfo(v_oCmProperties, glassContext, v_aPropertiesSpec); }); } // Based on type of given object, retrieve all potentially required information switch (v_oCmProperties ? v_oCmProperties.type : "none") { case undefined: rsCommon.reject( deferred, 'Missing properties or id', 'rsOpenHelper.retreiveCMInfo' ); break; case "none": deferred.resolve(undefined); break; case 'output': var v_aRequestProperties = f_determineMissingProperties( extractProperties(v_aPropertiesSpec, 'output') || m_aOutputProperties, v_oCmProperties ); getCMInfoForOpen( v_oCmProperties, v_aRequestProperties, glassContext ) .then( function( v_oOutput ) { if (v_aPropertiesSpec) { deferred.resolve(v_oOutput); } else { // For output, we need the reportVersion var v_oCmProperties = { id: v_oOutput.parent[0].id }; getCMInfoForOpen( v_oCmProperties, m_aReportVersionProperties, glassContext ) .then( function( v_oVersion ) { v_oOutput.parent[0] = v_oVersion; // link version to output // We also need the reportVersion parent (report, active report, reortView, query, analysis) // Since we are dealing with an output, we don't need the full set of report properties // so only ask for the minimal set. var v_oCmProperties = { id: v_oVersion.parent[0].id }; getCMInfoForOpen( v_oCmProperties, ['id', 'defaultName', 'type', 'base.type'], glassContext ) .then( function(v_oReport) { v_oVersion.parent[0] = v_oReport; // link report to reportVersion deferred.resolve(v_oOutput); }); }); } }) .catch( function(err){ console.log('rsOpenHelper.retreiveCMInfo ... FAILED'); deferred.reject(err); }); break; case 'reportVersion': var v_aRequestProperties = f_determineMissingProperties( extractProperties(v_aPropertiesSpec, 'reportVersion') || m_aReportVersionProperties, v_oCmProperties ); getCMInfoForOpen( v_oCmProperties, v_aRequestProperties, glassContext ) .then( function( v_oVersion ) { if (v_aPropertiesSpec) { deferred.resolve(v_oVersion); } else { // We also need the reportVersion parent (report, active report, reortView, query, analysis) // Since we are dealing with an output, we don't need the full set of report properties // so only ask for the minimal set. var v_oCmProperties = { id: v_oVersion.parent[0].id }; getCMInfoForOpen( v_oCmProperties, ['id', 'defaultName', 'type', 'base.type'], glassContext ) .then( function(v_oReport) { v_oVersion.parent[0] = v_oReport; deferred.resolve(v_oVersion); }); } }) .catch( function(err){ console.log('rsOpenHelper.retreiveCMInfo ... FAILED'); deferred.reject(err); }); break; case 'report': case 'reportView': case 'reportTemplate': case 'interactiveReport': case 'dataSet2': case 'query': case 'analysis': var v_aRequestProperties = f_determineMissingProperties( extractProperties(v_aPropertiesSpec, 'report') || m_aProperties, v_oCmProperties ); var v_bNeedBase = !v_aPropertiesSpec && v_oCmProperties.type == 'reportView'; if (v_bNeedBase) { // Dealing with a report view, get base properties var l = v_aRequestProperties.length; for (var i = 0; i < l; ++i) { v_aRequestProperties.push( 'base.' + v_aRequestProperties[i] ); } } else if (v_oCmProperties.type == 'report' && !(v_oCmProperties.metadataModelPackage && v_oCmProperties.metadataModelPackage[0] && v_oCmProperties.metadataModelPackage[0].effectiveUserCapabilities)) { v_aRequestProperties.push( 'metadataModelPackage.effectiveUserCapabilities' ); } if (v_aRequestProperties.length > 0) { getCMInfoForOpen( v_oCmProperties, v_aRequestProperties, glassContext ) .catch( function(err){ console.log('rsOpenHelper.retreiveCMInfo ... FAILED'); deferred.reject(err); }) .then(function(v_oUpdatedCmProperties) { //console.log('rsOpenHelper.retreiveCMInfo ... resolve/succeeded'); deferred.resolve(v_oUpdatedCmProperties); }); } else { // We know everything we need to //console.log('rsOpenHelper.retreiveCMInfo ... succeeded'); deferred.resolve(v_oCmProperties); } break; default: // Non-report like object, simply return it var v_aRequestProperties = f_determineMissingProperties( extractProperties(v_aPropertiesSpec, null) || ['type', 'searchPath'], v_oCmProperties ); if (v_aRequestProperties.length > 0) { getCMInfoForOpen( v_oCmProperties, v_aRequestProperties, glassContext ) .catch( function(err){ console.log('rsOpenHelper.retreiveCMInfo ... FAILED'); deferred.reject(err); }) .then(function(v_oUpdatedCmProperties) { //console.log('rsOpenHelper.retreiveCMInfo ... resolve/succeeded'); deferred.resolve(v_oUpdatedCmProperties); }); } else { // We know everything we need to //console.log('rsOpenHelper.retreiveCMInfo ... succeeded'); deferred.resolve(v_oCmProperties); } } return deferred.promise; } // 'spreadsheetML' | 'xlsxData' | 'PDF' | 'HTML' | 'CSV' | 'XML' function isOutputFormatSupportedInAdvancedViewer(v_sOutputFormat) { return ['HTML', 'PDF', 'spreadsheetML', 'xlsxData', 'CSV', 'XML'].indexOf(v_sOutputFormat) !== -1; } function isOutputForDownload(v_sOutputFormat) { return ['spreadsheetML', 'xlsxData', 'CSV', 'XML'].indexOf(v_sOutputFormat) !== -1; } function getValueFromFieldIfDefined(v_o, v_sField) { if (!v_o) { return; } // v_o may have come from a JSON response // JSON does not support undefined as a value // therefore we treat null as undefined if (typeof v_o[v_sField] === 'undefined' || v_o[v_sField] === null) { return; } return {value: v_o[v_sField]}; } function getFirstValueFromArrayFieldIfDefined(v_o, v_sField) { var o = getValueFromFieldIfDefined(v_o, v_sField); if (!o) { return; } var a = o.value; if (a.length < 1) { return; } // In certain cases 'a' is not an array but a string (powerPlay8Report for example) return {value: (Array.isArray(a) ? a[0]: a)}; } // Run in advanced viewer if the property says so function determineRunInAdvancedViewer(v_oProperties) { var o = getValueFromFieldIfDefined(v_oProperties, "runInAdvancedViewer"); return o ? o.value : false; } function consolidateRunInAdvancedViewer(v_oOpenSpec, v_sFormat) { // Determine the consolidated runInAdvancedViewer // The default for v_bRunInAdvancedViewer is false. // Why? // * For 'analysis' and 'query' we want to direct people to classic viewer to preserve their previous experience. // * For 'report' it maybe set, in which case we use the set value, or if not set, we use the default // * For 'interactiveReport' we don't care because we don't "view" them in the authoring perspective // var v_bRunInAdvancedViewer = false; var v_oProperties = v_oOpenSpec.launchSpec.cmProperties; if (determineRunInAdvancedViewer( v_oProperties.base && v_oProperties.base[0] ) || determineRunInAdvancedViewer( v_oProperties )) { v_bRunInAdvancedViewer = true; } if ( v_bRunInAdvancedViewer && v_sFormat && ! isOutputFormatSupportedInAdvancedViewer(v_sFormat)) { v_bRunInAdvancedViewer = false; } return v_bRunInAdvancedViewer; } function isRunInAdvancedViewer(v_oOpenSpec, v_sFormat) { // Determine the consolidated runInAdvancedViewer // The default for v_bRunInAdvancedViewer is false. // Why? // * For 'analysis' and 'query' we want to direct people to classic viewer to preserve their previous experience. // * For 'report' it maybe set, in which case we use the set value, or if not set, we use the default // * For 'interactiveReport' we don't care because we don't "view" them in the authoring perspective // var v_bRunInAdvancedViewer = false; var v_oCmProperties = v_oOpenSpec.urlMap.cmProperties; if ((v_oCmProperties && v_oCmProperties.base) ? determineRunInAdvancedViewer( v_oCmProperties.base[0] ) : determineRunInAdvancedViewer( v_oCmProperties )) { v_bRunInAdvancedViewer = true; } if ( v_bRunInAdvancedViewer && v_sFormat && ! isOutputFormatSupportedInAdvancedViewer(v_sFormat)) { v_bRunInAdvancedViewer = false; } return v_bRunInAdvancedViewer; } // Any run settings that have to be consolidated/reconciled from several sources, // i.e., the ultimate or final values // // returns // // { // format : null | 'HTML' | 'PDF' | etc // runInAdvancedViewer: true | false // prompt: true | false // } function consolidateAndReconcileRunOptions(v_oOpenSpec) { var urlMap = v_oOpenSpec.urlMap; var v_oCmBaseProperties = (urlMap.cmProperties && urlMap.cmProperties.base) ? urlMap.cmProperties.base[0] : null; var v_oCmProperties = urlMap.cmProperties || {}; var v_oPreferences = v_oOpenSpec.glassContext.services.userProfile.preferences; // Determine the consolidated output format if (urlMap.format == undefined) { var v_sFormat = v_oPreferences.format; var o = getFirstValueFromArrayFieldIfDefined(v_oCmBaseProperties && v_oCmBaseProperties.options, "outputFormat"); if (o) { v_sFormat = o.value || v_sFormat; } o = getFirstValueFromArrayFieldIfDefined(v_oCmProperties.options, "outputFormat"); if (o) { v_sFormat = o.value || v_sFormat; } if (isActiveReport(v_oCmProperties) || !rsCommon.isOutputFormatAllowed(v_sFormat, v_oOpenSpec.glassContext)) { // Replace invalid system determined format with HTML if format is invalid for current user v_sFormat = 'HTML'; } o = getValueFromFieldIfDefined(v_oOpenSpec.runOptions, "format"); if (o) { v_sFormat = o.value || v_sFormat; } urlMap.format = v_sFormat; } // Determine the consolidated a11y mode. // Note there is no run option for a11y in Titan, but there is a user preference & a report option if (urlMap.a11y == undefined) { var v_bA11y = v_oPreferences.accessibilityFeatures; var o = getValueFromFieldIfDefined(v_oCmBaseProperties && v_oCmBaseProperties.options, "http://developer.cognos.com/ceba/constants/systemOptionEnum#accessibilityFeatures"); if (o) { v_bA11y = o.value || v_bA11y; } o = getValueFromFieldIfDefined(v_oCmProperties.options, "http://developer.cognos.com/ceba/constants/systemOptionEnum#accessibilityFeatures"); if (o) { v_bA11y = o.value || v_bA11y; } urlMap.a11y = v_bA11y; } // Get bidi from user preferences - only place to set it in titan if (urlMap.bidi == undefined) { urlMap.bidi = v_oPreferences.biDirectionalFeaturesEnabled; } urlMap.Download = isOutputForDownload(urlMap.format) ? "true" : "false"; // Determine consolidated prompt value if (urlMap.prompt == undefined) { var v_bPrompt; // default value is undefined o = getValueFromFieldIfDefined(v_oCmBaseProperties && v_oCmBaseProperties.options, "prompt"); if (o) { v_bPrompt = o.value; } o = getValueFromFieldIfDefined(v_oCmProperties.options, "prompt"); if (o) { v_bPrompt = o.value; } // urlMap uses Prompt instead of executionPrompt, this happen in run options dialog in RS o = (urlMap.m_oLaunchParameters && urlMap.m_oLaunchParameters.RunOptions) ? getValueFromFieldIfDefined(urlMap.m_oLaunchParameters.RunOptions, "Prompt") : getValueFromFieldIfDefined(urlMap, "Prompt"); if (o) { v_bPrompt = (typeof o.value === "string") ? (o.value === "true") : !!o.value; } // runOptions uses prompt instead of executionPrompt o = getValueFromFieldIfDefined(v_oOpenSpec.runOptions, "prompt"); if (o) { v_bPrompt = o.value; } urlMap.prompt = v_bPrompt; } } function getActiveReportOutputURL( v_oCMProperties, v_oOutputProperties ) { var v_sReportId, v_sOutputId; if (v_oOutputProperties) { v_sReportId = v_oCMProperties.id; v_sOutputId = v_oOutputProperties.id; } else { if (v_oCMProperties.type == 'output') { v_sReportId = v_oCMProperties.parent[0].parent[0].id; v_sOutputId = v_oCMProperties.id; } else { v_sReportId = v_oCMProperties.id; v_sOutputId = 'default'; } } return 'v1/disp/repository/sid/cm/rid/' + v_sReportId + '/oid/' + v_sOutputId + '/content/mht/content'; } /** * Launch a URL by posting a form instead of using window.open * This ensures there are no issues with URL length. * @param sHref The URL to be opened * @param bNewWindow Specifies whether a new window (true) or current window (false) should be used. */ function openUrlViaForm(sHref, bNewWindow) { var v_nDrillForm; try { var v_sTarget = '_self'; if (bNewWindow) { v_sTarget = 'rsTarget' + Date.now(); if (!window.open("", v_sTarget)) { return false; } } var v_aUrlParts = sHref.split("?"); v_nDrillForm = document.body.appendChild(document.createElement("form")); v_nDrillForm.setAttribute("name", "drillForm"); v_nDrillForm.setAttribute("method", "post"); v_nDrillForm.setAttribute("action", decodeURIComponent(v_aUrlParts[0])); v_nDrillForm.setAttribute("target", v_sTarget); v_nDrillForm.style.display = "none"; if (v_aUrlParts.length == 2) { // Create an input element in the form for each parameter in the query string. var v_aParams = v_aUrlParts[1].split("&"); for (var i = 0; i < v_aParams.length; i++) { var v_aPair = v_aParams[i].split("="); var v_nFormField = v_nDrillForm.appendChild( document.createElement("input") ); v_nFormField.setAttribute("type", "hidden"); v_nFormField.setAttribute("name", decodeURIComponent(v_aPair[0])); v_nFormField.setAttribute("value", decodeURIComponent(v_aPair[1])); } } v_nDrillForm.submit(); } catch (e) { // If something went wrong, remove the form if it exists and return false indicating the window was not opened. if (v_nDrillForm) { document.body.removeChild(v_nDrillForm); } return false; } document.body.removeChild(v_nDrillForm); return true; } function launchViewSavedOutputApp(v_oOpenSpec, deferred) { if (v_oOpenSpec.href) { // classic active reports open in new window openUrlViaForm( v_oOpenSpec.href, true ); deferred.resolve(); } else { v_oOpenSpec.glassContext.openAppView(v_oOpenSpec.urlMap.perspective, {content: v_oOpenSpec.urlMap } ) .then( function() { deferred.resolve(); }); } } /** * This method either opens an object in the editor or runs's it and displays the results in a viewer. */ function launchEditOrRunApp(v_oOpenSpec, deferred) { var urlMap = v_oOpenSpec.urlMap; if (urlMap.action == 'run' && urlMap.isApplication && urlMap.perspective == "classicviewer") { // We are running an active report with the classic viewer. // This is done in a new window. runActiveReportInNewWindow( urlMap ) .then( function(v_activeReportResult){ //console.log('launchEditOrRunApp resolved'); deferred.resolve(v_activeReportResult); }) .catch( function(err) { console.log('launchEditOrRunApp rejected'); deferred.reject(err); }); return deferred.promise; } if (urlMap.perspective == "authoring") { var v_oRSParameters = rsCommon.createRSParameters(urlMap, v_oOpenSpec.glassContext); var v_oIFrameTemplateParameters = rsCommon.createTemplateParameters(v_oRSParameters); urlMap.launchPromise = rsIFrameManager.F_LaunchRS(v_oIFrameTemplateParameters, v_oOpenSpec.glassContext); // Pass RS parameters to rsContentView urlMap.m_oRSParameters = v_oRSParameters; } //console.log(' rsOpenHelper.launchEditOrRunApp - openingAppView ...'); // N.B. openAppView returns a jQuery deferred / promise v_oOpenSpec.glassContext.openAppView(urlMap.perspective, {content: urlMap } ) .fail(function(err){ console.log(' rsOpenHelper.launchEditOrRunApp - openingAppView ... FAILED'); deferred.reject(err); }) .done( function(v_oResult){ //console.log(' rsOpenHelper.launchEditOrRunApp - openingAppView ... succeeded'); deferred.resolve(v_oResult); }); } function launchApp(v_oOpenSpec) { //console.log('rsOpenHelper.launchApp ...'); var deferred = Q.defer(); switch (v_oOpenSpec.urlMap.action) { case 'none': // No action is available v_oOpenSpec.glassContext.showToast(StringResource.get('no_action_available'), {'type':'warning', 'btnLabel':'OK'}); deferred.resolve(); break; case 'viewOutput': launchViewSavedOutputApp(v_oOpenSpec, deferred); break; case 'run': case 'edit': launchEditOrRunApp(v_oOpenSpec, deferred); break; case 'legacy': var v_sLaunchUrl = getLegacyLaunchUrl( v_oOpenSpec ); if (!openUrlViaForm( v_sLaunchUrl, true )) { rsCommon.reject( deferred, 'Could not launch a new tab.', 'rsOpenHelper.launchApp' ); } else { deferred.resolve(); } break; default: rsCommon.reject( deferred, 'Unexpected action ' + v_oOpenSpec.urlMap.action + '.', 'rsOpenHelper.launchApp' ); } return deferred.promise; } function getSavedOutput(v_oGlassContext, v_oCmProperties, format, contentLocale) { if (v_oCmProperties.type == 'output') { // Already have the output which should include the required parentage from rsOpenHelper.retreiveCMInfo return Q.resolve( v_oCmProperties ); } return v_oGlassContext.getSvc('.Content') .then(function(v_oContentSvc) { // Get the appropriate output var v_sFormatHint = '"' + (format || '') + '"'; var v_sLocaleHint = '"' + (contentLocale || '') + '"'; var v_sSearchPath = 'defaultOutput(storeID("' + v_oCmProperties.id + '"),' + v_sFormatHint + ',' + v_sLocaleHint + ')'; var v_sCMQueryUrl = v_oContentSvc.getSearchPathUrl( v_sSearchPath ) + '&fields=dataDescriptor,parent,locale,format,permissions,ancestors,lastPage'; return v_oContentSvc.get(v_sCMQueryUrl, {}) .then(function( v_oSavedOutputResp ){ if (v_oSavedOutputResp && v_oSavedOutputResp.data && v_oSavedOutputResp.data.length > 0) { var v_oOutput = v_oSavedOutputResp.data[0]; if (v_oCmProperties.type == 'reportVersion') { // Already have the version and it's parent (as resolved by retreiveCMInfo) v_oOutput.parent[0] = v_oCmProperties; // link version in output return v_oOutput; } // Get the reportVersion and link to output var v_sCMQueryUrl = v_oContentSvc.getBaseObjectsURL() + '/' + v_oOutput.parent[0].id + '?fields=decoratedSpecification,id,parent'; return v_oContentSvc.get(v_sCMQueryUrl, {}) .then(function(v_oVersionResponse){ var v_oVersion = v_oVersionResponse.data[0]; v_oVersion.parent[0] = v_oCmProperties; // link report (or whatever) in version v_oOutput.parent[0] = v_oVersion; // link version in output return v_oOutput; }); } return null; }); }); } function resolveUrlMapForSavedOutput(v_oOpenSpec) { if (!v_oOpenSpec.urlMap.action) { return Q.reject(); } if (v_oOpenSpec.urlMap.action != 'viewOutput') { return Q.resolve(v_oOpenSpec); } return getSavedOutput( v_oOpenSpec.glassContext, v_oOpenSpec.urlMap.cmProperties, v_oOpenSpec.urlMap.format, v_oOpenSpec.urlMap.contentLocale ) .fail( function(err) { // Handle 404 response when there is no output return Q.resolve(null); }) .then(function(v_oOutput) { if (v_oOutput && v_oOutput.type == 'output' && v_oOutput.format != 'dataSet') { var v_bActiveReport = isActiveReport(v_oOutput); var v_sActiveReportOutputHref = v_bActiveReport ? getActiveReportOutputURL( v_oOutput ) : null; if (v_sActiveReportOutputHref && (!v_oOutput.dataDescriptor || v_oOutput.dataDescriptor.type != "interactive")) { // Force share URL that displays saved active report output of an activeReport // that uses the classic viewer to simply open the interactive report without the glass v_oOpenSpec.href = v_sActiveReportOutputHref; return Q.resolve( v_oOpenSpec ); } var v_oUrlMap = v_oOpenSpec.urlMap; //Required by glass: If a saved output has been found, the id will be set as the report id, that is used to trying to //open the view, the objRef will be updated to the saved output return rsCommon.getAvailableOutputs(v_oOpenSpec.glassContext, v_oOutput) .then(function(v_oSavedOutputFormats) { if (!v_oSavedOutputFormats || !v_oSavedOutputFormats.data || v_oSavedOutputFormats.data.length <= 0) { return Q.reject(new Error('unexpected response for rsCommon.getAvailableOutputs')); } v_oUrlMap.perspective = 'classicviewer'; if ((v_oOutput.dataDescriptor && v_oOutput.dataDescriptor.type == "interactive") || v_oOutput.format == 'PDF') { // If output is tagged as interactive or it is PDF then use interactive viewer v_oUrlMap.perspective = 'authoring'; v_oUrlMap.outputSpec = v_oOutput.parent[0].decoratedSpecification; } if ( v_oOpenSpec.glassContext.isEmbedded() ) { v_oUrlMap.perspective += '_embedded'; } if (!v_bActiveReport) { v_oUrlMap.format = v_oOutput.format || v_oUrlMap.format; } else { // active reports support only 1 format so no need to specify delete v_oUrlMap.format; } var v_oOutputLookup = {}; for (var i = 0; i < v_oSavedOutputFormats.data.length; ++i) { var v_oAltOutput = v_oSavedOutputFormats.data[i]; if (v_oAltOutput.locale == v_oOutput.locale) { v_oOutputLookup[v_oAltOutput.format] = v_oAltOutput; } } v_oUrlMap.outputFormatLookup = v_oOutputLookup; v_oUrlMap.reportProperties = { // report is output grand-parent id : v_oOutput.parent[0].parent[0].id, type : v_oOutput.parent[0].parent[0].type }; loadCmProperties( v_oUrlMap, v_oOutput ); v_oUrlMap.objRef = v_oOutput.id; // use id of output object delete v_oUrlMap.pathRef; return Q.resolve(v_oOpenSpec); }); } else { // No saved output, determine alternate action var v_aPermissions = v_oOpenSpec.urlMap.cmProperties.permissions; var v_sCmType = v_oOpenSpec.urlMap.cmProperties.type; switch (v_sCmType) { case 'query': case 'analysis': if (v_aPermissions.indexOf("execute") != -1) { // For analysis and query, the view action becomes edit if there is no saved output (but only if user can launch studio) // otherwise try run var v_bRead = v_aPermissions.indexOf("read") != -1; var v_bCapability = v_oOpenSpec.glassContext.hasCapability( v_sCmType == 'query' ? 'canUseQueryStudio' : 'canUseAnalysisStudio' ); var v_bTool = LegacyUtils.canUseLegacyTool( v_oOpenSpec.glassContext, v_sCmType == 'query' ? 'QueryStudio' : 'AnalysisStudio'); v_oOpenSpec.urlMap.action = (v_bRead && v_bCapability && v_bTool) ? 'legacy' : 'run'; } else { // use none as an indication that no action is allowed v_oOpenSpec.urlMap.action = 'none'; } break; default: // The value none is an indication that no action is allowed v_oOpenSpec.urlMap.action = 'none'; if (v_aPermissions.indexOf("execute") != -1 && v_oOpenSpec.glassContext.hasCapability('canUseCognosViewer')) { // viewOutput becomes run if there is no output v_oOpenSpec.urlMap.action = 'run'; } // If still no action and we are dealing with a default action, use edit if allowed if (v_oOpenSpec.urlMap.action == 'none' && v_oOpenSpec.defaultAction && v_aPermissions.indexOf("read") != -1 && v_oOpenSpec.glassContext.hasCapability('canUseReportStudio')) { v_oOpenSpec.urlMap.action = 'edit'; } } return Q.resolve(v_oOpenSpec); } }); } function resolveUrlMapForEditRun(v_oOpenSpec) { if (v_oOpenSpec.urlMap.action == 'viewOutput') { return Q.resolve(v_oOpenSpec); } if (!v_oOpenSpec.urlMap.perspective) { if (isDataSet2(v_oOpenSpec.urlMap.cmProperties)) { v_oOpenSpec.urlMap.perspective = 'datasets'; } else { var v_bRunInAdvancedViewer = isRunInAdvancedViewer(v_oOpenSpec, v_oOpenSpec.urlMap.format); // If using advanced viewer, perspective is authoring. Otherwise perspective is classic // unless we are editing then it is authoring. v_oOpenSpec.urlMap.perspective = (v_bRunInAdvancedViewer || v_oOpenSpec.urlMap.action == 'edit') ? 'authoring' : 'classicviewer'; } } if ( v_oOpenSpec.glassContext.isEmbedded() ) { v_oOpenSpec.urlMap.perspective += '_embedded'; } consolidateAndReconcileRunOptions(v_oOpenSpec); return Q.resolve(v_oOpenSpec); } function resolveUrlMap(v_oOpenSpec) { return retreiveCMInfo(v_oOpenSpec.cmProperties, v_oOpenSpec.glassContext) .then(prepareUrlMap.bind(null, v_oOpenSpec)) .then(resolveUrlMapForSavedOutput) .then(resolveUrlMapForEditRun) .then(function(v_oResolvedSpec) { v_oResolvedSpec.urlMap.rsResolved = true; return v_oResolvedSpec; }); } /** * Replace the current window with the given URL and * ensure glass does not complain or * open URL in new window and keep glass on current perspective. */ function processHref( sHref, deferred, glassContext ) { var v_oPerspective; var v_oCurrentContentView = (glassContext && glassContext.currentAppView) ? glassContext.currentAppView.currentContentView : null; if (v_oCurrentContentView) { // We have a current perspective, open url in new window and remain on current perspective v_oPerspective = { perspective: v_oCurrentContentView.perspective, id: v_oCurrentContentView.id }; if (!openUrlViaForm(sHref, true)) { rsCommon.reject( deferred, 'Could not launch a new tab.', 'rsOpenHelper.processHref' ); return; } } else { // Give something safe to glass to avoid error messages until window is replaced v_oPerspective = {perspective: 'home'}; // Replace current window with given href openUrlViaForm(sHref, false); } deferred.resolve( v_oPerspective ); } return { isReport_ish: isReport_ish, /** * Open the appropriate view based on input. * Minimum required information is * openSpec { * cmProperties { id, type } * glassContext * } */ openView: function( v_oOpenSpec ) { //console.log('rsOpenHelper.openView ...'); var deferred = Q.defer(); resolveUrlMap( v_oOpenSpec ) .then(launchApp) .catch( function(err){ console.log('rsOpenHelper.openView ... FAILED'); deferred.reject(err); }).done( function(v_oLaunchResult){ //console.log('rsOpenHelper.openView ... succeeded'); deferred.resolve(v_oLaunchResult); }); return deferred.promise; }, retrieveCmProperties: function (v_oGlassContext, v_oCmProperties, v_sStoreId) { var deferred = Q.defer(); if (v_sStoreId) { // Create an open spec compatible with retreiveCMInfo if (!v_oCmProperties) { v_oCmProperties = {}; } if (!v_oCmProperties.id) { v_oCmProperties.id = v_sStoreId; } if (v_oCmProperties.id != v_sStoreId) { // drill through between report and output v_oCmProperties.id = v_sStoreId; } retreiveCMInfo(v_oCmProperties, v_oGlassContext) .done(function (cmProperties) { deferred.resolve(cmProperties); }); } else { deferred.resolve(v_oCmProperties); } return deferred.promise; }, /** * Generate the urlMap with the appropriate entries to process the given open specification * The perspective is one of the values determined by this method which is used by the glass * when it needs to open a perspective for which the actual perspective is unknown * (e.g. share URL) */ getPerspective: function(v_oOpenSpec) { var deferred = Q.defer(); if (v_oOpenSpec.urlMap) { v_oOpenSpec.glassContext.getCoreSvc('.Config').getConfigValue('RS.TrimURLParameterValues') .done(function(result){ // Indicates if parameter values in the urlMap should be trimmed of leading and trailing spaces v_oOpenSpec.trimURLParameterValues = result === 'true'; resolveUrlMap(v_oOpenSpec) .catch( function(err) { console.log('rsOpenHelper.getPerspective ... FAILED'); deferred.reject(err); }).done( function(v_oOpenSpecResolved) { if (!v_oOpenSpecResolved) { // Could not resolve, report error so that glass can try next registered handler deferred.reject(); } else { if (v_oOpenSpecResolved.urlMap && v_oOpenSpecResolved.urlMap.action == 'legacy') { if (v_oOpenSpec.urlMap.launchParametersKey) { var v_oLaunchParameters = rsLaunchParameters.Retrieve(v_oOpenSpec.urlMap.launchParametersKey); delete v_oOpenSpec.urlMap.launchParametersKey; $.extend(true, v_oOpenSpec.urlMap, v_oLaunchParameters); } // legacy means the classic query/analysis studio should be launched. processHref( getLegacyLaunchUrl( v_oOpenSpec ), deferred, v_oOpenSpec.glassContext ); } else if (v_oOpenSpecResolved.href) { processHref( v_oOpenSpecResolved.href, deferred ); } else { deferred.resolve(v_oOpenSpecResolved.urlMap); } } }); }.bind(this)); } else { rsCommon.reject( deferred, 'urlMap is missing', 'rsOpenHelper.getPerspective' ); } return deferred.promise; }, determineDefaultAction: determineDefaultAction, resolveUrlMap: resolveUrlMap, updateCmProperties: function (v_oView, v_sStoreId) { // Clear existing values to avoid using stale data delete v_oView.cmProperties; delete v_oView.reportProperties; return this.retrieveCmProperties( v_oView.glassContext, null, v_sStoreId ) .then( function( v_oCmProperties ) { v_oView.cmProperties = v_oCmProperties; v_oView.id = v_oCmProperties.id; // whishfull thinking v_oView.type = v_oCmProperties.type; var v_oBaseReport; switch (v_oCmProperties.type) { case 'output': v_oBaseReport = v_oCmProperties.parent[0].parent[0]; break; case 'reportVersion': v_oBaseReport = v_oCmProperties.parent[0]; break; } if (v_oBaseReport) { v_oView.reportProperties = { id : v_oBaseReport.id, type : v_oBaseReport.type }; } }.bind(this)); }, //Interface for protected functions, used in rsShareHelper retreiveCMInfo: retreiveCMInfo }; });