/* IBM Confidential OCO Source Materials IBM Cognos Products: authoring (C) Copyright IBM Corp. 2015, 2020 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( [ 'bi/glass/app/ContentView', 'jquery', 'q', 'bi/authoring/nls/StringResource', 'bi/commons/utils/Utils', 'bi/authoring/utils/rsCommon', 'bi/authoring/utils/rsOpenHelper', 'bi/authoring/utils/rsPerformance', 'bi/authoring/utils/rsIFrameManager', 'bi/authoring/utils/pat/rsLaunchParameters', 'bi/authoring/utils/pat/rsPromptParameters', 'bi/authoring/utils/rsShareHelper', 'bi/admin/common/utils/parameters/ParameterValues' ], function(ContentView, $, Q, StringResource, Utils, rsCommon, rsOpenHelper, rsPerformance, rsIFrameManager, rsLaunchParameters, rsPromptParameters, rsShareHelper, ParameterValues) { 'use strict'; var v_sObserverId = "/authoring/js/rsContentView"; var v_aSpecModificationPluginIds = [ "com.ibm.bi.authoring.saveAsBtn", "com.ibm.bi.authoring.undoBtn", "com.ibm.bi.authoring.redoBtn", "com.ibm.bi.authoring.toggleEditViewer" ]; function handleTruthyValueAlreadySetOrAddObserver(v_oApplication, v_sPropertyName, v_fnOnChangeCallback) { if ( v_oApplication.SharedState.Get(v_sPropertyName) ) { v_fnOnChangeCallback(); } else { v_oApplication.SharedState.AddObserver(v_sObserverId, v_sPropertyName, v_fnOnChangeCallback); } } function handleTruthyValueAlreadySetAndAddObserver(v_oApplication, v_sPropertyName, v_fnOnChangeCallback) { if ( v_oApplication.SharedState.Get(v_sPropertyName) ) { v_fnOnChangeCallback(); } v_oApplication.SharedState.AddObserver(v_sObserverId, v_sPropertyName, v_fnOnChangeCallback); } var rsContentView = ContentView.extend({ init: function(options, appView) { this.m_oLaunchPromise = options.launchPromise; delete options.launchPromise; rsCommon.decodeAndMoveCMProperties(options); rsCommon.convertStringQSToValues(options, options.glassContext); rsCommon.decodeAndMoveRSOptions(options); // After the following call, every member of options is now a member of this rsContentView.inherited('init', this, arguments); this.m_fOnWindowResize = this.syncIFrameSizeToView.bind(this); window.addEventListener("resize", this.m_fOnWindowResize, false); this.m_oAppView = appView; var v_oAppViewFirstLoadedDeferred = Q.defer(); this.m_oRemoveAppViewLoadedHandler = this.glassContext.getCoreSvc('.Events').on( 'appView:loaded', this._handleFirstAppViewOnLoaded.bind(this,v_oAppViewFirstLoadedDeferred), this); this.m_oAppViewFirstLoadedPromise = v_oAppViewFirstLoadedDeferred.promise; // Extract information that is passed when creating view directly without going through open helper first. // Some examples are tryIt, launch from RS, invoking share URL with perspective specified. this.m_oRSParameters = this.m_oRSParameters || {}; // Make sure m_oRSParameters is initialized try { // to open a report passed on the URL and pass parameters, we need access to the // launch parameters stored in the calling window's Application object var v_oLaunchParameters = rsLaunchParameters.Retrieve(this.launchParametersKey); if (v_oLaunchParameters) { // This is the "run spec from RS" use case this.m_oLaunchParameters = v_oLaunchParameters; } else if (window.parent && this.launchParametersRef) { // This is the "edit parameter values" use case (typically called from share code) this.m_oLaunchParameters = window.parent[options.launchParametersRef]; } if (window.opener && !window.opener.closed && window.opener.RSParameters) { if (this.isNemesis) { var o = window.opener.RSParameters; for (var v_sAttrName in o) { if (v_sAttrName == 'reportXML') { // Passing the report spec text in an HTML encoded JSON object // is difficult. There are multiple levels of encoding. // Instead we pass a sentinel value and stash the original value // for later retrieval. this.m_oRSParameters.useGlassReportXML = true; this.m_sReportSpecFromOpener = o[v_sAttrName]; } else { this.m_oRSParameters[v_sAttrName] = o[v_sAttrName]; } } if (this.m_oRSParameters.useGlassReportXML) { this.m_oRSParameters.model = ""; } if (o.AppOnLoad) { this.AppOnLoad = window.opener[ o.AppOnLoad ]; } } //HACK, BY - The following 3 lines are for 'Try it'. 'Try it' still launch authoring with parameters passed with window.opener.RSParameters //We need this until 'Try it' starts passing parameters from URL. A defect will be logged to track this. else if (!this.m_oLaunchParameters && !this.isHomepage) { var v_oSrcParameters = window.opener.RSParameters; window.opener.RSParameters = undefined; // Copy the parameters from the opener's and then clear the // the opener's value this.startingTemplate = v_oSrcParameters.startingTemplate; this.moduleId = v_oSrcParameters.module; this.isViewer = v_oSrcParameters.isViewer; // not sure if this one is ever set this.m_oLaunchParameters = rsLaunchParameters.Retrieve(v_oSrcParameters.launchParametersKey); //Try it launches us with a module and startingTemplate but not a moduleSearchPath. Construct the moduleSearchPath if (this.moduleId && !this.moduleSearchPath && this.startingTemplate) { this.m_bIsTryIt = true; this.moduleSearchPath = "storeID(\"" + this.moduleId + "\")"; this.action = 'run'; console.log("rsContentView.init() - launched from try it setting module search path " + this.m_oRSParameters["moduleSearchPath"]); } } } } catch(e) { console.log("rsContentView.init() - Call to window.opener failed, assume it doesn't exist"); } this.m_bDisableRsLockUnlock = false; this.m_bFullyInitialized = false; }, _postInit: function() { if (this.m_bFullyInitialized) { return; } this.m_bFullyInitialized = true; var options = this; // convert parameters from JSON to SOAPy Bus Parameters if (options.parameterValuesJSON) { // option.parameterValuesXML get set the following ways // 1) by options passed (options.parameterValuesXML in SOAPy bus xml) into the perspective or // 2) by converting the parameterValuesJSON to a SOAPy bus xml. // The goal is eventual to phase out passing the parameterValuesXML // and solely use the parameterValuesJSON. // Not certain if the above goal still applies. // It forces the conversion of parameter values from SOAP XML to JSON only to convert them back // The prompt values are currently either pass one of the two ways mentioned above, but never both. // if you hand bomb the URL, the parameterValuesJSON will take precedence. options.parameterValuesXML = rsPromptParameters.rsBuildPromptParameters(undefined, options.parameterValuesJSON); delete options.parameterValuesJSON; } //console.log("rsContentView.init"); // If we have a launch promise then the RS parameters were already created // otherwise create them now but keep existing values if (!this.m_oLaunchPromise) { $.extend( this.m_oRSParameters, rsCommon.createRSParameters(options, this.glassContext) ); } this.m_bNewlyCreatedReport = this.m_oRSParameters.reportStoreID ? false : true; if (options.isSlideout) { this.m_bDisableRsLockUnlock = true; } if (this.m_oLaunchParameters && this.m_oLaunchParameters['RunOptions']) { //console.log("setting format" + this.m_oLaunchParameters['RunOptions'].OutputFormat); if ( !this.m_oRSParameters["rsFinalRunOptions"] ) { this.m_oRSParameters["rsFinalRunOptions"] = {}; } if (this.m_oLaunchParameters['RunOptions'].OutputFormat) { this.m_oRSParameters["rsFinalRunOptions"].format = this.m_oLaunchParameters['RunOptions'].OutputFormat; } if (this.m_oLaunchParameters['RunOptions'].isApplication) { this.m_oRSParameters["rsFinalRunOptions"].isApplication = this.m_oLaunchParameters['RunOptions'].isApplication; } if (this.m_oLaunchParameters['RunOptions'].globalParameters) { // Make global parameters available to viewer when running from editor. this.m_oRSParameters["rsFinalRunOptions"].globalParameters = this.m_oLaunchParameters['RunOptions'].globalParameters; } } this.m_bInitialIsViewerState = this.m_oRSParameters.isViewer; if (this.m_oLaunchParameters && this.m_oLaunchParameters.parameterValuesJSON) { // convert parameters from JSON to SOAPy Bus Parameters this.m_oLaunchParameters["parameterValuesXML"] = rsPromptParameters.rsBuildPromptParameters(undefined, this.m_oLaunchParameters.parameterValuesJSON); delete this.m_oLaunchParameters.parameterValuesJSON; } }, render: function() { if (this.rsResolved) { // urlMap already fully resolved so proceed with rendering return this._render(); } // Perspective was launched directly without going through rsOpenHelper // Complete open resolution then proceed with render. if (!this.cmProperties && this.objRef) { // Create cmProperties from available information so resolution has something to work with this.cmProperties = { id: this.objRef, type: this.type // may or not be available but that is OK }; } var v_oOpenSpec = { cmProperties: this.cmProperties, glassContext: this.glassContext, urlMap: this }; return rsOpenHelper.resolveUrlMap(v_oOpenSpec).then(function(v_oResolvedOpenSpec) { // Merge resolved urlMap back into this instance and proceed with rendering $.extend(this, v_oResolvedOpenSpec.urlMap); return this._render(); }.bind(this)); }, _render: function() { // Perform any final initialization now that urlMap is fully resolved this._postInit(); // N.B. Glass expected jQuery promises var $renderDeferred = $.Deferred(); if (this.m_oRSParameters.closePerspective || this.action == 'none') { // The perspective can't be opened var v_oState = { isViewer: true, objectType: '', runInAdvancedViewer: true }; this._updatePlugins( v_oState ); if (this.m_oRSParameters.closePerspective) { // Reject with message which the glass will display in a modal dialog var v_sError = StringResource.get('no_output_format_capability', {outputFormat: this.m_oRSParameters.rsFinalRunOptions.format}); $renderDeferred.reject({ message: v_sError }); } else { // Resolve without rendering anything and show toast. // We use toast so that this message is displayed in a consistent fashion (see rsOpenHelper) // We can't reject because the toast does not appear if we do. // Arrange to close perspective when toast is dismissed var v_sError = StringResource.get('no_action_available'); this.glassContext.showToast(v_sError, { 'type':'warning', 'btnLabel':'OK', 'callback': function() { this.glassContext.closeAppView("authoring", this.id); }.bind(this) }); $renderDeferred.resolve(); } return $renderDeferred.promise(); } //console.log("rsContentView.render() ..."); rsPerformance.mark('rsContentView.render'); console.timeEnd('rsperf: onSelectItem->render'); console.time('rsperf: render->OnRSApplicationReadyForObservers'); // This is the "early" rendering resolve - show the StartUp div right away $renderDeferred.resolve(this); // HACK: the Glass doesn't have an API to squish the sidebar this.m_oAppView.$('.navbar').addClass('narrow'); if (!this.m_oLaunchPromise) { var v_oTemplateParameters = rsCommon.createTemplateParameters(this.m_oRSParameters); this.m_oLaunchPromise = rsIFrameManager.F_LaunchRS(v_oTemplateParameters, this.glassContext, this.m_oLaunchParameters); } this.m_oLaunchPromise .catch(function(err) { console.log(err); this.hackUnlockGlass(); $renderDeferred.reject(err); }.bind(this)) .done(this._onRSApplicationReady.bind(this, $renderDeferred)); // Set the plugin state based on initial parameters. // This should reduce plugin "flickering". var v_oState = { isViewer: this.m_bInitialIsViewerState, objectType: '', runInAdvancedViewer: this.m_bNewlyCreatedReport }; if (this.cmProperties) { v_oState.objectType = this.cmProperties.type; if ( this.cmProperties.runInAdvancedViewer ) { v_oState.runInAdvancedViewer = true; } } this._updatePlugins( v_oState ); // Instrumentation wants specific terms // Some glass actions won't be instrumented var v_oGlassActionToInstrumentationEventType = { 'run' : 'Ran Process', 'viewOutput': 'Read Object', 'edit': 'Read Object', 'create' : 'Created Object' }; var v_sInstrumentationType = v_oGlassActionToInstrumentationEventType[ this.action ]; if (v_sInstrumentationType && this.glassContext) { var v_oInstrumentationService = this.glassContext.getCoreSvc('.Instrumentation'); if (v_oInstrumentationService && v_oInstrumentationService.enabled) { var v_sType; var v_sId; if (this.type == 'output' && this.cmProperties) { // our opener code should fill in the parent chain // cmProperties.parent[0] is the reportVersion object // cmProperties.parent[0].parent[0] is the object that has output versions var v_oVersionedAncestor = this.cmProperties.parent[0].parent[0]; v_oVersionedAncestor = v_oVersionedAncestor.base || v_oVersionedAncestor; v_sType = v_oVersionedAncestor.type; v_sId = v_oVersionedAncestor.id; } else { v_sType = this.type; v_sId = this.id; } if (v_sInstrumentationType === v_oGlassActionToInstrumentationEventType.edit && this.isNew) { v_sInstrumentationType = v_oGlassActionToInstrumentationEventType.create; v_sId = 'null'; if (!v_sType) { // if we don't have a type AND it's a new // assume we are creating a report v_sType = 'report'; } } var v_oEvent = { type: v_sInstrumentationType, objectType: v_sType, object: v_sId, milestoneName: v_sInstrumentationType + '_' + v_sType }; if (v_sInstrumentationType === v_oGlassActionToInstrumentationEventType.run) { v_oEvent['processType'] = 'Run a Report'; } if ( [v_oGlassActionToInstrumentationEventType.run, v_oGlassActionToInstrumentationEventType.viewOutput].indexOf(v_sInstrumentationType) !== -1 ) { v_oEvent['custom.viewer'] = 'interactive'; v_oEvent['custom.outputFormat'] = this.format; } v_oInstrumentationService.track( v_oEvent ); } } this.hackLockGlass(); return $renderDeferred.promise(); }, getTitle: function() { if (this.isApplicationLoaded() ) { return this.getAuthoringApplication().SharedState.Get("reportName"); } else { return StringResource.get(this.perspective == 'datasets' ? 'dataset_welcome' : 'authoring_welcome'); } }, getIcon: function() { var v_sIcon; if (this.perspective == 'datasets') { v_sIcon = 'common-dataset'; } else { var v_sReportType = this.getAuthoringApplication() && this.getAuthoringApplication().SharedState.Get("objectType"); switch(v_sReportType) { case 'interactiveReport' : v_sIcon = 'common-interactiveReport'; break; case 'reportView' : v_sIcon = 'common-report_view'; break; default : v_sIcon = 'common-report'; break; } } return v_sIcon; }, getIconTooltip: function() { return StringResource.get( this.perspective == 'datasets' ? 'dataset_welcome' : 'authoring_welcome'); }, getType: function() { var v_sObjectType; if (this.isApplicationLoaded()) { v_sObjectType = this.getAuthoringApplication().SharedState.Get("objectType"); } return v_sObjectType; }, isDirty: function() { var v_oSharedState = this.getAuthoringApplication() ? this.getAuthoringApplication().SharedState : null; var v_sObjectType = v_oSharedState ? v_oSharedState.Get("objectType") : ""; // reportViews can't be saved so don't mark them as dirty if (v_sObjectType != 'reportView' && !this.isNemesis && this.isApplicationLoaded() && !this.m_bIsTryIt) { var v_bIsModified = v_oSharedState && v_oSharedState.Get("isModified"); var v_bIsViewer = v_oSharedState && v_oSharedState.Get("isViewer"); if (v_bIsModified && v_bIsViewer) { var v_bRead = (!this.cmProperties || !this.cmProperties.permissions || this.cmProperties.permissions.indexOf("read") != -1); var v_bWrite = (!this.cmProperties || !this.cmProperties.permissions || this.cmProperties.permissions.indexOf("write") != -1); var v_bSaveAsCapabilities = this.glassContext.hasCapability("canUseReportStudio") && this.glassContext.hasCapability("canUseReportStudioFileManagement"); // Can't save if no read (unable to unstub in viewer) or no write (no save) and no save as capabilities if (!v_bRead || (!v_bWrite && !v_bSaveAsCapabilities)) { // Can't save/save as in viewer so don't mark as dirty to avoid message indicating object changed on exit. v_bIsModified = false; } } return v_bIsModified; } else { return false; } }, getAuthoringApplication: function() { return rsCommon.getAuthoringApplicationFromIFrame(this.m_iframeAuthoring); }, isApplicationLoaded: function() { var v_Application = this.getAuthoringApplication(); return !!(v_Application && v_Application.SharedState.Get("isAppLoaded")); }, canRun: function() { var v_oAuthoringApp = this.getAuthoringApplication(); return v_oAuthoringApp.SharedState.Get("canRun"); }, /* getContent - Called by the glass to cache the current state and set the url (eg for bookmarking) - By default we should return all our serializable state - when parameter options{mode:'bookmark'} is passed in, getContent is being called for the purposes of - determining the url/for bookmarking. We can discard transient state for this call. NOTE: If called too early getContent() returns undefined Else returns { .* // whatever was passed in as init(options) .cmProperties { // from the content team, typically includes: id type permissions ? } // maybe undefined if getContent() was called too early .application { .storeID, // the CM store id of the currently saved report, null if not saved .cmSearchPath, // the CM search path of the currently saved report, null if not saved .reportName, // the name of the current report .isModifed // true if there is a current report AND it needs to be saved .type // the CM type of the object } } */ getContent: function(options) { // console.log("rsContentView.getContent" ); return rsCommon.getContent( options, this, rsShareHelper ); }, getApplicationContent: function( v_oContent, v_oCmProperties ) { var application = {}; if (this.isApplicationLoaded()) { var v_oAuthoringApp = this.getAuthoringApplication(); var v_sStoreID = v_oAuthoringApp.SharedState.Get("storeID"); application.storeID = v_sStoreID; application.isModified = v_oAuthoringApp.SharedState.Get("isModified"); application.cmSearchPath = v_oAuthoringApp.SharedState.Get("cmSearchPath"); application.reportName = this.getTitle(); if ( ! v_oCmProperties ) { console.log("rsContentView.getContent no .cmProperties"); v_oCmProperties = { type: undefined }; } // authoring only supports editing or running of // { report, interactiveReport, reportTemplate } // even if we open something else (like a query or an analysis) // it is converted into a report var v_sType = ( v_oContent.objRef && v_oContent.type) || (v_oCmProperties && v_oCmProperties.type); if (v_sType === 'reportTemplate' || v_sType === 'dataSet2') { // if we opened a template it must have stayed as a template // because we can't convert it from template to anything else application.type = v_sType; } else if (v_oAuthoringApp.SharedState.Get("isActiveReport")) { application.type = 'interactiveReport'; } else { application.type = 'report'; } } return application; }, onAppLoaded: function() { var v_Application = this.getAuthoringApplication(); //console.time('rsperf: rsContentView.onAppLoaded_1->ContentView.onAppLoaded_2'); this.m_oAppViewFirstLoadedPromise.done( function(){ //console.timeEnd('rsperf: rsContentView.onAppLoaded_1->ContentView.onAppLoaded_2'); rsIFrameManager.F_PositionAndSizeIFrame( this.$el, this.m_iframeAuthoring); this.hackUnlockGlass(); handleTruthyValueAlreadySetAndAddObserver(v_Application, "reportName",this.updateTitle.bind(this)); handleTruthyValueAlreadySetOrAddObserver(v_Application, "isReportLoaded", this._on_isReportLoaded.bind(this)); v_Application.SharedState.AddObserver( v_sObserverId, "isViewer", this._on_isViewer.bind(this)); v_Application.SharedState.AddObserver( v_sObserverId, "isActiveReport", this._on_isActiveReport.bind(this)); v_Application.SharedState.AddObserver( v_sObserverId, "runInAdvancedViewer", this._on_runInAdvancedViewer.bind(this)); v_Application.SharedState.AddObserver( v_sObserverId, "viewer", this._on_viewer.bind(this)); v_Application.SharedState.AddObserver( v_sObserverId, "isModified", this._on_isModified.bind(this)); v_Application.SharedState.AddObserver( v_sObserverId, "storeID", this._on_storeID.bind(this)); if (this.onSavedCallback) { v_Application.SharedState.AddObserver(null, "onDatasetSaved", this.onSavedCallback); delete this.onSavedCallback; } if (this.onCancelCallback) { v_Application.SharedState.AddObserver(null, "onDatasetCancelled", this.onCancelCallback); delete this.onCancelCallback; } handleTruthyValueAlreadySetOrAddObserver(v_Application, "firstBeforeDraw", this.onViewBeforeFirstDraw.bind(this)); handleTruthyValueAlreadySetOrAddObserver(v_Application, "firstAfterDraw", this.onViewAfterFirstDraw.bind(this)); if (this.isNew && !rsOpenHelper.isReport_ish( this.cmProperties )) { // New report and cm properties are for a non-report like object // Remove the cm properties (which were likely the package/module we started from) // so we don't inadvertently use information thinking we have a report object. delete this.cmProperties; } }.bind(this)); }, onViewBeforeFirstDraw: function() { console.time('rsperf: ViewBeforeDraw->ViewAfterDraw'); rsPerformance.mark('rsContentView.onViewBeforeDraw'); }, onViewAfterFirstDraw: function() { rsPerformance.mark('rsContentView.onViewAfterDraw'); rsPerformance.mark('authoring-selectItemAndDraw-stop'); console.timeEnd('rsperf: ViewBeforeDraw->ViewAfterDraw'); console.timeEnd('rsperf: total_RunReport'); if (this.glassContext && this.glassContext.isDevInstall && this.glassContext.isDevInstall()) { rsPerformance.summarizeInteractiveViewerRun( this); } var v_Application = this.getAuthoringApplication(); if ((!this.m_oLaunchParameters || !this.m_oLaunchParameters["promptContext"]) && v_Application.GetUserDataSetting("PreLaunchRS")) { rsIFrameManager.F_PreLaunch(this.glassContext); } }, enablePluginForApplicationState: function( v_oOption ) { var v_oState = this.getAuthoringApplication().SharedState.Get(v_oOption.state); this._setEnableForPlugins(v_oState, [v_oOption.plugin]); }, highlightPluginForApplicationState: function( v_oOption ) { var v_oState = this.getAuthoringApplication().SharedState.Get(v_oOption.state); var v_oPlugin = this.glassContext.findPlugin(v_oOption.plugin); if (v_oPlugin) { if (v_oState) { console.log('rsContentView press %s', v_oOption.plugin); v_oPlugin.setPressed(); } else { console.log('rsContentView unpress %s', v_oOption.plugin); v_oPlugin.setUnpressed(); } } else { console.log("rsContentView highlightPluginForApplicationState - could not find plugin: %s", v_oOption.plugin); } }, showPluginForApplicationState: function( v_oOption ) { var v_oPlugin = this.glassContext.findPlugin(v_oOption.plugin); if (v_oPlugin) { var v_oState = this.getAuthoringApplication().SharedState.Get(v_oOption.state); if (v_oState) { //console.log('rsContentView enable %s', v_oOption.plugin); v_oPlugin.show(); } else { //console.log('rsContentView disable %s', v_oOption.plugin); v_oPlugin.hide(); } } else { console.log("rsContentView showPluginForApplicationState - could not find plugin: %s", v_oOption.plugin); } }, _setDisplayForPlugins: function(v_bShow, v_aPluginIds) { v_aPluginIds.forEach( function(v_sPluginId) { var v_oPlugin = this._hackFindPlugin(v_sPluginId); if ( v_oPlugin ) { if (v_bShow) { v_oPlugin.show(); } else { v_oPlugin.hide(); } } else { console.log('could not find plugin: %s', v_sPluginId); } }, this); }, _setEnableForPlugins: function(v_bEnable, v_aPluginIds) { v_aPluginIds.forEach( function(v_sPluginId) { var v_oPlugin = this._hackFindPlugin(v_sPluginId); if ( v_oPlugin ) { if (v_bEnable) { v_oPlugin.enable(); } else { v_oPlugin.disable(); } } else { console.log('could not find plugin: %s', v_sPluginId); } }, this); }, _updatePlugins: function(v_oState) { var v_aEditIds = [ "com.ibm.bi.authoring.runMenu", "com.ibm.bi.authoring.insertableObjectsBtn" ]; var v_aViewerIds = [ "com.ibm.bi.authoring.runBtn", "com.ibm.bi.authoring.refreshBtn", "com.ibm.bi.authoring.consumptionFilter", "com.ibm.bi.contentApps.teamFoldersSlideout", "com.ibm.bi.contentApps.myContentFoldersSlideout", "com.ibm.bi.search.search", "com.ibm.bi.contentApps.mruSlideout" ]; if (this.m_bIsTryIt) { this._setDisplayForPlugins(false, v_aViewerIds); this._setDisplayForPlugins(false, ["com.ibm.bi.authoring.saveAsBtn", "com.ibm.bi.authoring.outputBtn", "com.ibm.bi.authoring.runMenu"]); } else if (v_oState.objectType == 'output') { var v_bRun = this.cmProperties.permissions.indexOf("execute") != -1; this._setDisplayForPlugins(v_bRun,["com.ibm.bi.authoring.outputBtn"]); this._setDisplayForPlugins(false, [ "com.ibm.bi.authoring.runBtn", "com.ibm.bi.authoring.insertableObjectsBtn", "com.ibm.bi.authoring.runMenu", "com.ibm.bi.authoring.refreshBtn", "com.ibm.bi.authoring.consumptionFilter", "com.ibm.bi.authoring.saveAsBtn", "com.ibm.bi.authoring.undoBtn", "com.ibm.bi.authoring.redoBtn" ]); } else { if (v_oState.objectType == 'reportView') { // No save on report view this._setDisplayForPlugins(false, ["com.ibm.bi.authoring.saveAsBtn"]); } this._setDisplayForPlugins(false, ["com.ibm.bi.authoring.outputBtn"]); this._setDisplayForPlugins(!v_oState.isViewer, v_aEditIds); this._setDisplayForPlugins(v_oState.isViewer, v_aViewerIds); if (!v_oState.isViewer) { // hide Group Content button for authoring mode. // for consumption mode, the custom folder will be display, along with the my content + team content folders if the user has access this._setDisplayForPlugins(false, ["com.ibm.bi.contentApps.customFoldersSlideout"]); } if (v_oState.isViewer && this.m_oRSParameters.rsFinalRunOptions.format == 'PDF') { this._setDisplayForPlugins(false, ["com.ibm.bi.authoring.consumptionFilter"] ); } this._setDisplayForPlugins(!(v_oState.isViewer && v_oState.isFromRS), ["com.ibm.bi.glass.common.operations"]); } var v_bRead = (!this.cmProperties || !this.cmProperties.permissions || this.cmProperties.permissions.indexOf("read") != -1); var v_bCanToggleEditView = this.glassContext.hasCapability("canUseReportStudio") && v_oState.objectType == 'report' // this excludes interactiveReport and reportView && v_oState.runInAdvancedViewer && !v_oState.useReadOnlyViewer && !this.m_bIsTryIt && !(v_oState.isViewer && v_oState.isFromRS) // exclude viewers launched from RS (viewer running a spec) && (!v_oState.isViewer || v_bRead); // exclude viewers without read access (can't unstub report spec) if(v_oState.objectType == 'interactiveReport') { this._setDisplayForPlugins(false, ["com.ibm.bi.authoring.consumptionFilter", "com.ibm.bi.authoring.refreshBtn", "com.ibm.bi.authoring.outputBtn"]); } if (this.getAuthoringApplication()) { if (!v_oState.isViewer) { this.getAuthoringApplication().SharedState.Set(null, "showFilters", false); } this.getAuthoringApplication().SharedState.Set(null, "canToggleEditView", v_bCanToggleEditView); } else { // Until app is loaded, don't show the button. // When app is loaded, we come through here again but then the the code above is executed // which determines state of button. this._setDisplayForPlugins(false, ["com.ibm.bi.authoring.toggleEditViewer"]); } }, _updatePluginsForNewState: function() { var v_oState = { isViewer: this.getAuthoringApplication().SharedState.Get("isViewer"), objectType: this.getAuthoringApplication().SharedState.Get("objectType"), runInAdvancedViewer: this.getAuthoringApplication().SharedState.Get("runInAdvancedViewer"), useReadOnlyViewer: this.getAuthoringApplication().SharedState.Get("useReadOnlyViewer") }; if (this.m_oLaunchParameters && this.m_oLaunchParameters['RunOptions']) { if (this.m_oLaunchParameters['RunOptions'].isFromRS == true) { v_oState.isFromRS = true; } } this._updatePlugins(v_oState); }, _on_isViewer: function() { this._updatePluginsForNewState(); }, _on_isActiveReport: function() { this._updatePluginsForNewState(); }, _on_runInAdvancedViewer: function() { this._updatePluginsForNewState(); }, _on_viewer: function() { var v_Application = this.getAuthoringApplication(); // if HTML show the spec modification buttons, // otherwise hide them this._setDisplayForPlugins( v_Application.SharedState.Get("viewer").toUpperCase() == "HTML", v_aSpecModificationPluginIds ); this._updatePluginsForNewState(); this._updateButtonState(); }, _on_storeID: function() { var v_Application = this.getAuthoringApplication(); var v_sStoreId = v_Application.SharedState.Get("storeID"); // If there is no storeID then we are most likely dealing with a new report but we may have cmProperties of the module/package. // In this case we want to keep the cmProeprties hence we only update if we have an actual storeID. // Also, we only update if the storeID is different. if (v_sStoreId && (!this.cmProperties || v_sStoreId != this.cmProperties.id)) { rsOpenHelper.updateCmProperties(this, v_sStoreId) .then( function () { this._updatePluginsForNewState(); // Let glass know our id changed this.glassContext.updateCurrentCachedAppView(); }.bind(this)); } }, _updateButtonState: function() { var v_Application = this.getAuthoringApplication(); var v_aStateAndPlugin = [ {state: "canUndo", plugin: "com.ibm.bi.authoring.undoBtn"}, {state: "canRedo", plugin: "com.ibm.bi.authoring.redoBtn"}, // run button is in the menu until we get a "menu button" {state: "canRun", plugin: "com.ibm.bi.authoring.runBtn"}, {state: "canRun", plugin: "com.ibm.bi.authoring.runMenu"}, {state: "canRun", plugin: "com.ibm.bi.authoring.refreshBtn"} ]; v_aStateAndPlugin.forEach( function(v_o){ // set the initial state this.enablePluginForApplicationState(v_o); // listen for future changes v_Application.SharedState.AddObserver( v_sObserverId, v_o.state, this.enablePluginForApplicationState.bind(this, v_o)); }, this); }, _on_isReportLoaded: function() { var v_Application = this.getAuthoringApplication(); if (v_Application.SharedState.Get("useReadOnlyViewer")) { this._setDisplayForPlugins( false, v_aSpecModificationPluginIds ); var v_oStateAndPlugin = {state: "canRun", plugin: "com.ibm.bi.authoring.runBtn"}; // set the initial state this.enablePluginForApplicationState(v_oStateAndPlugin); // listen for future changes v_Application.SharedState.AddObserver( v_sObserverId, v_oStateAndPlugin.state, this.enablePluginForApplicationState.bind(this, v_oStateAndPlugin)); } else { this._updateButtonState(); var v_aLeftSideStateAndPlugin = [ {state: "showInsertableObjects", plugin: "com.ibm.bi.authoring.insertableObjectsBtn"} ]; v_aLeftSideStateAndPlugin.forEach( function(v_o){ this.highlightPluginForApplicationState(v_o); v_Application.SharedState.AddObserver(v_sObserverId, v_o.state, this.highlightPluginForApplicationState.bind(this, v_o)); }, this); var v_sToggleEditPluginId = "com.ibm.bi.authoring.toggleEditViewer"; var v_oToggleEditButtonPlugin = this._hackFindPlugin(v_sToggleEditPluginId); if (!v_oToggleEditButtonPlugin) { console.log('could not find plugin: %s', v_sToggleEditPluginId); } else { var v_bIsViewer = v_Application.SharedState.Get("isViewer"); if (v_bIsViewer) { v_oToggleEditButtonPlugin.setUnpressed(); } else { v_oToggleEditButtonPlugin.setPressed(); } this._updateToggleEditView(); // listen for future changes v_Application.SharedState.AddObserver(v_sObserverId, "canToggleEditView", this._updateToggleEditView.bind(this)); v_Application.SharedState.AddObserver(v_sObserverId, "canEditReport", this._updateToggleEditView.bind(this)); } } this._updatePluginsForNewState(); var v_oMRU; var v_oDummyCmProperties = { type: this.type }; if (rsOpenHelper.isReport_ish( v_oDummyCmProperties )) { // Only process if type is a report-like type // It may be a package in some cases so we don't want a MRU for the package (they don't work well) if (this.objRef) { //TODO, BY - content api is not ready to take 'objRef' as input yet. Once they are ready //we will do v_oMRU = $.extend(true, {}, this.m_oSerializableInitOptions); v_oMRU = {}; v_oMRU.id = this.objRef; v_oMRU.type = this.getAuthoringApplication().SharedState.Get("objectType"); v_oMRU.defaultName= this.getAuthoringApplication().SharedState.Get("reportName"); } else if (this.cmProperties) { v_oMRU = $.extend(true, {}, this.cmProperties); } } else { if (this.reportProperties) { v_oMRU = $.extend(true, {}, this.reportProperties); } } if (v_oMRU) { this._addToMRU(v_oMRU); } this.updateTitle(); }, _addToMRU: function(mruEntry) { return this.glassContext.getSvc('.Content').then(function(contentSvc) { return contentSvc.addToMRU(mruEntry); }); }, _updateToggleEditView: function() { var v_Application = this.getAuthoringApplication(); if (v_Application.SharedState.Get('canToggleEditView') && v_Application.SharedState.Get('canEditReport')) { var v_oPlugin = this.glassContext.findPlugin("com.ibm.bi.authoring.toggleEditViewer"); if (v_oPlugin) { v_oPlugin.show(); } } }, _on_isModified: function() { var v_oSharedState = this.getAuthoringApplication().SharedState; var v_bCantSaveModified = false; var v_bIsModified = v_oSharedState.Get("isModified"); if (v_bIsModified && v_oSharedState.Get("isViewer")) { // If viewing and no read then can't save/save as since this requires spec unstubbing which requires read access. var v_bRead = (!this.cmProperties || !this.cmProperties.permissions || this.cmProperties.permissions.indexOf("read") != -1); var v_bWrite = (!this.cmProperties || !this.cmProperties.permissions || this.cmProperties.permissions.indexOf("write") != -1); var v_bSaveAsCapabilities = this.glassContext.hasCapability("canUseReportStudio") && this.glassContext.hasCapability("canUseReportStudioFileManagement"); // Can't save if no read (unable to unstub) or no write (no save) and no save as capabilities v_bCantSaveModified = !v_bRead || (!v_bWrite && !v_bSaveAsCapabilities); } if (v_bCantSaveModified) { // can't save modified spec so disable save button and warn user this.glassContext.showToast(this.getAuthoringApplication().GetString("IDS_MSG_EDITS_LOST"), {'type':'info'}); this._setEnableForPlugins(false, ["com.ibm.bi.authoring.saveAsBtn"]); } else { this._setEnableForPlugins(true, ["com.ibm.bi.authoring.saveAsBtn"]); } this.trigger('change:dirty', {value: v_bIsModified}); }, updateTitle: function() { var v_sReportName = this.getAuthoringApplication().SharedState.Get("reportName"); this.trigger('change:title', {'value': v_sReportName}); }, // Add the "clsGlassUiDisplayed" class to the RS document body when the glass displays UI _addGlassBodyObserver: function() { if ( this.m_bIsIE === undefined ) { this.m_bIsIE = ( ( navigator.userAgent.toLowerCase().search(/trident\/([0-9]+\.[0-9]+)/) != -1 ) ? parseFloat( RegExp.$1 ) : 0 ) >= 7.0; } if ( !this.m_bIsIE ) { return; } this.m_oBodyObserver = new MutationObserver( function() { var v_aClasses = ["openedMenu" ,"openedSlideout", "openedAppViewSlideout", "openedDialog"]; if ( v_aClasses.some( function( s ) { return this.contains( s ); }, document.body.classList ) ) { this.m_iframeAuthoring.contentDocument.body.classList.add( "clsGlassUiDisplayed" ); } else { this.m_iframeAuthoring.contentDocument.body.classList.remove( "clsGlassUiDisplayed" ); } }.bind( this ) ); this.m_oBodyObserver.observe( document.body, { attributes: true, attributeFilter: ["class"] } ); }, _removeGlassBodyObserver: function() { if ( this.m_oBodyObserver ) { this.m_oBodyObserver.disconnect(); this.m_oBodyObserver = null; } }, show: function() { rsContentView.inherited('show', this, arguments); if (this.m_iframeAuthoring) { // div has not been rendered in DOM yet so has no size, need a setTimeout to let it happen setTimeout(rsIFrameManager.F_PositionAndSizeIFrame.bind(rsIFrameManager, this.$el, this.m_iframeAuthoring), 0); this.getAuthoringApplication().Activate(); } this._addGlassBodyObserver(); }, deactivate: function() { this._removeGlassBodyObserver(); if (this.m_iframeAuthoring) { this.getAuthoringApplication().Deactivate(); rsIFrameManager.F_HideIFrame(this.m_iframeAuthoring); } }, remove: function() { var v_oApplication = this.getAuthoringApplication(); if( this.m_bIsTryIt ) { v_oApplication.DeleteTempModule(this.moduleId); } if (this.m_fOnWindowResize) { window.removeEventListener("resize", this.m_fOnWindowResize, false); this.m_fOnWindowResize = null; } if (this.m_oRemoveAppViewLoadedHandler) { this.m_oRemoveAppViewLoadedHandler.remove(); this.m_oRemoveAppViewLoadedHandler = undefined; } if (this.m_iframeAuthoring) { // m_iframeAuthoring may not be defined if we are in an error state rsIFrameManager.F_DetachIFrame(this.m_iframeAuthoring); this.m_iframeAuthoring = null; } this.m_oLaunchPromise = null; this.m_oAppView = null; return true; }, /** * Hide a menu item from another provider. * * returns * false: if there is a valid itemId present and authoring would like to hide that menu item * true: for all other conditions */ isMenuItemVisible: function (context){ // if the function is called very early we may not have an application yet if (!this.getAuthoringApplication()) { return true; } var v_sMenuItem = context.target.itemId; if (v_sMenuItem) { var v_oCurrentContentView = context.glassContext.currentAppView.currentContentView; var v_bIsViewer = this.getAuthoringApplication().SharedState.Get("isViewer"); switch (v_sMenuItem) { case 'com.ibm.bi.share.subscribe': // hide Subscribe menu item in Edit mode or when prompting if (!v_bIsViewer || !rsShareHelper.isShareable(v_oCurrentContentView, false)) { return false; } break; case 'com.ibm.bi.glass.common.setHome': // hide Set Home menu item in Edit mode or prompting or for active report if (!v_bIsViewer || !rsShareHelper.isShareable(v_oCurrentContentView, false) || this.getAuthoringApplication().SharedState.Get('isActiveReport')) { return false; } break; } } return true; }, addPdfCssPositionStyling: function(v_sPositionStyle) { this.$el[0].style.position = v_sPositionStyle; }, removePdfCssPositionStyling: function() { this.$el[0].style.position = ""; }, _onRSApplicationReady: function(v_oContentViewDeferred, v_idIFrameAuthoring) { this.m_iframeAuthoring = document.getElementById(v_idIFrameAuthoring); console.timeEnd('rsperf: render->OnRSApplicationReadyForObservers'); rsPerformance.mark('rsContentView._onRSApplicationReady'); var v_oApplication = this.getAuthoringApplication(); this.glassContext.getCoreSvc(".UserProfile").getCapabilities().then(function(v_aCapabilities){ v_oApplication.SetGlassInfo({ "glassView": this, "glassContext": this.glassContext, "launchParameters": this.m_oLaunchParameters, "capabilities": v_aCapabilities }); handleTruthyValueAlreadySetOrAddObserver(v_oApplication, "isAppLoaded", this.onAppLoaded.bind(this)); v_oContentViewDeferred.resolve(this); }.bind(this)); }, _onRsLaunchError: function(v_oDeferred) { console.log("rsContentView._onRsLaunchError(). "); this.hackUnlockGlass(); v_oDeferred.reject( new Error("rsContentView: error during iframe load") ); }, _hackFindPlugin: function(id) { return rsCommon._hackFindPlugin(this.m_oAppView, id); }, hackLockGlass: function() { if (!this.m_bDisableRsLockUnlock) { rsCommon.hackLockGlass(this.m_oAppView); } }, hackUnlockGlass: function() { if (!this.m_bDisableRsLockUnlock) { rsCommon.hackUnlockGlass(this.m_oAppView); } }, getReportSpec: function() { return this.m_sReportSpecFromOpener; }, launchInExploration: function(v_nReport, v_aSelectionIids, v_sReportSpec, v_sExploreStoreID) { return require(["bi/authoring/utils/V5ToDashboard"], function(V5ToDashboard) { var v_oAuthoringApp = this.getAuthoringApplication(); return V5ToDashboard.LaunchInExploration(v_nReport, v_oAuthoringApp, v_aSelectionIids, v_sReportSpec, v_sExploreStoreID, this.glassContext) .then(function(){}); }.bind(this)); }, syncIFrameSizeToView : function() { if (this.m_iframeAuthoring && this.m_iframeAuthoring.style.visibility == "visible") { rsIFrameManager.F_PositionAndSizeIFrame(this.$el, this.m_iframeAuthoring); } }, /** * This method gets the parameters from the application * and optionally removes credential parameters. * This method should be used to get parameters values that will be exposed in URLs * because they are large but more importantly they are a security risk since * due to another defect, the contain username/passwords in plain text. * This is a public method used by other components and as such * must be defined in both rs and cv content views. */ getParameterValues : function( bStripCredentials ) { var v_oAuthoringApp = this.getAuthoringApplication(); var v_aParameters = null; var v_aAppParameters = v_oAuthoringApp.GetParameterValues(); if (v_aAppParameters) { v_aParameters = []; if (v_aAppParameters.length > 0) { v_aAppParameters.forEach( function(v_oParameter) { if (!bStripCredentials || !v_oParameter || !v_oParameter.name || v_oParameter.name.indexOf("credential:") != 0) { v_aParameters.push( v_oParameter ); } }); } } return v_aParameters; }, /** * Called by global parameter flyout to determine what parameters are used by the currently active view. * @return Object with parameter names as members that currently in use by the report. */ getParameters: function() { var v_oAuthoringApp = this.getAuthoringApplication(); if (v_oAuthoringApp && v_oAuthoringApp.SharedState.Get("isViewer")) { if (v_oAuthoringApp.SharedState.Get("isActiveReport")) { // When viewing active reports, global parameters can't be modified. return {}; } var v_aParameters = this.getParameterValues(true); return rsPromptParameters.convertParameterArrayToObject(v_aParameters); } return null; }, /** * Called by global parameter flyout to let content view know what global parameters have changed. * The method determines if any of the modified global parameters are used by the report and if so * the report is refreshed. * @param v_oGlobalParameters The global parameters that have been modified. * @param glassContext The glass context used to access complete global parameters. */ updateGlobalParameters: function( v_oNewGlobalParameters, v_oGlassContext ) { var v_Application = this.getAuthoringApplication(); if (v_Application && v_oNewGlobalParameters && !v_Application.SharedState.Get("isActiveReport")) { // Don't apply global parameter changes to active reports. var v_aGlobalParameters = rsCommon.convertToArray( v_oGlassContext ? v_oGlassContext.services.userProfile.userProfileSettings.parameter_values : null ); var v_sGlobalParameters = v_aGlobalParameters.length ? JSON.stringify( v_aGlobalParameters ) : null; var v_aGlobalParametersDelta = rsCommon.convertToArray( v_oNewGlobalParameters ); var v_sGlobalParametersDelta = v_aGlobalParametersDelta.length ? JSON.stringify( v_aGlobalParametersDelta ) : null; var v_oParameters = { globalParameters : v_sGlobalParameters, globalParametersDelta : v_sGlobalParametersDelta }; v_Application.SharedState.Call(null, "updateGlobalParameters", v_oParameters); } }, /** * Called by Collaboration to retrieve the DOM node for screen capturing and report's name. * @returns {array} Array of objects containing the DOM element and the name. */ getShareableItemsForCollaboration: function() { if (this.isApplicationLoaded() && this.m_iframeAuthoring) { var v_oAuthoringApp = this.getAuthoringApplication(); if (v_oAuthoringApp) { var doc = this.m_iframeAuthoring.contentDocument; var body = doc.body; if (v_oAuthoringApp.SharedState.Get("isActiveReport")) { // active reports are inside an iframe, grab the body of that iframe instead. var iframes = doc.querySelectorAll("iframe"); if (iframes && iframes.length === 1) { body = iframes[0].contentDocument.body; } } return [{ el: body, label: v_oAuthoringApp.SharedState.Get("reportName") }]; } } return []; }, _handleFirstAppViewOnLoaded: function(v_oDeferred, v_oEvent, v_sEventName) { if (v_sEventName != 'appView:loaded') { return; } if ( !v_oEvent || !v_oEvent.appView || v_oEvent.appView != this.m_oAppView) { return; } console.info('rsContentView._handleFirstAppViewOnLoaded'); v_oDeferred.resolve(true); this.m_oRemoveAppViewLoadedHandler.remove(); this.m_oRemoveAppViewLoadedHandler = undefined; }, /** * setFocus will be called whenever glass want to put focus inside contentView. * here, the code will check if interactive viewer is loaded then focus inside report viewer */ setFocus: function setFocus() { if (this.isApplicationLoaded()) { var v_oApplication = this.getAuthoringApplication(); if (v_oApplication && v_oApplication.SharedState && v_oApplication.SharedState.Get( "isReportLoaded" )) { v_oApplication.SetFocusToWorkarea(); } } else { rsContentView.inherited('setFocus', this, arguments); } } }); return rsContentView; });