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');