LicensePane.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. "use strict";
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: admin
  5. * Copyright IBM Corp. 2015, 2021
  6. * US Government Users Restricted Rights -
  7. * Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  8. */
  9. define(['q', 'bi/admin/common/slideout/BasePane', 'bi/admin/system/services/ApiSvc', 'text!bi/admin/license/templates/LicensePane.html', 'jquery', 'doT', 'bi/commons/ui/properties/PropertyUIControl', 'bi/admin/common/utils/WaitingMask', 'bi/commons/i18n/Formatter', 'bi/admin/nls/StringResource'], function (Q, BasePane, Api, template, $, doT, PropertyUIControl, WaitingMask, Formatter, StringResource) {
  10. //NOSONAR
  11. 'use strict'; //NOSONAR: meant to be strict
  12. var LicensePane = BasePane.extend({
  13. init: function init(options) {
  14. LicensePane.inherited('init', this, arguments);
  15. $.extend(this, options);
  16. Api.glassContext = this.glassContext;
  17. },
  18. renderBody: function renderBody() {
  19. var deferred = Q.defer();
  20. var envTypePromise = this.glassContext.services.ajax.ajax({
  21. dataType: 'json',
  22. type: 'GET',
  23. url: 'v1/license'
  24. });
  25. var licSummaryPromise = this.glassContext.services.ajax.ajax({
  26. dataType: 'json',
  27. type: 'GET',
  28. url: 'v1/licenses'
  29. });
  30. $.when(envTypePromise, licSummaryPromise).then(function (envTypeResult, licSummaryResult) {
  31. this.envType = envTypeResult[0];
  32. this.licenseSummary = this._sortLicenses(licSummaryResult[0]);
  33. this._renderPaneBody().then(function () {
  34. this.$el.find(".bi-admin-lic-counts-section input.bi-admin-lic-ownedValue").attr("type", "number");
  35. deferred.resolve(this);
  36. }.bind(this));
  37. }.bind(this));
  38. return deferred.promise;
  39. },
  40. fixButtonLabelling: function fixButtonLabelling() {
  41. var buttons = this.$el.find(".arrow.blueArrow.clickable.rightArrow");
  42. buttons.removeAttr("aria-labelledby");
  43. buttons.attr("aria-label", StringResource.get('licenseUsageByUser'));
  44. },
  45. _renderPaneBody: function _renderPaneBody() {
  46. var deferred = Q.defer();
  47. this.$body.html(doT.template(template)(this._getTemplateData()));
  48. this._oPropertyUIControl = new PropertyUIControl({
  49. 'el': this.$body.find('.bi-admin-licenses'),
  50. 'glassContext': this.glassContext,
  51. 'slideout': this.slideout,
  52. 'items': this._getPaneItems()
  53. });
  54. this._oPropertyUIControl.render().then(function () {
  55. this._disableApplyButton();
  56. this._showLinkIcons();
  57. this.fixButtonLabelling();
  58. deferred.resolve(this);
  59. }.bind(this));
  60. return deferred.promise;
  61. },
  62. _getApplyButton: function _getApplyButton() {
  63. var footerSection = this._oPropertyUIControl.getProperty('footerSection');
  64. return footerSection._oPropertyUIControl.getProperty('applyButton');
  65. },
  66. _disableApplyButton: function _disableApplyButton() {},
  67. _enableApplyButton: function _enableApplyButton() {},
  68. _showLinkIcons: function _showLinkIcons() {
  69. this.$body.find('.bi-admin-lic-link .svgIcon').css('visibility', 'visible');
  70. },
  71. _sortLicenses: function _sortLicenses(licensesSumary) {
  72. // Sort licenses in descending order of their levels
  73. licensesSumary.licenses.sort(function (licenseA, licenseB) {
  74. if (licenseA.level > licenseB.level) {
  75. return -1;
  76. } else if (licenseA.level < licenseB.level) {
  77. return 1;
  78. } else {
  79. return 0;
  80. }
  81. });
  82. return licensesSumary;
  83. },
  84. _getPaneItems: function _getPaneItems() {
  85. var items = [];
  86. this._addEnvTypeItems(items, this.envType);
  87. this._addLicensesUsageHeader(items);
  88. this._addLicenseCounts(items);
  89. this._addExportRefresh();
  90. this._addPaneFooter(items);
  91. return items;
  92. },
  93. _addSeparator: function _addSeparator(items, container) {
  94. items.push({
  95. 'type': 'Separator',
  96. 'el': container
  97. });
  98. },
  99. _addEnvTypeItems: function _addEnvTypeItems(items, envType) {
  100. var container = this.$body.find('.bi-admin-lic-envtype-section');
  101. items.push({
  102. 'type': 'SectionLabel',
  103. 'el': container,
  104. 'name': 'envType',
  105. 'label': StringResource.get('envType')
  106. });
  107. items.push({
  108. 'type': 'RadioButtonGroup',
  109. 'el': container,
  110. 'name': 'envTypeRadio',
  111. 'ariaLabel': StringResource.get('envType'),
  112. 'controlOnLeft': true,
  113. 'indent': 1,
  114. 'value': envType.status,
  115. 'items': [{
  116. 'value': 'production',
  117. 'label': StringResource.get('production')
  118. }, {
  119. 'value': 'non-production',
  120. 'label': StringResource.get('nonProduction')
  121. }],
  122. 'onChange': function () {
  123. this._enableApplyButton();
  124. }.bind(this)
  125. });
  126. },
  127. _addLicensesUsageHeader: function _addLicensesUsageHeader(items) {
  128. var container = this.$body.find('.bi-admin-lic-usageheader-section');
  129. items.push({
  130. 'type': 'SectionLabel',
  131. 'el': container,
  132. 'name': 'globalLicUsage',
  133. 'label': StringResource.get('globalLicUsage')
  134. });
  135. var descSecEl$ = $(this.$body.find('.bi-admin-lic-description-section'));
  136. descSecEl$.attr("aria-label", StringResource.get('globalLicenseDescription'));
  137. descSecEl$.text(StringResource.get('licUsageDescription'));
  138. },
  139. _getTemplateData: function _getTemplateData() {
  140. var totalUsedLicenses = 0;
  141. $.each(this.licenseSummary.licenses, function (index, licInfo) {
  142. if (licInfo.level !== -1) {
  143. totalUsedLicenses += licInfo.used;
  144. }
  145. });
  146. return {
  147. 'strings': {
  148. 'licenses': StringResource.get('licenses'),
  149. 'used': StringResource.get('usedLicenses'),
  150. 'owned': StringResource.get('ownedLicenses'),
  151. 'totalLicenses': StringResource.get('totalLicenses'),
  152. 'exportText': StringResource.get('export'),
  153. 'exportTitle': StringResource.get('exportAsCSV'),
  154. 'refreshText': StringResource.get('refresh'),
  155. 'refreshTitle': StringResource.get('refreshUsedLic'),
  156. 'lastRefreshLabel': StringResource.get('lastRefresh'),
  157. 'lastRefreshDateTime': Formatter.format(new Date(this.licenseSummary.asOfTime), {
  158. type: 'datetime',
  159. formatLength: 'short',
  160. locale: this.glassContext.services.userProfile.preferences.productLocale,
  161. timezone: this.glassContext.services.userProfile.preferences.timeZoneID
  162. })
  163. },
  164. 'licenses': this.licenseSummary.licenses,
  165. 'totalUsedLicenses': totalUsedLicenses
  166. };
  167. },
  168. _addLicenseCounts: function _addLicenseCounts(items) {
  169. var $tdElems = this.$el.find('.bi-admin-lic-separator');
  170. $.each($tdElems, function (index, tdElem) {
  171. this._addSeparator(items, tdElem);
  172. }.bind(this));
  173. this._addOwnedValues(items);
  174. this._addLicenseByUserPaneLinks(items);
  175. this._addTotalOwnedValues(items);
  176. },
  177. _addLicenseByUserPaneLinks: function _addLicenseByUserPaneLinks(items) {
  178. var $tdElems = this.$el.find('.bi-admin-lic-pane-links');
  179. $.each($tdElems, function (index, tdElem) {
  180. var licenseInfo = this.licenseSummary.licenses[index];
  181. items.push({
  182. 'type': 'SingleLineValue',
  183. 'el': tdElem,
  184. 'licenseInfo': licenseInfo,
  185. 'label': '',
  186. 'ellipses': true,
  187. 'licensePane': this,
  188. 'editCallback': this._showLicenseByUserPane
  189. });
  190. }.bind(this));
  191. },
  192. _addOwnedValues: function _addOwnedValues(items) {
  193. var $tdElems = this.$el.find('.bi-admin-lic-ownedCount');
  194. $.each($tdElems, function (index, tdElem) {
  195. var licenseInfo = this.licenseSummary.licenses[index];
  196. items.push({
  197. 'type': 'SingleLineLinks',
  198. 'el': tdElem,
  199. 'name': 'ownedValueLink',
  200. 'items': [{
  201. 'align': 'right',
  202. 'items': [{
  203. 'type': 'Input',
  204. 'name': 'ownedValue_' + licenseInfo.level,
  205. 'ellipses': false,
  206. 'inputType': 'number',
  207. 'inputClass': 'bi-admin-lic-ownedValueInput bi-admin-lic-ownedValue',
  208. 'highlightTextOnFocus': false,
  209. 'value': licenseInfo.owned,
  210. 'onChange': function (propertyId) {
  211. if (this._oPropertyUIControl.getProperty(propertyId).value < 0) {
  212. this.glassContext.appController.showToast(StringResource.get('licenseInvalidInput'), {
  213. 'type': 'warning'
  214. });
  215. this._oPropertyUIControl.getProperty(propertyId).setValue(0);
  216. }
  217. this._onOwnedValueChange();
  218. }.bind(this),
  219. 'handleReturnKey': true
  220. }, {
  221. 'type': 'icon',
  222. 'name': 'ownedValueIcon_' + licenseInfo.level,
  223. 'svgIcon': 'common-edit',
  224. 'class': 'bi-admin-lic-ownedValueIcon'
  225. }]
  226. }]
  227. });
  228. }.bind(this));
  229. $tdElems.hover(this._onHoverIn.bind(this), this._onHoverOut.bind(this));
  230. },
  231. _addTotalOwnedValues: function _addTotalOwnedValues(items) {
  232. // Add total owned value as a SingleLineLinks to make it align with
  233. // the rest of the owned values in the column
  234. var totalOwnedLicenses = 0;
  235. $.each(this.licenseSummary.licenses, function (index, licInfo) {
  236. if (licInfo.level !== -1) {
  237. totalOwnedLicenses += licInfo.owned;
  238. }
  239. });
  240. var $tdElem = this.$el.find('#bi-admin-lic-totalOwned');
  241. this._addOwnedColumnValue(items, $tdElem, 'totalOwnedLicLink', 'totalOwnedValue', totalOwnedLicenses);
  242. },
  243. _addOwnedColumnValue: function _addOwnedColumnValue(items, elem, controlName, rowName, value) {
  244. items.push({
  245. 'type': 'SingleLineLinks',
  246. 'el': elem,
  247. 'name': controlName,
  248. 'items': [{
  249. 'align': 'right',
  250. 'items': [{
  251. 'type': 'Input',
  252. 'name': rowName,
  253. 'inputType': 'number',
  254. 'ariaLabel': StringResource.get('totalOwnedLicenses'),
  255. 'ellipses': false,
  256. 'inputClass': 'bi-admin-lic-ownedValue bi-admin-lic-ownedValueInput ba-admin-lic-readOnly',
  257. 'value': value,
  258. 'readOnly': true
  259. }, {
  260. 'type': 'icon',
  261. 'svgIcon': 'common-edit',
  262. 'class': 'bi-admin-lic-ownedValueIcon'
  263. }]
  264. }]
  265. });
  266. },
  267. _editOwnedValue: function _editOwnedValue($el, evt) {
  268. var $input = $($el.parent()).find("input.bi-admin-lic-ownedValueInput");
  269. $input.focus();
  270. var $iconEl = this.$el.find('.bi-admin-lic-ownedValueIcon');
  271. $iconEl.css('visibility', 'hidden');
  272. $iconEl.off("primaryaction");
  273. },
  274. _onHoverIn: function _onHoverIn(evt) {
  275. var $el = $($(evt.target).find('.bi-admin-lic-ownedValueIcon'));
  276. $el.css('visibility', 'visible');
  277. $el.on("primaryaction", this._editOwnedValue.bind(this, $el));
  278. },
  279. _onHoverOut: function _onHoverOut(evt) {
  280. var $el = $($(evt.target).find('.bi-admin-lic-ownedValueIcon'));
  281. $el.css('visibility', 'hidden');
  282. $el.off("primaryaction");
  283. },
  284. _showLicenseByUserPane: function _showLicenseByUserPane() {
  285. var paneTitle = this.licenseInfo.name + ' - ' + StringResource.get('licenseUsageByUser');
  286. this.licensePane.glassContext.appController.showSlideOut({
  287. parent: this.licensePane.slideout,
  288. width: '650px',
  289. label: paneTitle,
  290. content: {
  291. module: 'bi/admin/license/slideout/LicenseByUserPane',
  292. title: paneTitle,
  293. licenseInfo: this.licenseInfo
  294. }
  295. });
  296. },
  297. _onOwnedValueChange: function _onOwnedValueChange() {
  298. this._enableApplyButton();
  299. var totalOwnedLicenses = 0;
  300. for (var i = 0; i < this.licenseSummary.licenses.length; i++) {
  301. if (this.licenseSummary.licenses[i].level === -1) {
  302. continue;
  303. }
  304. totalOwnedLicenses += this._oPropertyUIControl.getProperty('ownedValue_' + i).value;
  305. }
  306. var totalOwnedLink = this._oPropertyUIControl.getProperty('totalOwnedLicLink');
  307. var totalOwnedValue = totalOwnedLink._oPropertyUIControl.getProperty('totalOwnedValue');
  308. totalOwnedValue.setValue(totalOwnedLicenses);
  309. },
  310. _addExportRefresh: function _addExportRefresh() {
  311. this.$el.find('.bi-admin-lic-refresh-section').on('primaryaction', function () {
  312. WaitingMask.show(this.$body.find('.bi-admin-licenses'), StringResource.get('refreshingLicUsed'));
  313. this._refreshLicenseSummary();
  314. }.bind(this));
  315. },
  316. _addPaneFooter: function _addPaneFooter(items) {
  317. var container = this.$body.find('.bi-admin-lic-footer-section');
  318. items.push({
  319. 'type': 'Footer',
  320. 'el': container,
  321. 'name': 'footerSection',
  322. 'items': [{
  323. 'type': 'Button',
  324. 'name': 'applyButton',
  325. 'label': StringResource.get('apply'),
  326. 'primary': true,
  327. 'onSelect': this._onApplyButton.bind(this)
  328. }, {
  329. 'type': 'Button',
  330. 'name': 'cancelButton',
  331. 'label': StringResource.get('cancel'),
  332. 'primary': false,
  333. 'onSelect': function () {
  334. this.slideout.hide();
  335. }.bind(this)
  336. }]
  337. });
  338. },
  339. _onApplyButton: function _onApplyButton() {
  340. var envTypeSavePromise = this._saveEnvType();
  341. var ownedLicSavePromise = this._saveOwnedLicenses();
  342. return Q.when(envTypeSavePromise, ownedLicSavePromise).then(function () {
  343. this._disableApplyButton();
  344. }.bind(this));
  345. },
  346. _saveEnvType: function _saveEnvType() {
  347. var deferred = Q.defer();
  348. var modifiedProperties = this._oPropertyUIControl.getModifiedProperties();
  349. if (modifiedProperties.envTypeRadio) {
  350. deferred = Api.updateProductionSetting({
  351. 'status': modifiedProperties.envTypeRadio
  352. });
  353. } else {
  354. deferred.resolve();
  355. }
  356. return deferred.promise;
  357. },
  358. _saveOwnedLicenses: function _saveOwnedLicenses() {
  359. var deferred = Q.defer();
  360. var modifiedProperties = this._oPropertyUIControl.getModifiedProperties();
  361. var ownedValuesModified = !_.isUndefined(modifiedProperties.ownedValue_0) || !_.isUndefined(modifiedProperties.ownedValue_1) || !_.isUndefined(modifiedProperties.ownedValue_2) || !_.isUndefined(modifiedProperties.ownedValue_3);
  362. if (ownedValuesModified) {
  363. WaitingMask.show(this.$body.find('.bi-admin-licenses'), StringResource.get('refreshingLicUsed'));
  364. var ownedValues = [];
  365. for (var i = 0; i < this.licenseSummary.licenses.length; i++) {
  366. if (this.licenseSummary.licenses[i].level === -1) {
  367. continue;
  368. }
  369. ownedValues.push({
  370. 'level': i,
  371. 'owned': this._oPropertyUIControl.getProperty('ownedValue_' + i).value
  372. });
  373. }
  374. this.glassContext.services.ajax.ajax({
  375. dataType: 'json',
  376. contentType: 'application/json; charset=utf-8',
  377. type: 'PUT',
  378. data: JSON.stringify({
  379. 'licenses': ownedValues
  380. }),
  381. url: 'v1/licenses/owned'
  382. }).then(this._refreshLicenseSummary.bind(this)).then(function () {
  383. deferred.resolve();
  384. });
  385. } else {
  386. deferred.resolve();
  387. }
  388. return deferred.promise;
  389. },
  390. _refreshLicenseSummary: function _refreshLicenseSummary() {
  391. var deferred = Q.defer();
  392. this.glassContext.services.ajax.ajax({
  393. dataType: 'json',
  394. contentType: 'application/json; charset=utf-8',
  395. type: 'POST',
  396. url: 'v1/licenses'
  397. }).then(function (licSummary) {
  398. // Make sure the progress shows long enough to be able to see the message
  399. setTimeout(function () {
  400. WaitingMask.clear(this.$body.find('.bi-admin-licenses'));
  401. this.$body.find('.bi-admin-licenses').empty();
  402. if (licSummary.licenses) {
  403. this.licenseSummary = this._sortLicenses(licSummary);
  404. }
  405. this._renderPaneBody().then(function () {
  406. deferred.resolve(this);
  407. }.bind(this));
  408. }.bind(this), 1000);
  409. }.bind(this));
  410. return deferred.promise;
  411. }
  412. });
  413. return LicensePane;
  414. });