You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2015/03/26 20:22:51 UTC

[2/2] ambari git commit: AMBARI-10219. Ambari should very explicitly show in a globally visible area when config form validation errors occurred (alexantonenko)

AMBARI-10219. Ambari should very explicitly show in a globally visible area when config form validation errors occurred (alexantonenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/08833fe2
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/08833fe2
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/08833fe2

Branch: refs/heads/trunk
Commit: 08833fe285fc60cf3f87becb6913bc61130ba16c
Parents: cc69a00
Author: Alex Antonenko <hi...@gmail.com>
Authored: Thu Mar 26 17:58:35 2015 +0200
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Thu Mar 26 21:22:46 2015 +0200

----------------------------------------------------------------------
 .../app/controllers/wizard/step7_controller.js  | 21 ++++-
 ambari-web/app/messages.js                      |  3 +
 ambari-web/app/models/service_config.js         | 45 ++++++---
 ambari-web/app/styles/application.less          |  9 ++
 .../common/configs/service_config_category.hbs  |  7 +-
 .../common/configs/services_config.hbs          |  5 +-
 .../test/controllers/wizard/step7_test.js       | 97 +++++++++++++++++++-
 ambari-web/test/models/service_config_test.js   | 23 ++++-
 8 files changed, 187 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/app/controllers/wizard/step7_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js
index 009f60f..d466c51 100644
--- a/ambari-web/app/controllers/wizard/step7_controller.js
+++ b/ambari-web/app/controllers/wizard/step7_controller.js
@@ -224,6 +224,20 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
     }
   ],
 
+  issuesFilterText: function () {
+    return (this.get('isSubmitDisabled') && !this.get('submitButtonClicked') &&
+      this.get('filterColumns').findProperty('attributeName', 'isValid').get('selected')) ?
+        Em.I18n.t('installer.step7.showingPropertiesWithIssues') : '';
+  }.property('isSubmitDisabled', 'submitButtonClicked', 'filterColumns.@each.selected'),
+
+  issuesFilterLinkText: function () {
+    return (this.get('isSubmitDisabled') && !this.get('submitButtonClicked')) ?
+      (
+        this.get('filterColumns').findProperty('attributeName', 'isValid').get('selected') ?
+          Em.I18n.t('installer.step7.showAllProperties') : Em.I18n.t('installer.step7.showPropertiesWithIssues')
+      ) : '';
+  }.property('isSubmitDisabled', 'submitButtonClicked', 'filterColumns.@each.selected'),
+
   /**
    * Dropdown menu items in filter combobox
    */
@@ -510,7 +524,6 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
         break;
       case 'YARN':
         this.resolveYarnConfigs(configs);
-      default:
         break;
     }
   },
@@ -665,7 +678,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
       serviceConfigs.setEach('selected', false);
       this.get('selectedServiceNames').forEach(function (serviceName) {
         if (!serviceConfigs.findProperty('serviceName', serviceName)) return;
-        var selectedService = serviceConfigs.findProperty('serviceName', serviceName).set('selected', true);
+        serviceConfigs.findProperty('serviceName', serviceName).set('selected', true);
       }, this);
       this.get('installedServiceNames').forEach(function (serviceName) {
         var serviceConfigObj = serviceConfigs.findProperty('serviceName', serviceName);
@@ -1262,6 +1275,10 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, {
         });
       }
     });
