You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by xi...@apache.org on 2014/11/21 03:49:14 UTC
ambari git commit: AMBARI-8407. Alerts UI > Manage alert groups: add
ability to edit and save notifications.(XIWANG)
Repository: ambari
Updated Branches:
refs/heads/trunk dc50702ef -> eeac84a52
AMBARI-8407. Alerts UI > Manage alert groups: add ability to edit and save notifications.(XIWANG)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/eeac84a5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/eeac84a5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/eeac84a5
Branch: refs/heads/trunk
Commit: eeac84a522bfac86c6e28f9756bfc02bc8961edc
Parents: dc50702
Author: Xi Wang <xi...@apache.org>
Authored: Thu Nov 20 18:31:15 2014 -0800
Committer: Xi Wang <xi...@apache.org>
Committed: Thu Nov 20 18:48:26 2014 -0800
----------------------------------------------------------------------
.../alerts/manage_alert_groups_controller.js | 55 +++++--
ambari-web/app/models/alert_group.js | 7 +-
ambari-web/app/styles/application.less | 6 +
ambari-web/app/styles/common.less | 155 +++++++++++++++++++
.../app/templates/common/editable_list.hbs | 68 ++++++++
.../main/alerts/manage_alert_groups_popup.hbs | 14 +-
ambari-web/app/views.js | 1 +
ambari-web/app/views/common/editable_list.js | 126 +++++++++++++++
.../main/alerts/manage_alert_groups_view.js | 3 +-
9 files changed, 416 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js b/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
index 7833b5c..1d5bc57 100644
--- a/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
+++ b/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
@@ -36,6 +36,8 @@ App.ManageAlertGroupsController = Em.Controller.extend({
alertDefinitions: [],
+ alertNotifications: [],
+
// load alert definitions for all services
loadAlertDefinitions: function () {
App.ajax.send({
@@ -74,6 +76,37 @@ App.ManageAlertGroupsController = Em.Controller.extend({
console.error('Unable to load all alert definitions.');
},
+ // load all alert notifications
+ loadAlertNotifications: function () {
+ App.ajax.send({
+ name: 'alerts.load_alert_notification',
+ sender: this,
+ success: 'onLoadAlertNotificationsSuccess',
+ error: 'onLoadAlertNotificationsError'
+ });
+ },
+
+ onLoadAlertNotificationsSuccess: function (data) {
+ var alertNotifications = [];
+ if (data && data.items) {
+ data.items.forEach( function(target) {
+ if (target && target.AlertTarget) {
+ alertNotifications.pushObject (Em.Object.create({
+ name: target.AlertTarget.name,
+ type: target.AlertTarget.notification_type,
+ description: target.AlertTarget.description,
+ id: target.AlertTarget.id
+ }));
+ }
+ });
+ }
+ this.set('alertNotifications', alertNotifications);
+ },
+
+ onLoadAlertNotificationsError: function () {
+ console.error('Unable to load all alert notifications.');
+ },
+
loadAlertGroups: function () {
this.set('isLoaded', false);
this.set('alertGroups.length', 0);
@@ -112,7 +145,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
default: data.AlertGroup.default,
id: data.AlertGroup.id,
definitions: data.AlertGroup.definitions,
- targets: data.AlertGroup.targets
+ notifications: data.AlertGroup.targets
}));
}
if (this.get('alertGroupsCount') == alertGroups.length) {
@@ -358,7 +391,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
var originalGroup = originalGroups.findProperty('id', group.get('id'));
if (originalGroup) {
if (!(JSON.stringify(group.get('definitions').slice().sort()) === JSON.stringify(originalGroup.get('definitions').slice().sort()))
- || !(JSON.stringify(group.get('targets').slice().sort()) === JSON.stringify(originalGroup.get('targets').slice().sort()))) {
+ || !(JSON.stringify(group.get('notifications').slice().sort()) === JSON.stringify(originalGroup.get('notifications').slice().sort()))) {
groupsToSet.push(group.set('id', originalGroup.get('id')));
} else if (group.get('name') !== originalGroup.get('name') ) {
// should update name
@@ -378,7 +411,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
toSet: groupsToSet,
toCreate: groupsToCreate
};
- }.property('selectedAlertGroup.definitions.@each', 'selectedAlertGroup.definitions.length', 'alertGroups', 'isLoaded'),
+ }.property('selectedAlertGroup.definitions.@each', 'selectedAlertGroup.definitions.length', 'selectedAlertGroup.notifications.@each', 'selectedAlertGroup.notifications.length', 'alertGroups', 'isLoaded'),
isDefsModified: function () {
var modifiedGroups = this.get('defsModifiedAlertGroups');
@@ -403,7 +436,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
},
/**
- * ==============on API side: following are four functions to an alert group: create, delete, update definitions/targets/label of a group ===========
+ * ==============on API side: following are four functions to an alert group: create, delete, update definitions/notificationss/label of a group ===========
*/
/**
* Create a new alert group
@@ -412,15 +445,15 @@ App.ManageAlertGroupsController = Em.Controller.extend({
* @return Returns the created alert group
*/
postNewAlertGroup: function (newAlertGroupData, callback) {
- // create a new group with name , definition and target
+ // create a new group with name , definition and notifications
var data = {
'name': newAlertGroupData.get('name')
};
if (newAlertGroupData.get('definitions').length > 0) {
data.definitions = newAlertGroupData.get('definitions').mapProperty('id');
}
- if (newAlertGroupData.get('targets').length > 0) {
- data.targets = newAlertGroupData.get('targets').mapProperty('id');
+ if (newAlertGroupData.get('notifications').length > 0) {
+ data.targets = newAlertGroupData.get('notifications').mapProperty('id');
}
var sendData = {
name: 'alert_groups.create',
@@ -446,7 +479,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
/**
* PUTs the new alert group information on the server.
- * Changes possible here are the name, definitions, targets
+ * Changes possible here are the name, definitions, notifications
*
* @param {App.ConfigGroup} alertGroup
* @param {Function} successCallback
@@ -459,7 +492,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
"group_id": alertGroup.id,
'name': alertGroup.get('name'),
'definitions': alertGroup.get('definitions').mapProperty('id'),
- 'targets': alertGroup.get('targets').mapProperty('id')
+ 'targets': alertGroup.get('notifications').mapProperty('id')
},
success: 'successFunction',
error: 'errorFunction',
@@ -604,8 +637,8 @@ App.ManageAlertGroupsController = Em.Controller.extend({
var newAlertGroup = App.AlertGroupComplex.create({
name: this.get('alertGroupName').trim(),
definitions: [],
- targets: []
- }) ;
+ notifications: []
+ });
self.get('alertGroups').pushObject(newAlertGroup);
this.hide();
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/models/alert_group.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alert_group.js b/ambari-web/app/models/alert_group.js
index f9924c0..f14ebea 100644
--- a/ambari-web/app/models/alert_group.js
+++ b/ambari-web/app/models/alert_group.js
@@ -105,7 +105,6 @@ App.AlertGroup.FIXTURES = [];
App.AlertGroupComplex = Ember.Object.extend({
id: null,
name: null,
- description: null,
default: null,
definitions: [],
targets: [],
@@ -114,6 +113,11 @@ App.AlertGroupComplex = Ember.Object.extend({
* all alert definitions that belong to all services
*/
alertDefinitionsBinding: 'App.router.manageAlertGroupsController.alertDefinitions',
+ /**
+ * all alert notifications
+ */
+ alertNotificationsBinding: 'App.router.manageAlertGroupsController.alertNotifications',
+
displayName: function () {
var name = this.get('name');
@@ -152,6 +156,7 @@ App.AlertGroupComplex = Ember.Object.extend({
isAddDefinitionsDisabled: function () {
return (this.get('default') || this.get('availableDefinitions.length') === 0);
}.property('availableDefinitions.length')
+
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index 99a6d45..e834cab 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -6815,6 +6815,12 @@ i.icon-asterisks {
}
}
+.notification-editable-list {
+ .title {
+ font-weight: bold;
+ }
+}
+
.new-config-group-div {
td {
vertical-align: top;
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/styles/common.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/common.less b/ambari-web/app/styles/common.less
index e003989..8b1ad84 100644
--- a/ambari-web/app/styles/common.less
+++ b/ambari-web/app/styles/common.less
@@ -27,3 +27,158 @@
* Health status(service/host/host component health)icon colors ends
***********************************************************************/
+.editable-list-container.well{
+ padding: 10px;
+ position: relative;
+ margin-bottom: 25px;
+ cursor: pointer;
+}
+.editable-list-container.well.edit-mode{
+ cursor: default;
+}
+.editable-list-container.well.disabled{
+ background: white;
+}
+
+.editable-list-container .items-box{
+
+}
+.editable-list-container .items-box ul.items-list{
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+.editable-list-container .items-box ul.items-list li.item{
+ display: inline-block;
+ padding: 4px 8px;
+ margin: 0 5px 5px 2px;
+ background: white;
+ border: 1px solid #ebebeb;
+ max-width: 100%;
+ white-space: nowrap;
+ position: relative;
+}
+
+.editable-list-container.edit-mode .items-box ul.items-list li.item{
+ padding-right: 25px;
+}
+
+.editable-list-container .items-box ul.items-list li.item .close{
+ margin: -2px 0 0 5px;
+ width: 13px;
+ outline: none;
+ position: absolute;
+ display: none;
+}
+.editable-list-container.edit-mode .items-box ul.items-list li.item .close{
+ display: inline-block;
+}
+
+.editable-list-container .items-box ul.items-list li a{
+ text-decoration: none;
+}
+
+.editable-list-container.edit-mode .items-box ul.items-list li.item.add-item-input .ember-text-field{
+ display: inline-block!important;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ position: relative;
+ padding: 0px 0px;
+ margin: 0px 0px;
+ border: none;
+ width: 50px;
+ height: 18px;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+ -webkit-transition: none;
+ -moz-transition: none;
+ -o-transition: none;
+ transition: none;
+}
+
+.editable-list-container .items-box ul.items-list li.item.add-item{
+ color: #ddd;
+}
+
+.typeahead-box{
+ position: absolute;
+ left: 0;
+ margin-top: 5px;
+ background: white;
+ border: 1px solid #ebebeb;
+ z-index: 1000;
+ min-width: 65px;
+}
+.typeahead-box ul{
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+.typeahead-box ul li{
+ padding: 3px 5px;
+ display: block;
+ cursor: pointer;
+}
+
+.typeahead-box ul li.selected, .typeahead-box ul li:hover{
+ background: #eee;
+}
+
+.editable-list-container .actions-panel{
+ position: absolute;
+ right: 5px;
+ bottom: -30px;
+ padding: 2px 5px 5px 5px;
+ background: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ border-top: none;
+ border-radius: 0 0 4px 4px;
+
+ -webkit-transition: all 0.3s;
+ -o-transition: all 0.3s;
+ transition: all 0.3s;
+
+ -ms-transform-origin: 0% 0%; /* IE 9 */
+ -webkit-transform-origin: 0% 0%; /* Chrome, Safari, Opera */
+ transform-origin: 0% 0%;
+
+ -webkit-transform: rotateX(0deg);
+ -ms-transform: rotateX(0deg);
+ -o-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+
+ .btn-xs {
+ padding: 1px 5px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+ }
+ .icon-remove {
+ color: #000000;
+ }
+ .icon-ok {
+ color: white;
+ }
+}
+
+.editable-list-container.disabled .pencil-box{
+ display: none;
+}
+.editable-list-container .pencil-box{
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ opacity: 0;
+ -webkit-transition: all 0.3s;
+ -o-transition: all 0.3s;
+ transition: all 0.3s;
+}
+.editable-list-container:hover .pencil-box{
+ opacity: 1;
+}
+.editable-list-container.edit-mode:hover .pencil-box{
+ opacity: 0;
+}
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/templates/common/editable_list.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/editable_list.hbs b/ambari-web/app/templates/common/editable_list.hbs
new file mode 100644
index 0000000..c905662
--- /dev/null
+++ b/ambari-web/app/templates/common/editable_list.hbs
@@ -0,0 +1,68 @@
+{{!
+* 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.
+}}
+
+<div {{bindAttr class=":editable-list-container :well view.editMode"}}>
+ <div class="items-box" {{action enableEditMode target="view"}}>
+ <ul class="items-list">
+ {{#each item in view.items}}
+ <li class="item">
+ <span>
+ <a href>{{item.name}}</a>
+ <button {{action removeFromItems item target="view"}} type="button" class="close">
+ <span>×x</span>
+ </button>
+ </span>
+ </li>
+ {{/each}}
+ {{#if view.editMode}}
+ <li class="item add-item-input">
+ {{view Ember.TextField valueBinding="view.input" placeholder="New" classBinding="input-area"}}
+ {{#if view.typeahead}}
+ <div class="typeahead-box">
+ <ul>
+ {{#each item in view.typeahead}}
+ <li {{action addItem item target="view"}} class="">{{item.name}}</li>
+ {{/each}}
+ </ul>
+ </div>
+ {{/if}}
+ </li>
+ {{else}}
+ {{#if view.items}}
+ {{else}}
+ <li class="item add-item">Add</li>
+ {{/if}}
+ {{/if}}
+ </ul>
+ </div>
+
+ {{#if view.editMode}}
+ <div class="actions-panel">
+ <button class="btn btn-default btn-xs" {{action onSecondary target="view"}}>
+ <span class="icon-remove"></span>
+ </button>
+ <button class="btn btn-primary btn-xs" {{action onPrimary target="view"}}>
+ <span class="icon-ok"></span>
+ </button>
+ </div>
+ {{else}}
+ <div class="pencil-box" {{action enableEditMode target="view"}}>
+ <span class="icon-pencil"></span>
+ </div>
+ {{/if}}
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/templates/main/alerts/manage_alert_groups_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/alerts/manage_alert_groups_popup.hbs b/ambari-web/app/templates/main/alerts/manage_alert_groups_popup.hbs
index 3e47b3c..554f073 100644
--- a/ambari-web/app/templates/main/alerts/manage_alert_groups_popup.hbs
+++ b/ambari-web/app/templates/main/alerts/manage_alert_groups_popup.hbs
@@ -66,12 +66,14 @@
<a rel="button-info" {{bindAttr data-original-title="view.removeDefinitionTooltip" class=":btn isDeleteDefinitionsDisabled:disabled"}} {{action deleteDefinitions target="controller"}} ><i class="icon-minus"></i></a>
</div>
</div>
- <div class="row-fluid">
- <div class="span2">{{t alerts.actions.manage_alert_groups_popup.notifications}}</div>
- <div class="span10">
- {{#each target in selectedAlertGroup.targets}}
- {{target.name}}
- {{/each}}
+
+ <div class="row-fluid"> </div>
+ <div class="clearfix"></div>
+
+ <div class="row-fluid notification-editable-list">
+ <div class="span3 title"><span class="icon-envelope-alt"></span> {{t alerts.actions.manage_alert_groups_popup.notifications}}</div>
+ <div class="span8">
+ {{view App.EditableList itemsBinding="selectedAlertGroup.notifications" resourcesBinding="selectedAlertGroup.alertNotifications" nameBinding="selectedAlertGroup.displayName"}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index dab4751..586064f 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -25,6 +25,7 @@ require('views/common/chart/pie');
require('views/common/chart/linear');
require('views/common/chart/linear_time');
require('views/common/modal_popup');
+require('views/common/editable_list');
require('views/common/rolling_restart_view');
require('views/common/select_custom_date_view');
require('views/common/metric');
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/views/common/editable_list.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/editable_list.js b/ambari-web/app/views/common/editable_list.js
new file mode 100644
index 0000000..847c603
--- /dev/null
+++ b/ambari-web/app/views/common/editable_list.js
@@ -0,0 +1,126 @@
+/**
+ * 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.EditableList = Ember.View.extend({
+
+ templateName: require('templates/common/editable_list'),
+
+ items: [], // items show on list
+ resources: [], // originial resources including all items
+ itemsOriginal: [], //backup of items
+
+ editMode: false,
+ input: '',
+ typeahead: [],
+ selectedTypeahed: 0,
+
+ onPrimary: function (event) {
+ this.set('editMode', false);
+ this.set('input', '');
+ if(event){
+ event.stopPropagation();
+ }
+ },
+
+ onSecondary: function () {
+ // restore all items
+ this.set('items', this.get('itemsOriginal'));
+ this.set('input', '');
+ this.set('editMode', false);
+ },
+
+ enableEditMode: function() {
+ this.set('input', '');
+ this.set('editMode', true);
+ },
+
+ removeFromItems: function(event) {
+ var items = this.get('items');
+ items.removeObject(event.context);
+ this.set('input', '');
+ },
+
+ updateCategory: function() {
+ this.set('itemsOriginal', Em.copy(this.get('items')));
+ this.set('input', '');
+ this.set('editMode', false);
+ }.observes('name'),
+
+ /**
+ * available items to add, will show up typing ahead
+ */
+ availableItemsToAdd: function () {
+ var allItems = Em.copy(this.get('resources'));
+ var input = this.get('input');
+ var toRemove = [];
+ var existed = this.get('items');
+ allItems.forEach(function(item) {
+ if (item.name.indexOf(input) < 0 || existed.findProperty('name', item.name)) {
+ toRemove.push(item);
+ }
+ });
+ toRemove.forEach(function(item) {
+ allItems.removeObject(item);
+ });
+ return allItems;
+ }.property('items', 'input'),
+
+ addItem: function(event) {
+ var items = this.get('items');
+ var toAdd;
+ if (event.context) {
+ toAdd = event.context;
+ } else if (this.get('typeahead.length') > 0){
+ toAdd = this.get('typeahead')[this.get('selectedTypeahead')];
+ }
+ items.pushObject(event.context);
+ this.set('input', '');
+ },
+
+ updateTypeahead: function() {
+ var newValue = this.get('input');
+ var self = this;
+ if(newValue){
+ var newValue = newValue.split(',');
+ if( newValue.length > 1){
+ // If coma separated string, then just add all items to list
+ newValue.forEach( function(item) {
+ self.addItem(item);
+ });
+ self.clearInput();
+ self.focusOnInput();
+ } else {
+ // Load typeahed items based on current input
+ var items = self.get('availableItemsToAdd');
+ self.set('typeahead', items.slice(0, 5));
+ self.set('selectedTypeahed', 0);
+ }
+ } else {
+ self.set('typeahead', []);
+ self.set('selectedTypeahed', 0);
+ this.focusOnInput();
+ }
+
+ }.observes('input'),
+
+ focusOnInput: function() {
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/eeac84a5/ambari-web/app/views/main/alerts/manage_alert_groups_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/alerts/manage_alert_groups_view.js b/ambari-web/app/views/main/alerts/manage_alert_groups_view.js
index 7449803..a21a402 100644
--- a/ambari-web/app/views/main/alerts/manage_alert_groups_view.js
+++ b/ambari-web/app/views/main/alerts/manage_alert_groups_view.js
@@ -57,13 +57,14 @@ App.MainAlertsManageAlertGroupView = Em.View.extend({
onLoad: function () {
if (this.get('controller.isLoaded')) {
- this.set('selectedAlertGroup', this.get('controller.alertGroups')[0])
+ this.set('selectedAlertGroup', this.get('controller.alertGroups')[0]);
}
}.observes('controller.isLoaded', 'controller.alertGroups'),
willInsertElement: function() {
this.get('controller').loadAlertGroups();
this.get('controller').loadAlertDefinitions();
+ this.get('controller').loadAlertNotifications();
},
didInsertElement: function () {