step9_view.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  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 date = require('utils/date');
  20. App.WizardStep9View = App.TableView.extend({
  21. templateName: require('templates/wizard/step9'),
  22. /**
  23. * Overall progress-bar color
  24. * @type {string}
  25. */
  26. barColor: '',
  27. /**
  28. * Overall result message
  29. * @type {string}
  30. */
  31. resultMsg: '',
  32. /**
  33. * Overall message color
  34. * @type {string}
  35. */
  36. resultMsgColor: '',
  37. /**
  38. * When progress is 100, step is completed
  39. * @type {bool}
  40. */
  41. isStepCompleted: function() {
  42. return (this.get('controller.progress') === '100');
  43. }.property('controller.progress'),
  44. /**
  45. * Number of visible hosts
  46. * @type {string}
  47. */
  48. displayLength: "25",
  49. /**
  50. * Same to <code>controller.hosts</code>
  51. * @type {object[]}
  52. */
  53. content: function () {
  54. return this.get('controller.hosts');
  55. }.property('controller.hosts'),
  56. /**
  57. * Active category
  58. * @type {Ember.Object}
  59. */
  60. selectedCategory: function() {
  61. return this.get('categories').findProperty('isActive');
  62. }.property('categories.@each.isActive'),
  63. /**
  64. * Ember Object category. This object also contains
  65. * <code>
  66. * hostStatus: {String} A valid status of a host.
  67. * Used to filter hosts in that status.
  68. * hostsCount: {Int} Dynamic count of hosts displayed in the category label
  69. * label : {String} status and hosts in that status displayed which consists as a category on the page
  70. * isActive: {boolean} Gets set when the category is selected/clicked by the user
  71. * itemClass: {computed property} Binds the category link to active class when user clicks on the link
  72. * </code>
  73. */
  74. categoryObject: Em.Object.extend({
  75. hostsCount: 0,
  76. label: function () {
  77. return "%@ (%@)".fmt(this.get('value'), this.get('hostsCount'));
  78. }.property('value', 'hostsCount'),
  79. isActive: false,
  80. itemClass: function () {
  81. return this.get('isActive') ? 'active' : '';
  82. }.property('isActive')
  83. }),
  84. /**
  85. * Domputed property creates the category objects on the load of the page and sets 'All' as the active category
  86. * @Returns {Em.Object[]} All created categories which are binded and iterated in the template
  87. */
  88. categories: function () {
  89. return [
  90. this.categoryObject.create({value: Em.I18n.t('common.all'), hostStatus: 'all', isActive: true}),
  91. this.categoryObject.create({value: Em.I18n.t('installer.step9.hosts.status.label.inProgress'), hostStatus: 'inProgress'}),
  92. this.categoryObject.create({value: Em.I18n.t('installer.step9.hosts.status.label.warning'), hostStatus: 'warning'}),
  93. this.categoryObject.create({value: Em.I18n.t('common.success'), hostStatus: 'success'}),
  94. this.categoryObject.create({value: Em.I18n.t('common.fail'), hostStatus: 'failed', last: true })
  95. ];
  96. }.property(),
  97. /**
  98. * True if <code>controller.hostsWithHeartbeatLost</code> contains some values
  99. * @type {bool}
  100. */
  101. isHostHeartbeatLost: function () {
  102. return (this.get('controller.hostsWithHeartbeatLost').length > 0);
  103. }.property('controller.hostsWithHeartbeatLost.@each'),
  104. /**
  105. * Css-string to overall progress-bar width-property
  106. * @type {string}
  107. */
  108. barWidth: function () {
  109. var controller = this.get('controller');
  110. return 'width: ' + controller.get('progress') + '%;';
  111. }.property('controller.progress'),
  112. /**
  113. * Filter hosts info shown up on bottom of the box. Set by filter function, when 'seletedCategory' changed
  114. * @type {string}
  115. */
  116. filteredHostsInfo: '',
  117. /**
  118. * Message for overall progress
  119. * @type {string}
  120. */
  121. progressMessage: function () {
  122. return Em.I18n.t('installer.step9.overallProgress').format(this.get('controller.progress'));
  123. }.property('controller.progress'),
  124. /**
  125. * Run <code>countCategoryHosts</code>, <code>filter</code> only once
  126. * @method hostStatusObserver
  127. */
  128. hostStatusObserver: function(){
  129. Em.run.once(this, 'countCategoryHosts');
  130. Em.run.once(this, 'filter');
  131. }.observes('content.@each.status'),
  132. /**
  133. * Count each category hosts to update label
  134. * @method countCategoryHosts
  135. */
  136. countCategoryHosts: function () {
  137. var counters = {
  138. "info": 0,
  139. "pending": 0,
  140. "in_progress": 0,
  141. "heartbeat_lost": 0,
  142. "warning": 0,
  143. "success": 0,
  144. "failed": 0
  145. };
  146. this.get('content').forEach(function (host) {
  147. if (counters[host.get('status')] !== undefined) {
  148. counters[host.get('status')]++;
  149. }
  150. }, this);
  151. counters["all"] = this.get('content.length');
  152. counters["inProgress"] = counters["info"] + counters["pending"] + counters["in_progress"];
  153. counters["failed"] += counters["heartbeat_lost"];
  154. this.get('categories').forEach(function(category) {
  155. category.set('hostsCount', counters[category.get('hostStatus')]);
  156. }, this);
  157. },
  158. /**
  159. * Filter hosts by category
  160. * @method filter
  161. */
  162. filter: function () {
  163. var self = this;
  164. Em.run.next(function () {
  165. self.doFilter();
  166. });
  167. }.observes('selectedCategory'),
  168. /**
  169. * Real filter-method
  170. * Called from <code>filter</code> in Em.run.next-wrapper
  171. * @method doFilter
  172. */
  173. doFilter: function() {
  174. var result = [];
  175. var content = this.get('content');
  176. var selectedCategory = this.get('selectedCategory');
  177. if (!selectedCategory || selectedCategory.get('hostStatus') === 'all') {
  178. result = content;
  179. } else if (selectedCategory.get('hostStatus') == 'inProgress') {
  180. result = content.filter(function (_host) {
  181. return (_host.get('status') == 'info' || _host.get('status') == 'pending' || _host.get('status') == 'in_progress');
  182. });
  183. } else if (selectedCategory.get('hostStatus') == 'failed') {
  184. result = content.filter(function (_host) {
  185. return (_host.get('status') == 'failed' || _host.get('status') == 'heartbeat_lost');
  186. });
  187. } else {
  188. result = content.filterProperty('status', selectedCategory.get('hostStatus'));
  189. }
  190. this.set('filteredContent', result);
  191. this.set('filteredHostsInfo', Em.I18n.t('installer.step9.hosts.filteredHostsInfo').format(result.get('length'), content.get('length')));
  192. },
  193. /**
  194. * On click handler for 'show all' link
  195. * @method showAllHosts
  196. */
  197. showAllHosts: function () {
  198. this.get('categories').forEach(function (category) {
  199. category.set('isActive', (category.get('hostStatus') === 'all'));
  200. });
  201. },
  202. /**
  203. * Trigger on Category click
  204. * @param {Object} event
  205. * @method selectCategory
  206. */
  207. selectCategory: function (event) {
  208. var categoryStatus = event.context.get('hostStatus');
  209. this.get('categories').forEach(function (category) {
  210. category.set('isActive', (category.get('hostStatus') === categoryStatus));
  211. });
  212. },
  213. didInsertElement: function () {
  214. this.onStatus();
  215. this.get('controller').navigateStep();
  216. },
  217. /**
  218. * Set <code>resultMsg</code>, <code>resultMsg</code>, <code>resultMsgColor</code> according to
  219. * <code>controller.status</code>, <code>controller.startCallFailed</code>, <code>isHostHeartbeatLost</code>
  220. * @method onStatus
  221. */
  222. onStatus: function () {
  223. if (this.get('controller.status') === 'info') {
  224. this.set('resultMsg', '');
  225. this.set('barColor', 'progress-info');
  226. } else if (this.get('controller.status') === 'warning') {
  227. this.set('barColor', 'progress-warning');
  228. this.set('resultMsg', Em.I18n.t('installer.step9.status.warning'));
  229. this.set('resultMsgColor', 'alert-warning');
  230. } else if (this.get('controller.status') === 'failed') {
  231. this.set('barColor', 'progress-danger');
  232. this.set('resultMsgColor', 'alert-error');
  233. console.log('TRACE: Inside error view step9');
  234. if (this.get('isHostHeartbeatLost')) {
  235. // When present requests succeeds but some host components are in UNKNOWN or INSTALL_FAILED state and
  236. // hosts are in HEARTBEAT_LOST state
  237. this.set('resultMsg', Em.I18n.t('installer.step9.status.hosts.heartbeat_lost').format(this.get('controller.hostsWithHeartbeatLost').length));
  238. } else if (this.get('controller.startCallFailed')) {
  239. this.set('resultMsg', Em.I18n.t('installer.step9.status.start.services.failed'));
  240. } else {
  241. this.set('resultMsg', Em.I18n.t('installer.step9.status.failed'));
  242. }
  243. } else if (this.get('controller.status') === 'success') {
  244. console.log('TRACE: Inside success view step9');
  245. this.set('barColor', 'progress-success');
  246. this.set('resultMsg', Em.I18n.t('installer.step9.status.success'));
  247. this.set('resultMsgColor', 'alert-success');
  248. }
  249. }.observes('controller.status', 'controller.startCallFailed','isHostHeartbeatLost'),
  250. /**
  251. * Show popup with info about failed hosts
  252. * @return {App.ModalPopup}
  253. * @method hostWithInstallFailed
  254. */
  255. hostWithInstallFailed: function () {
  256. var controller = this.get('controller');
  257. return App.ModalPopup.show({
  258. header: Em.I18n.t('installer.step9.host.heartbeat_lost.header'),
  259. classNames: ['sixty-percent-width-modal'],
  260. autoHeight: false,
  261. secondary: null,
  262. bodyClass: Em.View.extend({
  263. templateName: require('templates/wizard/step9/step9_install_host_popup'),
  264. c: controller,
  265. failedHosts: function () {
  266. return controller.get('hostsWithHeartbeatLost');
  267. }.property()
  268. })
  269. });
  270. }
  271. });
  272. App.HostStatusView = Em.View.extend({
  273. tagName: 'tr',
  274. /**
  275. * Current host
  276. * @type {Em.Object}
  277. */
  278. obj: null,
  279. /**
  280. * wizardStep9Controller
  281. * @type {App.WizardStep9Controller}
  282. */
  283. controller: null,
  284. /**
  285. * Progress-bar color for current host
  286. * @type {string}
  287. */
  288. barColor: '',
  289. /**
  290. * Css-string to progress-bar width-property
  291. * @type {string}
  292. */
  293. barWidth: function () {
  294. return 'width: ' + this.get('obj.progress') + '%;';
  295. }.property('obj.progress'),
  296. /**
  297. * Is current host failed
  298. * @type {bool}
  299. */
  300. isFailed: function () {
  301. return (this.get('isHostCompleted') && (this.get('obj.status') === 'failed' || this.get('obj.status') === 'heartbeat_lost'));
  302. }.property('obj.status', 'isHostCompleted'),
  303. /**
  304. * Is current host successfully installed
  305. * @type {bool}
  306. */
  307. isSuccess: function () {
  308. return (this.get('isHostCompleted') && this.get('obj.status') === 'success');
  309. }.property('obj.status', 'isHostCompleted'),
  310. /**
  311. * Current host has warnings
  312. * @type {bool}
  313. */
  314. isWarning: function () {
  315. return(this.get('isHostCompleted') && this.get('obj.status') === 'warning');
  316. }.property('obj.status', 'isHostCompleted'),
  317. /**
  318. * Current host completed all its tasks
  319. * @type {bool}
  320. */
  321. isHostCompleted: function () {
  322. return this.get('obj.progress') == 100;
  323. }.property('obj.progress'),
  324. didInsertElement: function () {
  325. this.onStatus();
  326. },
  327. /**
  328. * Set <code>barColor</code>, <code>obj.progress</code>, <code>obj.message</code> according to
  329. * <code>obj.status</code>, <code>obj.progress</code>, <code>controller.progress</code>
  330. * @method onStatus
  331. */
  332. onStatus: function () {
  333. if (this.get('obj.status') === 'info') {
  334. this.set('barColor', 'progress-info');
  335. } else if (this.get('obj.status') === 'warning') {
  336. this.set('barColor', 'progress-warning');
  337. if (this.get('obj.progress') === '100') {
  338. this.set('obj.message', Em.I18n.t('installer.step9.host.status.warning'));
  339. }
  340. } else if (this.get('obj.status') === 'failed') {
  341. this.set('barColor', 'progress-danger');
  342. if (this.get('obj.progress') === '100') {
  343. this.set('obj.message', Em.I18n.t('installer.step9.host.status.failed'));
  344. }
  345. } else if (this.get('obj.status') === 'heartbeat_lost') {
  346. this.set('barColor', 'progress-danger');
  347. if (this.get('obj.progress') === '100') {
  348. this.set('obj.message', Em.I18n.t('installer.step9.host.heartbeat_lost'));
  349. }
  350. } else if (this.get('obj.status') === 'success' && this.get('isHostCompleted') && parseInt(this.get('controller.progress')) > 34) {
  351. this.set('barColor', 'progress-success');
  352. this.set('obj.message', Em.I18n.t('installer.step9.host.status.success'));
  353. }
  354. }.observes('obj.status', 'obj.progress', 'controller.progress'),
  355. /**
  356. * Show popup with host logs
  357. * @return {App.ModalPopup}
  358. * @method hostLogPopup
  359. */
  360. hostLogPopup: function () {
  361. var controller = this.get('controller');
  362. var host = this.get('obj');
  363. return App.ModalPopup.show({
  364. header: host.get('name'),
  365. classNames: ['sixty-percent-width-modal'],
  366. autoHeight: false,
  367. secondary: null,
  368. /**
  369. * Current host
  370. * @type {Em.Object}
  371. */
  372. host: host,
  373. /**
  374. * wizardStep9Controller
  375. * @type {App.WizardStep9Controller}
  376. */
  377. c: controller,
  378. onClose: function () {
  379. this.set('c.currentOpenTaskId', 0);
  380. this.hide();
  381. },
  382. bodyClass: App.WizardStep9HostLogPopupBodyView
  383. });
  384. }
  385. });