Merge Autoscaler UI implemetation

This change includes the new dialog box for the CloudStack Autoscaler
implementation. It is accessible by a button ('Autoscaler') that
appears under each LB rule.

This also contains changes to the multiEdit widget to support features
required for Autoscaler:

-Fixes context/data passing to custom button widgets
-Fixes data retrieval for select fields
This commit is contained in:
Brian Federle 2012-07-30 11:02:23 -07:00
parent d467ff8a49
commit c11aab3c7e
7 changed files with 1584 additions and 10 deletions

View File

@ -9634,6 +9634,229 @@ div.panel.ui-dialog div.list-view div.fixed-header {
overflow: auto;
}
/*Autoscaler*/
.ui-dialog div.autoscaler {
overflow: auto;
max-height: 600px;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=securityGroups] {
display: block;
width: 370px;
float: left;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=diskOfferingId] {
display: inline-block;
width: 370px;
float: left;
position: relative;
margin-top: 1px;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=minInstance] {
display: block;
width: 50%;
float: left;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=maxInstance] {
display: inline-block;
width: 50%;
float: left;
left: -30px;
position: relative;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=interval] {
display: block;
width: 50%;
float: left;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=quietTime] {
display: inline-block;
width: 50%;
float: left;
left: -15px;
position: relative;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=snmpCommunity] {
display: block;
width: 50%;
float: left;
}
.ui-dialog div.autoscaler div.form-container div.form-item[rel=snmpPort] {
display: inline-block;
width: 50%;
float: left;
left: -15px;
position: relative;
}
.ui-dialog div.autoscaler div.form-container div.value select {
width: 88%;
float: left;
}
div.ui-dialog div.autoscaler div.scale-up-policy-title div.form-container {
height: 55px;
}
div.ui-dialog div.autoscaler div.scale-down-policy-title div.form-container {
height: 55px;
}
div.ui-dialog div.autoscaler div.scale-up-policy div.multi-edit {
margin-top: 0px;
}
div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit {
margin-top: 0px;
}
div.ui-dialog div.autoscaler div.scale-up-policy-title {
color: #0055BB;
margin-left: -650px;
margin-top: 40px;
}
div.ui-dialog div.autoscaler div.scale-up-policy-title label {
font-size: 13px;
margin-left: 200px;
margin-right: 10px;
}
div.ui-dialog div.autoscaler div.scale-up-policy-title hr.policy-divider {
border-left: 1px none #38546D;
border-right: 1px none #16222C;
border-top: 1px none #38546D;
margin-bottom: 12px;
}
div.ui-dialog div.autoscaler div.scale-down-policy-title hr.policy-divider {
border-left: 1px none #38546D;
border-right: 1px none #16222C;
border-top: 1px none #38546D;
margin-bottom: 12px;
}
div.ui-dialog div.autoscaler div.field-group.bottom-fields hr.policy-divider {
border-left: 1px none #38546D;
border-right: 1px none #16222C;
border-top: 1px none #38546D;
margin-top: 15px;
margin-bottom: -1px;
}
div.ui-dialog div.autoscaler div.scale-down-policy-title label {
font-size: 13px;
margin-left: 170px;
margin-right: 10px;
}
div.ui-dialog div.autoscaler div.scale-down-policy-title {
color: #0055BB;
margin-left: -620px;
margin-top: 10px;
}
div.ui-dialog div.autoscaler div.scale-up-policy-title div.form-container div.form-item div.value input[type=text] {
margin-left: 195px;
width: 30%;
margin-top: 1px;
}
div.ui-dialog div.autoscaler div.scale-up-policy-title div.form-container div.form-item div.name {
margin-left: 390px;
}
div.ui-dialog div.autoscaler div.scale-down-policy-title div.form-container div.form-item div.value input[type=text] {
margin-left: 670px;
width: 30%;
margin-top: -16px;
}
div.ui-dialog div.autoscaler div.scale-down-policy-title div.form-container div.form-item div.name {
margin-left: 390px;
}
div.ui-dialog div.autoscaler div.scale-up-policy div.multi-edit div.data div.data-body div.data-item {
margin-bottom: 0px;
margin-right: 22px;
}
div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-body div.data-item {
margin-bottom: 0px;
margin-right: 22px;
}
div.ui-dialog div.autoscaler div.scale-up-policy div.slide-label {
color: #A5A3A7;
font-size: 14px;
margin-bottom: 3px;
margin-left: 755px;
width: 12px;
}
div.ui-dialog div.autoscaler div.scale-down-policy div.slide-label {
color: #A5A3A7;
font-size: 14px;
margin-bottom: 3px;
margin-left: 755px;
width: 12px;
}
div.ui-dialog div.autoscaler div.scale-up-policy div.hide {
background: #FFFFFF url("../images/minus.png") no-repeat 38% 59%;
border: 1px solid #D0D0D0;
border-radius: 9px 9px 9px 9px;
cursor: pointer;
float: right;
height: 15px;
margin: -20px 45px 0 11px;
width: 14px;
}
div.ui-dialog div.autoscaler div.scale-down-policy div.hide {
background: #FFFFFF url("../images/minus.png") no-repeat 31% 54%;
border: 1px solid #D0D0D0;
border-radius: 9px 9px 9px 9px;
cursor: pointer;
float: right;
height: 15px;
margin: -20px 45px 0 11px;
width: 14px;
}
div.ui-dialog div.autoscaler div.scale-up-policy div.expand {
background: #FFFFFF url("../images/sprites.png") repeat -541px -499px;
border: 1px solid #D0D0D0;
border-radius: 9px 9px 9px 9px;
cursor: pointer;
float: right;
height: 15px;
margin: -20px 45px 0 11px;
width: 14px;
}
div.ui-dialog div.autoscaler div.scale-down-policy div.expand {
background: #FFFFFF url("../images/sprites.png") repeat -541px -499px;
border: 1px solid #D0D0D0;
border-radius: 9px 9px 9px 9px;
cursor: pointer;
float: right;
height: 15px;
margin: -20px 45px 0 11px;
width: 14px;
}
div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-item div.name label {
font-size: 11px;
}
/*Action icons*/
.action.edit .icon {
background-position: 1px -1px;

BIN
ui/images/minus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1624,6 +1624,8 @@
<script type="text/javascript" src="scripts/ui-custom/projects.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/cloudStack.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/lbStickyPolicy.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/autoscaler.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/autoscaler.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/zoneChart.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/dashboard.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/installWizard.js?t=<%=now%>"></script>

1038
ui/scripts/autoscaler.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -929,6 +929,13 @@
action: cloudStack.lbStickyPolicy.dialog()
}
},
'autoScale': {
label: 'AutoScale',
custom: {
buttonLabel: 'label.configure',
action: cloudStack.uiCustom.autoscaler(cloudStack.autoscaler)
}
},
'add-vm': {
label: 'label.add.vms',
addButton: true
@ -2244,6 +2251,14 @@
action: cloudStack.lbStickyPolicy.dialog()
}
},
'autoScale': {
label: 'AutoScale',
custom: {
buttonLabel: 'label.configure',
action: cloudStack.uiCustom.autoscaler(cloudStack.autoscaler)
}
},
'add-vm': {
label: 'label.add.vms',
addButton: true
@ -2544,7 +2559,10 @@
_maxLength: {
name: 7
},
sticky: stickyData
sticky: stickyData,
autoScale: {
lbRuleID: item.id
}
});
});

