Explorar o código

AMBARI-4958. Update Ember. (onechiporenko)

Oleg Nechiporenko %!s(int64=11) %!d(string=hai) anos
pai
achega
3c44c313e6

+ 1 - 15
ambari-web/app/app.js

@@ -17,7 +17,7 @@
  */
 
 // Application bootstrapper
-
+require('utils/ember_reopen');
 var stringUtils = require('utils/string_utils');
 
 module.exports = Em.Application.create({
@@ -235,18 +235,4 @@ module.exports = Em.Application.create({
       return require('data/service_components').filterProperty('isClient', true).mapProperty('component_name').uniq();
     }.property().cacheable()
   })
-});
-
-/**
- * overwritten set method of Ember.View to avoid uncaught errors
- * when trying to set property of destroyed view
- */
-Em.View.reopen({
-  set: function(attr, value){
-    if(!this.get('isDestroyed') && !this.get('isDestroying')){
-      this._super(attr, value);
-    } else {
-      console.debug('Calling set on destroyed view');
-    }
-  }
 });

+ 1 - 10
ambari-web/app/controllers/installer.js

@@ -180,16 +180,7 @@ App.InstallerController = App.WizardController.extend({
   loadStacksVersionsSuccessCallback: function (data) {
     var result = [];
     var stackVersions = data.items.filterProperty('Versions.active');
-    stackVersions.sort(function (a, b) {
-      if (a.Versions.stack_version > b.Versions.stack_version) {
-        return -1;
-      }
-      if (a.Versions.stack_version < b.Versions.stack_version) {
-        return 1;
-      }
-      return 0;
-    });
-    stackVersions.forEach(function (version) {
+    stackVersions.sortProperty('Versions.stack_version').reverse().forEach(function (version) {
       /*
        * operatingSystems:[
        *  {

+ 1 - 4
ambari-web/app/controllers/main/admin/highAvailability/step2_controller.js

@@ -63,10 +63,7 @@ App.HighAvailabilityWizardStep2Controller = App.WizardStep5Controller.extend({
       mapping.pushObject(mappingObject);
     }, this);
 
-    mapping.sortBy('host_name');
-
-    return mapping;
-
+    return mapping.sortProperty('host_name');
   }.property("selectedServicesMasters.@each.selectedHost"),
 
   /**

+ 1 - 25
ambari-web/app/controllers/main/alerts_controller.js

@@ -130,33 +130,9 @@ App.MainAlertsController = Em.Controller.extend({
         }));
       }, this);
     }
-    this.set('alerts', this.sortAlerts(alerts));
+    this.set('alerts', alerts.sortProperty('status','date').reverse());
     this.set('isLoaded', true);
   },
-  /**
-   * alerts sorting
-   * firstly by status
-   * 1. UNKNOWN
-   * 2. CRITICAL
-   * 3. WARNING
-   * 4. OK
-   * secondly by date
-   * @param array
-   * @return {*}
-   */
-  sortAlerts: function (array) {
-    return array.sort(function (left, right) {
-      var statusDiff = right.get('status') - left.get('status');
-      if (statusDiff == 0) { // same error severity - sort by time
-        var rightTime = right.get('date');
-        var leftTime = left.get('date');
-        rightTime = rightTime ? rightTime.getTime() : 0;
-        leftTime = leftTime ? leftTime.getTime() : 0;
-        statusDiff = rightTime - leftTime;
-      }
-      return statusDiff;
-    });
-  },
 
   getAlertsErrorCallback: function(){
     this.set('isLoaded', true);

+ 1 - 1
ambari-web/app/controllers/main/jobs_controller.js

@@ -266,7 +266,7 @@ App.MainJobsController = Em.ArrayController.extend({
           if(sortColumn && sortColumn.get('status')){
             var sortColumnStatus = sortColumn.get('status');
             sortColumn.set('content', self.get('content'));
-            sortColumn.get('parentView').sort(sortColumn, sortColumnStatus === "sorting_desc" ? true : false);
+            sortColumn.get('parentView').sort(sortColumn, sortColumnStatus === "sorting_desc");
             sortColumn.set('status', sortColumnStatus);
             self.set('content',sortColumn.get('parentView').get('content'));
           }

+ 1 - 5
ambari-web/app/controllers/main/mirroring_controller.js

@@ -161,11 +161,7 @@ App.MainMirroringController = Em.ArrayController.extend({
     if (this.get('datasetCount') < 1) {
       var sortedDatasets = [];
       App.dataSetMapper.map(datasetsData);
-      sortedDatasets = App.Dataset.find().toArray().sort(function (a, b) {
-        if (a.get('name') < b.get('name'))  return -1;
-        if (a.get('name') > b.get('name'))  return 1;
-        return 0;
-      });
+      sortedDatasets = App.Dataset.find().toArray().sortProperty('name');
       this.set('isDatasetsLoaded', true);
       var selectedDataset = this.get('selectedDataset');
       if (!selectedDataset) {

+ 1 - 4
ambari-web/app/controllers/main/service/manage_config_groups_controller.js

@@ -46,10 +46,7 @@ App.ManageConfigGroupsController = Em.Controller.extend({
     }
     var defaultConfigGroup = configGroups.findProperty('isDefault');
     configGroups.removeObject(defaultConfigGroup);
-    var sorted = configGroups.sort(function(configGroupA, configGroupB){
-      return String(configGroupA.get('name')) >= String(configGroupB.get('name'));
-    });
-    sorted = [defaultConfigGroup].concat(sorted);
+    var sorted = [defaultConfigGroup].concat(configGroups.sortProperty('name'));
 
     this.removeObserver('configGroups.@each.name', this, 'resortConfigGroup');
     this.set('configGroups', sorted);

+ 1 - 2
ambari-web/app/controllers/main/service/reassign/step2_controller.js

@@ -77,8 +77,7 @@ App.ReassignMasterWizardStep2Controller = App.WizardStep5Controller.extend({
       if (item.get('selectedHost') == this.get('currentHostId') && item.get('component_name') == this.get('content.reassign.component_name')) {
         item.set('selectedHost', preparedAvailableHosts.objectAt(0).host_name);
       }
-      preparedAvailableHosts.sortBy('host_name');
-      item.set("availableHosts", preparedAvailableHosts);
+      item.set("availableHosts", preparedAvailableHosts.sortProperty('host_name'));
     }, this);
   }
 });

+ 1 - 10
ambari-web/app/controllers/wizard/step3_controller.js

@@ -821,16 +821,7 @@ App.WizardStep3Controller = Em.Controller.extend({
     var warnings = [];
     var warning;
     var hosts = [];
-    data.items.sort(function (a, b) {
-      if (a.Hosts.host_name > b.Hosts.host_name) {
-        return 1;
-      }
-      if (a.Hosts.host_name < b.Hosts.host_name) {
-        return -1;
-      }
-      return 0;
-    });
-    data.items.forEach(function (_host) {
+    data.items.sortProperty('Hosts.host_name').forEach(function (_host) {
       var host = {
         name: _host.Hosts.host_name,
         warnings: []

+ 1 - 3
ambari-web/app/controllers/wizard/step5_controller.js

@@ -468,9 +468,7 @@ App.WizardStep5Controller = Em.Controller.extend({
       mapping.pushObject(mappingObject);
     }, this);
 
-    mapping.sortBy('host_name');
-
-    return mapping;
+    return mapping.sortProperty('host_name');
   }.property("selectedServicesMasters.@each.selectedHost"),
 
   remainingHosts:function () {

+ 1 - 3
ambari-web/app/controllers/wizard/step7_controller.js

@@ -179,9 +179,7 @@ App.WizardStep7Controller = Em.Controller.extend({
     if (!selectedConfigGroup) {
       selectedConfigGroup = defaultConfigGroup;
     }
-    configGroups.sort(function(configGroupA, configGroupB){
-      return (configGroupA.name > configGroupB.name);
-    });
+    configGroups = configGroups.sortProperty('name');
     configGroups.unshift(defaultConfigGroup);
     if (App.supports.hostOverrides) {
       service.set('configGroups', configGroups);

+ 2 - 18
ambari-web/app/mappers/hosts_mapper.js

@@ -98,7 +98,7 @@ App.hostsMapper = App.QuickDataMapper.create({
       }, this);
 
       App.cache['previousHostStatuses'] = currentHostStatuses;
-      hostsWithFullInfo = this.sortByPublicHostName(hostsWithFullInfo);
+      hostsWithFullInfo = hostsWithFullInfo.sortProperty('public_host_name');
 
       var clientHosts = App.Host.find();
 
@@ -173,7 +173,7 @@ App.hostsMapper = App.QuickDataMapper.create({
    */
   getDiscrepancies: function (current, previous) {
     var result = {};
-    var fields = ['disk_total', 'disk_free', 'health_status', 'load_one', 'cpu_system', 'cpu_user', 'mem_total', 'mem_free', 'critical_alerts_count', 'passive_state'];
+    var fields = Em.A(['disk_total', 'disk_free', 'health_status', 'load_one', 'cpu_system', 'cpu_user', 'mem_total', 'mem_free', 'critical_alerts_count', 'passive_state']);
     if (previous) {
       fields.forEach(function (field) {
         if (current[field] != previous[field]) result[field] = current[field];
@@ -188,22 +188,6 @@ App.hostsMapper = App.QuickDataMapper.create({
       return result;
     }
     return current;
-  },
-
-  /**
-   * Default data sorting by public_host_name field
-   * @param data
-   * @return {Array}
-   */
-  sortByPublicHostName: function(data) {
-    data.sort(function(a, b) {
-      var ap = a.public_host_name;
-      var bp = b.public_host_name;
-      if (ap > bp) return 1;
-      if (ap < bp) return -1;
-      return 0;
-    });
-    return data;
   }
 
 });

+ 1 - 10
ambari-web/app/mappers/jobs/hive_job_mapper.js

@@ -38,15 +38,6 @@ App.hiveJobMapper = App.QuickDataMapper.create({
   model : App.HiveJob,
   map : function(json) {
     var model = this.get('model');
-    var sortById = function (a, b) {
-      if (a.id > b.id) {
-        return 1;
-      } else if (a.id < b.id) {
-        return -1;
-      } else {
-        return 0;
-      };
-    };
     if (!model) {
       return;
     }
@@ -187,7 +178,7 @@ App.hiveJobMapper = App.QuickDataMapper.create({
       }
       var hiveJobRecord = App.HiveJob.find(hiveJob.id);
       if (hiveJobRecord != null) {
-        hiveJobRecord.set('stages', hiveJob.stages.sort(sortById));
+        hiveJobRecord.set('stages', hiveJob.stages.sortProperty('id'));
         hiveJobRecord.set('startTime', hiveJob.startTime);
         hiveJobRecord.set('endTime', hiveJob.endTime);
         if (hiveJob.tezDag != null) {

+ 1 - 3
ambari-web/app/models/dataset.js

@@ -65,9 +65,7 @@ App.Dataset = DS.Model.extend({
   healthClass: function () {
     var jobs = this.get('datasetJobs').toArray();
     jobs = jobs.filterProperty('status', 'FAILED').concat(jobs.filterProperty('status', 'SUCCESSFUL'));
-    jobs.sort(function (a, b) {
-      return a.get('endDate') - b.get('endDate');
-    });
+    jobs = jobs.sortProperty('endDate');
     return jobs.length && jobs[0].get('status') === 'FAILED' ? 'health-status-DEAD-RED' : 'health-status-LIVE';
   }.property('datasetJobs', 'datasetJobs.@each.status')
 });

+ 2 - 9
ambari-web/app/utils/config.js

@@ -385,16 +385,9 @@ App.config = Em.Object.create({
       }
     }, this);
 
-    var alphabeticalSort = function (a, b) {
-      if (a.name < b.name) return -1;
-      if (a.name > b.name) return 1;
-      return 0;
-    };
-
-
     return {
-      globalConfigs: globalStart.concat(globalConfigs.sort(alphabeticalSort)),
-      configs: siteStart.concat(siteConfigs.sort(alphabeticalSort)),
+      globalConfigs: globalStart.concat(globalConfigs.sortProperty('name')),
+      configs: siteStart.concat(siteConfigs.sortProperty('name')),
       mappingConfigs: configSet.mappingConfigs
     }
   },

+ 129 - 0
ambari-web/app/utils/ember_reopen.js

@@ -0,0 +1,129 @@
+/**
+ * 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.
+ */
+
+/**
+ Merge the contents of two objects together into the first object.
+
+ ```javascript
+ Ember.merge({first: 'Tom'}, {last: 'Dale'}); // {first: 'Tom', last: 'Dale'}
+ var a = {first: 'Yehuda'}, b = {last: 'Katz'};
+ Ember.merge(a, b); // a == {first: 'Yehuda', last: 'Katz'}, b == {last: 'Katz'}
+ ```
+
+ @method merge
+ @for Ember
+ @param {Object} original The object to merge into
+ @param {Object} updates The object to copy properties from
+ @return {Object}
+ */
+Ember.merge = function(original, updates) {
+  for (var prop in updates) {
+    if (!updates.hasOwnProperty(prop)) { continue; }
+    original[prop] = updates[prop];
+  }
+  return original;
+};
+
+/**
+ Returns true if the passed value is null or undefined. This avoids errors
+ from JSLint complaining about use of ==, which can be technically
+ confusing.
+
+ ```javascript
+ Ember.isNone();              // true
+ Ember.isNone(null);          // true
+ Ember.isNone(undefined);     // true
+ Ember.isNone('');            // false
+ Ember.isNone([]);            // false
+ Ember.isNone(function() {});  // false
+ ```
+
+ @method isNone
+ @for Ember
+ @param {Object} obj Value to test
+ @return {Boolean}
+ */
+Ember.isNone = function(obj) {
+  return obj === null || obj === undefined;
+};
+
+/**
+ Verifies that a value is `null` or an empty string, empty array,
+ or empty function.
+
+ Constrains the rules on `Ember.isNone` by returning false for empty
+ string and empty arrays.
+
+ ```javascript
+ Ember.isEmpty();                // true
+ Ember.isEmpty(null);            // true
+ Ember.isEmpty(undefined);       // true
+ Ember.isEmpty('');              // true
+ Ember.isEmpty([]);              // true
+ Ember.isEmpty('Adam Hawkins');  // false
+ Ember.isEmpty([0,1,2]);         // false
+ ```
+
+ @method isEmpty
+ @for Ember
+ @param {Object} obj Value to test
+ @return {Boolean}
+ */
+Ember.isEmpty = function(obj) {
+  return Ember.isNone(obj) || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
+};
+
+/**
+ A value is blank if it is empty or a whitespace string.
+
+ ```javascript
+ Ember.isBlank();                // true
+ Ember.isBlank(null);            // true
+ Ember.isBlank(undefined);       // true
+ Ember.isBlank('');              // true
+ Ember.isBlank([]);              // true
+ Ember.isBlank('\n\t');          // true
+ Ember.isBlank('  ');            // true
+ Ember.isBlank({});              // false
+ Ember.isBlank('\n\t Hello');    // false
+ Ember.isBlank('Hello world');   // false
+ Ember.isBlank([1,2,3]);         // false
+ ```
+
+ @method isBlank
+ @for Ember
+ @param {Object} obj Value to test
+ @return {Boolean}
+ */
+Ember.isBlank = function(obj) {
+  return Ember.isEmpty(obj) || (typeof obj === 'string' && obj.match(/\S/) === null);
+};
+
+Em.View.reopen({
+  /**
+   * overwritten set method of Ember.View to avoid uncaught errors
+   * when trying to set property of destroyed view
+   */
+  set: function(attr, value){
+    if(!this.get('isDestroyed') && !this.get('isDestroying')){
+      this._super(attr, value);
+    } else {
+      console.debug('Calling set on destroyed view');
+    }
+  }
+});

+ 0 - 17
ambari-web/app/utils/helper.js

@@ -79,23 +79,6 @@ Number.prototype.toDaysHoursMinutes = function () {
   return formatted;
 };
 
-/**
- * sort array of objects by property;
- * by default sorting has ascending order
- * if @desc - true, then descending order
- * @param property
- * @param desc
- */
-Array.prototype.sortBy = function(property, desc) {
-  this.sort(function (a, b) {
-    if (a[property] > b[property])
-      return (desc) ? -1 : 1;
-    else
-      return (desc) ? 1 : -1;
-  });
-  return this;
-};
-
 Em.CoreObject.reopen({
   t:function (key, attrs) {
     return Em.I18n.t(key, attrs)

+ 3 - 14
ambari-web/app/utils/host_progress_popup.js

@@ -376,7 +376,7 @@ App.HostPopup = Em.Object.create({
           });
 
           if (tasks.length) {
-            tasks = self.sortTasksById(tasks);
+            tasks = tasks.sortProperty('Tasks.id');
             var hostStatus = self.getStatus(tasks);
             var hostProgress = self.getProgress(tasks);
             hostInfo.set('status', App.format.taskStatus(hostStatus[0]));
@@ -389,8 +389,8 @@ App.HostPopup = Em.Object.create({
           hostInfo.set('logTasks', tasks);
           hostsArr.push(hostInfo);
         }
-        //sort hosts by name
-        this.sortArray(hostsArr, "name");
+
+        hostsArr = hostsArr.sortProperty('name');
         hostsArr.setEach("serviceName", this.get("serviceName"));
         self.set("hosts", hostsArr);
         self.set('previousServiceId', this.get('currentServiceId'));
@@ -398,17 +398,6 @@ App.HostPopup = Em.Object.create({
     }
   },
 
-  /**
-   * Sort tasks by it`s id
-   * @param tasks
-   * @return {Array}
-   */
-  sortTasksById: function (tasks) {
-    return tasks.sort(function (a, b) {
-      return (a.Tasks.id > b.Tasks.id) ? 1 : (a.Tasks.id < b.Tasks.id) ? -1 : 0;
-    });
-  },
-
   /**
    * Show popup
    * @return PopupObject For testing purposes

+ 1 - 3
ambari-web/app/views/main/jobs/hive_job_details_view.js

@@ -59,9 +59,7 @@ App.MainHiveJobDetailsView = Em.View.extend({
     var vertices = this.get('content.tezDag.vertices');
     if (vertices != null) {
       vertices = vertices.toArray();
-      return vertices.sort(function(v1, v2) {
-        return Ember.compare(v1.get('name'), v2.get('name'));
-      });
+      return vertices.sortProperty('name');
     }
     return vertices;
   }.property('content.tezDag.vertices'),

+ 1 - 3
ambari-web/app/views/wizard/step9_view.js

@@ -246,9 +246,7 @@ App.HostStatusView = Em.View.extend({
           var tasksArr = [];
           var host = this.get('parentView.host');
           var tasks = this.getStartedTasks(host);
-          tasks = tasks.sort(function (a, b) {
-            return a.Tasks.id - b.Tasks.id;
-          });
+          tasks = tasks.sortProperty('Tasks.id');
           if (tasks.length) {
             tasks.forEach(function (_task) {
               var taskInfo = Ember.Object.create({});

+ 1 - 39
ambari-web/test/mappers/hosts_mapper_test.js

@@ -26,44 +26,6 @@ require('mappers/hosts_mapper');
 
 describe('App.hostsMapper', function () {
 
-  describe('#sortByPublicHostName()', function () {
-    var tests = [
-      {
-        i: [
-          {public_host_name: 'host0'},
-          {public_host_name: 'host1'},
-          {public_host_name: 'host2'},
-          {public_host_name: 'host3'}
-        ],
-        m: 'Sorted array',
-        e: ['host0','host1','host2','host3']
-      },
-      {
-        i: [
-          {public_host_name: 'host3'},
-          {public_host_name: 'host2'},
-          {public_host_name: 'host1'},
-          {public_host_name: 'host0'}
-        ],
-        m: 'Reverse sorted array',
-        e: ['host0','host1','host2','host3']
-      },
-      {
-        i: [
-          {public_host_name: 'host2'},
-          {public_host_name: 'host3'},
-          {public_host_name: 'host0'},
-          {public_host_name: 'host1'}
-        ],
-        m: 'Shuffled array',
-        e: ['host0','host1','host2','host3']
-      }
-    ];
-    tests.forEach(function(test) {
-      it(test.m, function() {
-        expect(App.hostsMapper.sortByPublicHostName(test.i).mapProperty('public_host_name')).to.eql(test.e);
-      });
-    });
-  });
+
 
 });

+ 92 - 1
ambari-web/vendor/scripts/ember-latest.js

@@ -6564,7 +6564,98 @@ Ember.Enumerable = Ember.Mixin.create(
     Ember.propertyDidChange(this, '[]');
 
     return this ;
-  }
+  },
+
+    /**
+     Converts the enumerable into an array and sorts by the keys
+     specified in the argument.
+
+     You may provide multiple arguments to sort by multiple properties.
+
+     @method sortProperty
+     @param {String} property name(s) to sort on
+     @return {Array} The sorted array.
+     */
+    sortProperty: function() {
+      var sortKeys = arguments;
+      return this.toArray().sort(function(a, b){
+        for(var i = 0; i < sortKeys.length; i++) {
+          var key = sortKeys[i],
+            propA = Ember.get(a, key),
+            propB = Ember.get(b, key);
+          // return 1 or -1 else continue to the next sortKey
+          var compareValue = Ember.compare(propA, propB);
+          if (compareValue) { return compareValue; }
+        }
+        return 0;
+      });
+    },
+
+    /**
+     Returns an array with all of the items in the enumeration where the passed
+     function returns false for. This method is the inverse of filter().
+
+     The callback method you provide should have the following signature (all
+     parameters are optional):
+
+     ```javascript
+     function(item, index, enumerable);
+     ```
+
+     - *item* is the current item in the iteration.
+     - *index* is the current index in the iteration
+     - *enumerable* is the enumerable object itself.
+
+     It should return the a falsey value to include the item in the results.
+
+     Note that in addition to a callback, you can also pass an optional target
+     object that will be set as "this" on the context. This is a good way
+     to give your iterator function access to the current object.
+
+     @method reject
+     @param {Function} callback The callback to execute
+     @param {Object} [target] The target object to use
+     @return {Array} A rejected array.
+     */
+    reject: function(callback, target) {
+      return this.filter(function() {
+        return !(callback.apply(target, arguments));
+      });
+    },
+
+    /**
+     Returns an array with the items that do not have truthy values for
+     key.  You can pass an optional second argument with the target value.  Otherwise
+     this will match any property that evaluates to false.
+
+     @method rejectProperty
+     @param {String} key the property to test
+     @param {String} [value] optional value to test against.
+     @return {Array} rejected array
+     */
+    rejectProperty: function(key, value) {
+      var exactValue = function(item) { return Ember.get(item, key) === value; },
+        hasValue = function(item) { return !!Ember.get(item, key); },
+        use = (arguments.length === 2 ? exactValue : hasValue);
+
+      return this.reject(use);
+    },
+
+    /**
+     Returns a copy of the array without elements with `key` equal to `null` and `undefined`.
+
+     ```javascript
+     var arr = [Ember.Object.create({a: null}), {a: 1}, {a: false}, {a: ''}, {a: undefined}, {a: 0}, {a: null}];
+     arr.compactProperty("a");  // [{a: 1}, {a: false}, {a: ''}, {a: 0}]
+     ```
+
+     @method compactProperty
+     @param {String} key name of the property
+     @return {Array} the array without elements with `key` equal to `null` and `undefined`.
+     */
+    compactProperty: function(key) {
+      return this.filter(function(item) { return !Ember.isNone(Ember.get(item, key)); });
+    }
 
 }) ;