summary.js 28 KB

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