View File

@ -0,0 +1,278 @@
// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
(function($, cloudStack) {
cloudStack.uiCustom.autoscaler = function(args) {
// Place outer args here as local variables
// i.e, -- var dataProvider = args.dataProvider
var forms = $.extend(true, {}, args.forms);
var topfields = forms.topFields;
var bottomfields = forms.bottomFields;
var scaleuppolicy = forms.scaleUpPolicy;
var scaledownpolicy = forms.scaleDownPolicy;
var dataProvider = cloudStack.autoscaler.dataProvider;
return function(args) {
var context = args.data ?
$.extend(true, {}, args.context, {
lbRules: [args.data]
}) : args.context;
var formData = args.formData;
var $autoscalerDialog = $('<div>').addClass('autoscaler');
var $topFields = $('<div>').addClass('field-group top-fields');
var $bottomFields = $('<div>').addClass('field-group bottom-fields');
var $scaleUpPolicy = $('<div>').addClass('scale-up-policy');
var $slideScaleUp = $('<div></div>').addClass('expand');
var $hideScaleUp = $('<div></div>').addClass('hide');
var $scaleUpLabel= $('<div>Show</div>').addClass('slide-label');
var $scaleUpHideLabel=$('<div>Hide</div>').addClass('slide-label');
var $scaleDownHideLabel=$('<div>Hide</div>').addClass('slide-label');
var $scaleDownLabel=$('<div>Show</div>').addClass('slide-label');
var $slideScaleDown = $('<div></div>').addClass('expand');
var $hideScaleDown = $('<div></div>').addClass('hide');
var $scaleUpDivider = $('<hr></hr>').addClass('policy-divider');
var $scaleDownDivider = $('<hr></hr>').addClass('policy-divider');
var $bottomFieldDivider = $('<hr></hr>').addClass('policy-divider');
var $scaleDownPolicy = $('<div>').addClass('scale-down-policy');
var $scaleUpPolicyTitle = $('<div>').addClass('scale-up-policy-title')
.html("Scale Up Policy");
var $scaleDownPolicyTitle = $('<div>').addClass('scale-down-policy-title')
.html("Scale Down Policy");
var topFieldForm, $topFieldForm,
bottomFieldForm, $bottomFieldForm,
scaleUpPolicyTitleForm, $scaleUpPolicyTitleForm,
scaleDownPolicyTitleForm, $scaleDownPolicyTitleForm,
scaleUpPolicyForm, scaleDownPolicyForm;
var renderDialogContent = function(args) {
var data = args.data ? args.data : {};
// Setup default values, in case where existing data is present
var setDefaultFields = function(fieldID, field) {
var fieldData = data[fieldID];
if (fieldData && !field.isBoolean) {
field.defaultValue = fieldData;
} else {
field.isChecked = fieldData;
}
};
$.each(topfields, setDefaultFields);
$.each(bottomfields, setDefaultFields);
// Create and append top fields
// -- uses create form to generate fields
topFieldForm = cloudStack.dialog.createForm({
context: context,
noDialog: true, // Don't render a dialog, just return $formContainer
form: {
title: '',
fields: topfields
}
});
$topFieldForm = topFieldForm.$formContainer;
$topFieldForm.appendTo($topFields);
scaleUpPolicyTitleForm = cloudStack.dialog.createForm({
context: context,
noDialog: true,
form: {
title: '',
fields: {
scaleUpDuration: { label: 'Duration', validation: { required: true } }
}
}
});
$scaleUpPolicyTitleForm = scaleUpPolicyTitleForm.$formContainer;
$scaleUpPolicyTitleForm.appendTo($scaleUpPolicyTitle);
scaleDownPolicyTitleForm = cloudStack.dialog.createForm({
context: context,
noDialog: true,
form: {
title: '',
fields: {
scaleDownDuration: { label: 'Duration', validation: { required: true } }
}
}
});
$scaleDownPolicyTitleForm = scaleDownPolicyTitleForm.$formContainer;
$scaleDownPolicyTitleForm.appendTo($scaleDownPolicyTitle);
// Make multi-edits
//
// Scale up policy
if (data.scaleUpPolicy && $.isArray(data.scaleUpPolicy.conditions)) {
$autoscalerDialog.data('autoscaler-scale-up-data',
data.scaleUpPolicy.conditions);
}
if (data.scaleUpPolicy && data.scaleUpPolicy.duration) {
$scaleUpPolicyTitleForm.find('input[name=scaleUpDuration]').val(
data.scaleUpPolicy.duration
);
}
scaleuppolicy.context = context;
scaleUpPolicyForm = $scaleUpPolicy.multiEdit(scaleuppolicy);
// Scale down policy
if (data.scaleDownPolicy && $.isArray(data.scaleDownPolicy.conditions)) {
$autoscalerDialog.data('autoscaler-scale-down-data',
data.scaleDownPolicy.conditions);
}
if (data.scaleDownPolicy && data.scaleDownPolicy.duration) {
$scaleDownPolicyTitleForm.find('input[name=scaleDownDuration]').val(
data.scaleDownPolicy.duration
);
}
scaledownpolicy.context = context;
scaleDownPolicyForm = $scaleDownPolicy.multiEdit(scaledownpolicy);
// Create and append bottom fields
bottomFieldForm = cloudStack.dialog.createForm({
context: context,
noDialog: true, // Don't render a dialog, just return $formContainer
form: {
title: '',
fields: bottomfields
}
});
$bottomFieldForm = bottomFieldForm.$formContainer;
$bottomFieldForm.appendTo($bottomFields);
// Append main div elements
$autoscalerDialog.append(
$topFields,
$scaleUpPolicyTitle,
$scaleUpPolicy,
$scaleDownPolicyTitle,
$scaleDownPolicy,
$bottomFields
);
// Render dialog
//$autoscalerDialog.find('.form-item[rel=templateNames] label').hide();
/* Duration Fields*/
//$('div.ui-dialog div.autoscaler').find('div.scale-up-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
//$('div.ui-dialog div.autoscaler').find('div.scale-down-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
/*Dividers*/
$autoscalerDialog.find('div.scale-up-policy-title').prepend($scaleUpDivider);
$autoscalerDialog.find('div.scale-down-policy-title').prepend($scaleDownDivider);
$autoscalerDialog.find('div.field-group.bottom-fields').prepend($bottomFieldDivider);
/* Hide effects for multi-edit table*/
$autoscalerDialog.find('div.scale-up-policy').prepend($hideScaleUp);
$autoscalerDialog.find('div.scale-down-policy ').prepend($hideScaleDown);
$autoscalerDialog.find('div.scale-up-policy').prepend($scaleUpHideLabel);
$autoscalerDialog.find('div.scale-down-policy').prepend($scaleDownHideLabel);
/*Toggling the labels and data-item table - SCALE UP POLICY*/
$autoscalerDialog.find('div.scale-up-policy div.hide').click(function() {
$autoscalerDialog.find('div.scale-up-policy div.multi-edit div.data-item').slideToggle();
$scaleUpLabel = $autoscalerDialog.find('div.scale-up-policy div.slide-label').replaceWith($scaleUpLabel);
});
/*Toggling the images */
$('div.ui-dialog div.autoscaler div.scale-up-policy div.hide').click(function() {
$(this).toggleClass('expand hide');
});
$('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
$(this).toggleClass('expand hide');
});
/*Toggling the labels and data-item table - SCALE DOWN POLICY*/
$('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
$('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle();
$scaleDownLabel = $('div.ui-dialog div.autoscaler div.scale-down-policy div.slide-label').replaceWith($scaleDownLabel);
});
$('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.expand').click(function() { $('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle(); });
$autoscalerDialog.dialog('option', 'position', 'center');
$autoscalerDialog.dialog('option', 'height', 'auto');
};
var $loading = $('<div>').addClass('loading-overlay').appendTo($autoscalerDialog);
$autoscalerDialog.dialog({
title: 'AutoScale Configuration Wizard',
width: 825,
height: 600,
draggable: true,
closeonEscape: false,
overflow:'auto',
open:function() {
$("button").each(function(){
$(this).attr("style", "left: 600px; position: relative; margin-right: 5px; ");
});
},
buttons: [
{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$autoscalerDialog.dialog('destroy');
$('.overlay').remove();
}
},
{
text: _l('Apply'),
'class': 'ok',
click: function() {
var data = cloudStack.serializeForm($('.ui-dialog .autoscaler form'));
$loading.appendTo($autoscalerDialog);
cloudStack.autoscaler.actions.add({
formData: formData,
context: context,
data: data,
response: {
success: function() {
$loading.remove();
$autoscalerDialog.dialog('destroy');
$autoscalerDialog.closest(':ui-dialog').remove();
$('.overlay').remove();
cloudStack.dialog.notice({
message: 'Autoscaler configured successfully.'
});
},
error: function(message) {
cloudStack.dialog.notice({ message: message });
$loading.remove();
}
}
});
}
}
]
}).closest('.ui-dialog').overlay();
dataProvider({
context: context,
response: {
success: function(args) {
$loading.remove();
renderDialogContent(args);
if (args.data && args.data.isAdvanced) {
$autoscalerDialog.find('input[type=checkbox]').trigger('click');
$autoscalerDialog.find('input[type=checkbox]').attr('checked', 'checked');
}
}
}
});
};
};
}(jQuery, cloudStack));

View File

@ -124,13 +124,20 @@
$td.attr('title', data[fieldName]);
}
} else if (field.select) {
$td.append($('<span>').html(_s(
// Get matching option text
$multi.find('select').filter(function() {
return $(this).attr('name') == fieldName;
}).find('option').filter(function() {
return $(this).val() == data[fieldName];
}).html())));
// Get matching option text
var $matchingSelect = $multi.find('select')
.filter(function() {
return $(this).attr('name') == fieldName;
});
var $matchingOption = $matchingSelect.find('option')
.filter(function() {
return $(this).val() == data[fieldName];
});
var matchingValue = $matchingOption.size() ?
$matchingOption.html() : data[fieldName];
$td.append($('<span>').html(_s(matchingValue)));
} else if (field.addButton && !options.noSelect) {
if (options.multipleAdd) {
$addButton.click(function() {
@ -169,9 +176,14 @@
_l(data[fieldName]['_buttonLabel']) : _l(field.custom.buttonLabel));
$button.click(function() {
var $button = $(this);
var context = $.extend(true, {},
options.context ?
options.context : cloudStack.context, {
multiRules: [data]
});
field.custom.action({
context: options.context ? options.context : cloudStack.context,
context: context,
data: $td.data('multi-custom-data'),
$item: $td,
response: {
@ -749,7 +761,10 @@
$('<div>').addClass('button add-vm custom-action')
.html(_l(field.custom.buttonLabel))
.click(function() {
var formData = getMultiData($multi);
field.custom.action({
formData: formData,
context: context,
data: $td.data('multi-custom-data'),
response: {
@ -942,7 +957,7 @@
}
// Get existing data
getData();
setTimeout(function() { getData(); });
var fullRefreshEvent = function(event) {
if ($multi.is(':visible')) {