widgets.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var filters = require('views/common/filter_view');
  20. App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, {
  21. name: 'mainDashboardWidgetsView',
  22. templateName:require('templates/main/dashboard/widgets'),
  23. didInsertElement:function () {
  24. this.setWidgetsDataModel();
  25. this.setInitPrefObject();
  26. this.setOnLoadVisibleWidgets();
  27. this.set('isDataLoaded',true);
  28. Em.run.next(this, 'makeSortable');
  29. },
  30. /**
  31. * List of services
  32. * @type {Ember.Enumerable}
  33. */
  34. content:[],
  35. /**
  36. * @type {bool}
  37. */
  38. isDataLoaded: false,
  39. /**
  40. * Make widgets' list sortable on New Dashboard style
  41. */
  42. makeSortable: function () {
  43. var self = this;
  44. $( "#sortable" ).sortable({
  45. items: "> div",
  46. //placeholder: "sortable-placeholder",
  47. cursor: "move",
  48. update: function (event, ui) {
  49. if (!App.testMode) {
  50. // update persist then translate to real
  51. var widgetsArray = $('div[viewid]'); // get all in DOM
  52. self.getUserPref(self.get('persistKey'));
  53. var oldValue = self.get('currentPrefObject') || self.getDBProperty(self.get('persistKey'));
  54. var newValue = Em.Object.create({
  55. dashboardVersion: oldValue.dashboardVersion,
  56. visible: [],
  57. hidden: oldValue.hidden,
  58. threshold: oldValue.threshold
  59. });
  60. var size = oldValue.visible.length;
  61. for(var j = 0; j <= size -1; j++){
  62. var viewID = widgetsArray.get(j).getAttribute('viewid');
  63. var id = viewID.split("-").get(1);
  64. newValue.visible.push(id);
  65. }
  66. self.postUserPref(self.get('persistKey'), newValue);
  67. self.setDBProperty(self.get('persistKey'), newValue);
  68. //self.translateToReal(newValue);
  69. }
  70. }
  71. }).disableSelection();
  72. },
  73. /**
  74. * Set Service model values
  75. */
  76. setWidgetsDataModel: function () {
  77. var services = App.Service.find();
  78. var self = this;
  79. services.forEach(function (item) {
  80. switch (item.get('serviceName')) {
  81. case "HDFS":
  82. self.set('hdfs_model', App.HDFSService.find(item.get('id')) || item);
  83. break;
  84. case "YARN":
  85. self.set('yarn_model', App.YARNService.find(item.get('id')) || item);
  86. break;
  87. case "MAPREDUCE":
  88. self.set('mapreduce_model', App.MapReduceService.find(item.get('id')) || item);
  89. break;
  90. case "HBASE":
  91. self.set('hbase_model', App.HBaseService.find(item.get('id')) || item);
  92. break;
  93. case "STORM":
  94. self.set('storm_model', item);
  95. break;
  96. case "FLUME":
  97. self.set('flume_model', item);
  98. break;
  99. }
  100. }, this);
  101. },
  102. /**
  103. * Load widget statuses to <code>initPrefObject</code>
  104. */
  105. setInitPrefObject: function() {
  106. //in case of some service not installed
  107. var visibleFull = [
  108. '2', '4', '8', '10',
  109. '17', '11', '12', '13', '14',
  110. '18', '1', '6', '5', '9',
  111. '3', '7', '15', '16', '20',
  112. '19', '21', '23',
  113. '24', '25', '26', '27',// all yarn
  114. '28', // storm
  115. '29' // flume
  116. ]; // all in order
  117. var hiddenFull = [['22','Region In Transition']];
  118. if (this.get('hdfs_model') == null) {
  119. var hdfs= ['1', '2', '3', '4', '5', '15', '17'];
  120. hdfs.forEach ( function (item) {
  121. visibleFull = visibleFull.without(item);
  122. }, this);
  123. }
  124. if (this.get('mapreduce_model') == null) {
  125. var map = ['6', '7', '8', '9', '10', '16', '18'];
  126. map.forEach ( function (item) {
  127. visibleFull = visibleFull.without(item);
  128. }, this);
  129. }
  130. if (this.get('hbase_model') == null) {
  131. var hbase = ['19', '20', '21', '23'];
  132. hbase.forEach ( function (item) {
  133. visibleFull = visibleFull.without(item);
  134. }, this);
  135. hiddenFull = [];
  136. }
  137. if (this.get('yarn_model') == null) {
  138. var yarn = ['24', '25', '26', '27'];
  139. yarn.forEach ( function (item) {
  140. visibleFull = visibleFull.without(item);
  141. }, this);
  142. }
  143. if (this.get('storm_model') == null) {
  144. var storm = ['28'];
  145. storm.forEach(function(item) {
  146. visibleFull = visibleFull.without(item);
  147. }, this);
  148. }
  149. if (this.get('flume_model') == null) {
  150. var flume = ['29'];
  151. flume.forEach(function(item) {
  152. visibleFull = visibleFull.without(item);
  153. }, this);
  154. }
  155. var obj = this.get('initPrefObject');
  156. obj.set('visible', visibleFull);
  157. obj.set('hidden', hiddenFull);
  158. },
  159. hdfs_model: null,
  160. mapreduce_model: null,
  161. mapreduce2_model: null,
  162. yarn_model: null,
  163. hbase_model: null,
  164. storm_model: null,
  165. flume_model: null,
  166. /**
  167. * List of visible widgets
  168. * @type {Ember.Enumerable}
  169. */
  170. visibleWidgets: [],
  171. /**
  172. * List of hidden widgets
  173. * @type {Ember.Enumerable}
  174. */
  175. hiddenWidgets: [], // widget child view will push object in this array if deleted
  176. /**
  177. * Submenu view for New Dashboard style
  178. * @type {Ember.View}
  179. */
  180. plusButtonFilterView: filters.createComponentView({
  181. /**
  182. * Base methods was implemented in <code>filters.componentFieldView</code>
  183. */
  184. hiddenWidgetsBinding: 'parentView.hiddenWidgets',
  185. visibleWidgetsBinding: 'parentView.visibleWidgets',
  186. layout: null,
  187. filterView: filters.componentFieldView.extend({
  188. templateName:require('templates/main/dashboard/plus_button_filter'),
  189. hiddenWidgetsBinding: 'parentView.hiddenWidgets',
  190. visibleWidgetsBinding: 'parentView.visibleWidgets',
  191. valueBinding: '',
  192. applyFilter:function() {
  193. this._super();
  194. var parent = this.get('parentView').get('parentView');
  195. var hiddenWidgets = this.get('hiddenWidgets');
  196. var checkedWidgets = hiddenWidgets.filterProperty('checked', true);
  197. if (App.testMode) {
  198. var visibleWidgets = this.get('visibleWidgets');
  199. checkedWidgets.forEach(function(item){
  200. var newObj = parent.widgetsMapper(item.id);
  201. visibleWidgets.pushObject(newObj);
  202. hiddenWidgets.removeObject(item);
  203. }, this);
  204. } else {
  205. //save in persist
  206. parent.getUserPref(parent.get('persistKey'));
  207. var oldValue = parent.get('currentPrefObject') || parent.getDbProperty(parent.get('persistKey'));
  208. var newValue = Em.Object.create({
  209. dashboardVersion: oldValue.dashboardVersion,
  210. visible: oldValue.visible,
  211. hidden: [],
  212. threshold: oldValue.threshold
  213. });
  214. checkedWidgets.forEach(function(item){
  215. newValue.visible.push(item.id);
  216. hiddenWidgets.removeObject(item);
  217. }, this);
  218. hiddenWidgets.forEach(function(item){
  219. newValue.hidden.push([item.id, item.displayName]);
  220. }, this);
  221. parent.postUserPref(parent.get('persistKey'), newValue);
  222. parent.setDBProperty(parent.get('persistKey'), newValue);
  223. parent.translateToReal(newValue);
  224. }
  225. }
  226. })
  227. }),
  228. /**
  229. * Translate from Json value got from persist to real widgets view
  230. */
  231. translateToReal: function (value) {
  232. var version = value.dashboardVersion;
  233. var visible = value.visible;
  234. var hidden = value.hidden;
  235. var threshold = value.threshold;
  236. if (version == 'classic') {
  237. this.set('isClassicDashboard', true);
  238. } else if (version == 'new') {
  239. this.set('isClassicDashboard', false);
  240. var visibleWidgets = [];
  241. var hiddenWidgets = [];
  242. // re-construct visibleWidgets and hiddenWidgets
  243. for (var j = 0; j <= visible.length -1; j++) {
  244. var id = visible[j];
  245. var widgetClass = this.widgetsMapper(id);
  246. //override with new threshold
  247. if (threshold[id].length > 0) {
  248. widgetClass.reopen({
  249. thresh1: threshold[id][0],
  250. thresh2: threshold[id][1]
  251. });
  252. }
  253. visibleWidgets.pushObject(widgetClass);
  254. }
  255. for (var j = 0; j <= hidden.length -1; j++) {
  256. var id = hidden[j][0];
  257. var title = hidden[j][1];
  258. hiddenWidgets.pushObject(Em.Object.create({displayName:title , id: id, checked: false}));
  259. }
  260. this.set('visibleWidgets', visibleWidgets);
  261. this.set('hiddenWidgets', hiddenWidgets);
  262. }
  263. },
  264. /**
  265. * Set visibility-status for widgets
  266. */
  267. setOnLoadVisibleWidgets: function () {
  268. if (App.testMode) {
  269. this.translateToReal(this.get('initPrefObject'));
  270. } else {
  271. // called when first load/refresh/jump back page
  272. this.getUserPref(this.get('persistKey'));
  273. var currentPrefObject = this.get('currentPrefObject') || this.getDBProperty(this.get('persistKey'));
  274. if (currentPrefObject) { // fit for no dashboard version
  275. if (!currentPrefObject.dashboardVersion) {
  276. currentPrefObject.dashboardVersion = 'new';
  277. this.postUserPref(this.get('persistKey'), currentPrefObject);
  278. this.setDBProperty(this.get('persistKey'), currentPrefObject);
  279. }
  280. this.set('currentPrefObject', this.checkServicesChange(currentPrefObject));
  281. this.translateToReal(this.get('currentPrefObject'));
  282. }
  283. else {
  284. // post persist then translate init object
  285. this.postUserPref(this.get('persistKey'), this.get('initPrefObject'));
  286. this.setDBProperty(this.get('persistKey'), this.get('initPrefObject'));
  287. this.translateToReal(this.get('initPrefObject'));
  288. }
  289. }
  290. },
  291. /**
  292. * Remove widget from visible and hidden lists
  293. * @param {Object} value
  294. * @param {Object} widget
  295. * @returns {*}
  296. */
  297. removeWidget: function (value, widget) {
  298. value.visible = value.visible.without(widget);
  299. for (var j = 0; j <= value.hidden.length -1; j++) {
  300. if (value.hidden[j][0] == widget) {
  301. value.hidden.splice(j, 1);
  302. }
  303. }
  304. return value;
  305. },
  306. /**
  307. * Check if widget is in visible or hidden list
  308. * @param {Object} value
  309. * @param {Object} widget
  310. * @returns {bool}
  311. */
  312. containsWidget: function (value, widget) {
  313. var flag = value.visible.contains (widget);
  314. for (var j = 0; j <= value.hidden.length -1; j++) {
  315. if ( !flag && value.hidden[j][0] == widget) {
  316. flag = true;
  317. break;
  318. }
  319. }
  320. return flag;
  321. },
  322. /**
  323. * check if stack has upgraded from HDP 1.0 to 2.0 OR add/delete services.
  324. * Update the value on server if true.
  325. * @param {Object} currentPrefObject
  326. * @return {Object}
  327. */
  328. checkServicesChange: function (currentPrefObject) {
  329. var toDelete = $.extend(true, {}, currentPrefObject);
  330. var toAdd = [];
  331. var self = this;
  332. // check each service, find out the newly added service and already deleted service
  333. if (this.get('hdfs_model') != null) {
  334. var hdfsAndMetrics= ['1', '2', '3', '4', '5', '15', '17', '11', '12', '13', '14'];
  335. hdfsAndMetrics.forEach ( function (item) {
  336. toDelete = self.removeWidget(toDelete, item);
  337. }, this);
  338. }
  339. if (this.get('mapreduce_model') != null) {
  340. var map = ['6', '7', '8', '9', '10', '16', '18'];
  341. var flag = self.containsWidget(toDelete, map[0]);
  342. if (flag) {
  343. map.forEach ( function (item) {
  344. toDelete = self.removeWidget(toDelete, item);
  345. }, this);
  346. } else {
  347. toAdd = toAdd.concat(map);
  348. }
  349. }
  350. if (this.get('hbase_model') != null) {
  351. var hbase = ['19', '20', '21', '22', '23'];
  352. var flag = self.containsWidget(toDelete, hbase[0]);
  353. if (flag) {
  354. hbase.forEach ( function (item) {
  355. toDelete = self.removeWidget(toDelete, item);
  356. }, this);
  357. } else {
  358. toAdd = toAdd.concat(hbase);
  359. }
  360. }
  361. if (this.get('yarn_model') != null) {
  362. var yarn = ['24', '25', '26', '27'];
  363. var flag = self.containsWidget(toDelete, yarn[0]);
  364. if (flag) {
  365. yarn.forEach ( function (item) {
  366. toDelete = self.removeWidget(toDelete, item);
  367. }, this);
  368. } else {
  369. toAdd = toAdd.concat(yarn);
  370. }
  371. }
  372. if (this.get('storm_model') != null) {
  373. var storm = ['28'];
  374. var flag = self.containsWidget(toDelete, storm[0]);
  375. if (flag) {
  376. storm.forEach ( function (item) {
  377. toDelete = self.removeWidget(toDelete, item);
  378. }, this);
  379. } else {
  380. toAdd = toAdd.concat(storm);
  381. }
  382. }
  383. if (this.get('flume_model') != null) {
  384. var flume = ['29'];
  385. var flag = self.containsWidget(toDelete, flume[0]);
  386. if (flag) {
  387. flume.forEach ( function (item) {
  388. toDelete = self.removeWidget(toDelete, item);
  389. }, this);
  390. } else {
  391. toAdd = toAdd.concat(flume);
  392. }
  393. }
  394. var value = currentPrefObject;
  395. if (toDelete.visible.length || toDelete.hidden.length) {
  396. toDelete.visible.forEach ( function (item) {
  397. value = self.removeWidget(value, item);
  398. }, this);
  399. toDelete.hidden.forEach ( function (item) {
  400. value = self.removeWidget(value, item[0]);
  401. }, this);
  402. }
  403. if (toAdd.length) {
  404. value.visible = value.visible.concat(toAdd);
  405. var allThreshold = this.get('initPrefObject').threshold;
  406. // add new threshold OR override with default value
  407. toAdd.forEach ( function (item) {
  408. value.threshold[item] = allThreshold[item];
  409. }, this);
  410. }
  411. return value;
  412. },
  413. /**
  414. * Get view for widget by widget's id
  415. * @param {string} id
  416. * @returns {Ember.View}
  417. */
  418. widgetsMapper: function (id) {
  419. return Em.get({
  420. '1': App.NameNodeHeapPieChartView,
  421. '2': App.NameNodeCapacityPieChartView,
  422. '3': App.NameNodeCpuPieChartView,
  423. '4': App.DataNodeUpView,
  424. '5': App.NameNodeRpcView,
  425. '6': App.JobTrackerHeapPieChartView,
  426. '7': App.JobTrackerCpuPieChartView,
  427. '8': App.TaskTrackerUpView,
  428. '9': App.JobTrackerRpcView,
  429. '10': App.MapReduceSlotsView,
  430. '11': App.ChartClusterMetricsMemoryWidgetView,
  431. '12': App.ChartClusterMetricsNetworkWidgetView,
  432. '13': App.ChartClusterMetricsCPUWidgetView,
  433. '14': App.ChartClusterMetricsLoadWidgetView,
  434. '15': App.NameNodeUptimeView,
  435. '16': App.JobTrackerUptimeView,
  436. '17': App.HDFSLinksView,
  437. '18': App.MapReduceLinksView,
  438. '19': App.HBaseLinksView,
  439. '20': App.HBaseMasterHeapPieChartView,
  440. '21': App.HBaseAverageLoadView,
  441. '22': App.HBaseRegionsInTransitionView,
  442. '23': App.HBaseMasterUptimeView,
  443. '24': App.ResourceManagerHeapPieChartView,
  444. '25': App.ResourceManagerUptimeView,
  445. '26': App.NodeManagersLiveView,
  446. '27': App.YARNMemoryPieChartView,
  447. '28': App.SuperVisorUpView,
  448. '29': App.FlumeAgentUpView
  449. }, id);
  450. },
  451. /**
  452. * @type {Object|null}
  453. */
  454. currentPrefObject: null,
  455. /**
  456. * @type {Ember.Object}
  457. */
  458. initPrefObject: Em.Object.create({
  459. dashboardVersion: 'new',
  460. visible: [],
  461. hidden: [],
  462. threshold: {1: [80, 90], 2: [85, 95], 3: [90, 95], 4: [80, 90], 5: [1000, 3000], 6: [70, 90], 7: [90, 95], 8: [50, 75], 9: [30000, 120000],
  463. 10: [], 11: [], 12: [], 13: [], 14: [], 15: [], 16: [], 17: [], 18: [], 19: [], 20: [70, 90], 21: [10, 19.2], 22: [3, 10], 23: [],
  464. 24: [70, 90], 25: [], 26: [50, 75], 27: [50, 75], 28: [85, 95], 29: [85, 95]} // id:[thresh1, thresh2]
  465. }),
  466. /**
  467. * Key-name to store data in Local Storage and Persist
  468. * @type {string}
  469. */
  470. persistKey: function () {
  471. return 'user-pref-' + App.router.get('loginName') + '-dashboard';
  472. }.property(),
  473. makeRequestAsync: false,
  474. getUserPrefSuccessCallback: function (response, request, data) {
  475. if (response) {
  476. console.log('Got persist value from server with key ' + data.key + '. Value is: ' + response);
  477. this.set('currentPrefObject', response);
  478. }
  479. },
  480. getUserPrefErrorCallback: function (request) {
  481. // this user is first time login
  482. if (request.status == 404) {
  483. console.log('Persist did NOT find the key');
  484. }
  485. },
  486. /**
  487. * Reset widgets visibility-status
  488. */
  489. resetAllWidgets: function() {
  490. var self = this;
  491. App.showConfirmationPopup(function() {
  492. if(!App.testMode) {
  493. self.postUserPref(self.get('persistKey'), self.get('initPrefObject'));
  494. self.setDBProperty(self.get('persistKey'), self.get('initPrefObject'));
  495. }
  496. self.translateToReal(self.get('initPrefObject'));
  497. });
  498. },
  499. /**
  500. * @type {string}
  501. */
  502. gangliaUrl: function () {
  503. return App.router.get('clusterController.gangliaUrl') + "/?r=hour&cs=&ce=&m=&s=by+name&c=HDPSlaves&tab=m&vn=";
  504. }.property('App.router.clusterController.gangliaUrl'),
  505. showAlertsPopup: function (event) {
  506. var service = event.context;
  507. App.router.get('mainAlertsController').loadAlerts(service.get('serviceName'), "SERVICE");
  508. App.ModalPopup.show({
  509. header: this.t('services.alerts.headingOfList'),
  510. bodyClass: Ember.View.extend({
  511. templateName: require('templates/main/dashboard/alert_notification_popup'),
  512. service: service,
  513. controllerBinding: 'App.router.mainAlertsController',
  514. warnAlerts: function () {
  515. return this.get('controller.alerts').filterProperty('isOk', false).filterProperty('ignoredForServices', false);
  516. }.property('controller.alerts'),
  517. warnAlertsCount: function () {
  518. return this.get('warnAlerts').length;
  519. }.property('warnAlerts'),
  520. warnAlertsMessage: function() {
  521. return Em.I18n.t('services.alerts.head').format(this.get('warnAlertsCount'));
  522. }.property('warnAlertsCount'),
  523. nagiosUrl: function () {
  524. return App.router.get('clusterController.nagiosUrl');
  525. }.property('App.router.clusterController.nagiosUrl'),
  526. closePopup: function () {
  527. this.get('parentView').hide();
  528. },
  529. viewNagiosUrl: function () {
  530. window.open(this.get('nagiosUrl'), "_blank");
  531. this.closePopup();
  532. },
  533. selectService: function () {
  534. App.router.transitionTo('services.service.summary', service);
  535. this.closePopup();
  536. }
  537. }),
  538. primary: Em.I18n.t('common.close'),
  539. secondary : null,
  540. didInsertElement: function () {
  541. this.$().find('.modal-footer').addClass('align-center');
  542. this.$().children('.modal').css({'margin-top': '-350px'});
  543. }
  544. });
  545. event.stopPropagation();
  546. }
  547. });