| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| var App = require('app'); |
| |
| App.WidgetSectionMixin = Ember.Mixin.create({ |
| |
| /** |
| * @Type {App.WidgetLayout} |
| */ |
| activeWidgetLayout: {}, |
| |
| activeNSWidgetLayouts: [], |
| |
| selectedNSWidgetLayout: {}, |
| |
| /** |
| * UI default layout name |
| */ |
| defaultLayoutName: function () { |
| var heatmapType; |
| if (this.get('content.serviceName')) { |
| heatmapType = this.get('content.serviceName').toLowerCase(); |
| } else { |
| heatmapType = "system"; |
| } |
| return "default_" + heatmapType + this.layoutNameSuffix; |
| }.property('content.serviceName'), |
| |
| /** |
| * UI user default layout name |
| */ |
| userLayoutName: function () { |
| var heatmapType; |
| var loginName = App.router.get('loginName'); |
| if (this.get('content.serviceName')) { |
| heatmapType = this.get('content.serviceName').toLowerCase(); |
| } else { |
| heatmapType = "system"; |
| } |
| return loginName + "_" + heatmapType + this.layoutNameSuffix; |
| }.property('content.serviceName'), |
| |
| /** |
| * UI section name |
| */ |
| sectionName: function () { |
| if (this.get('content.serviceName')) { |
| return this.get('content.serviceName') + this.sectionNameSuffix; |
| } else { |
| return "SYSTEM" + this.sectionNameSuffix |
| } |
| }.property('content.serviceName'), |
| |
| |
| /** |
| * @type {Em.A} |
| */ |
| widgetLayouts: function () { |
| return App.WidgetLayout.find(); |
| }.property('isWidgetLayoutsLoaded'), |
| |
| |
| /** |
| * Does Service has widget descriptor defined in the stack |
| * @type {boolean} |
| */ |
| isServiceWithEnhancedWidgets: function () { |
| var isServiceWithWidgetdescriptor; |
| var serviceName = this.get('content.serviceName'); |
| if (serviceName) { |
| isServiceWithWidgetdescriptor = App.StackService.find(serviceName).get('isServiceWithWidgets'); |
| } else if (this.get('sectionName') === 'SYSTEM_HEATMAPS') { |
| isServiceWithWidgetdescriptor = true; |
| } |
| return isServiceWithWidgetdescriptor; |
| }.property('content.serviceName'), |
| |
| isHDFSFederatedSummary: function () { |
| return this.get('content.serviceName') === 'HDFS' && this.get('sectionNameSuffix') === '_SUMMARY' && App.get('hasNameNodeFederation'); |
| }.property('content.serviceName', 'sectionNameSuffix', 'App.hasNameNodeFederation'), |
| |
| /** |
| * @type {Em.A} |
| */ |
| widgets: function () { |
| if (this.get('isWidgetsLoaded') && this.get('activeWidgetLayout.widgets')) { |
| return this.get('activeWidgetLayout.widgets').toArray(); |
| } |
| return []; |
| }.property('isWidgetsLoaded', 'activeWidgetLayout.widgets'), |
| |
| isAmbariMetricsInstalled: function () { |
| return App.Service.find().someProperty('serviceName', 'AMBARI_METRICS'); |
| }.property('App.router.mainServiceController.content.length'), |
| |
| switchNameServiceLayout: function (data) { |
| this.set('selectedNSWidgetLayout', data.context); |
| }, |
| |
| /** |
| * load widgets defined by user |
| * @returns {$.ajax} |
| */ |
| getActiveWidgetLayout: function () { |
| var sectionName = this.get('sectionName'); |
| var urlParams = 'WidgetLayoutInfo/section_name=' + sectionName; |
| this.set('activeWidgetLayout', {}); |
| this.set('activeNSWidgetLayouts', []); |
| this.set('isWidgetsLoaded', false); |
| if (this.get('isServiceWithEnhancedWidgets')) { |
| return App.ajax.send({ |
| name: 'widgets.layouts.active.get', |
| sender: this, |
| data: { |
| userName: App.router.get('loginName'), |
| sectionName: sectionName, |
| urlParams: urlParams |
| }, |
| success: 'getActiveWidgetLayoutSuccessCallback' |
| }); |
| } else { |
| this.set('isWidgetsLoaded', true); |
| } |
| }, |
| |
| |
| /** |
| * success callback of <code>getActiveWidgetLayout()</code> |
| * @param {object|null} data |
| */ |
| getActiveWidgetLayoutSuccessCallback: function (data) { |
| if (this.get('isHDFSFederatedSummary')) { |
| this.getNameNodeWidgets().done((widgets) => { |
| widgets = widgets.items; |
| var widgetsNamespaces = widgets.mapProperty('WidgetInfo.tag').uniq().without(null); |
| var namespaces = App.HDFSService.find('HDFS').get('masterComponentGroups').mapProperty('name'); |
| var defaultNNWidgets = widgets.filterProperty('WidgetInfo.tag', null); |
| var widgetsToCreateCount; |
| if (namespaces.length > widgetsNamespaces.length) { |
| widgetsToCreateCount = (namespaces.length - widgetsNamespaces.length) * defaultNNWidgets.length; |
| namespaces.forEach((namespace) => { |
| if (!widgetsNamespaces.contains(namespace)) { |
| defaultNNWidgets.forEach((widget) => { |
| this.postNNWidgets(widget, widgetsToCreateCount, data, namespace); |
| }); |
| } |
| }); |
| } else { |
| this.createLayouts(data); |
| } |
| }) |
| } else { |
| this.createLayouts(data); |
| } |
| }, |
| |
| /** |
| * |
| * @param widget |
| * @param widgetsToCreateCount |
| * @param data |
| * @param namespace |
| */ |
| postNNWidgets: function(widget, widgetsToCreateCount, data, namespace) { |
| if (widget.href) { |
| delete widget.href; |
| delete widget.WidgetInfo.id; |
| delete widget.WidgetInfo.cluster_name; |
| delete widget.WidgetInfo.author; |
| widget.WidgetInfo.metrics = JSON.parse(widget.WidgetInfo.metrics); |
| widget.WidgetInfo.values = JSON.parse(widget.WidgetInfo.values); |
| } |
| widget.WidgetInfo.tag = namespace; |
| this.postWidget(widget).done(() => { |
| if (!--widgetsToCreateCount) { |
| this.createLayouts(data); |
| } |
| }); |
| }, |
| |
| getNameNodeWidgets: function () { |
| return App.ajax.send({ |
| name: 'widgets.get', |
| sender: this, |
| data: { |
| urlParams: 'WidgetInfo/widget_type.in(GRAPH,NUMBER,GAUGE)&WidgetInfo/scope=CLUSTER&WidgetInfo/metrics.matches(.*\"component_name\":\"NAMENODE\".*)&fields=*' |
| } |
| }); |
| }, |
| |
| postWidget: function (data) { |
| return App.ajax.send({ |
| name: 'widgets.wizard.add', |
| sender: this, |
| data: { |
| data: data |
| } |
| }); |
| }, |
| |
| createLayouts: function (data) { |
| var self = this; |
| if (data.items[0]) { |
| var hdfs = App.HDFSService.find('HDFS'); |
| if (hdfs.get('isLoaded') && this.get('isHDFSFederatedSummary') && hdfs.get('masterComponentGroups').length + 2 !== data.items.length) { |
| this.createFederationWidgetLayouts(data); |
| } else { |
| this.getWidgetLayoutSuccessCallback(data); |
| } |
| } else { |
| this.getAllActiveWidgetLayouts().done(function (activeWidgetLayoutsData) { |
| self.getDefaultWidgetLayoutByName(self.get('defaultLayoutName')).done(function (defaultWidgetLayoutData) { |
| defaultWidgetLayoutData = defaultWidgetLayoutData.items[0].WidgetLayoutInfo; |
| defaultWidgetLayoutData.layout_name = self.get('userLayoutName'); |
| self.createUserWidgetLayout(defaultWidgetLayoutData).done(function (userLayoutIdData) { |
| self.createUserWidgetLayoutCallback(userLayoutIdData, activeWidgetLayoutsData); |
| }); |
| }); |
| }); |
| } |
| }, |
| |
| /** |
| * |
| * @param userLayoutIdData |
| * @param activeWidgetLayoutsData |
| */ |
| createUserWidgetLayoutCallback: function(userLayoutIdData, activeWidgetLayoutsData) { |
| var activeWidgetLayouts; |
| var widgetLayouts = []; |
| if (!!activeWidgetLayoutsData.items.length) { |
| widgetLayouts = activeWidgetLayoutsData.items.map(function (item) { |
| return { |
| "id": item.WidgetLayoutInfo.id |
| } |
| }); |
| } |
| widgetLayouts.push({id: userLayoutIdData.resources[0].WidgetLayoutInfo.id}); |
| activeWidgetLayouts = { |
| "WidgetLayouts": widgetLayouts |
| }; |
| this.saveActiveWidgetLayouts(activeWidgetLayouts).done(() => { |
| this.getActiveWidgetLayout(); |
| }); |
| }, |
| |
| getAllActiveWidgetLayouts: function () { |
| return App.ajax.send({ |
| name: 'widgets.layouts.all.active.get', |
| sender: this, |
| data: { |
| userName: App.router.get('loginName') |
| } |
| }); |
| }, |
| |
| /** |
| * success callback of <code>getWidgetLayout()</code> |
| * @param {object|null} data |
| */ |
| getWidgetLayoutSuccessCallback: function (data) { |
| if (data) { |
| data.items.forEach(function (item) { |
| App.widgetMapper.map(item.WidgetLayoutInfo); |
| }); |
| App.widgetLayoutMapper.map(data); |
| this.set('activeWidgetLayout', App.WidgetLayout.find().findProperty('layoutName', this.get('userLayoutName'))); |
| if (this.get('isHDFSFederatedSummary')) { |
| this.set('activeNSWidgetLayouts', App.WidgetLayout.find().filterProperty('sectionName', this.get('sectionName')).rejectProperty('layoutName', this.get('userLayoutName'))); |
| this.set('selectedNSWidgetLayout', this.get('activeNSWidgetLayouts')[0]); |
| } |
| this.set('isWidgetsLoaded', true); |
| } |
| }, |
| |
| getDefaultWidgetLayoutByName: function (layoutName) { |
| var urlParams = 'WidgetLayoutInfo/layout_name=' + layoutName; |
| return App.ajax.send({ |
| name: 'widget.layout.get', |
| sender: this, |
| data: { |
| urlParams: urlParams |
| } |
| }); |
| }, |
| |
| createUserWidgetLayout: function (widgetLayoutData) { |
| var layout = widgetLayoutData; |
| var data = { |
| "WidgetLayoutInfo": { |
| "display_name": layout.display_name, |
| "layout_name": layout.layout_name, |
| "scope": "USER", |
| "section_name": layout.section_name, |
| "user_name": App.router.get('loginName'), |
| "widgets": layout.widgets.map(function (widget) { |
| return { |
| "id": widget.WidgetInfo.id |
| } |
| }) |
| } |
| }; |
| return App.ajax.send({ |
| name: 'widget.layout.create', |
| sender: this, |
| data: { |
| data: data |
| } |
| }); |
| }, |
| |
| updateUserWidgetLayout: function (widgetLayoutData) { |
| var layout = widgetLayoutData; |
| var data = { |
| "WidgetLayoutInfo": { |
| "display_name": layout.display_name, |
| "layout_name": layout.layout_name, |
| "id": layout.id, |
| "scope": "USER", |
| "section_name": layout.section_name, |
| "user_name": App.router.get('loginName'), |
| "widgets": layout.widgets.map(function (widget) { |
| return { |
| "id": widget.WidgetInfo.id |
| } |
| }) |
| } |
| }; |
| return App.ajax.send({ |
| name: 'widget.layout.edit', |
| sender: this, |
| data: { |
| layoutId: layout.id, |
| data: data |
| }, |
| }); |
| }, |
| |
| saveActiveWidgetLayouts: function (activeWidgetLayouts) { |
| return App.ajax.send({ |
| name: 'widget.activelayouts.edit', |
| sender: this, |
| data: { |
| data: activeWidgetLayouts, |
| userName: App.router.get('loginName') |
| } |
| }); |
| }, |
| |
| |
| /** |
| * save layout after re-order widgets |
| * @param {Array} widgets |
| * @param {Object} widgetLayout: Optional. by default active widget layout is honored. |
| * return {$.ajax} |
| */ |
| saveWidgetLayout: function (widgets, widgetLayout) { |
| var activeLayout = widgetLayout || this.get('activeWidgetLayout'); |
| var data = { |
| "WidgetLayoutInfo": { |
| "display_name": activeLayout.get("displayName"), |
| "id": activeLayout.get("id"), |
| "layout_name": activeLayout.get("layoutName"), |
| "scope": activeLayout.get("scope"), |
| "section_name": activeLayout.get("sectionName"), |
| "widgets": widgets.map(function (widget) { |
| return { |
| "id": widget.get('id') |
| } |
| }) |
| } |
| }; |
| return App.ajax.send({ |
| name: 'widget.layout.edit', |
| sender: this, |
| data: { |
| layoutId: activeLayout.get("id"), |
| data: data |
| } |
| }); |
| }, |
| |
| /** |
| * After closing widget section, layout should be reset |
| */ |
| clearActiveWidgetLayout: function () { |
| this.set('activeWidgetLayout', {}); |
| this.set('activeNSWidgetLayouts', []); |
| }, |
| |
| createFederationWidgetLayouts: function (data) { |
| var currentLayouts = data.items; |
| |
| this.getDefaultWidgetLayoutByName(this.get('defaultLayoutName')).done((defaultWidgetLayoutData) => { |
| this.getNameNodeWidgets().done((widgets) => { |
| var newLayout = defaultWidgetLayoutData.items[0].WidgetLayoutInfo; |
| var nameServiceToWidgetMap = {all: []}; |
| var nonNameServiceSpecific = newLayout.widgets.slice(); |
| widgets.items.forEach((widget) => { |
| var tag = widget.WidgetInfo.tag; |
| nonNameServiceSpecific = nonNameServiceSpecific.without(nonNameServiceSpecific.findProperty('WidgetInfo.id', widget.WidgetInfo.id)); |
| if (tag) { |
| if (!nameServiceToWidgetMap[tag]) { |
| nameServiceToWidgetMap[tag] = []; |
| } |
| nameServiceToWidgetMap[tag].push(widget); |
| nameServiceToWidgetMap.all.push(widget); |
| } |
| }); |
| if (currentLayouts.length === 1) { |
| this.createSingleLayout(currentLayouts, newLayout, nonNameServiceSpecific, nameServiceToWidgetMap); |
| } else { |
| this.createMultipleLayouts(currentLayouts, newLayout, nameServiceToWidgetMap); |
| } |
| }); |
| }); |
| }, |
| |
| /** |
| * |
| * @param currentLayouts |
| * @param newLayout |
| * @param nonNameServiceSpecific |
| * @param nameServiceToWidgetMap |
| */ |
| createSingleLayout: function(currentLayouts, newLayout, nonNameServiceSpecific, nameServiceToWidgetMap) { |
| const userLayoutName = this.get('userLayoutName'); |
| const newLayoutsIds = []; |
| |
| this.removeWidgetLayout(currentLayouts[0].WidgetLayoutInfo.id).done(() => { |
| newLayout.layout_name = userLayoutName; |
| newLayout.widgets = nonNameServiceSpecific; |
| this.createUserWidgetLayout(newLayout).done((data) => { |
| newLayoutsIds.push(data.resources[0].WidgetLayoutInfo.id); |
| Em.keys(nameServiceToWidgetMap).forEach((nameService) => { |
| newLayout.layout_name = userLayoutName + '_nameservice_' + nameService; |
| newLayout.display_name = nameService === 'all' ? 'All' : nameService; |
| newLayout.widgets = nameServiceToWidgetMap[nameService]; |
| this.createUserWidgetLayout(newLayout).done((data) => { |
| newLayoutsIds.push(data.resources[0].WidgetLayoutInfo.id); |
| if (newLayoutsIds.length >= Em.keys(nameServiceToWidgetMap).length + 1) { |
| this.saveActiveWidgetLayouts({ |
| "WidgetLayouts": newLayoutsIds.map(function (layout) { |
| return {id: layout}; |
| }) |
| }).done(() => { |
| this.getActiveWidgetLayout(); |
| }); |
| } |
| }); |
| }) |
| }); |
| }); |
| }, |
| |
| /** |
| * |
| * @param currentLayouts |
| * @param newLayout |
| * @param nameServiceToWidgetMap |
| */ |
| createMultipleLayouts: function(currentLayouts, newLayout, nameServiceToWidgetMap) { |
| const newNameServices = []; |
| const newLayoutsIds = []; |
| let newWidgets = []; |
| const userLayoutName = this.get('userLayoutName'); |
| const namespaces = App.HDFSService.find('HDFS').get('masterComponentGroups').mapProperty('name'); |
| const currentLayoutsNames = currentLayouts.map((l) => { |
| return l.WidgetLayoutInfo.layout_name.split('_nameservice_')[1]; |
| }).without(undefined).without('all'); |
| namespaces.forEach(function (n) { |
| if (!currentLayoutsNames.contains(n)) { |
| newNameServices.push(n); |
| } |
| }); |
| newNameServices.forEach((nameService) => { |
| newLayout.layout_name = userLayoutName + '_nameservice_' + nameService; |
| newLayout.display_name = nameService; |
| newLayout.widgets = nameServiceToWidgetMap[nameService]; |
| newWidgets = newWidgets.concat(nameServiceToWidgetMap[nameService]); |
| this.createUserWidgetLayout(newLayout).done((data) => { |
| newLayoutsIds.push(data.resources[0].WidgetLayoutInfo.id); |
| if (newLayoutsIds.length >= newNameServices.length) { |
| this.saveActiveWidgetLayouts({ |
| "WidgetLayouts": newLayoutsIds.concat(currentLayouts.mapProperty('WidgetLayoutInfo.id')).map(function (layout) { |
| return {id: layout}; |
| }) |
| }).done(() => { |
| var allNSLayout = currentLayouts.findProperty('WidgetLayoutInfo.display_name', 'All').WidgetLayoutInfo; |
| allNSLayout.widgets = allNSLayout.widgets.concat(newWidgets); |
| this.updateUserWidgetLayout(allNSLayout).done(() => { |
| this.getActiveWidgetLayout(); |
| }); |
| }); |
| } |
| }); |
| }); |
| }, |
| |
| removeWidgetLayout: function (id) { |
| return App.ajax.send({ |
| name: 'widget.layout.delete', |
| sender: this, |
| data: { |
| layoutId: id |
| }, |
| }); |
| } |
| }); |