Quellcode durchsuchen

AMBARI-10624. Not apparent where the error is in Customize Services page (onechiporenko)

Oleg Nechiporenko vor 10 Jahren
Ursprung
Commit
c97446c586

+ 2 - 0
ambari-web/app/assets/test/tests.js

@@ -286,6 +286,8 @@ var files = ['test/init_model_test',
   'test/models/user_test',
   'test/models/host_stack_version_test',
   'test/models/upgrade_entity_test',
+  'test/models/configs/sub_section_test',
+  'test/models/configs/section_test',
   'test/models/configs/service_config_version_test',
   'test/models/configs/config_property_test',
   'test/routes/views_test',

+ 10 - 0
ambari-web/app/controllers/main/service/info/configs.js

@@ -172,6 +172,16 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM
    */
   loadedClusterSiteToTagMap: {},
 
+  /**
+   * Number of errors in the configs in the selected service
+   * @type {number}
+   */
+  errorsCount: function () {
+    return this.get('selectedService.configs').filter(function (config) {
+      return Em.isNone(config.get('widget'));
+    }).filterProperty('isValid', false).length;
+  }.property('selectedService.configs.@each.isValid'),
+
   /**
    * Determines if Save-button should be disabled
    * Disabled if some configs have invalid values or save-process currently in progress

+ 10 - 0
ambari-web/app/controllers/wizard/step7_controller.js

@@ -132,6 +132,16 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E
     return (this.get('isAdvancedConfigLoaded') && this.get('isAppliedConfigLoaded'));
   }.property('isAdvancedConfigLoaded', 'isAppliedConfigLoaded'),
 
+  /**
+   * Number of errors in the configs in the selected service
+   * @type {number}
+   */
+  errorsCount: function () {
+    return this.get('selectedService.configs').filter(function (config) {
+      return Em.isNone(config.get('widget'));
+    }).filterProperty('isValid', false).length;
+  }.property('selectedService.configs.@each.isValid'),
+
   /**
    * Should Next-button be disabled
    * @type {bool}

+ 10 - 0
ambari-web/app/models/configs/section.js

@@ -30,6 +30,16 @@ App.Section = DS.Model.extend({
   sectionRows: DS.attr('number', {defaultValue: 1}),
   subSections: DS.hasMany('App.SubSection'),
   tab: DS.belongsTo('App.Tab'),
+
+  /**
+   * Number of the errors in all subsections in the current section
+   * @type {number}
+   */
+  errorsCount: function () {
+    var errors = this.get('subSections').mapProperty('errorsCount');
+    return errors.length ? errors.reduce(Em.sum) : 0;
+  }.property('subSections.@each.errorsCount'),
+
   isFirstRow: function () {
     return this.get('rowIndex') == 0;
   }.property(),

+ 10 - 0
ambari-web/app/models/configs/sub_section.js

@@ -29,6 +29,16 @@ App.SubSection = DS.Model.extend({
   columnSpan: DS.attr('number', {defaultValue: 1}),
   section: DS.belongsTo('App.Section'),
   configProperties: DS.hasMany('App.StackConfigProperty'),
+  configs: [],
+
+  /**
+   * Number of the errors in all configs
+   * @type {number}
+   */
+  errorsCount: function () {
+    return this.get('configs').filterProperty('isValid', false).length;
+  }.property('configs.@each.isValid'),
+
   isFirstRow: function () {
     return this.get('rowIndex') == 0;
   }.property(),

+ 10 - 0
ambari-web/app/models/configs/tab.js

@@ -27,6 +27,16 @@ App.Tab = DS.Model.extend({
   isAdvanced: DS.attr('boolean', {defaultValue: false}),
   serviceName: DS.attr('string'),
   sections: DS.hasMany('App.Section'),
+
+  /**
+   * Number of the errors in all sections in the current tab
+   * @type {number}
+   */
+  errorsCount: function () {
+    var errors = this.get('sections').mapProperty('errorsCount');
+    return errors.length ? errors.reduce(Em.sum) : 0;
+  }.property('sections.@each.errorsCount'),
+
   /**
    * Class name used for tab switching
    *

+ 1 - 1
ambari-web/app/models/service_config.js

@@ -40,7 +40,7 @@ App.ServiceConfig = Ember.Object.extend({
     });
     configs.forEach(function (item) {
       var category = configCategories.findProperty('name', item.get('category'));
-      if (category && !item.get('isValid') && item.get('isVisible')) {
+      if (category && !item.get('isValid') && item.get('isVisible') && !item.get('widget')) {
         category.incrementProperty('nonSlaveErrorCount');
         masterErrors++;
       }

+ 14 - 1
ambari-web/app/templates/common/configs/service_config.hbs

@@ -92,7 +92,20 @@
     <ul class="nav nav-tabs">
       {{#each tab in view.tabs}}
         {{#unless tab.isHiddenByFilter}}
-          <li {{bindAttr class="tab.isActive:active" }}><a href="#" {{action "setActiveTab" tab target="view"}} {{bindAttr data-target="tab.headingClass"}} data-toggle="tab">{{tab.displayName}}</a></li>
+          <li {{bindAttr class="tab.isActive:active" }}>
+            <a href="#" {{action "setActiveTab" tab target="view"}} {{bindAttr data-target="tab.headingClass"}} data-toggle="tab">
+              {{tab.displayName}}
+                {{#if tab.isAdvanced}}
+                  {{#if controller.errorsCount}}
+                  <span class="badge badge-important">{{controller.errorsCount}}</span>
+                {{/if}}
+              {{else}}
+                {{#if tab.errorsCount}}
+                  <span class="badge badge-important">{{tab.errorsCount}}</span>
+                {{/if}}
+              {{/if}}
+            </a>
+          </li>
         {{/unless}}
       {{/each}}
     </ul>

+ 14 - 1
ambari-web/app/templates/common/configs/service_config_wizard.hbs

@@ -51,7 +51,20 @@
 {{#if view.supportsConfigLayout}}
   <ul class="nav nav-tabs">
     {{#each tab in view.tabs}}
-      <li {{bindAttr class="tab.isActive:active" }}><a href="#" {{bindAttr data-target="tab.headingClass"}} data-toggle="tab">{{tab.displayName}}</a></li>
+      <li {{bindAttr class="tab.isActive:active" }}>
+        <a href="#" {{bindAttr data-target="tab.headingClass"}} data-toggle="tab">
+          {{tab.displayName}}
+          {{#if tab.isAdvanced}}
+            {{#if controller.errorsCount}}
+              <span class="badge badge-important">{{controller.errorsCount}}</span>
+            {{/if}}
+          {{else}}
+            {{#if tab.errorsCount}}
+              <span class="badge badge-important">{{tab.errorsCount}}</span>
+            {{/if}}
+          {{/if}}
+        </a>
+      </li>
     {{/each}}
   </ul>
   <div class="tab-content">

+ 19 - 0
ambari-web/test/controllers/main/service/info/config_test.js

@@ -1305,4 +1305,23 @@ describe("App.MainServiceInfoConfigsController", function () {
 
   });
 
+  describe('#errorsCount', function () {
+
+    it('should ignore configs with widgets (enhanced configs)', function () {
+
+      mainServiceInfoConfigsController.reopen({selectedService: {
+        configs: [
+          Em.Object.create({widget: Em.View, isValid: false}),
+          Em.Object.create({widget: Em.View, isValid: true}),
+          Em.Object.create({isValid: true}),
+          Em.Object.create({isValid: false})
+        ]
+      }});
+
+      expect(mainServiceInfoConfigsController.get('errorsCount')).to.equal(1);
+
+    });
+
+  });
+
 });

+ 20 - 1
ambari-web/test/controllers/wizard/step7_test.js

@@ -1952,4 +1952,23 @@ describe('App.InstallerStep7Controller', function () {
     });
   });
 
-});
+  describe('#errorsCount', function () {
+
+    it('should ignore configs with widgets (enhanced configs)', function () {
+
+      installerStep7Controller.reopen({selectedService: {
+        configs: [
+          Em.Object.create({widget: Em.View, isValid: false}),
+          Em.Object.create({widget: Em.View, isValid: true}),
+          Em.Object.create({isValid: true}),
+          Em.Object.create({isValid: false})
+        ]
+      }});
+
+      expect(installerStep7Controller.get('errorsCount')).to.equal(1);
+
+    });
+
+  });
+
+});

+ 43 - 0
ambari-web/test/models/configs/section_test.js

@@ -0,0 +1,43 @@
+/**
+ * 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');
+var model;
+
+describe('App.Section', function () {
+
+  beforeEach(function () {
+    model = App.Section.createRecord();
+  });
+
+  describe('#errorsCount', function () {
+
+    beforeEach(function () {
+      model.reopen({subSections: [
+        App.SubSection.createRecord({configs: [{isValid: true}, {isValid: false}]}),
+        App.SubSection.createRecord({configs: [{isValid: true}, {isValid: false}]})
+      ]});
+    });
+
+    it('should use subsections.@each.errorsCount', function () {
+      expect(model.get('errorsCount')).to.equal(2);
+    });
+
+  });
+
+});

+ 45 - 0
ambari-web/test/models/configs/sub_section_test.js

@@ -0,0 +1,45 @@
+/**
+ * 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');
+var model;
+
+describe('App.SubSection', function () {
+
+  beforeEach(function () {
+    model = App.SubSection.createRecord();
+  });
+
+  describe('#errorsCount', function () {
+
+    beforeEach(function () {
+      model.set('configs', [
+        {isValid: false},
+        {isValid: true},
+        {isValid: false},
+        {isValid: true}
+      ]);
+    });
+
+    it('should use configs.@each.isValid', function () {
+      expect(model.get('errorsCount')).to.equal(2);
+    });
+
+  });
+
+});