rsCommon.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. /*
  2. IBM Confidential
  3. OCO Source Materials
  4. IBM Cognos Products: rs
  5. (C) Copyright IBM Corp. 2003, 2020
  6. 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.
  7. */
  8. define([
  9. 'jquery',
  10. 'q',
  11. 'doT',
  12. 'bi/commons/utils/Utils',
  13. 'bi/authoring/utils/pat/rsPromptParameters'
  14. ],
  15. function($, Q, dot, Utils, rsPromptParameters){
  16. 'use strict';
  17. //search for simple prompt parameters : p_Product
  18. function findPromptParameters(options) {
  19. var v_oPromptParameters;
  20. for(var v_sKey in options)
  21. {
  22. if (options.hasOwnProperty(v_sKey) && v_sKey.length > 2 && v_sKey.indexOf('p_') == 0 && options[v_sKey])
  23. {
  24. var v_sName = v_sKey.substring(2);
  25. if (!v_oPromptParameters)
  26. {
  27. v_oPromptParameters = {};
  28. }
  29. if (!v_oPromptParameters[v_sName])
  30. {
  31. v_oPromptParameters[v_sName] = [];
  32. }
  33. var v_aOptions = Array.isArray(options[v_sKey]) ? options[v_sKey] : [options[v_sKey]];
  34. for(var i=0; i<v_aOptions.length; i++)
  35. {
  36. v_oPromptParameters[v_sName].push({use: v_aOptions[i], display: v_aOptions[i]});
  37. }
  38. }
  39. }
  40. return v_oPromptParameters;
  41. }
  42. //search for complex prompt parameters
  43. function findPromptParametersComplex(options) {
  44. return options["promptParameters"];
  45. }
  46. function isOutputForDownload(v_sOutputFormat) {
  47. return ['spreadsheetML', 'xlsxData', 'CSV', 'XML'].indexOf(v_sOutputFormat) !== -1;
  48. }
  49. /**
  50. * Takes an object representing global parameter values where the name of the parameter is used
  51. * as the the object property name and converts to an array of parameter values.
  52. * e.g.
  53. * { 'product': {'name': 'product', 'values': [...]}, 'date': {'name':'date', 'values':[...]} }
  54. * becomes
  55. * [ {'name': 'product', 'values': [...]}, {'name':'date', 'values':[...]} ]
  56. */
  57. function convertToArrayImpl( v_oParameterValues ) {
  58. var v_aParameterValues = [];
  59. if (v_oParameterValues != null)
  60. {
  61. for (var v_sKey in v_oParameterValues)
  62. {
  63. if (v_oParameterValues.hasOwnProperty(v_sKey) && v_oParameterValues[v_sKey])
  64. {
  65. v_aParameterValues.push( v_oParameterValues[v_sKey] );
  66. }
  67. }
  68. }
  69. return v_aParameterValues;
  70. }
  71. function useViewer( options )
  72. {
  73. var v_bIsViewer = false;
  74. if (options.type === 'dataSet2') {
  75. // Datasets can only be edited
  76. v_bIsViewer = false;
  77. }
  78. else
  79. {
  80. switch (options.action)
  81. {
  82. case 'edit':
  83. v_bIsViewer = false;
  84. break;
  85. case 'run':
  86. case 'viewOutput':
  87. v_bIsViewer = true;
  88. break;
  89. default:
  90. if (options.isViewer || (options.cmProperties && options.cmProperties.type == "output"))
  91. {
  92. v_bIsViewer = true;
  93. }
  94. }
  95. }
  96. return v_bIsViewer;
  97. }
  98. return {
  99. reject : function( deferred, msg, tag ) {
  100. console.log( (tag ? (tag + ': ') : '' ) + msg );
  101. deferred.reject( new Error(msg) );
  102. },
  103. isObjectOfType : function( cmProperties, v_oType ) {
  104. if (cmProperties) {
  105. if (Array.isArray(v_oType)) {
  106. for (var idx = 0; idx < v_oType.length; ++idx) {
  107. if (this.isObjectOfType(cmProperties, v_oType[idx])) {
  108. return true;
  109. }
  110. }
  111. return false;
  112. }
  113. if (cmProperties.base && cmProperties.base[0].type === v_oType)
  114. {
  115. return true;
  116. }
  117. switch (cmProperties.type)
  118. {
  119. case v_oType:
  120. return true;
  121. case 'reportVersion':
  122. return cmProperties.parent &&
  123. (cmProperties.parent[0].type == v_oType || (cmProperties.parent[0].type == 'reportView' && cmProperties.parent[0].base[0].type == v_oType));
  124. case 'output':
  125. return cmProperties.parent &&
  126. (cmProperties.parent[0].parent[0].type == v_oType || (cmProperties.parent[0].parent[0].type == 'reportView' && cmProperties.parent[0].parent[0].base[0].type == v_oType));
  127. }
  128. }
  129. return false;
  130. },
  131. createTemplateParameters : function(v_oRSParameters) {
  132. var v_oTemplateParameters = {};
  133. v_oTemplateParameters.rsUrl = "pat/rsapp.htm";
  134. v_oTemplateParameters.rsParameters = JSON.stringify(v_oRSParameters);
  135. return v_oTemplateParameters;
  136. },
  137. /**
  138. * Takes an object representing global parameter values where the name of the parameter is used
  139. * as the the object property name and converts to an array of parameter values.
  140. * e.g.
  141. * { 'product': {'name': 'product', 'values': [...]}, 'date': {'name':'date', 'values':[...]} }
  142. * becomes
  143. * [ {'name': 'product', 'values': [...]}, {'name':'date', 'values':[...]} ]
  144. */
  145. convertToArray : function ( v_oParameterValues )
  146. {
  147. return convertToArrayImpl( v_oParameterValues );
  148. },
  149. extractGlassSettings : function( options )
  150. {
  151. var glassSettings;
  152. if (typeof options.ui_appbar !== 'undefined' || typeof options.ui_navbar !== 'undefined') {
  153. glassSettings = {};
  154. // Anything other than true is considered false by glass
  155. if (typeof options.ui_appbar !== 'undefined' && options.ui_appbar !== true) {
  156. glassSettings.ui_appbar = false;
  157. }
  158. if (typeof options.ui_navbar !== 'undefined' && options.ui_navbar !== true) {
  159. glassSettings.ui_navbar = false;
  160. }
  161. }
  162. return glassSettings;
  163. },
  164. isOutputFormatAllowed: function(v_sOutputFormat, glassContext)
  165. {
  166. switch(v_sOutputFormat)
  167. {
  168. case "CSV":
  169. return glassContext.hasCapability("canGenerateCSVOutput");
  170. case "XML":
  171. return glassContext.hasCapability("canGenerateXMLOutput");
  172. case "PDF":
  173. return glassContext.hasCapability("canGeneratePDFOutput");
  174. case "spreadsheetML":
  175. case "xlsxData":
  176. return glassContext.hasCapability("canGenerateXLSOutput");
  177. default:
  178. //"HTML"
  179. }
  180. return true;
  181. },
  182. createRSParameters : function( options, glassContext )
  183. {
  184. var v_sGatewayUrl= "../v1/disp";
  185. var v_sCafContextId = (glassContext && glassContext.cafContextId) || "";
  186. var v_sStoreId = options.cmProperties && options.cmProperties.id;
  187. var v_sReportStoreId = "";
  188. var v_sModuleStoreId = options.moduleId;
  189. var v_sModuleSearchPath = options.moduleSearchPath;
  190. var v_sPackageSearchPath = "";
  191. var v_sType = options.type || "";
  192. if (options.isNew) {
  193. if (this.isObjectOfType(options.cmProperties, 'package')) {
  194. v_sPackageSearchPath = options.cmProperties.searchPath + "/model[last()]";
  195. }
  196. else if (v_sStoreId) {
  197. // We have a CM object but it's not a package - assume module
  198. v_sModuleStoreId = v_sStoreId;
  199. v_sModuleSearchPath = options.cmProperties.searchPath;
  200. }
  201. }
  202. else {
  203. // Loading a report from the glass should only ever be done using a store id, never with a CM search path
  204. // failure to use a store id will result in the interactive viewer not working correctly.
  205. v_sReportStoreId = v_sStoreId;
  206. }
  207. var v_bIsViewer = useViewer( options );
  208. var v_sFormat = options.format;
  209. var v_bRunInAdvancedViewer = options.cmProperties && typeof options.cmProperties.runInAdvancedViewer !== 'undefined' ? !!options.cmProperties.runInAdvancedViewer : true;
  210. options.rsFinalRunOptions = options.rsFinalRunOptions || {};
  211. if (options.rsFinalRunOptions.prompt === undefined && options.prompt !== undefined)
  212. {
  213. options.rsFinalRunOptions.prompt = options.prompt;
  214. }
  215. if (!options.rsFinalRunOptions.globalParameters)
  216. {
  217. var v_oParameterValues = null;
  218. if (glassContext &&
  219. glassContext.services &&
  220. glassContext.services.userProfile &&
  221. glassContext.services.userProfile.userProfileSettings)
  222. {
  223. v_oParameterValues = glassContext.services.userProfile.userProfileSettings.parameter_values;
  224. }
  225. // Always calculate globalParameters. This ensures that RSVP can tell the difference between
  226. // the fact there are no global parameters and that that presence of global parameters is unknown.
  227. // In the latter case, RSVP will call CM to try to get them. If it knows there are none, we avoid the CM call.
  228. var v_aParameterValues = convertToArrayImpl( v_oParameterValues );
  229. options.rsFinalRunOptions.globalParameters = JSON.stringify( v_aParameterValues );
  230. }
  231. if (v_sFormat && !options.rsFinalRunOptions.format )
  232. {
  233. options.rsFinalRunOptions.format = v_sFormat;
  234. }
  235. if (options.rsFinalRunOptions.format && ! options.rsFinalRunOptions.Download)
  236. {
  237. options.rsFinalRunOptions.Download = isOutputForDownload(options.rsFinalRunOptions.format).toString();
  238. }
  239. if (options.editSpecification)
  240. {
  241. options.rsFinalRunOptions.editSpecification = options.editSpecification;
  242. }
  243. else if ( options.m_oLaunchParameters && options.m_oLaunchParameters.editSpecification )
  244. {
  245. options.rsFinalRunOptions.editSpecification = options.m_oLaunchParameters.editSpecification;
  246. }
  247. options.rsFinalRunOptions.isApplication = options.isApplication;
  248. var v_oRSParameters = {
  249. parentType: "RSFrame",
  250. rs_UIProfile : options.UIProfile,
  251. reportStoreID: v_sReportStoreId,
  252. gateway : v_sGatewayUrl,
  253. isViewer : v_bIsViewer,
  254. model : v_sPackageSearchPath,
  255. module : v_sModuleStoreId,
  256. moduleSearchPath : v_sModuleSearchPath,
  257. htmlContainerPath : document.location.pathname,
  258. productLocale : glassContext.services.userProfile.preferences.productLocale || "en",
  259. contentLocale : glassContext.services.userProfile.preferences.contentLocale || "en-us",
  260. runInAdvancedViewer : v_bRunInAdvancedViewer,
  261. cafcontextid : v_sCafContextId,
  262. type : v_sType,
  263. rsFinalRunOptions: options.objRef ? {
  264. //Supported viewer API parameters only
  265. format: v_sFormat || 'HTML',
  266. Download: isOutputForDownload(v_sFormat).toString(),
  267. bidi: options.bidi != undefined ? !!(options.bidi) : undefined,
  268. a11y: options.a11y != undefined ? !!(options.a11y) : undefined,
  269. prompt: options.prompt != undefined ? !!(options.prompt) : undefined,
  270. globalParameters: options.rsFinalRunOptions.globalParameters,
  271. editSpecification: options.rsFinalRunOptions.editSpecification,
  272. isApplication: !!options.rsFinalRunOptions.isApplication
  273. } : options.rsFinalRunOptions,
  274. parameterValuesXML: options.parameterValuesXML,
  275. cmProperties : options.cmProperties,
  276. outputSpec: options.outputSpec,
  277. glassSettings: this.extractGlassSettings(options)
  278. };
  279. if (options.contentLocale)
  280. {
  281. v_oRSParameters.rsFinalRunOptions.contentLocale = options.contentLocale;
  282. }
  283. if (options.action == 'run' && !this.isOutputFormatAllowed( options.rsFinalRunOptions.format, glassContext ))
  284. {
  285. // The selected format is invalid, arrange to close the perspective
  286. v_oRSParameters.closePerspective = true;
  287. }
  288. v_oRSParameters.startingTemplate = options.startingTemplate;
  289. v_oRSParameters.isSlideout = options.isSlideout;
  290. // need promptResponse parameter to pass through. in this case, viewer will show prompt pages of response retrieved from parent RS
  291. v_oRSParameters.promptResponse = options.promptResponse;
  292. var v_oPromptParameters = findPromptParameters(options);
  293. var v_oPromptParametersComplex = findPromptParametersComplex(options);
  294. var v_sParameterValues = rsPromptParameters.rsBuildPromptParameters(v_oPromptParameters, v_oPromptParametersComplex);
  295. if (v_sParameterValues)
  296. {
  297. v_oRSParameters.parameterValuesXML = v_sParameterValues;
  298. }
  299. return v_oRSParameters;
  300. },
  301. _hackFindPlugin: function(appView, id) {
  302. // If we used glassContext.findPlugin() it will find
  303. // plugins from the current perspective -- which MAY NOT be us!
  304. //
  305. // instead use the registeredPlugins on our app view
  306. // HACK - glass does not provide away to go from content-view to app-view
  307. // so have to use our cached value
  308. var plugin;
  309. if (id && appView ) {
  310. plugin = appView.registeredPlugins[id];
  311. }
  312. return plugin;
  313. },
  314. hackLockGlass: function(appView) {
  315. // glassContext.lockGlass() locks the glass for the current perspective
  316. // we only want to lock the glass for our perspective
  317. // when lockglass is called we may not be the current perspective
  318. // HACK until glass provides
  319. //console.log('rsCommon.hackLockGlass');
  320. if (appView) {
  321. appView.$('.navbar').addClass('disabled');
  322. appView.$('.appbar').addClass('disabled');
  323. }
  324. },
  325. hackUnlockGlass: function(appView) {
  326. // glassContext.lockGlass() locks the glass for the current perspective
  327. // we only want to lock the glass for our perspective
  328. // when lockglass is called we may not be the current perspective
  329. // HACK until glass provides
  330. //console.log('rsCommon.hackUnlockGlass');
  331. if (appView) {
  332. appView.$('.navbar').removeClass('disabled');
  333. appView.$('.appbar').removeClass('disabled');
  334. }
  335. },
  336. getAuthoringApplicationFromIFrame: function(iFrame) {
  337. return iFrame && iFrame.contentWindow && iFrame.contentWindow.Application;
  338. },
  339. F_XMLEncode: function(v_sString) {
  340. // &lt; for <
  341. // &gt; for >
  342. // &amp; for &
  343. // &apos; for ' (required for attribute values delimited by the same character)
  344. // &quot; for " (required for attribute values delimited by the same character)
  345. return v_sString.replace( /&/g, "&amp;" ).replace( /</g, "&lt;" ).replace( />/g, "&gt;" ).replace( /'/g, "&apos;" ).replace( /"/g, "&quot;" );
  346. },
  347. /**
  348. * The content view getContent method adds cmProperties to the response. However, when the resulting URL is submitted after pressing F5,
  349. * the cmProeprties is passed to the content view init() method not as the original object but rather a series of properties whose name is
  350. * "cmProperties[prop name]".
  351. * To avoid this unexpected flatening of the object, getContent puts the JSON string representation of cmProperties instead.
  352. * In the case of saved output, reportProperties is also stringified.
  353. * This method turns these string back into the original object form.
  354. */
  355. decodeAndMoveCMProperties: function(options)
  356. {
  357. if (options && options.cmPropStr && !options.cmProperties)
  358. {
  359. var v_oCmProperties;
  360. try {
  361. v_oCmProperties = JSON.parse(options.cmPropStr);
  362. }
  363. catch (e) {
  364. v_oCmProperties = null;
  365. }
  366. if (v_oCmProperties) {
  367. options.cmProperties = v_oCmProperties;
  368. }
  369. }
  370. delete options.cmPropStr;
  371. if (options && options.reportPropStr && !options.reportProperties)
  372. {
  373. var v_oReportProperties;
  374. try {
  375. v_oReportProperties = JSON.parse(options.reportPropStr);
  376. }
  377. catch (e) {
  378. v_oReportProperties = null;
  379. }
  380. if (v_oReportProperties) {
  381. options.reportProperties = v_oReportProperties;
  382. }
  383. }
  384. delete options.reportPropStr;
  385. },
  386. /**
  387. * rsEncodedOptions are used to pass rs options in such a way as to avoid any possible conflict with other
  388. * parameters that exist or may exist in the future that originate from some other component.
  389. */
  390. decodeAndMoveRSOptions: function(options)
  391. {
  392. if (options && options.rsEncodedOptions)
  393. {
  394. // options.rsEncodedOptions exists, decode it and copy it into options
  395. var v_oRsOptions = JSON.parse(options.rsEncodedOptions);
  396. Object.keys(v_oRsOptions).forEach( function(v_sKey) {
  397. options[v_sKey] = v_oRsOptions[v_sKey];
  398. });
  399. delete options.rsEncodedOptions;
  400. }
  401. },
  402. M_aConvertList : [
  403. 'isViewer',
  404. 'isNew',
  405. 'isApplication',
  406. 'a11y',
  407. 'bidi',
  408. 'runInAdvancedViewer',
  409. 'prompt',
  410. 'rsFinalRunOptions',
  411. 'promptParameters',
  412. 'ui_appbar',
  413. 'ui_navbar'
  414. ],
  415. convertStringQSToValues: function(options, glassContext, trimURLParameterValues) {
  416. var v_bStringOnlyQS = glassContext.getCoreSvc('.FeatureChecker').checkValue('ba-glass', 'stringOnlyQS', 'enabled');
  417. if (!v_bStringOnlyQS)
  418. {
  419. return;
  420. }
  421. for(var propertyName in options)
  422. {
  423. if (options[propertyName])
  424. {
  425. if (this.M_aConvertList.indexOf(propertyName) != -1)
  426. {
  427. if (typeof options[propertyName] === 'object')
  428. {
  429. this.convertStringQSToValues(options[propertyName], glassContext);
  430. }
  431. else if (typeof options[propertyName] === 'string')
  432. {
  433. if (options[propertyName] === 'true')
  434. {
  435. options[propertyName] = true;
  436. }
  437. else if (options[propertyName] === 'false')
  438. {
  439. options[propertyName] = false;
  440. }
  441. else
  442. {
  443. var v_numberValue = Number(options[propertyName]);
  444. options[propertyName] = isNaN(v_numberValue) ? options[propertyName] : v_numberValue;
  445. }
  446. }
  447. }
  448. else if (propertyName.indexOf('p_') == 0 && trimURLParameterValues === true)
  449. {
  450. options[propertyName] = options[propertyName].trim();
  451. }
  452. }
  453. }
  454. },
  455. getAvailableOutputs: function(glassContext, v_oOutputProperties)
  456. {
  457. return glassContext.getSvc('.Content')
  458. .then(function(v_oContentSvc) {
  459. var v_sCMQueryUrl = v_oContentSvc.getBaseObjectsURL() + '/' + v_oOutputProperties.parent[0].id + '/outputs?fields=dataDescriptor,parent,locale,format,permissions,ancestors,lastPage';
  460. return v_oContentSvc.get(v_sCMQueryUrl, {});
  461. });
  462. },
  463. /**
  464. * Generic implementation of glass getContent method.
  465. * @param options The options parameter passed from glass
  466. * @param v_oContentView The actual content view instance (rv or cv) being called
  467. * @param rsShareHelper Pass share helper module to avoid having to declare it and introduce circular dependency
  468. */
  469. getContent: function( options, v_oContentView, rsShareHelper ) {
  470. var v_bOnlyBookmarkContent = options && options.mode == "bookmark";
  471. var v_oReturn = {};
  472. var v_oCmProperties;
  473. if (v_oContentView.cmProperties) {
  474. // Start with the basic share link
  475. v_oReturn = rsShareHelper.buildShareUrlMap(v_oContentView);
  476. // The glass adds the perspective to the URL created from the getContent response.
  477. // As a result, when the URL is processed by the browser (via F5 or copy/paste)
  478. // it is not handled as a share link due to the presence of the perspective.
  479. // Therefore the authoring code that expands the share link information to the full set of data needed by authoring is not called.
  480. // As a result, we are forced to add additional information to ensure the URL created from the getContent response
  481. // actually works.
  482. // Need minimal cm property information
  483. v_oCmProperties = {
  484. id: v_oContentView.cmProperties.id,
  485. type: v_oContentView.cmProperties.type,
  486. defaultName: v_oContentView.cmProperties.defaultName,
  487. permissions: v_oContentView.cmProperties.permissions
  488. };
  489. if (v_oContentView.cmProperties.type == 'output')
  490. {
  491. // Saved output requires more info
  492. if (v_oContentView.cmProperties.ancestors) {
  493. var v_sReportName = v_oContentView.cmProperties.ancestors[v_oContentView.cmProperties.ancestors.length-2].defaultName;
  494. v_oCmProperties.defaultName = v_sReportName + " - " + v_oContentView.cmProperties.modificationTime.substring(0, 10)+ " - " + v_oContentView.cmProperties.format;
  495. }
  496. v_oCmProperties.modificationTime = v_oContentView.cmProperties.modificationTime;
  497. v_oCmProperties.format = v_oContentView.cmProperties.format;
  498. if (v_oContentView.cmProperties.parent && v_oContentView.cmProperties.parent.length > 0)
  499. {
  500. v_oCmProperties.parent = [
  501. {
  502. id: v_oContentView.cmProperties.parent[0].id,
  503. type: v_oContentView.cmProperties.parent[0].type
  504. }
  505. ];
  506. }
  507. if (v_oContentView.reportProperties) {
  508. v_oReturn.reportPropStr = JSON.stringify( {
  509. id: v_oContentView.reportProperties.id,
  510. type: v_oContentView.reportProperties.type,
  511. defaultName: v_oContentView.reportProperties.defaultName
  512. } );
  513. }
  514. v_oReturn.type = 'output';
  515. delete v_oReturn.objRef;
  516. }
  517. v_oReturn.cmPropStr = JSON.stringify( v_oCmProperties );
  518. }
  519. if (v_oContentView.id) {
  520. v_oReturn.id = v_oContentView.id;
  521. }
  522. if (!v_bOnlyBookmarkContent)
  523. {
  524. v_oReturn.application = v_oContentView.getApplicationContent( v_oReturn, v_oCmProperties );
  525. }
  526. else
  527. {
  528. // APAR 120836 REPORT FAILS TO RUN IN IE11 IF THE DRILL-THROUGH PROMPTPARAMETER VALUES ARE LARGER THAN 2,083 CHAR LIMIT
  529. // On bookmark, remove the prompt params as that can make the URL too long leading to a long REFERER header
  530. delete v_oReturn.promptParameters;
  531. }
  532. return v_oReturn;
  533. }
  534. };
  535. });