Ver código fonte

AMBARI-15599. Create computed macros `truncate` (onechiporenko)

Oleg Nechiporenko 9 anos atrás
pai
commit
3b6bea5c92

+ 1 - 4
ambari-web/app/controllers/application.js

@@ -36,10 +36,7 @@ App.ApplicationController = Em.Controller.extend(App.UserPref, {
     return (App.router.get('installerController.ambariServerVersion') || App.router.get('mainController.ambariServerVersion') || Em.I18n.t('common.notAvailable'));
   }.property('App.router.installerController.ambariServerVersion', 'App.router.mainController.ambariServerVersion'),
 
-  clusterDisplayName: function () {
-    var name = this.get('clusterName');
-    return name.length > 13 ? name.substr(0, 10) + "..." : name;
-  }.property('clusterName'),
+  clusterDisplayName: Em.computed.truncate('clusterName', 13, 10),
 
   isClusterDataLoaded: Em.computed.and('App.router.clusterController.isLoaded','App.router.loggedIn'),
 

+ 3 - 13
ambari-web/app/models/configs/service_config_version.js

@@ -22,7 +22,6 @@ var dateUtil = require('utils/date/date');
 
 
 App.ServiceConfigVersion = DS.Model.extend({
-  MAX_AUTHOR_LENGTH: 20,
   MAX_NOTES_LENGTH: 80,
   serviceName: DS.attr('string'),
   displayName: Em.computed.formatRole('serviceName', true),
@@ -54,12 +53,7 @@ App.ServiceConfigVersion = DS.Model.extend({
   /**
    * @type {string}
    */
-  authorFormatted: function () {
-    var author = this.get('author');
-    if (author) {
-      return author.length > this.get('MAX_AUTHOR_LENGTH') ? author.slice(0, this.get('MAX_AUTHOR_LENGTH')) + '...' : author;
-    }
-  }.property('author'),
+  authorFormatted: Em.computed.truncate('author', 20, 20),
 
   /**
    * @type {string}
@@ -73,16 +67,12 @@ App.ServiceConfigVersion = DS.Model.extend({
   /**
    * @type {string}
    */
-  briefNotes: function () {
-    return this.get('fullNotes').slice(0, (this.get('MAX_NOTES_LENGTH') + 1));
-  }.property('fullNotes'),
+  briefNotes: Em.computed.truncate('fullNotes', 81, 81, ''),
 
   /**
    * @type {boolean}
    */
-  moreNotesExists: function () {
-    return (typeof this.get('notes') === 'string') && this.get('notes').length > this.get('MAX_NOTES_LENGTH');
-  }.property('notes'),
+  moreNotesExists: Em.computed.notEqualProperties('fullNotes', 'briefNotes'),
 
   /**
    * @type {string}

+ 3 - 12
ambari-web/app/models/host_component.js

@@ -31,20 +31,11 @@ App.HostComponent = DS.Model.extend({
   service: DS.belongsTo('App.Service'),
   adminState: DS.attr('string'),
 
-  serviceDisplayName: function(){
-    var name = this.get('service.displayName');
-    return name.length > 14 ? name.substr(0, 11) + "..." : name;
-  }.property('service'),
+  serviceDisplayName: Em.computed.truncate('service.displayName', 14, 11),
 
-  getDisplayName:function(){
-    var name = this.get('displayName');
-    return name.length > 19 ? name.substr(0, 16) + "..." : name;
-  }.property('displayName'),
+  getDisplayName: Em.computed.truncate('displayName', 19, 16),
 
-  getDisplayNameAdvanced:function(){
-    var name = this.get('displayNameAdvanced');
-    return name.length > 19 ? name.substr(0, 16) + "..." : name;
-  }.property('displayNameAdvanced'),
+  getDisplayNameAdvanced:Em.computed.truncate('displayNameAdvanced', 19, 16),
 
   summaryLabelClassName:function(){
     return 'label_for_'+this.get('componentName').toLowerCase();

+ 34 - 0
ambari-web/app/utils/ember_computed.js

@@ -1133,4 +1133,38 @@ computed.getByKey = function (objectKey, propertyKey, defaultValue) {
     }
     return object.hasOwnProperty(property) ? object[property] : defaultValue;
   });
+}
+
+/**
+ * A computed property that returns dependent value truncated to the `reduceTo`-size if its length is greater than `maxLength`
+ * Truncated part may be replaced with `replacer` if it's provided ('...' by default)
+ * <pre>
+ *   var o = Em.Object.create({
+ *     p1: Em.computed.truncate('p2', 8, 5, '###'),
+ *     p2: 'some string',
+ *     p3: Em.computed.truncate('p2', 8, 5)
+ *   });
+ *   console.log(o.get('p1')); // 'some ###'
+ *   console.log(o.get('p3')); // 'some ...'
+ *   o.set('p2', '123456789');
+ *   console.log(o.get('p1')); // '12345###'
+ *   console.log(o.get('p3')); // '12345...'
+ * </pre>
+ *
+ * @param {string} dependentKey
+ * @param {number} maxLength
+ * @param {number} reduceTo
+ * @param {string} [replacer] default - '...'
+ * @returns {Ember.ComputedProperty}
+ */
+computed.truncate = function (dependentKey, maxLength, reduceTo, replacer) {
+  Em.assert('`reduceTo` should be <=`maxLength`', reduceTo <= maxLength);
+  var _replacer = arguments.length > 3 ? replacer : '...';
+  return computed(dependentKey, function () {
+    var value = smartGet(this, dependentKey) || '';
+    if (value.length > maxLength) {
+      return value.substr(0, reduceTo) + _replacer;
+    }
+    return value;
+  });
 }

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

@@ -653,9 +653,7 @@ App.HostPopup = Em.Object.create({
       var hostInfo = Em.Object.create({
         name: hostName,
         publicName: _host.publicName,
-        displayName: function () {
-          return this.get('name').length < 43 ? this.get('name') : this.get('name').substr(0, 40) + '...';
-        }.property('name'),
+        displayName: Em.computed.truncate('name', 43, 40),
         progress: 0,
         status: App.format.taskStatus("PENDING"),
         serviceName: _host.serviceName,

+ 1 - 7
ambari-web/app/views/common/configs/config_history_flow.js

@@ -79,13 +79,7 @@ App.ConfigHistoryFlowView = Em.View.extend({
   /**
    * formatted notes ready to display
    */
-  shortNotes: function () {
-    //100 is number of symbols that fit into label
-    if (this.get('showMoreLink')) {
-      return this.get('displayedServiceVersion.notes').slice(0, 100) + '...';
-    }
-    return this.get('displayedServiceVersion.notes');
-  }.property('displayedServiceVersion'),
+  shortNotes: Em.computed.truncate('displayedServiceVersion.notes', 100, 100),
 
   serviceVersions: function () {
     var groupName = this.get('controller.selectedConfigGroup.isDefault') ? 'default'

+ 103 - 0
ambari-web/test/aliases/computed/truncate.js

@@ -0,0 +1,103 @@
+/**
+ * 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 helpers = App.TestAliases.helpers;
+
+var strTemplate = '0123456789';
+
+/**
+ * 10 -> '0123456789'
+ *  5 -> '01234'
+ * 15 -> '012345678901234'
+ *
+ * @param length
+ * @returns {string}
+ */
+function getStr(length) {
+  var ret = '';
+  var n = Math.floor(length / 10);
+  var m = length % 10;
+  for (var i = 0; i < n; i++) {
+    ret += strTemplate;
+  }
+  ret += strTemplate.substr(0, m);
+  return ret;
+}
+
+/**
+ *
+ * @param {Em.Object} context
+ * @param {string} propertyName
+ * @param {string} dependentKey
+ * @param {number} maxLength
+ * @param {number} reduceTo
+ * @param {string} [replacer]
+ */
+App.TestAliases.testAsComputedTruncate = function (context, propertyName, dependentKey, maxLength, reduceTo, replacer) {
+
+  var _replacer = arguments.length > 5 ? replacer : '...';
+
+  describe('#' + propertyName + ' as Em.computed.truncate', function () {
+
+    afterEach(function () {
+      helpers.smartRestoreGet(context);
+    });
+
+    it('has valid dependent keys', function () {
+      expect(Em.meta(context).descs[propertyName]._dependentKeys).to.eql([dependentKey]);
+    });
+
+    it('should be truncated if `maxLength` > ' + JSON.stringify(dependentKey) + ' length', function () {
+      var val = getStr(maxLength + 1);
+      var expectedValue = val.substr(0, reduceTo) + _replacer;
+      helpers.smartStubGet(context, dependentKey, val)
+        .propertyDidChange(context, propertyName);
+      var value = helpers.smartGet(context, propertyName);
+      expect(value).to.be.equal(expectedValue);
+    });
+
+    it('should not be truncated if `maxLength` = ' + JSON.stringify(dependentKey) + ' length', function () {
+      var val = getStr(maxLength);
+      var expectedValue = val;
+      helpers.smartStubGet(context, dependentKey, val)
+        .propertyDidChange(context, propertyName);
+      var value = helpers.smartGet(context, propertyName);
+      expect(value).to.be.equal(expectedValue);
+    });
+
+    it('should not be truncated if `maxLength` < ' + JSON.stringify(dependentKey) + ' length', function () {
+      var val = getStr(maxLength - 1);
+      var expectedValue = val;
+      helpers.smartStubGet(context, dependentKey, val)
+        .propertyDidChange(context, propertyName);
+      var value = helpers.smartGet(context, propertyName);
+      expect(value).to.be.equal(expectedValue);
+    });
+
+    it('should be "" if ' + JSON.stringify(dependentKey) + ' value is empty', function () {
+      var val = null;
+      var expectedValue = '';
+      helpers.smartStubGet(context, dependentKey, val)
+        .propertyDidChange(context, propertyName);
+      var value = helpers.smartGet(context, propertyName);
+      expect(value).to.be.equal(expectedValue);
+    });
+
+  });
+
+};

+ 2 - 0
ambari-web/test/controllers/application_test.js

@@ -29,6 +29,8 @@ describe('App.ApplicationController', function () {
 
   var applicationController = getController();
 
+  App.TestAliases.testAsComputedTruncate(getController(), 'clusterDisplayName', 'clusterName', 13, 10);
+
   App.TestAliases.testAsComputedAnd(getController(), 'isClusterDataLoaded', ['App.router.clusterController.isLoaded','App.router.loggedIn']);
 
   App.TestAliases.testAsComputedAnd(getController(), 'isExistingClusterDataLoaded', ['App.router.clusterInstallCompleted','isClusterDataLoaded']);

+ 1 - 1
ambari-web/test/controllers/main/host_test.js

@@ -114,7 +114,7 @@ describe('MainHostController', function () {
         return db[k];
       });
       sinon.stub(App.db, 'setSortingStatuses', function (k, v) {
-        db[k] = Em.typeOf(v) === 'array' ? v : [v];
+        db[k] = Em.makeArray(v);
       });
     });
 

+ 3 - 3
ambari-web/test/helpers.js

@@ -37,7 +37,7 @@ module.exports = {
   nestedExpect: function (expected, actual) {
     expected.forEach(function (group, i) {
       Em.keys(group).forEach(function (key) {
-        if ('array' === Em.typeOf(actual[i][key])) {
+        if (Em.isArray(actual[i][key])) {
           expect(group[key]).to.eql(actual[i][key].toArray());
         }
         else {
@@ -74,7 +74,7 @@ module.exports = {
    * @returns {array|null}
    */
   findAjaxRequest: function(property, value) {
-    if (Em.typeOf(App.ajax.send.args) !== 'array') {
+    if (!Em.isArray(App.ajax.send.args)) {
       return null;
     }
     return App.ajax.send.args.find(function (request) {
@@ -116,7 +116,7 @@ module.exports = {
    * @returns {array}
    */
   filterAjaxRequests: function (property, value) {
-    if (Em.typeOf(App.ajax.send.args) !== 'array') {
+    if (!Em.isArray(App.ajax.send.args)) {
       return [];
     }
     return App.ajax.send.args.filter(function (request) {

+ 2 - 1
ambari-web/test/init_computed_aliases.js

@@ -194,4 +194,5 @@ require('test/aliases/computed/sumBy');
 require('test/aliases/computed/and');
 require('test/aliases/computed/or');
 require('test/aliases/computed/formatUnavailable');
-require('test/aliases/computed/getByKey');
+require('test/aliases/computed/getByKey');
+require('test/aliases/computed/truncate');

+ 3 - 60
ambari-web/test/models/configs/service_config_version_test.js

@@ -33,29 +33,11 @@ describe('App.ServiceConfigVersion', function () {
 
   App.TestAliases.testAsComputedAnd(getModel(), 'canBeMadeCurrent', ['isCompatible', '!isCurrent']);
 
-  describe('#authorFormatted', function () {
+  App.TestAliases.testAsComputedTruncate(getModel(), 'authorFormatted', 'author', 20, 20);
 
-    var cases = [
-      {
-        author: 'admin',
-        authorFormatted: 'admin',
-        title: 'should display username as is'
-      },
-      {
-        author: 'userNameIsTooLongToDisplay',
-        authorFormatted: 'userNameIsTooLongToD...',
-        title: 'should trim username to 20 chars'
-      }
-    ];
-
-    cases.forEach(function (item) {
-      it(item.title, function () {
-        model.set('author', item.author);
-        expect(model.get('authorFormatted')).to.equal(item.authorFormatted);
-      });
-    });
+  App.TestAliases.testAsComputedTruncate(getModel(), 'briefNotes', 'fullNotes', 81, 81, '');
 
-  });
+  App.TestAliases.testAsComputedNotEqualProperties(getModel(), 'moreNotesExists', 'fullNotes', 'briefNotes');
 
   describe("#configGroupName", function() {
 
@@ -95,45 +77,6 @@ describe('App.ServiceConfigVersion', function () {
 
   });
 
-  describe("#briefNotes", function() {
-
-    it("notes shorter than MAX_NOTES_LENGTH", function() {
-      model.reopen({
-        fullNotes: 'short-notes'
-      });
-      expect(model.get('briefNotes')).to.equal('short-notes');
-    });
-
-    it("notes longer than MAX_NOTES_LENGTH", function() {
-      model.reopen({
-        fullNotes: 'long-notes-long-notes-long-notes-long-notes-long-notes-long-notes-long-notes-long-notes' +
-        '-long-notes-long-notes-long-notes-long-notes-long-notes'
-      });
-      expect(model.get('briefNotes')).to.equal('long-notes-long-notes-long-notes-long-notes-long-notes-long-notes-long-notes-long');
-    });
-
-  });
-
-  describe("#moreNotesExists", function() {
-
-    it("notes is null", function() {
-      model.set('notes', null);
-      expect(model.get('moreNotesExists')).to.be.false;
-    });
-
-    it("notes is shorter than MAX_NOTES_LENGTH", function() {
-      model.set('notes', 'short-notes');
-      expect(model.get('moreNotesExists')).to.be.false;
-    });
-
-    it("notes is longer than MAX_NOTES_LENGTH", function() {
-      model.set('notes', 'long-notes-long-notes-long-notes-long-notes-long-notes-long-notes-long-notes-long-notes' +
-      '-long-notes-long-notes-long-notes-long-notes-long-notes');
-      expect(model.get('moreNotesExists')).to.be.true;
-    });
-
-  });
-
   describe("#createdDate", function() {
 
     it("should return created date", function() {

+ 4 - 0
ambari-web/test/models/host_component_test.js

@@ -331,6 +331,10 @@ describe('App.HostComponent', function() {
   });
 
 
+  App.TestAliases.testAsComputedTruncate(hc, 'serviceDisplayName', 'service.displayName', 14, 11);
+  App.TestAliases.testAsComputedTruncate(hc, 'getDisplayName', 'displayName', 19, 16);
+  App.TestAliases.testAsComputedTruncate(hc, 'getDisplayNameAdvanced', 'displayNameAdvanced', 19, 16);
+
   describe("#serviceDisplayName",function(){
     var testCases = [
       {

+ 73 - 0
ambari-web/test/utils/ember_computed_test.js

@@ -1534,4 +1534,77 @@ describe('Ember.computed macros', function () {
 
   });
 
+  describe('#truncate', function () {
+
+    beforeEach(function () {
+      this.obj = Em.Object.create({
+        prop1: '123456789',
+        prop2: Em.computed.truncate('prop1', 8, 5),
+        prop3: Em.computed.truncate('App.someRandomTestingKey', 8, 5),
+        prop4: Em.computed.truncate('prop1', 8, 5, '###')
+      });
+      App.set('someAnotherKey', 'abcdefghi');
+    });
+
+    it('prop2 dependent keys are valid', function () {
+      expect(Em.meta(this.obj).descs.prop2._dependentKeys).to.be.eql(['prop1']);
+    });
+
+    it('prop3 dependent keys are valid', function () {
+      expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.be.eql(['App.someRandomTestingKey']);
+    });
+
+    it('prop4 dependent keys are valid', function () {
+      expect(Em.meta(this.obj).descs.prop4._dependentKeys).to.be.eql(['prop1']);
+    });
+
+    it('prop2 value is 12345...', function () {
+      expect(this.obj.get('prop2')).to.be.equal('12345...');
+    });
+
+    it('prop2 value is 54321...', function () {
+      this.obj.set('prop1', '543216789');
+      expect(this.obj.get('prop2')).to.be.equal('54321...');
+    });
+
+    it('prop2 value is 1234', function () {
+      this.obj.set('prop1', '1234');
+      expect(this.obj.get('prop2')).to.be.equal('1234');
+    });
+
+    it('prop2 value is ""', function () {
+      this.obj.set('prop1', null);
+      expect(this.obj.get('prop2')).to.be.equal('');
+    });
+
+    it('prop3 value is abcde...', function () {
+      expect(this.obj.get('prop3')).to.be.equal('abcde...');
+    });
+
+    it('prop3 value is edcba...', function () {
+      App.set('someAnotherKey', 'edcbafghi');
+      expect(this.obj.get('prop3')).to.be.equal('edcba...');
+    });
+
+    it('prop3 value is abcd', function () {
+      App.set('someAnotherKey', 'abcd');
+      expect(this.obj.get('prop3')).to.be.equal('abcd');
+    });
+
+    it('prop4 value is 12345###', function () {
+      expect(this.obj.get('prop4')).to.be.equal('12345###');
+    });
+
+    it('prop4 value is 54321###', function () {
+      this.obj.set('prop1', '543216789');
+      expect(this.obj.get('prop4')).to.be.equal('54321###');
+    });
+
+    it('prop4 value is 12345', function () {
+      this.obj.set('prop1', '12345');
+      expect(this.obj.get('prop4')).to.be.equal('12345');
+    });
+
+  });
+
 });

+ 3 - 83
ambari-web/test/views/common/configs/config_history_flow_test.js

@@ -33,91 +33,11 @@ describe.skip('App.ConfigHistoryFlowView', function () {
 
   App.TestAliases.testAsComputedAlias(view, 'serviceName', 'controller.selectedService.serviceName', 'string');
 
-  describe('#isSaveDisabled', function () {
-    var testCases = [
-      {
-        params: {
-          isSubmitDisabled: false,
-          versionLoaded: true
-        },
-        result: false
-      },
-      {
-        params: {
-          isSubmitDisabled: true,
-          versionLoaded: true
-        },
-        result: true
-      },
-      {
-        params: {
-          isSubmitDisabled: false,
-          versionLoaded: false
-        },
-        result: true
-      },
-      {
-        params: {
-          isSubmitDisabled: true,
-          versionLoaded: false
-        },
-        result: true
-      }
-    ];
-    testCases.forEach(function (test) {
-      it('isSubmitDisabled - ' + test.params.isSubmitDisabled + ', versionLoaded - ' + test.params.versionLoaded, function () {
-        view.set('controller.isSubmitDisabled', test.params.isSubmitDisabled);
-        view.set('controller.versionLoaded', test.params.versionLoaded);
-        expect(view.get('isSaveDisabled')).to.equal(test.result);
-      });
-    });
-  });
+  App.TestAliases.testAsComputedOr(view, 'isSaveDisabled', ['controller.isSubmitDisabled', '!controller.versionLoaded', '!controller.isPropertiesChanged']);
 
-  describe('#showMoreLink', function () {
-    var testCases = [
-      {
-        params: {
-          count: 0
-        },
-        result: false
-      },
-      {
-        params: {
-          count: 100
-        },
-        result: false
-      },
-      {
-        params: {
-          count: 101
-        },
-        result: true
-      }
-    ];
-    testCases.forEach(function (test) {
-      it('notes length - ' + test.params.count, function () {
-        view.set('displayedServiceVersion', Em.Object.create({
-          notes: new Array(test.params.count)
-        }));
-        expect(view.get('showMoreLink')).to.equal(test.result);
-      });
-    });
-  });
+  App.TestAliases.testAsComputedGt(view, 'displayedServiceVersion.notes.length', 100);
 
-  describe('#shortNotes', function () {
-    it('notes length more than 100', function () {
-      view.set('displayedServiceVersion', Em.Object.create({
-        notes: '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123'
-      }));
-      expect(view.get('shortNotes')).to.equal('1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890...');
-    });
-    it('notes length less than 100', function () {
-      view.set('displayedServiceVersion', Em.Object.create({
-        notes: 'notes'
-      }));
-      expect(view.get('shortNotes')).to.equal('notes');
-    });
-  });
+  App.TestAliases.testAsComputedTruncate(view, 'shortNotes', 'displayedServiceVersion.notes', 100, 100);
 
   describe('#visibleServiceVersion', function () {
     var testCases = [

+ 6 - 5
ambari-web/test/views/main/service/services/flume_test.js

@@ -33,7 +33,7 @@ describe('App.MainDashboardServiceFlumeView', function () {
   describe("#content", function() {
 
     it("should return content", function() {
-      view.set('service.agents',  [
+      view.set('service.agents', [
         {hostName: 'host1'},
         {hostName: 'host2'},
         {hostName: 'host2'}
@@ -141,10 +141,11 @@ describe('App.MainDashboardServiceFlumeView', function () {
         ]
       });
       view.setActionsDropdownClasses();
-      expect(view.get('content')[0].get('agents')[0].get('isStartAgentDisabled')).to.be.true;
-      expect(view.get('content')[0].get('agents')[0].get('isStopAgentDisabled')).to.be.false;
-      expect(view.get('content')[0].get('agents')[1].get('isStartAgentDisabled')).to.be.false;
-      expect(view.get('content')[0].get('agents')[1].get('isStopAgentDisabled')).to.be.true;
+      var agents = view.get('content.0.agents');
+      expect(agents[0].get('isStartAgentDisabled')).to.be.true;
+      expect(agents[0].get('isStopAgentDisabled')).to.be.false;
+      expect(agents[1].get('isStartAgentDisabled')).to.be.false;
+      expect(agents[1].get('isStopAgentDisabled')).to.be.true;
     });
   });
 

+ 0 - 1
ambari-web/test/views/main/service/services/hdfs_test.js

@@ -18,7 +18,6 @@
 
 var App = require('app');
 var date = require('utils/date/date');
-var numberUtils = require('utils/number_utils');
 require('/views/main/service/services/hdfs');
 
 function getView(options) {