+  },
+
+  toggleIssuesFilter: function () {
+    this.get('filterColumns').findProperty('attributeName', 'isValid').toggleProperty('selected');
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 34aa562..50d62f0 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -713,6 +713,9 @@ Em.I18n.translations = {
   'installer.step7.header':'Customize Services',
   'installer.step7.body':'We have come up with recommended configurations for the services you selected. Customize them as you see fit.',
   'installer.step7.attentionNeeded':'<b>Attention:</b> Some configurations need your attention before you can proceed.',
+  'installer.step7.showPropertiesWithIssues':'Show me properties with issues',
+  'installer.step7.showingPropertiesWithIssues':'Showing properties with issues.',
+  'installer.step7.showAllProperties':'Show all properties',
   'installer.step7.config.addProperty':'Add Property',
   'installer.step7.ConfigErrMsg.header':'Custom configuration error: ',
   'installer.step7.ConfigErrMsg.message':'Error in custom configuration. Some properties entered in the box are already exposed on this page',

http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/app/models/service_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/service_config.js b/ambari-web/app/models/service_config.js
index 9cbf09d..8f4889f 100644
--- a/ambari-web/app/models/service_config.js
+++ b/ambari-web/app/models/service_config.js
@@ -29,22 +29,32 @@ App.ServiceConfig = Ember.Object.extend({
   configGroups: [],
   initConfigsLength: 0, // configs length after initialization in order to watch changes
   errorCount: function () {
-    var overrideErrors = 0;
-    this.get('configs').filterProperty("overrides").forEach(function (e) {
-      e.overrides.forEach(function (e) {
-        if (e.error) {
-          overrideErrors += 1;
-        }
-      })
-    });
-    var categoryNames = this.get('configCategories').mapProperty('name');
-    var masterErrors = this.get('configs').filter(function (item) {
-      return categoryNames.contains(item.get('category'));
-    }).filterProperty('isValid', false).filterProperty('isVisible', true).get('length');
-    var slaveErrors = 0;
-    this.get('configCategories').forEach(function (_category) {
+    var overrideErrors = 0,
+      masterErrors = 0,
+      slaveErrors = 0,
+      configs = this.get('configs'),
+      configCategories = this.get('configCategories');
+    configCategories.forEach(function (_category) {
       slaveErrors += _category.get('slaveErrorCount');
-    }, this);
+      _category.set('nonSlaveErrorCount', 0);
+    });
+    configs.forEach(function (item) {
+      var category = configCategories.findProperty('name', item.get('category'));
+      if (category && !item.get('isValid') && item.get('isVisible')) {
+        category.incrementProperty('nonSlaveErrorCount');
+        masterErrors++;
+      }
+      if (item.get('overrides')) {
+        item.get('overrides').forEach(function (e) {
+          if (e.error) {
+            if (category) {
+              category.incrementProperty('nonSlaveErrorCount');
+            }
+            overrideErrors++;
+          }
+        });
+      }
+    });
     return masterErrors + slaveErrors + overrideErrors;
   }.property('configs.@each.isValid', 'configs.@each.isVisible', 'configCategories.@each.slaveErrorCount', 'configs.@each.overrideErrorTrigger'),
 
@@ -78,6 +88,7 @@ App.ServiceConfigCategory = Ember.Object.extend({
    * Can this category add new properties. Used for custom configurations.
    */
   canAddProperty: false,
+  nonSlaveErrorCount: 0,
   primaryName: function () {
     switch (this.get('name')) {
       case 'DataNode':
@@ -115,6 +126,10 @@ App.ServiceConfigCategory = Ember.Object.extend({
     return length;
   }.property('slaveConfigs.groups.@each.errorCount'),
 
+  errorCount: function () {
+    return this.get('slaveErrorCount') + this.get('nonSlaveErrorCount');
+  }.property('slaveErrorCount', 'nonSlaveErrorCount'),
+
   isAdvanced : function(){
     var name = this.get('name');
     return name.indexOf("Advanced") !== -1 ;

http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index 8b05711..3026fec 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -1044,6 +1044,9 @@ h1 {
     .icon-refresh{
       margin-left:10px;
     }
+    .icon-warning-sign {
+      color: @health-status-yellow;
+    }
   }
   .collapsable {
     cursor: pointer;
@@ -1206,6 +1209,12 @@ h1 {
       box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
       cursor: not-allowed;
     }
+    a.accordion-toggle:hover {
+      text-decoration: none;
+      .category-name {
+        text-decoration: underline;
+      }
+    }
   }
   .capacity-scheduler {
     .header {

http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/app/templates/common/configs/service_config_category.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/service_config_category.hbs b/ambari-web/app/templates/common/configs/service_config_category.hbs
index cf37b47..0ab60c2 100644
--- a/ambari-web/app/templates/common/configs/service_config_category.hbs
+++ b/ambari-web/app/templates/common/configs/service_config_category.hbs
@@ -18,7 +18,12 @@
 
 <div class="accordion-heading" {{action "onToggleBlock" category target="view"}}>
   <i {{bindAttr class=":pull-left :accordion-toggle view.category.isCollapsed:icon-caret-right:icon-caret-down"}}></i>
-  <a class="accordion-toggle">{{view.category.displayName}}</a>
+  <a class="accordion-toggle">
+    <span class="category-name">{{view.category.displayName}}</span>
+    {{#if view.category.errorCount}}
+      <span class="badge badge-important">{{view.category.errorCount}}</span>
+    {{/if}}
+  </a>
 </div>
 
 <div class="accordion-body collapse in" {{bindAttr style="view.isCategoryBodyVisible"}}>

http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/app/templates/common/configs/services_config.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/services_config.hbs b/ambari-web/app/templates/common/configs/services_config.hbs
index a0cd1d1..0076c11 100644
--- a/ambari-web/app/templates/common/configs/services_config.hbs
+++ b/ambari-web/app/templates/common/configs/services_config.hbs
@@ -36,7 +36,10 @@
     <p class="loading align-center"></p>
     {{#if isSubmitDisabled}}
       {{#unless submitButtonClicked}}
-        <div class="alert">{{t installer.step7.attentionNeeded}}</div>
+        <div class="alert">
+          <span class="icon-warning-sign"></span> {{t installer.step7.attentionNeeded}}<br />
+          {{issuesFilterText}} <a href="#" {{action toggleIssuesFilter target="controller"}}>{{issuesFilterLinkText}}</a>
+        </div>
       {{/unless}}
     {{/if}}
 {{/if}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/test/controllers/wizard/step7_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step7_test.js b/ambari-web/test/controllers/wizard/step7_test.js
index 2e753c7..eade984 100644
--- a/ambari-web/test/controllers/wizard/step7_test.js
+++ b/ambari-web/test/controllers/wizard/step7_test.js
@@ -22,7 +22,64 @@ require('mixins/common/localStorage');
 require('models/config_group');
 require('controllers/wizard/step7_controller');
 
-var installerStep7Controller;
+var installerStep7Controller,
+  issuesFilterCases = [
+    {
+      isSubmitDisabled: true,
+      submitButtonClicked: true,
+      isIssuesFilterActive: true,
+      issuesFilterText: '',
+      issuesFilterLinkText: '',
+      title: 'issues filter on, submit button clicked'
+    },
+    {
+      isSubmitDisabled: true,
+      submitButtonClicked: false,
+      isIssuesFilterActive: true,
+      issuesFilterText: Em.I18n.t('installer.step7.showingPropertiesWithIssues'),
+      issuesFilterLinkText: Em.I18n.t('installer.step7.showAllProperties'),
+      title: 'issues filter on, submit button disabled'
+    },
+    {
+      isSubmitDisabled: true,
+      submitButtonClicked: true,
+      isIssuesFilterActive: false,
+      issuesFilterText: '',
+      issuesFilterLinkText: '',
+      title: 'issues filter off, submit button clicked'
+    },
+    {
+      isSubmitDisabled: true,
+      submitButtonClicked: false,
+      isIssuesFilterActive: false,
+      issuesFilterText: '',
+      issuesFilterLinkText: Em.I18n.t('installer.step7.showPropertiesWithIssues'),
+      title: 'issues filter off, submit button disabled'
+    },
+    {
+      isSubmitDisabled: false,
+      submitButtonClicked: false,
+      isIssuesFilterActive: true,
+      issuesFilterText: '',
+      issuesFilterLinkText: '',
+      title: 'issues filter on, submit button enabled'
+    },
+    {
+      isSubmitDisabled: false,
+      submitButtonClicked: false,
+      isIssuesFilterActive: false,
+      issuesFilterText: '',
+      issuesFilterLinkText: '',
+      title: 'issues filter off, submit button enabled'
+    }
+  ],
+  issuesFilterTestSetup = function (controller, testCase) {
+    controller.set('submitButtonClicked', testCase.submitButtonClicked);
+    controller.reopen({
+      isSubmitDisabled: testCase.isSubmitDisabled
+    });
+    controller.get('filterColumns').findProperty('attributeName', 'isValid').set('selected', testCase.isIssuesFilterActive);
+  };
 
 describe('App.InstallerStep7Controller', function () {
 
@@ -468,9 +525,10 @@ describe('App.InstallerStep7Controller', function () {
       installerStep7Controller.resolveStormConfigs.restore();
       installerStep7Controller.resolveYarnConfigs.restore();
     });
-    var serviceNames = [
+    [
       {serviceName: 'STORM', method: "resolveStormConfigs"},
-      {serviceName: 'YARN', method: "resolveYarnConfigs"}].forEach(function(t) {
+      {serviceName: 'YARN', method: "resolveYarnConfigs"}
+    ].forEach(function(t) {
       it("should call " + t.method + " if serviceName is " + t.serviceName, function () {
         var configs = [
           {},
@@ -1457,4 +1515,37 @@ describe('App.InstallerStep7Controller', function () {
 
   });
 
+  describe('#issuesFilterText', function () {
+
+    issuesFilterCases.forEach(function (item) {
+      it(item.title, function () {
+        issuesFilterTestSetup(installerStep7Controller, item);
+        expect(installerStep7Controller.get('issuesFilterText')).to.equal(item.issuesFilterText);
+      })
+    });
+
+  });
+
+  describe('#issuesFilterLinkText', function () {
+
+    issuesFilterCases.forEach(function (item) {
+      it(item.title, function () {
+        issuesFilterTestSetup(installerStep7Controller, item);
+        expect(installerStep7Controller.get('issuesFilterLinkText')).to.equal(item.issuesFilterLinkText);
+      })
+    });
+
+  });
+
+  describe('#toggleIssuesFilter', function () {
+    it('should toggle issues filter', function () {
+      var issuesFilter = installerStep7Controller.get('filterColumns').findProperty('attributeName', 'isValid');
+      issuesFilter.set('selected', false);
+      installerStep7Controller.toggleIssuesFilter();
+      expect(issuesFilter.get('selected')).to.be.true;
+      installerStep7Controller.toggleIssuesFilter();
+      expect(issuesFilter.get('selected')).to.be.false;
+    });
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/08833fe2/ambari-web/test/models/service_config_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/service_config_test.js b/ambari-web/test/models/service_config_test.js
index bba0f31..f381ab8 100644
--- a/ambari-web/test/models/service_config_test.js
+++ b/ambari-web/test/models/service_config_test.js
@@ -27,6 +27,7 @@ var serviceConfig,
   serviceConfigPropertyInit,
   configsData = [
     Ember.Object.create({
+      category: 'c0',
       overrides: [
         {
           error: true,
@@ -39,23 +40,28 @@ var serviceConfig,
       ]
     }),
     Ember.Object.create({
+      category: 'c1',
       isValid: false,
       isVisible: true
     }),
-      Ember.Object.create({
+    Ember.Object.create({
+      category: 'c0',
       isValid: true,
       isVisible: true
     }),
     Ember.Object.create({
+      category: 'c1',
       isValid: false,
       isVisible: false
     })
   ],
   configCategoriesData = [
     Em.Object.create({
+      name: 'c0',
       slaveErrorCount: 1
     }),
     Em.Object.create({
+      name: 'c1',
       slaveErrorCount: 2
     })
   ],
@@ -365,6 +371,8 @@ describe('App.ServiceConfig', function () {
         configCategories: configCategoriesData
       });
       expect(serviceConfig.get('errorCount')).to.equal(6);
+      expect(serviceConfig.get('configCategories').findProperty('name', 'c0').get('nonSlaveErrorCount')).to.equal(2);
+      expect(serviceConfig.get('configCategories').findProperty('name', 'c1').get('nonSlaveErrorCount')).to.equal(1);
     });
   });
 
@@ -422,6 +430,19 @@ describe('App.ServiceConfigCategory', function () {
     });
   });
 
+  describe('#errorCount', function () {
+    it('should sum all errors for category', function () {
+      serviceConfigCategory.reopen({
+        slaveErrorCount: 1
+      });
+      expect(serviceConfigCategory.get('errorCount')).to.equal(1);
+      serviceConfigCategory.set('nonSlaveErrorCount', 2);
+      expect(serviceConfigCategory.get('errorCount')).to.equal(3);
+      serviceConfigCategory.set('slaveErrorCount', 0);
+      expect(serviceConfigCategory.get('errorCount')).to.equal(2);
+    });
+  });
+
   describe('#isAdvanced', function () {
     it('should be true', function () {
       serviceConfigCategory.set('name', 'Advanced');