8.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. 'use strict';
  2. /*
  3. *+------------------------------------------------------------------------+
  4. *| Licensed Materials - Property of IBM
  5. *| IBM Cognos Products: BI Dashboard
  6. *| (C) Copyright IBM Corp. 2016, 2019
  7. *|
  8. *| US Government Users Restricted Rights - Use, duplication or disclosure
  9. *| restricted by GSA ADP Schedule Contract with IBM Corp.
  10. *+------------------------------------------------------------------------+
  11. */
  12. define(['../../../lib/@waca/core-client/js/core-client/ui/core/Class', '../../../lib/@waca/upgrades/UpgradeBase', '../../../lib/@waca/dashboard-common/dist/query/FacetDataObject', 'jquery', 'underscore'], function (Class, UpgradeBase, FacetObject, $, _) {
  13. var UPLOADED_FILE_TYPE = 'uploadedFile';
  14. var DATASET2_TYPE = 'dataSet2';
  15. var Upgrade = Class.extend([UpgradeBase], {
  16. init: function init() {
  17. this.VERSION = 8;
  18. },
  19. /**
  20. * Perform upgrade
  21. *
  22. * @param {object} spec - spec to perform upgrade on
  23. *
  24. * @return {Promise} Promise always resolved when upgrade performed; error is logged only
  25. */
  26. up: function up(spec) {
  27. if (!spec) {
  28. return Promise.resolve(spec);
  29. }
  30. this._upgradeEventGroups(spec);
  31. this._upgradeTimeline(spec);
  32. return this._upgradeIdentifiers(spec).catch(function (error) {
  33. if (this.data.logger) {
  34. this.data.logger.error(error);
  35. }
  36. return spec;
  37. }.bind(this));
  38. },
  39. // Update columnId: change from content-locale to model-locale
  40. _upgradeIdentifiers: function _upgradeIdentifiers(boardSpec) {
  41. var _this = this;
  42. var initialDatasetInfos = [];
  43. // Collect all columnIds from widgets - Also update filter values in widgets
  44. _.each(boardSpec.widgets, function (widgetSpec) {
  45. var datasetInfo = _this._collectColumnIdsInWidget(widgetSpec);
  46. if (datasetInfo) {
  47. var exist = _.findWhere(initialDatasetInfos, {
  48. datasetId: datasetInfo.datasetId
  49. });
  50. if (!exist) {
  51. initialDatasetInfos.push(datasetInfo);
  52. } else {
  53. // concatenate column lists with existing dataset
  54. exist.columnIds = exist.columnIds.concat(datasetInfo.columnIds);
  55. }
  56. }
  57. });
  58. // Collect all columnIds from datasetShaping (calculations, data tray filters) - Also update filter values in dataset shaping
  59. if (boardSpec.datasetShaping && boardSpec.datasetShaping.length > 0) {
  60. this._collectColumnIdsFromDatasetShaping(boardSpec.datasetShaping, initialDatasetInfos);
  61. }
  62. // We have updated all filter values for R6 to have use/display format, now we can eliminate datasets
  63. // of type uploaded file or dataSet2 as these datasets do not support multi-lingual
  64. var datasetInfos = _.filter(initialDatasetInfos, function (datasetInfo) {
  65. if (datasetInfo.datasetType !== UPLOADED_FILE_TYPE && datasetInfo.datasetType !== DATASET2_TYPE) {
  66. return datasetInfo;
  67. }
  68. });
  69. // If the same dataset is used in different widgets, merge their list of columnIds to call Moser once per dataset
  70. this._mergeDatasetColumnIds(datasetInfos);
  71. // Call Moser REST-API to get identifiers in model locale
  72. var identifierPromises = [];
  73. _.each(datasetInfos, function (datasetInfo) {
  74. if (!datasetInfo.merged) {
  75. identifierPromises.push(_this._getIdentifiersInModelLocale(datasetInfo));
  76. }
  77. });
  78. return Promise.all(identifierPromises).then(function () {
  79. for (var i = 0; i < datasetInfos.length; ++i) {
  80. if (datasetInfos[i].newColumnIds && datasetInfos[i].newColumnIds.length > 0) {
  81. _this._replaceIdentifiersInAllWidgets(datasetInfos[i], boardSpec);
  82. _this._replaceIdentifiersInDatasetShaping(datasetInfos[i], boardSpec);
  83. }
  84. }
  85. return boardSpec;
  86. });
  87. },
  88. _collectColumnIdsFromDatasetShaping: function _collectColumnIdsFromDatasetShaping(datasetShaping, datasetInfos) {
  89. for (var i = 0; i < datasetShaping.length; ++i) {
  90. var aDatasetShaping = datasetShaping[i];
  91. var datasetInfo = _.findWhere(datasetInfos, {
  92. datasetId: aDatasetShaping.id
  93. });
  94. if (!datasetInfo) {
  95. // create new datasetInfo
  96. datasetInfo = {
  97. datasetId: aDatasetShaping.id,
  98. columnIds: [],
  99. datasetType: 'module' //Unable find to a matched dataset from any widget.
  100. };
  101. datasetInfos.push(datasetInfo);
  102. }
  103. if (aDatasetShaping.calculations && aDatasetShaping.calculations.length > 0) {
  104. this._collectCalculationColumnIds(aDatasetShaping.calculations, datasetInfo.columnIds);
  105. }
  106. if (aDatasetShaping.filters && aDatasetShaping.filters.length > 0) {
  107. this._collectFilterColumnIdsAndUpgradeFilterValues(aDatasetShaping.filters, datasetInfo.columnIds);
  108. }
  109. if (datasetInfo.columnIds.length > 0) {
  110. datasetInfo.columnIds = _.uniq(datasetInfo.columnIds);
  111. }
  112. }
  113. },
  114. _collectCalculationColumnIds: function _collectCalculationColumnIds(calculations, columnIds) {
  115. _.each(calculations, function (calculation) {
  116. if (calculation.expr && calculation.expr.params && calculation.expr.params.length > 0) {
  117. _.each(calculation.expr.params, function (param) {
  118. if (param.col) {
  119. columnIds.push(param.col);
  120. }
  121. });
  122. }
  123. });
  124. },
  125. /*
  126. *@param {Array} filters
  127. *@param {Array} columnIds, array that holds collected column IDs, Optional
  128. */
  129. _collectFilterColumnIdsAndUpgradeFilterValues: function _collectFilterColumnIdsAndUpgradeFilterValues(filters, columnIds) {
  130. var _this2 = this;
  131. _.each(filters, function (filter) {
  132. if (filter.columnId) {
  133. if (columnIds) {
  134. columnIds.push(filter.columnId);
  135. }
  136. _this2._upgradeFilterValues(filter);
  137. }
  138. });
  139. },
  140. _mergeDatasetColumnIds: function _mergeDatasetColumnIds(datasetInfos) {
  141. if (datasetInfos.length === 0) {
  142. return;
  143. }
  144. for (var i = 0; i < datasetInfos.length; ++i) {
  145. // Remove duplicates
  146. datasetInfos[i].columnIds = _.uniq(datasetInfos[i].columnIds);
  147. }
  148. },
  149. _findSameDataset: function _findSameDataset(datasetId, startIndex, datasetInfos) {
  150. for (var j = startIndex + 1; j < datasetInfos.length; ++j) {
  151. if (!datasetInfos[j].merged && datasetInfos[j].datasetId === datasetId) {
  152. return j;
  153. }
  154. }
  155. return -1;
  156. },
  157. _collectColumnIdsInWidget: function _collectColumnIdsInWidget(widgetModel) {
  158. if (!widgetModel || !widgetModel.dataSet) {
  159. return null; //Upgrade is not needed
  160. }
  161. // Collect all columnIds used in this widget
  162. var columnIdsOfWidget = this._collectColumnIds(widgetModel);
  163. if (columnIdsOfWidget.length === 0) {
  164. return null;
  165. }
  166. return {
  167. datasetId: widgetModel.dataSet.id,
  168. columnIds: columnIdsOfWidget,
  169. datasetType: widgetModel.dataSet.type
  170. };
  171. },
  172. _collectColumnIds: function _collectColumnIds(widgetModel) {
  173. var columnIds = [];
  174. _.each(widgetModel.mapping, function (mapping) {
  175. if (mapping.columnId) {
  176. columnIds.push(mapping.columnId);
  177. }
  178. }.bind(this));
  179. //Update model filters attributes
  180. _.each(widgetModel.filters, function (filter) {
  181. if (filter.columnId) {
  182. columnIds.push(filter.columnId);
  183. this._upgradeFilterValues(filter);
  184. } else {
  185. // compound filters with nested values structure (see example in unit test)
  186. this._collectColumnIdsInCompoundFilter(filter, columnIds);
  187. }
  188. }.bind(this));
  189. //Update model local filters attributes
  190. this._collectFilterColumnIdsAndUpgradeFilterValues(widgetModel.localFilters, columnIds);
  191. return _.uniq(columnIds);
  192. },
  193. /*Upgrade pre-R6 filter values to R6 FacetDataObject*/
  194. _upgradeFilterValues: function _upgradeFilterValues(filter) {
  195. if (filter && _.isArray(filter.values) && filter.values.length > 0) {
  196. var result = [];
  197. _.each(filter.values, function (value) {
  198. //include NULL values
  199. result.push(!_.isObject(value) ? new FacetObject(value).toJSONObject() : value);
  200. });
  201. filter.values = result;
  202. }
  203. },
  204. _collectColumnIdsInCompoundFilter: function _collectColumnIdsInCompoundFilter(filter, columnIds) {
  205. if (filter.columnId) {
  206. columnIds.push(filter.columnId);
  207. }
  208. if (filter.values) {
  209. this._collectColumnIdsInValues(filter.values, columnIds);
  210. }
  211. },
  212. _collectColumnIdsInValues: function _collectColumnIdsInValues(values, columnIds) {
  213. _.each(values, function (value) {
  214. if (value.columnId) {
  215. columnIds.push(value.columnId);
  216. }
  217. this._upgradeFilterValues(value);
  218. if (value.values) {
  219. this._collectColumnIdsInValues(value.values, columnIds);
  220. }
  221. }.bind(this));
  222. },
  223. _getIdentifiersInModelLocale: function _getIdentifiersInModelLocale(datasetInfo) {
  224. var _this3 = this;
  225. var datasetId = datasetInfo.datasetId;
  226. return this.data.ajaxSvc.ajax({
  227. url: 'v1/metadata/modules/' + datasetId + '/identifiers',
  228. type: 'GET',
  229. data: {
  230. idArray: JSON.stringify(datasetInfo.columnIds.sort())
  231. },
  232. headers: {
  233. Accept: 'application/json'
  234. }
  235. }).then(function (response) {
  236. // Moser response is an array of objects:
  237. // {
  238. // 'source': <identifier in dashboard>
  239. // 'target': <identifier in model locale>
  240. // }
  241. datasetInfo.newColumnIds = response.data;
  242. return response;
  243. }).catch(function (error) {
  244. _this3.data.logger.error('Error calling Modeling service API to update identifiers');
  245. var err = '';
  246. if (error.jqXHR.responseText) {
  247. err = error.jqXHR.responseText;
  248. _this3.data.logger.error(err);
  249. }
  250. throw err; // re-throw
  251. });
  252. },
  253. _replaceIdentifiersInAllWidgets: function _replaceIdentifiersInAllWidgets(datasetInfo, boardSpec) {
  254. var _this4 = this;
  255. _.each(boardSpec.widgets, function (widgetSpec) {
  256. if (widgetSpec.dataSet && widgetSpec.dataSet.id === datasetInfo.datasetId) {
  257. _this4._replaceIdentifiersInOneWidget(widgetSpec, datasetInfo.newColumnIds);
  258. }
  259. });
  260. },
  261. _replaceIdentifiersInDatasetShaping: function _replaceIdentifiersInDatasetShaping(datasetInfo, boardSpec) {
  262. if (boardSpec.datasetShaping) {
  263. var aDatasetShaping = _.findWhere(boardSpec.datasetShaping, {
  264. id: datasetInfo.datasetId
  265. });
  266. if (aDatasetShaping) {
  267. if (aDatasetShaping.calculations && aDatasetShaping.calculations.length > 0) {
  268. this._replaceIdentifiersInCalculations(aDatasetShaping.calculations, datasetInfo.newColumnIds);
  269. }
  270. if (aDatasetShaping.filters && aDatasetShaping.filters.length > 0) {
  271. this._replaceIdentifiersInFilters(aDatasetShaping.filters, datasetInfo.newColumnIds);
  272. }
  273. }
  274. }
  275. },
  276. _replaceIdentifiersInCalculations: function _replaceIdentifiersInCalculations(calculations, columnIdsMapping) {
  277. _.each(calculations, function (calculation) {
  278. if (calculation.expr && calculation.expr.params && calculation.expr.params.length > 0) {
  279. _.each(calculation.expr.params, function (param) {
  280. if (param.col) {
  281. var newColumn = _.findWhere(columnIdsMapping, {
  282. source: param.col
  283. });
  284. if (newColumn) {
  285. param.col = newColumn.target;
  286. }
  287. }
  288. });
  289. }
  290. });
  291. },
  292. _replaceIdentifiersInFilters: function _replaceIdentifiersInFilters(filters, columnIdsMapping) {
  293. _.each(filters, function (filter) {
  294. if (filter.columnId) {
  295. this._replaceIdentifierOfColumn(filter, columnIdsMapping);
  296. }
  297. }.bind(this));
  298. },
  299. _replaceIdentifiersInCompoundFilters: function _replaceIdentifiersInCompoundFilters(filter, columnIdsMapping) {
  300. if (filter.columnId) {
  301. this._replaceIdentifierOfColumn(filter.columnId, columnIdsMapping);
  302. }
  303. if (filter.values) {
  304. this._replaceIdentifiersInValues(filter.values, columnIdsMapping);
  305. }
  306. },
  307. _replaceIdentifiersInValues: function _replaceIdentifiersInValues(values, columnIdsMapping) {
  308. _.each(values, function (value) {
  309. if (value.columnId) {
  310. this._replaceIdentifierOfColumn(value, columnIdsMapping);
  311. }
  312. if (value.values) {
  313. this._replaceIdentifiersInValues(value.values, columnIdsMapping);
  314. }
  315. }.bind(this));
  316. },
  317. _replaceIdentifiersInOneWidget: function _replaceIdentifiersInOneWidget(widgetModel, columnIdsMapping) {
  318. _.each(widgetModel.mapping, function (mapping) {
  319. if (mapping.columnId) {
  320. this._replaceIdentifierOfColumn(mapping, columnIdsMapping);
  321. }
  322. }.bind(this));
  323. //Update model filters attributes
  324. _.each(widgetModel.filters, function (filter) {
  325. if (filter.columnId) {
  326. this._replaceIdentifierOfColumn(filter, columnIdsMapping);
  327. } else {
  328. this._replaceIdentifiersInCompoundFilters(filter, columnIdsMapping);
  329. }
  330. }.bind(this));
  331. //Update model local filters attributes
  332. _.each(widgetModel.localFilters, function (filter) {
  333. if (filter.columnId) {
  334. this._replaceIdentifierOfColumn(filter, columnIdsMapping);
  335. }
  336. }.bind(this));
  337. },
  338. _replaceIdentifierOfColumn: function _replaceIdentifierOfColumn(column, columnIdsMapping) {
  339. var newColumn = _.findWhere(columnIdsMapping, {
  340. source: column.columnId
  341. });
  342. if (newColumn) {
  343. column.columnId = newColumn.target;
  344. }
  345. },
  346. _upgradeEventGroups: function _upgradeEventGroups(boardSpec) {
  347. if (boardSpec && boardSpec.layout && !boardSpec.evenGroups) {
  348. var eventGroups = [];
  349. var root = boardSpec.layout;
  350. var isSinglePage = true;
  351. // Consider it as single page if the root's children is empty or contains a group or widget
  352. if (root.items && root.items.length > 0) {
  353. isSinglePage = _.find(root.items, function (layout) {
  354. return layout.type === 'widget' || layout.type === 'group';
  355. }) ? true : false;
  356. }
  357. if (isSinglePage) {
  358. eventGroups.push(this._buildEventGroup(root));
  359. } else {
  360. _.each(root.items, function (tab) {
  361. eventGroups.push(this._buildEventGroup(tab));
  362. }.bind(this));
  363. }
  364. boardSpec.eventGroups = eventGroups;
  365. }
  366. },
  367. _buildEventGroup: function _buildEventGroup(layout, eventGroup) {
  368. // define an empty event group
  369. eventGroup = eventGroup || {
  370. id: layout.id + ':1',
  371. widgetIds: []
  372. };
  373. if (layout.type === 'widget') {
  374. eventGroup.widgetIds.push(layout.id);
  375. } else {
  376. _.each(layout.items, function (layout) {
  377. this._buildEventGroup(layout, eventGroup);
  378. }.bind(this));
  379. }
  380. return eventGroup;
  381. },
  382. _upgradeTimeline: function _upgradeTimeline(boardSpec) {
  383. if (boardSpec && boardSpec.timeline) {
  384. var episodes = [];
  385. _.each(boardSpec.timeline.items, function (timelineModel) {
  386. // preserve old behavior... it's not clear how this could happen
  387. if (timelineModel.id) {
  388. episodes.push(this._upgradeTimelineSpec(timelineModel));
  389. }
  390. }.bind(this));
  391. delete boardSpec.timeline.items;
  392. boardSpec.timeline.episodes = episodes;
  393. }
  394. },
  395. _upgradeTimelineSpec: function _upgradeTimelineSpec(timelineSpec) {
  396. var acts = [];
  397. if (timelineSpec.episode) {
  398. acts.push({
  399. timer: timelineSpec.episode.timer1 || timelineSpec.episode.timer1 === 0 ? timelineSpec.episode.timer1 : 0,
  400. action: timelineSpec.episode.action1 || 'show'
  401. });
  402. acts.push({
  403. timer: timelineSpec.episode.timer2 || timelineSpec.episode.timer2 === 0 ? timelineSpec.episode.timer2 : 5000,
  404. action: timelineSpec.episode.action2 || 'hide'
  405. });
  406. }
  407. return {
  408. id: timelineSpec.id,
  409. type: timelineSpec.type,
  410. acts: acts
  411. };
  412. },
  413. down: function down(spec) {
  414. // no downgrade at this time; return as is
  415. return Promise.resolve(spec);
  416. }
  417. });
  418. return new Upgrade();
  419. });
  420. //# sourceMappingURL=8.js.map