This is an automated email from the ASF dual-hosted git repository.
atkach pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new 15ec6f5 AMBARI-22940 Service-auto start page update of UI
15ec6f5 is described below
commit 15ec6f5e084f81a21b3a3545dbdf4ed33492bc0f
Author: Andrii Tkach <[email protected]>
AuthorDate: Mon Feb 12 19:26:18 2018 +0200
AMBARI-22940 Service-auto start page update of UI
---
ambari-web/app/assets/test/tests.js | 1 -
.../controllers/main/admin/service_auto_start.js | 250 ++++++---------
ambari-web/app/messages.js | 4 +-
ambari-web/app/routes/main.js | 2 +-
ambari-web/app/styles/application.less | 45 ++-
ambari-web/app/styles/bootstrap_overrides.less | 7 +
ambari-web/app/styles/circle-toggle-switch.less | 87 ++++++
.../templates/main/admin/service_auto_start.hbs | 131 +++-----
.../service_auto_start/component_auto_start.hbs | 19 --
.../service_auto_start_indicator.hbs | 19 --
ambari-web/app/views.js | 2 -
.../app/views/main/admin/service_auto_start.js | 68 +++--
.../service_auto_start/component_auto_start.js | 58 ----
.../service_auto_start_indicator.js | 34 ---
.../main/admin/service_auto_start_test.js | 335 +++++++++------------
.../component_auto_start_test.js | 64 ----
.../views/main/admin/service_auto_start_test.js | 69 ++++-
17 files changed, 528 insertions(+), 667 deletions(-)
diff --git a/ambari-web/app/assets/test/tests.js
b/ambari-web/app/assets/test/tests.js
index 51e9f3e..195ba72 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -292,7 +292,6 @@ var files = [
'test/views/main/admin/stack_upgrade/services_view_test',
'test/views/main/admin/stack_upgrade/menu_view_test',
'test/views/main/admin/stack_upgrade/failed_hosts_modal_view_test',
- 'test/views/main/admin/service_auto_start/component_auto_start_test',
'test/views/main/admin/service_auto_start_test',
'test/views/main/dashboard/config_history_view_test',
'test/views/main/dashboard/config_history_search_box_test',
diff --git a/ambari-web/app/controllers/main/admin/service_auto_start.js
b/ambari-web/app/controllers/main/admin/service_auto_start.js
index df07c94..0d34ef0 100644
--- a/ambari-web/app/controllers/main/admin/service_auto_start.js
+++ b/ambari-web/app/controllers/main/admin/service_auto_start.js
@@ -30,77 +30,105 @@ App.MainAdminServiceAutoStartController =
Em.Controller.extend({
/**
* @type {Array}
*/
- componentsConfigs: [],
+ componentsConfigsCached: [],
+
+ /**
+ * @type {object}
+ */
+ componentsConfigsCachedMap: function() {
+ const map = {};
+
this.get('componentsConfigsCached').mapProperty('ServiceComponentInfo').forEach((component)
=> {
+ map[component.component_name] = component.recovery_enabled === 'true'
+ });
+ return map;
+
}.property('[email protected]_enabled'),
+
+ /**
+ * @type {Array}
+ */
+ componentsConfigsGrouped: [],
/**
* @type {boolean}
- * @default false
*/
- isSaveDisabled: true,
+ isLoaded: false,
/**
- * Current value of servicesAutoStart
* @type {boolean}
*/
- servicesAutoStart: false,
+ isGeneralRecoveryEnabled: false,
/**
- * Value of servicesAutoStart saved on server
* @type {boolean}
*/
- servicesAutoStartSaved: false,
+ isGeneralRecoveryEnabledCached: false,
/**
- * config version tag,
- * required to sync cluster configs locally without reload
- * @type {?object}
+ * @type {boolean}
*/
- tag: null,
+ saveInProgress: false,
/**
* @type {boolean}
*/
- isServicesAutoStartChanged:
Em.computed.notEqualProperties('servicesAutoStart', 'servicesAutoStartSaved'),
+ isModified: function() {
+ return this.get('isGeneralModified') || this.get('isComponentModified');
+ }.property('isGeneralModified', 'isComponentModified'),
- valueChanged: function() {
- var isSaveDisabled = true;
+ /**
+ * @type {boolean}
+ */
+ isGeneralModified: function() {
+ return this.get('isGeneralRecoveryEnabled') !==
this.get('isGeneralRecoveryEnabledCached')
+ }.property('isGeneralRecoveryEnabled', 'isGeneralRecoveryEnabledCached'),
- if (this.get('isServicesAutoStartChanged')) {
- this.set('clusterConfigs.recovery_enabled',
this.get('servicesAutoStart') + '');
- isSaveDisabled = false;
- }
- this.get('tabs').forEach(function(tab) {
- if (isSaveDisabled) {
- isSaveDisabled = !tab.get('components').someProperty('isChanged');
- }
- });
+ /**
+ * @type {boolean}
+ */
+ isComponentModified: function() {
+ const componentsConfigsCachedMap = this.get('componentsConfigsCachedMap');
- this.set('isSaveDisabled', isSaveDisabled);
+ return this.get('componentsConfigsGrouped').some((component) => {
+ return component.get('recoveryEnabled') !==
componentsConfigsCachedMap[component.get('componentName')];
+ });
+ }.property('[email protected]',
'componentsConfigsCachedMap'),
+
+ parseComponentConfigs: function(componentsConfigsCached) {
+ const componentsConfigsGrouped = [];
+ const servicesMap = componentsConfigsCached
+ .mapProperty('ServiceComponentInfo.service_name').uniq().toWickMap();
+
+
componentsConfigsCached.mapProperty('ServiceComponentInfo').forEach((component)
=> {
+ componentsConfigsGrouped.push(Em.Object.create({
+ serviceDisplayName: App.format.role(component.service_name, true),
+ isFirst: servicesMap[component.service_name],
+ componentName: component.component_name,
+ displayName: App.format.role(component.component_name, false),
+ recoveryEnabled: component.recovery_enabled === 'true'
+ }));
+ servicesMap[component.service_name] = false;
+ });
+ return componentsConfigsGrouped;
},
load: function() {
- var self = this;
- var dfd = $.Deferred();
-
- return this.loadClusterConfig().done(function (data) {
- var tag = [
+ this.loadClusterConfig().done((data) => {
+ const tag = [
{
siteName: 'cluster-env',
tagName: data.Clusters.desired_configs['cluster-env'].tag,
newTagName: null
}
];
- self.set('tag', tag);
-
App.router.get('configurationController').getConfigsByTags(tag).done(function
(data) {
- var servicesAutoStart = data[0].properties.recovery_enabled === 'true';
- self.set('clusterConfigs', data[0].properties);
- self.set('servicesAutoStart', servicesAutoStart);
- self.set('servicesAutoStartSaved', servicesAutoStart);
- self.loadComponentsConfigs().done(dfd.resolve).fail(dfd.reject);
- }).fail(dfd.reject);
- }).fail(dfd.reject);
-
- return dfd.promise();
+
App.router.get('configurationController').getConfigsByTags(tag).done((data) => {
+ this.set('clusterConfigs', data[0].properties);
+ this.set('isGeneralRecoveryEnabled',
data[0].properties.recovery_enabled === 'true');
+ this.set('isGeneralRecoveryEnabledCached',
this.get('isGeneralRecoveryEnabled'));
+ this.loadComponentsConfigs().then(() => {
+ this.set('isLoaded', true);
+ });
+ });
+ });
},
loadClusterConfig: function () {
@@ -122,7 +150,8 @@ App.MainAdminServiceAutoStartController =
Em.Controller.extend({
},
loadComponentsConfigsSuccess: function (data) {
- this.set('componentsConfigs', data.items);
+ this.set('componentsConfigsCached', data.items);
+ this.set('componentsConfigsGrouped',
this.parseComponentConfigs(data.items));
},
saveClusterConfigs: function (clusterConfigs) {
@@ -149,123 +178,28 @@ App.MainAdminServiceAutoStartController =
Em.Controller.extend({
});
},
- tabs: function() {
- var services = {};
- var tabs = [];
-
- this.get('componentsConfigs').forEach(function (component) {
- var serviceComponentInfo = component.ServiceComponentInfo;
- if (serviceComponentInfo.total_count) {
- if (serviceComponentInfo.category === "MASTER" ||
serviceComponentInfo.category === "SLAVE") {
- var componentRecovery =
this.createRecoveryComponent(serviceComponentInfo);
- var service = services[serviceComponentInfo.service_name];
-
- if (service) {
- service.get('components').pushObject(componentRecovery);
- service.set('enabledComponents',
services[serviceComponentInfo.service_name].get('enabledComponents') +
(componentRecovery.get('recovery_enabled') ? 1 : 0));
- service.set('totalComponents',
services[serviceComponentInfo.service_name].get('totalComponents') + 1);
- } else {
- services[serviceComponentInfo.service_name] =
this.createTab(serviceComponentInfo, componentRecovery);
- }
- }
- }
- }, this);
- for (var name in services ) {
- tabs.push(services[name]);
- }
- if (tabs.length) {
- tabs[0].set('isActive', true);
- }
- return tabs;
- }.property('componentsConfigs'),
-
- createRecoveryComponent: function(serviceComponentInfo) {
- return Ember.Object.create({
- displayName: App.format.role(serviceComponentInfo.component_name, false),
- componentName: serviceComponentInfo.component_name,
- recoveryEnabled: serviceComponentInfo.recovery_enabled === 'true',
- recoveryEnabledSaved: serviceComponentInfo.recovery_enabled === 'true',
- isChanged: Em.computed.notEqualProperties('recoveryEnabled',
'recoveryEnabledSaved'),
- serviceName: serviceComponentInfo.service_name
- });
- },
-
- createTab: function(serviceComponentInfo, componentRecovery) {
- return Ember.Object.create({
- service_name: serviceComponentInfo.service_name,
- display_name: App.format.role(serviceComponentInfo.service_name, true),
- headingClass: "." + serviceComponentInfo.service_name,
- isActive: false,
- tooltip: function () {
- var percentage = this.get('enabledComponents') /
this.get('totalComponents');
- var text = Em.I18n.t('admin.serviceAutoStart.tooltip.text');
- if (percentage === 1) {
- return text.format("All");
- } else if (percentage === 0) {
- return text.format("No");
- } else {
- return text.format(this.get('enabledComponents') + "/" +
this.get('totalComponents'));
- }
- }.property('enabledComponents', 'totalComponents'),
- components: Em.A([componentRecovery]),
- enabledComponents: componentRecovery.recoveryEnabled ? 1 : 0,
- totalComponents: 1,
- indicator: function () {
- var percentage = this.get('enabledComponents') /
this.get('totalComponents');
- var indicator = "icon-adjust";
- if (percentage === 1) {
- indicator = "icon-circle";
- } else if (percentage === 0) {
- indicator = "icon-circle-blank";
- }
- return indicator;
- }.property('enabledComponents', 'totalComponents')
- });
- },
-
- filterTabsByRecovery: function(tabs, isRecoveryEnabled) {
- var components = [];
-
- tabs.forEach(function (service) {
- service.get('components').forEach(function (component) {
- if (component.get('isChanged') && component.get('recoveryEnabled') ===
isRecoveryEnabled) {
- components.push(component.get('componentName'));
- }
- });
- });
- return components;
- },
-
syncStatus: function () {
- var servicesAutoStart = this.get('servicesAutoStart');
- this.set('servicesAutoStartSaved', servicesAutoStart);
-
App.router.get('configurationController').getConfigsByTags(this.get('tag')).done(function(data)
{
- data[0].properties.recovery_enabled = servicesAutoStart + '';
- App.router.get('configurationController').saveToDB(data);
+ const componentsConfigsGrouped = this.get('componentsConfigsGrouped');
+ this.set('isGeneralRecoveryEnabledCached',
this.get('isGeneralRecoveryEnabled'));
+
this.get('componentsConfigsCached').mapProperty('ServiceComponentInfo').forEach((component)
=> {
+ const actualComponent =
componentsConfigsGrouped.findProperty('componentName',
component.component_name);
+ component.recovery_enabled =
String(actualComponent.get('recoveryEnabled'));
});
- this.get('tabs').forEach(function(tab) {
- tab.get('components').forEach(function(component) {
- component.set('recoveryEnabledSaved',
component.get('recoveryEnabled'));
- });
- });
- this.valueChanged();
+ this.propertyDidChange('componentsConfigsCached');
},
- revertStatus: function () {
- this.set('servicesAutoStart', this.get('servicesAutoStartSaved'));
- this.get('tabs').forEach(function(tab) {
- tab.get('components').forEach(function(component) {
- component.set('recoveryEnabled',
component.get('recoveryEnabledSaved'));
- });
- });
+ restoreCachedValues: function () {
+ this.set('isGeneralRecoveryEnabled',
this.get('isGeneralRecoveryEnabledCached'));
+ this.set('componentsConfigsGrouped',
this.parseComponentConfigs(this.get('componentsConfigsCached')));
},
- enableAll: function (event) {
- event.context.get('components').setEach('recoveryEnabled', true);
- },
+ filterComponentsByChange: function(components, value) {
+ const map = this.get('componentsConfigsCachedMap');
- disableAll: function (event) {
- event.context.get('components').setEach('recoveryEnabled', false);
+ return components.filter((component) => {
+ return component.get('recoveryEnabled') !==
map[component.get('componentName')]
+ && component.get('recoveryEnabled') === value;
+ }).mapProperty('componentName');
},
/**
@@ -296,13 +230,14 @@ App.MainAdminServiceAutoStartController =
Em.Controller.extend({
primary: Em.I18n.t('common.save'),
secondary: Em.I18n.t('common.cancel'),
onSave: function () {
- var clusterConfigsCall, enabledComponentsCall, disabledComponentsCall;
+ let clusterConfigsCall, enabledComponentsCall, disabledComponentsCall;
- if (self.get('isServicesAutoStartChanged')) {
+ if (self.get('isGeneralModified')) {
clusterConfigsCall =
self.saveClusterConfigs(self.get('clusterConfigs'));
}
- var enabledComponents = self.filterTabsByRecovery(self.get('tabs'),
true);
- var disabledComponents = self.filterTabsByRecovery(self.get('tabs'),
false);
+
+ const enabledComponents =
self.filterComponentsByChange(self.get('componentsConfigsGrouped'), true);
+ const disabledComponents =
self.filterComponentsByChange(self.get('componentsConfigsGrouped'), false);
if (enabledComponents.length) {
enabledComponentsCall = self.saveComponentSettingsCall('true',
enabledComponents);
@@ -310,16 +245,19 @@ App.MainAdminServiceAutoStartController =
Em.Controller.extend({
if (disabledComponents.length) {
disabledComponentsCall = self.saveComponentSettingsCall('false',
disabledComponents);
}
+ self.set('saveInProgress', true);
$.when(clusterConfigsCall, enabledComponentsCall,
disabledComponentsCall).done(function () {
if (typeof transitionCallback === 'function') {
transitionCallback();
}
self.syncStatus();
+ }).always(function() {
+ self.set('saveInProgress', false);
});
this.hide();
},
onDiscard: function () {
- self.revertStatus();
+ self.restoreCachedValues();
if (typeof transitionCallback === 'function') {
transitionCallback();
}
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index b71cfa3..36185a1 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1739,10 +1739,10 @@ Em.I18n.translations = {
'admin.misc.nothingToShow': 'No user accounts to display',
'admin.serviceAutoStart.title': "Service Auto Start",
- 'admin.serviceAutoStart.header': "Service Auto Start Configuration",
'admin.serviceAutoStart.header.text': "Ambari services can be configured to
start automatically on system boot. Each service can be configured to start all
components, masters and workers, or selectively.",
- 'admin.serviceAutoStart.body.text': "Auto-Start Services",
+ 'admin.serviceAutoStart.general.switcher': "Auto Start Settings",
'admin.serviceAutoStart.tooltip.text': "{0} components enabled",
+ 'admin.serviceAutoStart.column.autoStart': "Auto Start",
'admin.stackVersions.filter.notInstalled': "Not Installed ({0})",
'admin.stackVersions.filter.all': "All ({0})",
diff --git a/ambari-web/app/routes/main.js b/ambari-web/app/routes/main.js
index 8021043..a5f9345 100644
--- a/ambari-web/app/routes/main.js
+++ b/ambari-web/app/routes/main.js
@@ -664,7 +664,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
},
exitRoute: function (router, context, callback) {
var controller = router.get('mainAdminServiceAutoStartController');
- if (!controller.get('isSaveDisabled')) {
+ if (controller.get('isModified')) {
controller.showSavePopup(callback);
} else {
callback();
diff --git a/ambari-web/app/styles/application.less
b/ambari-web/app/styles/application.less
index 1d5056b..59b50e4 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -1282,16 +1282,43 @@ table.graphs {
margin-left: 20px
}
-.admin-auto-start {
- .nav i {
- margin-top: 0;
- color: @green;
+#admin-auto-start {
+ background-color: #fff;
+ padding: 30px;
+ .description {
+ color: @gray-text;
}
- .services-heading {
- padding: 8px;
- color: #999;
- font-size: 13px;
- font-weight: bold;
+ .table {
+ th {
+ font-weight: normal;
+ }
+ th:first-child {
+ color: #666;
+ }
+ th:first-child,
+ td:first-child,
+ th:first-child + th,
+ td:first-child + td {
+ line-height: 24px;
+ min-width: 200px;
+ width: 20%;
+ }
+ th:first-child + th + th,
+ td:first-child + td + td {
+ width: 15%;
+ text-align: center;
+ }
+ .skip-border {
+ border: none;
+ }
+ .all-checkbox {
+ display: inline-block;
+ top: 2px;
+ }
+ }
+ .general-auto-start {
+ display: inline-block;
+ margin-left: 15px;
}
}
diff --git a/ambari-web/app/styles/bootstrap_overrides.less
b/ambari-web/app/styles/bootstrap_overrides.less
index b2ed244..db98047 100644
--- a/ambari-web/app/styles/bootstrap_overrides.less
+++ b/ambari-web/app/styles/bootstrap_overrides.less
@@ -458,4 +458,11 @@ select.form-control {
input[type="checkbox"]:checked + label:after {
line-height: 2em;
+}
+
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+ padding-top: 0;
}
\ No newline at end of file
diff --git a/ambari-web/app/styles/circle-toggle-switch.less
b/ambari-web/app/styles/circle-toggle-switch.less
new file mode 100644
index 0000000..f5ec73d
--- /dev/null
+++ b/ambari-web/app/styles/circle-toggle-switch.less
@@ -0,0 +1,87 @@
+/**
+ * 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.
+ */
+
+
+@bg-color-on: #1EB475;
+@bg-color-off: #EBECF1;
+@text-color-off: #666;
+@circle-size: 20px;
+
+.circle-toggle-switch {
+ .bootstrap-switch {
+ border-radius: 28px;
+ border: none;
+
+ .bootstrap-switch-label {
+ border-radius: @circle-size;
+ width: @circle-size !important;
+ height: @circle-size;
+ line-height: 14px;
+ }
+
+ .bootstrap-switch-container {
+ height: 28px;
+ }
+ }
+
+ .bootstrap-switch-on {
+ background-color: @bg-color-on;
+ .bootstrap-switch-container {
+ background-color: transparent;
+ }
+ .bootstrap-switch-label {
+ box-shadow: 1px 1px 30px 1px @text-color-off;
+ margin-top: 4px;
+ margin-left: -4px;
+ margin-right: 4px;
+ }
+ }
+
+ .bootstrap-switch-off {
+ box-shadow: inset 0 0 5px @text-color-off;
+ background-color: @bg-color-off;
+
+ .bootstrap-switch-container {
+ background-color: transparent;
+ }
+ .bootstrap-switch-label {
+ margin-top: 4px;
+ margin-left: 4px;
+ margin-right: 5px;
+ background-color: #999;
+ border: none;
+ }
+ }
+
+ .bootstrap-switch-handle-on.bootstrap-switch-success,
+ .bootstrap-switch-handle-off.bootstrap-switch-success {
+ background-color: transparent !important;
+ }
+
+ .bootstrap-switch-handle-on.bootstrap-switch-default,
+ .bootstrap-switch-handle-off.bootstrap-switch-default {
+ background-color: transparent !important;
+ color: @text-color-off !important;
+ text-align: left;
+ }
+
+ .bootstrap-switch-handle-off.bootstrap-switch-default:hover {
+ background-color: transparent !important;
+ color: @text-color-off !important;
+ }
+}
diff --git a/ambari-web/app/templates/main/admin/service_auto_start.hbs
b/ambari-web/app/templates/main/admin/service_auto_start.hbs
index 6dc7dc5..0955d22 100644
--- a/ambari-web/app/templates/main/admin/service_auto_start.hbs
+++ b/ambari-web/app/templates/main/admin/service_auto_start.hbs
@@ -16,90 +16,59 @@
* limitations under the License.
}}
-<div class="admin-auto-start">
- <h4>{{t admin.serviceAutoStart.header}}</h4>
- <p>{{t admin.serviceAutoStart.header.text}}</p>
- {{#if view.isLoaded}}
- <div class="cluster-switcher row">
- <div class="col-md-2">
- <strong>{{t admin.serviceAutoStart.body.text}}</strong>
- </div>
- <div class="col-md-4">
- {{view App.CheckboxView checkedBinding="controller.servicesAutoStart"}}
- </div>
- <div class="col-md-6">
- <div class="pull-right operations-button">
- <button class="btn btn-default" {{action revertStatus
target="controller"}} {{bindAttr disabled="controller.isSaveDisabled"}}>{{t
common.discard}}</button>
- <button class="btn btn-success" {{action showSavePopup
target="controller"}} {{bindAttr disabled="controller.isSaveDisabled"}}>{{t
common.save}}</button>
- </div>
- </div>
+<div id="admin-auto-start">
+ <p class="description">{{t admin.serviceAutoStart.header.text}}</p>
+ {{#if controller.isLoaded}}
+ <div class="cluster-level-switcher">
+ <span class="h2">{{t admin.serviceAutoStart.general.switcher}}</span>
+ {{view App.CheckboxView
+ didInsertElementBinding="view.initSwitcher"
+ classNames="general-auto-start circle-toggle-switch"
+ disabledBinding="view.isDisabled"
+ checkedBinding="controller.isGeneralRecoveryEnabled"}}
</div>
- <hr>
- <div class="row">
- <div class="col-md-4 col-lg-3">
- <div class="services-heading">{{t common.service}}</div>
- <div class="row">
- <div class="col-md-12">
- <ul class="nav nav-tabs nav-stacked nav-tabs-left">
- {{#each tab in controller.tabs}}
- <li {{bindAttr class="tab.isActive:active"}}>
- <a href="#" data-toggle="tab" {{bindAttr
data-target="tab.headingClass"}}>
- {{tab.display_name}}
- {{view App.MainAdminServiceAutoStartIndicatorView
tabBinding="tab"}}
- </a>
- </li>
- {{/each}}
- </ul>
- </div>
- </div>
- </div>
- <div class="col-md-8 col-lg-9 row">
- <div class="tab-content col-md-12">
- {{#each tab in controller.tabs}}
- <div {{bindAttr class=":tab-pane tab.isActive:active
tab.service_name"}}>
- <table class="table table-hover">
- <thead>
- <tr>
- <th class="col-md-4">
- {{t common.component}}
- </th>
- <th class="col-md-8">
- {{t common.status}}
- </th>
- </tr>
- </thead>
- <tbody>
- {{#each component in tab.components}}
- <tr>
- <td class="col-md-4">
- {{component.displayName}}
- </td>
- <td class="col-md-8">
- {{view App.MainAdminServiceAutoStartComponentView
componentBinding="component" tabBinding="tab"}}
- </td>
- </tr>
- {{/each}}
- </tbody>
- {{#isAuthorized "SERVICE.MANAGE_AUTO_START"}}
- <tfoot>
- <tr>
- <td class="col-md-4"></td>
- <td class="col-md-8">
- <a href="#" class="enable-all-link" {{action enableAll
tab target="controller"}}>
- {{t common.enableAll}}
- </a> |
- <a href="#" {{action disableAll tab
target="controller"}}>{{t common.disableAll}}</a>
- </td>
- </tr>
- </tfoot>
- {{/isAuthorized}}
- </table>
- </div>
- {{/each}}
- </div>
- </div>
+ <div class="form-horizontal">
+ <table class="table">
+ <thead>
+ <tr>
+ <th>{{t common.service}}</th>
+ <th>{{t common.components}}</th>
+ <th>
+ {{view App.CheckboxView
+ disabledBinding="view.isDisabled"
+ classNames="all-checkbox"
+ checkedBinding="view.allComponentsChecked"}}
+ {{t admin.serviceAutoStart.column.autoStart}}
+ </th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#each component in componentsConfigsGrouped}}
+ <tr>
+ <td {{bindAttr class="component.isFirst::skip-border"}}>
+ {{#if component.isFirst}}
+ {{component.serviceDisplayName}}
+ {{/if}}
+ </td>
+ <td>{{component.displayName}}</td>
+ <td>{{view App.CheckboxView
+ disabledBinding="view.isDisabled"
+ checkedBinding="component.recoveryEnabled"}}</td>
+ <td></td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
</div>
{{else}}
{{view App.SpinnerView}}
{{/if}}
+ <div {{bindAttr class="view.isDisablad:hidden :configs-save-panel"}}>
+ <div class="pull-right">
+ <button class="btn btn-default" {{action restoreCachedValues
target="controller"}} {{bindAttr disabled="view.isSaveDisabled"}}>{{t
common.cancel}}</button>
+ <button class="btn btn-success" {{action showSavePopup
target="controller"}} {{bindAttr disabled="view.isSaveDisabled"}}>{{t
common.save}}</button>
+ </div>
+ <div class="clearfix"></div>
+ </div>
</div>
diff --git
a/ambari-web/app/templates/main/admin/service_auto_start/component_auto_start.hbs
b/ambari-web/app/templates/main/admin/service_auto_start/component_auto_start.hbs
deleted file mode 100644
index a52dcfd..0000000
---
a/ambari-web/app/templates/main/admin/service_auto_start/component_auto_start.hbs
+++ /dev/null
@@ -1,19 +0,0 @@
-{{!
-* 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.
-}}
-
-{{view App.CheckboxView checkedBinding="view.component.recoveryEnabled"}}
diff --git
a/ambari-web/app/templates/main/admin/service_auto_start/service_auto_start_indicator.hbs
b/ambari-web/app/templates/main/admin/service_auto_start/service_auto_start_indicator.hbs
deleted file mode 100644
index 4abcc13..0000000
---
a/ambari-web/app/templates/main/admin/service_auto_start/service_auto_start_indicator.hbs
+++ /dev/null
@@ -1,19 +0,0 @@
-{{!
-* 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.
-}}
-
-<i {{bindAttr class=":pull-right tab.indicator"
data-original-title="tab.tooltip"}} rel="tooltip"></i>
\ No newline at end of file
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index fa51bfa..3b1520e 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -169,8 +169,6 @@ require('views/main/host/metrics/processes');
require('views/main/host/addHost/step4_view');
require('views/main/admin');
require('views/main/admin/service_auto_start');
-require('views/main/admin/service_auto_start/component_auto_start');
-require('views/main/admin/service_auto_start/service_auto_start_indicator');
require('views/main/admin/highAvailability/nameNode/wizard_view');
require('views/main/admin/highAvailability/progress_view');
require('views/main/admin/highAvailability/nameNode/rollback_view');
diff --git a/ambari-web/app/views/main/admin/service_auto_start.js
b/ambari-web/app/views/main/admin/service_auto_start.js
index 0399944..2c7a9a1 100644
--- a/ambari-web/app/views/main/admin/service_auto_start.js
+++ b/ambari-web/app/views/main/admin/service_auto_start.js
@@ -23,25 +23,40 @@ App.MainAdminServiceAutoStartView = Em.View.extend({
/**
* @type {boolean}
- * @default false
*/
- isLoaded: false,
+ isSaveDisabled: Em.computed.or('!controller.isModified',
'controller.saveInProgress'),
+ /**
+ * @type {boolean}
+ * @default false
+ */
isDisabled: false,
+ /**
+ * @type {boolean}
+ */
+ skipCyclicCall: false,
+
+ /**
+ * @type {boolean}
+ */
+ allComponentsChecked: false,
+
+ /**
+ * @type {?object}
+ */
+ switcher: null,
+
didInsertElement: function () {
this.set('isDisabled', !App.isAuthorized('CLUSTER.MANAGE_AUTO_START'));
- this.get('controller').load().then(() => {
- this.set('isLoaded', true);
- Em.run.next(() => Em.run.next(() => this.initSwitcher()));
- });
+ this.get('controller').load();
},
onValueChange: function () {
if (this.get('switcher')) {
- this.get('switcher').bootstrapSwitch('state',
this.get('controller.servicesAutoStart'));
+ this.get('switcher').bootstrapSwitch('state',
this.get('controller.isGeneralRecoveryEnabled'));
}
- }.observes('controller.servicesAutoStart'),
+ }.observes('controller.isGeneralRecoveryEnabled'),
/**
* Init switcher plugin.
@@ -49,22 +64,41 @@ App.MainAdminServiceAutoStartView = Em.View.extend({
* @method initSwitcher
*/
initSwitcher: function () {
- var self = this;
- if (this.$) {
- this.set('switcher', this.$("input:eq(0)").bootstrapSwitch({
- state: self.get('controller.servicesAutoStart'),
+ const self = this.get('parentView');
+ if (self.get('controller.isLoaded')) {
+ self.set('switcher', $(".general-auto-start>input").bootstrapSwitch({
+ state: self.get('controller.isGeneralRecoveryEnabled'),
onText: Em.I18n.t('common.enabled'),
offText: Em.I18n.t('common.disabled'),
offColor: 'default',
onColor: 'success',
- disabled: this.get('isDisabled'),
+ disabled: self.get('isDisabled'),
handleWidth: Math.max(Em.I18n.t('common.enabled').length,
Em.I18n.t('common.disabled').length) * 8,
- onSwitchChange: function (event, state) {
- self.set('controller.servicesAutoStart', state);
- self.get('controller').valueChanged();
+ onSwitchChange: (event, state) => {
+ self.set('controller.isGeneralRecoveryEnabled', state);
}
}));
}
- }
+ },
+
+ observeAllComponentsChecked: function() {
+ if (this.get('skipCyclicCall')) {
+ this.set('skipCyclicCall', false);
+ } else {
+
this.get('controller.componentsConfigsGrouped').setEach('recoveryEnabled',
this.get('allComponentsChecked'));
+ }
+ }.observes('allComponentsChecked'),
+
+ observesEachComponentChecked: function() {
+ const components = this.get('controller.componentsConfigsGrouped');
+ if (this.get('allComponentsChecked') &&
components.someProperty('recoveryEnabled', false)) {
+ this.set('skipCyclicCall', true);
+ this.set('allComponentsChecked', false);
+ } else if (!this.get('allComponentsChecked') &&
components.everyProperty('recoveryEnabled', true)) {
+ this.set('skipCyclicCall', true);
+ this.set('allComponentsChecked', true);
+ }
+ }.observes('[email protected]')
+
});
diff --git
a/ambari-web/app/views/main/admin/service_auto_start/component_auto_start.js
b/ambari-web/app/views/main/admin/service_auto_start/component_auto_start.js
deleted file mode 100644
index b8ad812..0000000
--- a/ambari-web/app/views/main/admin/service_auto_start/component_auto_start.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * 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');
-
-App.MainAdminServiceAutoStartComponentView = Em.View.extend({
- templateName:
require('templates/main/admin/service_auto_start/component_auto_start'),
-
- tab: null,
- component: null,
-
- didInsertElement: function () {
- this.initSwitcher();
- },
-
- onValueChange: function () {
- this.get('switcher').bootstrapSwitch('state',
this.get('component.recoveryEnabled'));
- }.observes('component.recoveryEnabled'),
-
- /**
- * Init switcher plugin.
- *
- * @method initSwitcher
- */
- initSwitcher: function () {
- var self = this;
- if (this.$()) {
- this.set('switcher', this.$("input:eq(0)").bootstrapSwitch({
- onText: Em.I18n.t('common.enabled'),
- offText: Em.I18n.t('common.disabled'),
- offColor: 'default',
- onColor: 'success',
- disabled: !App.isAuthorized('SERVICE.MANAGE_AUTO_START'),
- handleWidth: Math.max(Em.I18n.t('common.enabled').length,
Em.I18n.t('common.disabled').length) * 8,
- onSwitchChange: function (event, state) {
- self.set('tab.enabledComponents', self.get('tab.enabledComponents')
+ (state ? 1 : -1));
- self.set('component.recoveryEnabled', state);
- self.get('controller').valueChanged();
- }
- }));
- }
- }
-});
\ No newline at end of file
diff --git
a/ambari-web/app/views/main/admin/service_auto_start/service_auto_start_indicator.js
b/ambari-web/app/views/main/admin/service_auto_start/service_auto_start_indicator.js
deleted file mode 100644
index 49a80e3..0000000
---
a/ambari-web/app/views/main/admin/service_auto_start/service_auto_start_indicator.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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');
-
-App.MainAdminServiceAutoStartIndicatorView = Em.View.extend({
- templateName:
require('templates/main/admin/service_auto_start/service_auto_start_indicator'),
- tagName: 'span',
-
- tab: null,
-
- didInsertElement: function () {
- App.tooltip(this.$("[rel='tooltip']"));
- },
-
- willDestroyElement: function () {
- this.$("[rel='tooltip']").tooltip('destroy');
- }
-});
\ No newline at end of file
diff --git a/ambari-web/test/controllers/main/admin/service_auto_start_test.js
b/ambari-web/test/controllers/main/admin/service_auto_start_test.js
index 8cb176e..66d8b70 100644
--- a/ambari-web/test/controllers/main/admin/service_auto_start_test.js
+++ b/ambari-web/test/controllers/main/admin/service_auto_start_test.js
@@ -28,59 +28,100 @@ describe('App.MainAdminServiceAutoStartController',
function() {
});
});
+ describe('#parseComponentConfigs', function() {
- describe('#valueChanged()', function() {
+ it('should return parsed components', function() {
+ var components = [
+ {
+ ServiceComponentInfo: {
+ service_name: 'S1',
+ component_name: 'C1',
+ recovery_enabled: 'true'
+ }
+ },
+ {
+ ServiceComponentInfo: {
+ service_name: 'S1',
+ component_name: 'C2',
+ recovery_enabled: 'false'
+ }
+ }
+ ];
+ expect(controller.parseComponentConfigs(components)).to.be.eql([
+ Em.Object.create({
+ "componentName": "C1",
+ "displayName": "C1",
+ "isFirst": true,
+ "recoveryEnabled": true,
+ "serviceDisplayName": "S1"
+ }),
+ Em.Object.create({
+ "componentName": "C2",
+ "displayName": "C2",
+ "isFirst": false,
+ "recoveryEnabled": false,
+ "serviceDisplayName": "S1"
+ })
+ ]);
+ });
+ });
- it('servicesAutoStart is changed', function() {
- controller.reopen({
- servicesAutoStart: true,
- servicesAutoStartSaved: false,
- tabs: []
+ describe('#load', function() {
+ var mock = {
+ getConfigsByTags: sinon.stub().returns({
+ done: function(callback) {
+ callback([
+ {
+ properties: {
+ recovery_enabled: 'true'
+ }
+ }
+ ]);
+ }
+ })
+ };
+ beforeEach(function() {
+ sinon.stub(controller, 'loadClusterConfig').returns({
+ done: function(callback) {
+ callback({
+ Clusters: {
+ desired_configs: {
+ 'cluster-env': {
+ tag: 1
+ }
+ }
+ }
+ });
+ }
});
- controller.valueChanged();
- expect(controller.get('isSaveDisabled')).to.be.false;
+ sinon.stub(App.router, 'get').returns(mock);
+ sinon.stub(controller, 'loadComponentsConfigs').returns({
+ then: Em.clb
+ });
+ controller.load();
+ });
+ afterEach(function() {
+ controller.loadClusterConfig.restore();
+ App.router.get.restore();
+ controller.loadComponentsConfigs.restore();
});
- it('servicesAutoStart is not changed', function() {
- controller.reopen({
- servicesAutoStart: true,
- servicesAutoStartSaved: true,
- tabs: []
+ it('clusterConfigs should be set', function() {
+ expect(controller.get('clusterConfigs')).to.be.eql({
+ recovery_enabled: 'true'
});
- controller.valueChanged();
- expect(controller.get('isSaveDisabled')).to.be.true;
});
- it('components state is not changed', function() {
- controller.reopen({
- servicesAutoStart: true,
- servicesAutoStartSaved: true,
- tabs: [Em.Object.create({
- components: [
- Em.Object.create({
- isChanged: false
- })
- ]
- })]
- });
- controller.valueChanged();
- expect(controller.get('isSaveDisabled')).to.be.true;
+ it('isGeneralRecoveryEnabled should be true', function() {
+ expect(controller.get('isGeneralRecoveryEnabled')).to.be.true;
});
- it('components state is changed', function() {
- controller.reopen({
- servicesAutoStart: true,
- servicesAutoStartSaved: true,
- tabs: [Em.Object.create({
- components: [
- Em.Object.create({
- isChanged: true
- })
- ]
- })]
- });
- controller.valueChanged();
- expect(controller.get('isSaveDisabled')).to.be.false;
+ it('isGeneralRecoveryEnabledCached should be true', function() {
+ expect(controller.get('isGeneralRecoveryEnabledCached')).to.be.true;
+ });
+
+ it('isLoaded should be true', function() {
+ expect(controller.get('isLoaded')).to.be.true;
});
});
@@ -114,9 +155,21 @@ describe('App.MainAdminServiceAutoStartController',
function() {
describe('#loadComponentsConfigsSuccess()', function() {
- it('componentsConfigs should be set', function() {
+ beforeEach(function() {
+ sinon.stub(controller, 'parseComponentConfigs').returns({});
+ });
+ afterEach(function() {
+ controller.parseComponentConfigs.restore();
+ });
+
+ it('componentsConfigsCached should be set', function() {
+ controller.loadComponentsConfigsSuccess({items: [{prop1: 'val1'}]});
+ expect(controller.get('componentsConfigsCached')).to.be.eql([{prop1:
'val1'}]);
+ });
+
+ it('componentsConfigsGrouped should be set', function() {
controller.loadComponentsConfigsSuccess({items: {prop1: 'val1'}});
- expect(controller.get('componentsConfigs')).to.be.eql({prop1: 'val1'});
+ expect(controller.get('componentsConfigsGrouped')).to.be.eql({});
});
});
@@ -154,173 +207,79 @@ describe('App.MainAdminServiceAutoStartController',
function() {
});
});
- describe('#createRecoveryComponent()', function() {
-
- it('should return recovery component', function() {
- var serviceComponentInfo = {
- component_name: 'c1',
- recovery_enabled: 'true',
- service_name: 's1'
- };
-
expect(controller.createRecoveryComponent(serviceComponentInfo)).to.be.an.object;
- });
- });
-
- describe('#createTab()', function() {
-
- it('should return tab', function() {
- var serviceComponentInfo = {
- component_name: 'c1',
- recovery_enabled: 'true',
- service_name: 's1'
- };
- expect(controller.createTab(serviceComponentInfo, {})).to.be.an.object;
- });
- });
-
- describe('#filterTabsByRecovery()', function() {
-
- it('should return empty when no components were changed', function() {
- var tabs = [Em.Object.create({
- components: [
- Em.Object.create({
- isChanged: false
- })
- ]
- })];
- expect(controller.filterTabsByRecovery(tabs, true)).to.be.empty;
- });
-
- it('should return enabled components ', function() {
- var tabs = [Em.Object.create({
- components: [
- Em.Object.create({
- isChanged: true,
- recoveryEnabled: true
- })
- ]
- })];
- expect(controller.filterTabsByRecovery(tabs, true)).to.have.length(1);
- });
-
- it('should return disabled components ', function() {
- var tabs = [Em.Object.create({
- components: [
- Em.Object.create({
- isChanged: true,
- recoveryEnabled: false
- })
- ]
- })];
- expect(controller.filterTabsByRecovery(tabs, false)).to.have.length(1);
- });
- });
-
- describe('#syncStatus()', function() {
- var mock = {
- getConfigsByTags: function() {
- return {
- done: function(callback) {
- callback([{properties: {}}]);
- }
- }
- },
- saveToDB: Em.K
- };
-
+ describe('#syncStatus', function() {
beforeEach(function() {
- sinon.stub(App.router, 'get').returns(mock);
- sinon.spy(mock, 'saveToDB');
- sinon.stub(controller, 'valueChanged');
+ sinon.stub(controller, 'propertyDidChange');
});
-
afterEach(function() {
- App.router.get.restore();
- mock.saveToDB.restore();
- controller.valueChanged.restore();
+ controller.propertyDidChange.restore();
});
- it('should save servicesAutoStart to local DB', function() {
- controller.setProperties({
- servicesAutoStart: true
- });
- controller.syncStatus();
- expect(mock.saveToDB.getCall(0).args[0]).to.be.eql([{
- properties: {
- recovery_enabled: 'true'
+ it('should apply new values', function() {
+ controller.set('isGeneralRecoveryEnabled', true);
+ controller.set('componentsConfigsCached', [
+ {
+ ServiceComponentInfo: {
+ component_name: 'C1',
+ recovery_enabled: 'false'
+ }
}
- }]);
- });
-
- it('recoveryEnabledSaved should be synced with recoveryEnabled',
function() {
- controller.reopen({
- servicesAutoStart: true,
- tabs: [Em.Object.create({
- components: [
- Em.Object.create({
- recoveryEnabled: true,
- recoveryEnabledSaved: false
- })
- ]
- })]
- });
- controller.syncStatus();
-
expect(controller.get('tabs')[0].get('components')[0].get('recoveryEnabledSaved')).to.be.true;
- });
-
- it('valueChanged should be called', function() {
+ ]);
+ controller.set('componentsConfigsGrouped', [
+ Em.Object.create({
+ componentName: 'C1',
+ recoveryEnabled: true
+ })
+ ]);
controller.syncStatus();
- expect(controller.valueChanged).to.be.calledonce;
+
expect(controller.get('componentsConfigsCached')[0].ServiceComponentInfo.recovery_enabled).to.be.equal('true');
+ expect(controller.get('isGeneralRecoveryEnabledCached')).to.be.true;
});
});
- describe('#revertStatus()', function() {
+ describe('#restoreCachedValues', function() {
+ beforeEach(function() {
+ sinon.stub(controller, 'parseComponentConfigs').returns([]);
+ controller.set('isGeneralRecoveryEnabledCached', true);
+ controller.restoreCachedValues();
+ });
+ afterEach(function() {
+ controller.parseComponentConfigs.restore();
+ });
- it('component recoveryEnabled should be reverted', function() {
- controller.reopen({
- tabs: [Em.Object.create({
- components: [
- Em.Object.create({
- recoveryEnabled: true,
- recoveryEnabledSaved: false
- })
- ]
- })]
- });
- controller.revertStatus();
-
expect(controller.get('tabs')[0].get('components')[0].get('recoveryEnabled')).to.be.false;
+ it('isGeneralRecoveryEnabled should be true', function() {
+ expect(controller.get('isGeneralRecoveryEnabled')).to.be.true;
});
- it('servicesAutoStart should be reverted', function() {
- controller.reopen({
- servicesAutoStart: true,
- servicesAutoStartSaved: false
- });
- controller.revertStatus();
- expect(controller.get('servicesAutoStart')).to.be.false;
+ it('componentsConfigsGrouped should be set', function() {
+ expect(controller.get('componentsConfigsGrouped')).to.be.eql([]);
});
});
- describe('#enableAll()', function() {
+ describe('#filterComponentsByChange', function() {
- it('should set each recoveryEnabled to true', function() {
+ it('should return checked components', function() {
var components = [
- Em.Object.create({recoveryEnabled: false})
+ Em.Object.create({
+ recoveryEnabled: true,
+ componentName: 'C1'
+ })
];
- controller.enableAll({context: Em.Object.create({components:
components})});
- expect(components[0].get('recoveryEnabled')).to.be.true;
+ controller.set('componentsConfigsCachedMap', {'C1': false});
+ expect(controller.filterComponentsByChange(components,
true)).to.be.eql(['C1']);
});
- });
- describe('#disableAll()', function() {
-
- it('should set each recoveryEnabled to false', function() {
+ it('should return unchecked components', function() {
var components = [
- Em.Object.create({recoveryEnabled: true})
+ Em.Object.create({
+ recoveryEnabled: false,
+ componentName: 'C1'
+ })
];
- controller.disableAll({context: Em.Object.create({components:
components})});
- expect(components[0].get('recoveryEnabled')).to.be.false;
+ controller.set('componentsConfigsCachedMap', {'C1': true});
+ expect(controller.filterComponentsByChange(components,
false)).to.be.eql(['C1']);
});
});
+
});
diff --git
a/ambari-web/test/views/main/admin/service_auto_start/component_auto_start_test.js
b/ambari-web/test/views/main/admin/service_auto_start/component_auto_start_test.js
deleted file mode 100644
index 70fd61e..0000000
---
a/ambari-web/test/views/main/admin/service_auto_start/component_auto_start_test.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * 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 view;
-
-describe('App.MainAdminServiceAutoStartComponentView', function () {
-
- beforeEach(function () {
- view = App.MainAdminServiceAutoStartComponentView.create();
- });
-
-
- describe('#didInsertElement()', function() {
-
- beforeEach(function() {
- sinon.stub(view, 'initSwitcher');
- });
-
- afterEach(function() {
- view.initSwitcher.restore();
- });
-
- it('initSwitcher should be called', function() {
- view.didInsertElement();
- expect(view.initSwitcher).to.be.calledOnce;
- });
- });
-
- describe('#onValueChange()', function() {
- var mock = {
- bootstrapSwitch: Em.K
- };
-
- beforeEach(function() {
- sinon.spy(mock, 'bootstrapSwitch');
- });
-
- afterEach(function() {
- mock.bootstrapSwitch.restore();
- });
-
- it('bootstrapSwitch should be called', function() {
- view.set('switcher', mock);
- view.onValueChange();
- expect(mock.bootstrapSwitch).to.be.calledOnce;
- });
- });
-});
\ No newline at end of file
diff --git a/ambari-web/test/views/main/admin/service_auto_start_test.js
b/ambari-web/test/views/main/admin/service_auto_start_test.js
index 0edcf28..ec70d9b 100644
--- a/ambari-web/test/views/main/admin/service_auto_start_test.js
+++ b/ambari-web/test/views/main/admin/service_auto_start_test.js
@@ -24,7 +24,8 @@ describe('App.MainAdminServiceAutoStartView', function () {
beforeEach(function () {
view = App.MainAdminServiceAutoStartView.create({
controller: Em.Object.create({
- load: Em.K
+ load: Em.K,
+ componentsConfigsGrouped: []
})
});
});
@@ -33,27 +34,15 @@ describe('App.MainAdminServiceAutoStartView', function () {
describe('#didInsertElement()', function() {
beforeEach(function() {
- sinon.stub(view, 'initSwitcher');
- sinon.stub(Em.run, 'next', Em.clb);
- sinon.stub(view.get('controller'), 'load').returns({
- then: Em.clb
- })
+ sinon.stub(view.get('controller'), 'load');
});
-
afterEach(function() {
- view.initSwitcher.restore();
view.get('controller').load.restore();
- Em.run.next.restore();
- });
-
- it('initSwitcher should be called', function() {
- view.didInsertElement();
- expect(view.initSwitcher).to.be.calledOnce;
});
- it('isLoaded should be true', function() {
+ it('load should be called', function() {
view.didInsertElement();
- expect(view.get('isLoaded')).to.be.true;
+ expect(view.get('controller').load.calledOnce).to.be.true;
});
});
@@ -82,4 +71,52 @@ describe('App.MainAdminServiceAutoStartView', function () {
expect(mock.bootstrapSwitch).to.be.calledOnce;
});
});
+
+ describe('#observeAllComponentsChecked', function() {
+
+ it('should skip checking child checkboxes', function() {
+ view.set('skipCyclicCall', true);
+ view.observeAllComponentsChecked();
+ expect(view.get('skipCyclicCall')).to.be.false;
+ });
+
+ it('should check all child checkboxes', function() {
+ view.get('controller').set('componentsConfigsGrouped', [
+ Em.Object.create({
+ recoveryEnabled: false
+ })
+ ]);
+ view.set('skipCyclicCall', false);
+ view.set('allComponentsChecked', true);
+ view.observeAllComponentsChecked();
+
expect(view.get('controller.componentsConfigsGrouped').mapProperty('recoveryEnabled')).to.be.eql(
+ [true]
+ );
+ });
+ });
+
+ describe('#observesEachComponentChecked', function() {
+
+ it('should be false when at least one checkbox unchecked', function() {
+ view.set('allComponentsChecked', true);
+ view.get('controller').set('componentsConfigsGrouped', [
+ Em.Object.create({
+ recoveryEnabled: false
+ })
+ ]);
+ view.observesEachComponentChecked();
+ expect(view.get('allComponentsChecked')).to.be.false;
+ });
+
+ it('should be true when all checked', function() {
+ view.set('allComponentsChecked', false);
+ view.get('controller').set('componentsConfigsGrouped', [
+ Em.Object.create({
+ recoveryEnabled: true
+ })
+ ]);
+ view.observesEachComponentChecked();
+ expect(view.get('allComponentsChecked')).to.be.true;
+ });
+ });
});
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
[email protected].