summary.js 23 KB

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