summary.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with this
  4. * work for additional information regarding copyright ownership. The ASF
  5. * licenses this file to you under the Apache License, Version 2.0 (the
  6. * "License"); you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. */
  17. var App = require('app');
  18. App.MainServiceInfoSummaryController = Em.Controller.extend(App.WidgetSectionMixin, {
  19. name: 'mainServiceInfoSummaryController',
  20. selectedFlumeAgent: null,
  21. /**
  22. * Indicates whether Ranger plugins status update polling is active
  23. * @type {boolean}
  24. */
  25. isRangerUpdateWorking: false,
  26. /**
  27. * Indicates whether array with initial Ranger plugins data is set
  28. * @type {boolean}
  29. */
  30. isRangerPluginsArraySet: false,
  31. /**
  32. * Indicates whether previous AJAX request for Ranger plugins config properties has failed
  33. * @type {boolean}
  34. */
  35. isPreviousRangerConfigsCallFailed: false,
  36. layoutNameSuffix: "_dashboard",
  37. sectionNameSuffix: "_SUMMARY",
  38. /**
  39. * Ranger plugins data
  40. * @type {array}
  41. */
  42. rangerPlugins: [
  43. {
  44. serviceName: 'HDFS',
  45. type: 'ranger-hdfs-plugin-properties',
  46. propertyName: 'ranger-hdfs-plugin-enabled',
  47. valueForEnable: 'Yes'
  48. },
  49. {
  50. serviceName: 'YARN',
  51. type: 'ranger-yarn-plugin-properties',
  52. propertyName: 'ranger-yarn-plugin-enabled',
  53. valueForEnable: 'Yes'
  54. },
  55. {
  56. serviceName: 'HBASE',
  57. type: 'ranger-hbase-plugin-properties',
  58. propertyName: 'ranger-hbase-plugin-enabled',
  59. valueForEnable: 'Yes'
  60. },
  61. {
  62. serviceName: 'HIVE',
  63. type: 'hive-env',
  64. propertyName: 'hive_security_authorization',
  65. valueForEnable: 'Ranger'
  66. },
  67. {
  68. serviceName: 'KNOX',
  69. type: 'ranger-knox-plugin-properties',
  70. propertyName: 'ranger-knox-plugin-enabled',
  71. valueForEnable: 'Yes'
  72. },
  73. {
  74. serviceName: 'STORM',
  75. type: 'ranger-storm-plugin-properties',
  76. propertyName: 'ranger-storm-plugin-enabled',
  77. valueForEnable: 'Yes'
  78. },
  79. {
  80. serviceName: 'KAFKA',
  81. type: 'ranger-kafka-plugin-properties',
  82. propertyName: 'ranger-kafka-plugin-enabled',
  83. valueForEnable: 'Yes'
  84. },
  85. {
  86. serviceName: 'KAFKA',
  87. type: 'ranger-kafka-plugin-properties',
  88. propertyName: 'ranger-kafka-plugin-enabled',
  89. valueForEnable: 'Yes'
  90. }
  91. ],
  92. /**
  93. * Some widget has type `GRAPH`
  94. *
  95. * @type {boolean}
  96. */
  97. someWidgetGraphExists: Em.computed.someBy('widgets', 'widgetType', 'GRAPH'),
  98. /**
  99. * @type {boolean}
  100. */
  101. showTimeRangeControl: Em.computed.or('!isServiceWithEnhancedWidgets', 'someWidgetGraphExists'),
  102. /**
  103. * Set initial Ranger plugins data
  104. * @method setRangerPlugins
  105. */
  106. setRangerPlugins: function () {
  107. if (App.get('router.clusterController.isLoaded') && !this.get('isRangerPluginsArraySet')) {
  108. // Display order of ranger plugin for services should be decided from App.StackService.displayOrder to keep consistency
  109. // with display order of services at other places in the application like `select service's page` and `service menu bar`
  110. var displayOrderLength = App.StackService.displayOrder.length;
  111. var rangerPlugins = this.get('rangerPlugins').map(function (item, index) {
  112. var displayOrderIndex = App.StackService.displayOrder.indexOf(item.serviceName);
  113. return $.extend(item, {
  114. index: displayOrderIndex == -1 ? displayOrderLength + index : displayOrderIndex
  115. });
  116. }).sortProperty('index');
  117. this.setProperties({
  118. rangerPlugins: rangerPlugins.map(function (item) {
  119. var stackService = App.StackService.find().findProperty('serviceName', item.serviceName);
  120. var displayName = (stackService) ? stackService.get('displayName') : item.serviceName;
  121. return $.extend(item, {
  122. pluginTitle: Em.I18n.t('services.service.summary.ranger.plugin.title').format(displayName),
  123. isDisplayed: App.Service.find().someProperty('serviceName', item.serviceName) &&
  124. stackService.get('configTypes').hasOwnProperty(item.type),
  125. status: Em.I18n.t('services.service.summary.ranger.plugin.loadingStatus')
  126. });
  127. }),
  128. isRangerPluginsArraySet: true
  129. });
  130. }
  131. }.observes('App.router.clusterController.isLoaded'),
  132. /**
  133. * Get latest config tags
  134. * @method updateRangerPluginsStatus
  135. * @param callback
  136. */
  137. updateRangerPluginsStatus: function (callback) {
  138. App.ajax.send({
  139. name: 'config.tags',
  140. sender: this,
  141. success: 'getRangerPluginsStatus',
  142. callback: callback
  143. });
  144. },
  145. /**
  146. * Get latest Ranger plugins config properties
  147. * @method getRangerPluginsStatus
  148. * @param data
  149. */
  150. getRangerPluginsStatus: function (data) {
  151. var urlParams = [];
  152. this.get('rangerPlugins').forEach(function (item) {
  153. if (App.Service.find().someProperty('serviceName', item.serviceName) && data.Clusters.desired_configs.hasOwnProperty(item.type)) {
  154. var currentTag = data.Clusters.desired_configs[item.type].tag;
  155. var isTagChanged = item.tag != currentTag;
  156. Em.set(item, 'isDisplayed', true);
  157. //Request for properties should be sent either if configs have changed or if previous Ranger plugins config properties has failed
  158. if (isTagChanged || this.get('isPreviousRangerConfigsCallFailed')) {
  159. Em.set(item, 'tag', currentTag);
  160. urlParams.push('(type=' + item.type + '&tag=' + currentTag + ')');
  161. }
  162. } else {
  163. Em.set(item, 'isDisplayed', false);
  164. }
  165. }, this);
  166. if (urlParams.length) {
  167. App.ajax.send({
  168. name: 'reassign.load_configs',
  169. sender: this,
  170. data: {
  171. urlParams: urlParams.join('|')
  172. },
  173. success: 'getRangerPluginsStatusSuccess',
  174. error: 'getRangerPluginsStatusError'
  175. });
  176. }
  177. },
  178. /**
  179. * Set Ranger plugins statuses
  180. * @method getRangerPluginsStatusSuccess
  181. * @param data
  182. */
  183. getRangerPluginsStatusSuccess: function (data) {
  184. this.set('isPreviousRangerConfigsCallFailed', false);
  185. data.items.forEach(function (item) {
  186. var serviceName = this.get('rangerPlugins').findProperty('type', item.type).serviceName;
  187. var propertyName = this.get('rangerPlugins').findProperty('type', item.type).propertyName;
  188. var propertyValue = this.get('rangerPlugins').findProperty('type', item.type).valueForEnable;
  189. var statusString;
  190. if (item.properties[propertyName]) {
  191. statusString = item.properties[propertyName] == propertyValue ? 'alerts.table.state.enabled' : 'alerts.table.state.disabled';
  192. }
  193. else {
  194. statusString = 'common.unknown';
  195. }
  196. Em.set(this.get('rangerPlugins').findProperty('serviceName', serviceName), 'status', Em.I18n.t(statusString));
  197. }, this);
  198. },
  199. /**
  200. * Method executed if Ranger plugins config properties request has failed
  201. * @method getRangerPluginsStatusError
  202. */
  203. getRangerPluginsStatusError: function () {
  204. this.set('isPreviousRangerConfigsCallFailed', true);
  205. },
  206. /**
  207. * Send start command for selected Flume Agent
  208. * @method startFlumeAgent
  209. */
  210. startFlumeAgent: function () {
  211. var selectedFlumeAgent = arguments[0].context;
  212. if (selectedFlumeAgent && selectedFlumeAgent.get('status') === 'NOT_RUNNING') {
  213. var self = this;
  214. App.showConfirmationPopup(function () {
  215. var state = 'STARTED';
  216. var context = Em.I18n.t('services.service.summary.flume.start.context').format(selectedFlumeAgent.get('name'));
  217. self.sendFlumeAgentCommandToServer(state, context, selectedFlumeAgent);
  218. });
  219. }
  220. },
  221. /**
  222. * Send stop command for selected Flume Agent
  223. * @method stopFlumeAgent
  224. */
  225. stopFlumeAgent: function () {
  226. var selectedFlumeAgent = arguments[0].context;
  227. if (selectedFlumeAgent && selectedFlumeAgent.get('status') === 'RUNNING') {
  228. var self = this;
  229. App.showConfirmationPopup(function () {
  230. var state = 'INSTALLED';
  231. var context = Em.I18n.t('services.service.summary.flume.stop.context').format(selectedFlumeAgent.get('name'));
  232. self.sendFlumeAgentCommandToServer(state, context, selectedFlumeAgent);
  233. });
  234. }
  235. },
  236. /**
  237. * Send command for Flume Agent to server
  238. * @param {string} state
  239. * @param {string} context
  240. * @param {Object} agent
  241. * @method sendFlumeAgentCommandToServer
  242. */
  243. sendFlumeAgentCommandToServer: function (state, context, agent) {
  244. App.ajax.send({
  245. name: 'service.flume.agent.command',
  246. sender: this,
  247. data: {
  248. state: state,
  249. context: context,
  250. agentName: agent.get('name'),
  251. host: agent.get('hostName')
  252. },
  253. success: 'commandSuccessCallback'
  254. });
  255. },
  256. /**
  257. * Callback, that shows Background operations popup if request was successful
  258. */
  259. commandSuccessCallback: function () {
  260. // load data (if we need to show this background operations popup) from persist
  261. App.router.get('userSettingsController').dataLoading('show_bg').done(function (showPopup) {
  262. if (showPopup) {
  263. App.router.get('backgroundOperationsController').showPopup();
  264. }
  265. });
  266. },
  267. gotoConfigs: function () {
  268. App.router.get('mainServiceItemController').set('routeToConfigs', true);
  269. App.router.transitionTo('main.services.service.configs', this.get('content'));
  270. App.router.get('mainServiceItemController').set('routeToConfigs', false);
  271. },
  272. showServiceAlertsPopup: function (event) {
  273. var service = event.context;
  274. return App.ModalPopup.show({
  275. header: Em.I18n.t('services.service.summary.alerts.popup.header').format(service.get('displayName')),
  276. autoHeight: false,
  277. classNames: ['forty-percent-width-modal'],
  278. bodyClass: Em.View.extend({
  279. templateName: require('templates/main/service/info/service_alert_popup'),
  280. classNames: ['service-alerts'],
  281. controllerBinding: 'App.router.mainAlertDefinitionsController',
  282. didInsertElement: function () {
  283. Em.run.next(this, function () {
  284. App.tooltip(this.$(".timeago"));
  285. });
  286. },
  287. willDestroyElement:function () {
  288. this.$(".timeago").tooltip('destroy');
  289. },
  290. alerts: function () {
  291. var serviceDefinitions = this.get('controller.content').filterProperty('service', service);
  292. // definitions should be sorted in order: critical, warning, ok, unknown, other
  293. var criticalDefinitions = [], warningDefinitions = [], okDefinitions = [], unknownDefinitions = [];
  294. serviceDefinitions.forEach(function (definition) {
  295. if (definition.get('isCritical')) {
  296. criticalDefinitions.push(definition);
  297. serviceDefinitions = serviceDefinitions.without(definition);
  298. } else if (definition.get('isWarning')) {
  299. warningDefinitions.push(definition);
  300. serviceDefinitions = serviceDefinitions.without(definition);
  301. } else if (definition.get('isOK')) {
  302. okDefinitions.push(definition);
  303. serviceDefinitions = serviceDefinitions.without(definition);
  304. } else if (definition.get('isUnknown')) {
  305. unknownDefinitions.push(definition);
  306. serviceDefinitions = serviceDefinitions.without(definition);
  307. }
  308. });
  309. serviceDefinitions = criticalDefinitions.concat(warningDefinitions, okDefinitions, unknownDefinitions, serviceDefinitions);
  310. return serviceDefinitions;
  311. }.property('controller.content'),
  312. gotoAlertDetails: function (event) {
  313. if (event && event.context) {
  314. this.get('parentView').hide();
  315. App.router.transitionTo('main.alerts.alertDetails', event.context);
  316. }
  317. },
  318. closePopup: function () {
  319. this.get('parentView').hide();
  320. }
  321. }),
  322. isHideBodyScroll: false,
  323. primary: Em.I18n.t('common.close'),
  324. secondary: null
  325. });
  326. },
  327. /**
  328. * @type {boolean}
  329. */
  330. isWidgetLayoutsLoaded: false,
  331. /**
  332. * @type {boolean}
  333. */
  334. isAllSharedWidgetsLoaded: false,
  335. /**
  336. * @type {boolean}
  337. */
  338. isMineWidgetsLoaded: false,
  339. /**
  340. * load widget layouts across all users in CLUSTER scope
  341. * @returns {$.ajax}
  342. */
  343. loadWidgetLayouts: function () {
  344. this.set('isWidgetLayoutsLoaded', false);
  345. return App.ajax.send({
  346. name: 'widgets.layouts.get',
  347. sender: this,
  348. data: {
  349. sectionName: this.get('sectionName')
  350. },
  351. success: 'loadWidgetLayoutsSuccessCallback'
  352. });
  353. },
  354. loadWidgetLayoutsSuccessCallback: function (data) {
  355. App.widgetLayoutMapper.map(data);
  356. this.set('isWidgetLayoutsLoaded', true);
  357. },
  358. /**
  359. * load all shared widgets to show on widget browser
  360. * @returns {$.ajax}
  361. */
  362. loadAllSharedWidgets: function () {
  363. this.set('isAllSharedWidgetsLoaded', false);
  364. return App.ajax.send({
  365. name: 'widgets.all.shared.get',
  366. sender: this,
  367. success: 'loadAllSharedWidgetsSuccessCallback'
  368. });
  369. },
  370. /**
  371. * success callback of <code>loadAllSharedWidgets</code>
  372. * @param {object|null} data
  373. */
  374. loadAllSharedWidgetsSuccessCallback: function (data) {
  375. var widgetIds = this.get('widgets').mapProperty('id');
  376. if (data.items[0] && data.items.length) {
  377. this.set("allSharedWidgets",
  378. data.items.filter(function (widget) {
  379. return widget.WidgetInfo.widget_type != "HEATMAP";
  380. }).map(function (widget) {
  381. var widgetType = widget.WidgetInfo.widget_type;
  382. var widgetName = widget.WidgetInfo.widget_name;
  383. var widgetId = widget.WidgetInfo.id;
  384. return Em.Object.create({
  385. id: widgetId,
  386. widgetName: widgetName,
  387. description: widget.WidgetInfo.description,
  388. widgetType: widgetType,
  389. iconPath: "/img/widget-" + widgetType.toLowerCase() + ".png",
  390. serviceName: JSON.parse(widget.WidgetInfo.metrics).mapProperty('service_name').uniq().join('-'),
  391. added: widgetIds.contains(widgetId),
  392. isShared: widget.WidgetInfo.scope == "CLUSTER"
  393. });
  394. })
  395. );
  396. }
  397. this.set('isAllSharedWidgetsLoaded', true);
  398. },
  399. allSharedWidgets: [],
  400. mineWidgets: [],
  401. /**
  402. * load all mine widgets of current user to show on widget browser
  403. * @returns {$.ajax}
  404. */
  405. loadMineWidgets: function () {
  406. this.set('isMineWidgetsLoaded', false);
  407. return App.ajax.send({
  408. name: 'widgets.all.mine.get',
  409. sender: this,
  410. data: {
  411. loginName: App.router.get('loginName')
  412. },
  413. success: 'loadMineWidgetsSuccessCallback'
  414. });
  415. },
  416. /**
  417. * success callback of <code>loadMineWidgets</code>
  418. * @param {object|null} data
  419. */
  420. loadMineWidgetsSuccessCallback: function (data) {
  421. var widgetIds = this.get('widgets').mapProperty('id');
  422. if (data.items[0] && data.items.length) {
  423. this.set("mineWidgets",
  424. data.items.filter(function (widget) {
  425. return widget.WidgetInfo.widget_type != "HEATMAP";
  426. }).map(function (widget) {
  427. var widgetType = widget.WidgetInfo.widget_type;
  428. var widgetName = widget.WidgetInfo.widget_name;
  429. var widgetId = widget.WidgetInfo.id;
  430. return Em.Object.create({
  431. id: widget.WidgetInfo.id,
  432. widgetName: widgetName,
  433. description: widget.WidgetInfo.description,
  434. widgetType: widgetType,
  435. iconPath: "/img/widget-" + widgetType.toLowerCase() + ".png",
  436. serviceName: JSON.parse(widget.WidgetInfo.metrics).mapProperty('service_name').uniq().join('-'),
  437. added: widgetIds.contains(widgetId),
  438. isShared: widget.WidgetInfo.scope == "CLUSTER"
  439. });
  440. })
  441. );
  442. } else {
  443. this.set("mineWidgets", []);
  444. }
  445. this.set('isMineWidgetsLoaded', true);
  446. },
  447. /**
  448. * add widgets, on click handler for "Add"
  449. */
  450. addWidget: function (event) {
  451. var widgetToAdd = event.context;
  452. var activeLayout = this.get('activeWidgetLayout');
  453. var widgetIds = activeLayout.get('widgets').map(function(widget) {
  454. return {
  455. "id": widget.get("id")
  456. }
  457. });
  458. widgetIds.pushObject({
  459. "id": widgetToAdd.id
  460. });
  461. var data = {
  462. "WidgetLayoutInfo": {
  463. "display_name": activeLayout.get("displayName"),
  464. "id": activeLayout.get("id"),
  465. "layout_name": activeLayout.get("layoutName"),
  466. "scope": activeLayout.get("scope"),
  467. "section_name": activeLayout.get("sectionName"),
  468. "widgets": widgetIds
  469. }
  470. };
  471. widgetToAdd.set('added', !widgetToAdd.added);
  472. return App.ajax.send({
  473. name: 'widget.layout.edit',
  474. sender: this,
  475. data: {
  476. layoutId: activeLayout.get("id"),
  477. data: data
  478. },
  479. success: 'updateActiveLayout'
  480. });
  481. },
  482. /**
  483. * hide widgets, on click handler for "Added"
  484. */
  485. hideWidget: function (event) {
  486. var widgetToHide = event.context;
  487. var activeLayout = this.get('activeWidgetLayout');
  488. var widgetIds = activeLayout.get('widgets').map(function (widget) {
  489. return {
  490. "id": widget.get("id")
  491. }
  492. });
  493. var data = {
  494. "WidgetLayoutInfo": {
  495. "display_name": activeLayout.get("displayName"),
  496. "id": activeLayout.get("id"),
  497. "layout_name": activeLayout.get("layoutName"),
  498. "scope": activeLayout.get("scope"),
  499. "section_name": activeLayout.get("sectionName"),
  500. "widgets": widgetIds.filter(function (widget) {
  501. return widget.id !== widgetToHide.id;
  502. })
  503. }
  504. };
  505. widgetToHide.set('added', !widgetToHide.added);
  506. return App.ajax.send({
  507. name: 'widget.layout.edit',
  508. sender: this,
  509. data: {
  510. layoutId: activeLayout.get("id"),
  511. data: data
  512. },
  513. success: 'hideWidgetSuccessCallback'
  514. });
  515. },
  516. /**
  517. * @param {object|null} data
  518. * @param {object} opt
  519. * @param {object} params
  520. */
  521. hideWidgetSuccessCallback: function (data, opt, params) {
  522. params.data.WidgetLayoutInfo.widgets = params.data.WidgetLayoutInfo.widgets.map(function (widget) {
  523. return {
  524. WidgetInfo: {
  525. id: widget.id
  526. }
  527. }
  528. });
  529. App.widgetLayoutMapper.map({items: [params.data]});
  530. this.propertyDidChange('widgets');
  531. },
  532. /**
  533. * update current active widget layout
  534. */
  535. updateActiveLayout: function () {
  536. this.getActiveWidgetLayout();
  537. },
  538. /**
  539. * delete widgets, on click handler for "Delete"
  540. */
  541. deleteWidget: function (event) {
  542. var widget = event.context;
  543. var self = this;
  544. var confirmMsg = widget.get('isShared') ? Em.I18n.t('dashboard.widgets.browser.action.delete.shared.bodyMsg').format(widget.widgetName) : Em.I18n.t('dashboard.widgets.browser.action.delete.mine.bodyMsg').format(widget.widgetName);
  545. var bodyMessage = Em.Object.create({
  546. confirmMsg: confirmMsg,
  547. confirmButton: Em.I18n.t('dashboard.widgets.browser.action.delete.btnMsg')
  548. });
  549. return App.showConfirmationFeedBackPopup(function (query) {
  550. return App.ajax.send({
  551. name: 'widget.action.delete',
  552. sender: self,
  553. data: {
  554. id: widget.id
  555. },
  556. success: 'updateWidgetBrowser'
  557. });
  558. }, bodyMessage);
  559. },
  560. /**
  561. * update widget browser content after deleted some widget
  562. */
  563. updateWidgetBrowser: function () {
  564. this.loadAllSharedWidgets();
  565. this.loadMineWidgets();
  566. },
  567. /**
  568. * Share widgets, on click handler for "Share"
  569. */
  570. shareWidget: function (event) {
  571. var widget = event.context;
  572. var self = this;
  573. var bodyMessage = Em.Object.create({
  574. confirmMsg: Em.I18n.t('dashboard.widgets.browser.action.share.confirmation'),
  575. confirmButton: Em.I18n.t('dashboard.widgets.browser.action.share')
  576. });
  577. return App.showConfirmationFeedBackPopup(function (query) {
  578. return App.ajax.send({
  579. name: 'widgets.wizard.edit',
  580. sender: self,
  581. data: {
  582. data: {
  583. "WidgetInfo": {
  584. "widget_name": widget.get("widgetName"),
  585. "scope": "CLUSTER"
  586. }
  587. },
  588. widgetId: widget.get("id")
  589. },
  590. success: 'updateWidgetBrowser'
  591. });
  592. }, bodyMessage);
  593. },
  594. /**
  595. * create widget
  596. */
  597. createWidget: function () {
  598. App.router.send('createServiceWidget', Em.Object.create({
  599. layout: this.get('activeWidgetLayout'),
  600. serviceName: this.get('content.serviceName')
  601. }));
  602. },
  603. /**
  604. * edit widget
  605. * @param {App.Widget} content
  606. */
  607. editWidget: function (content) {
  608. content.set('serviceName', this.get('content.serviceName'));
  609. App.router.send('editServiceWidget', content);
  610. },
  611. /**
  612. * launch Widgets Browser popup
  613. * @method showPopup
  614. * @return {App.ModalPopup}
  615. */
  616. goToWidgetsBrowser: function () {
  617. var self = this;
  618. return App.ModalPopup.show({
  619. header: Em.I18n.t('dashboard.widgets.browser.header'),
  620. classNames: ['sixty-percent-width-modal', 'widgets-browser-popup'],
  621. onPrimary: function () {
  622. this.hide();
  623. self.set('isAllSharedWidgetsLoaded', false);
  624. self.set('allSharedWidgets', []);
  625. self.set('isMineWidgetsLoaded', false);
  626. self.set('mineWidgets', []);
  627. },
  628. autoHeight: false,
  629. isHideBodyScroll: false,
  630. footerClass: Ember.View.extend({
  631. templateName: require('templates/common/modal_popups/widget_browser_footer'),
  632. isShowMineOnly: false,
  633. onPrimary: function() {
  634. this.get('parentView').onPrimary();
  635. }
  636. }),
  637. isShowMineOnly: false,
  638. bodyClass: Ember.View.extend({
  639. templateName: require('templates/common/modal_popups/widget_browser_popup'),
  640. controller: self,
  641. willInsertElement: function () {
  642. this.get('controller').loadAllSharedWidgets();
  643. this.get('controller').loadMineWidgets();
  644. },
  645. isLoaded: Em.computed.and('controller.isAllSharedWidgetsLoaded', 'controller.isMineWidgetsLoaded'),
  646. isWidgetEmptyList: Em.computed.empty('filteredContent'),
  647. activeService: '',
  648. activeStatus: '',
  649. content: function () {
  650. if (this.get('parentView.isShowMineOnly')) {
  651. return this.get('controller.mineWidgets');
  652. } else {
  653. // merge my widgets and all shared widgets, no duplicated is allowed
  654. var content = [];
  655. var widgetMap = {};
  656. var allWidgets = this.get('controller.allSharedWidgets').concat(this.get('controller.mineWidgets'));
  657. allWidgets.forEach(function(widget) {
  658. if (!widgetMap[widget.get("id")]) {
  659. content.pushObject(widget);
  660. widgetMap[widget.get("id")] = true;
  661. }
  662. });
  663. return content;
  664. }
  665. }.property('controller.allSharedWidgets.length', 'controller.isAllSharedWidgetsLoaded',
  666. 'controller.mineWidgets.length', 'controller.isMineWidgetsLoaded', 'parentView.isShowMineOnly'),
  667. /**
  668. * displaying content filtered by service name and status.
  669. */
  670. filteredContent: function () {
  671. var activeService = this.get('activeService') ? this.get('activeService') : this.get('controller.content.serviceName');
  672. var result = [];
  673. this.get('content').forEach(function (widget) {
  674. if (widget.get('serviceName').indexOf(activeService) >= 0) {
  675. result.pushObject(widget);
  676. }
  677. });
  678. return result;
  679. }.property('content', 'activeService', 'activeStatus'),
  680. /**
  681. * service name filter
  682. */
  683. services: function () {
  684. var view = this;
  685. var services = App.Service.find().filter(function(item){
  686. var stackService = App.StackService.find().findProperty('serviceName', item.get('serviceName'));
  687. return stackService.get('isServiceWithWidgets');
  688. });
  689. return services.map(function (service) {
  690. return Em.Object.create({
  691. value: service.get('serviceName'),
  692. label: service.get('displayName'),
  693. isActive: function () {
  694. var activeService = view.get('activeService') ? view.get('activeService') : view.get('controller.content.serviceName');
  695. return this.get('value') == activeService;
  696. }.property('value', 'view.activeService')
  697. })
  698. });
  699. }.property('activeService'),
  700. filterByService: function (event) {
  701. this.set('activeService', event.context);
  702. },
  703. createWidget: function () {
  704. this.get('parentView').onPrimary();
  705. this.get('controller').createWidget();
  706. },
  707. ensureTooltip: function () {
  708. Em.run.later(this, function () {
  709. App.tooltip($("[rel='shared-icon-tooltip']"));
  710. }, 1000);
  711. }.observes('activeService', 'parentView.isShowMineOnly'),
  712. didInsertElement: function () {
  713. this.ensureTooltip();
  714. }
  715. })
  716. });
  717. }
  718. });