1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-26 06:50:09 +03:00

Feature #4317: Add new user-input types, make capacity user-inputs

New types: number, range, list. The capacity definition creates
user inputs for the CPU, MEMORY and VCPU
This commit is contained in:
Carlos Martín 2016-02-12 10:51:03 +01:00
parent 6653c64c6e
commit 1f1d0fcf01
12 changed files with 884 additions and 263 deletions

View File

@ -27,6 +27,7 @@ define(function(require) {
var CustomTagsTable = require('utils/custom-tags-table');
var FilesTable = require('tabs/files-tab/datatable')
var OpenNebulaHost = require('opennebula/host');
var UserInputs = require('utils/user-inputs');
/*
TEMPLATES
@ -161,28 +162,76 @@ define(function(require) {
that.contextFilesTable.initialize(selectOptions);
that.contextFilesTable.refreshResourceTableSelect();
// TODO: bug, user_input_name pattern is ignored
context.on("click", ".add_service_custom_attr", function() {
$(".service_custom_attrs tbody").append(
$(".service_custom_attrs tbody", context).append(
'<tr>' +
'<td>' +
'<input class="user_input_name" type="text" pattern="[\\w]+"/>' +
'<small class="error">' + Locale.tr("Only word characters are allowed") + '</small>' +
'<label>' + Locale.tr("Name") +
'<input class="user_input_name" type="text" pattern="[\\w]+"/>' +
'<small class="error">' + Locale.tr("Only word characters are allowed") + '</small>' +
'</label>' +
'</td>' +
'<td>' +
'<select class="user_input_type" >' +
'<option value="text">' + Locale.tr("text") + '</option>' +
'<option value="text64">' + Locale.tr("text (base64)") + '</option>' +
'<option value="password">' + Locale.tr("password") + '</option>' +
'</select>' +
'<label>' + Locale.tr("Type") +
'<select class="user_input_type" >' +
'<option value="text">' + Locale.tr("text") + '</option>' +
'<option value="text64">' + Locale.tr("text (base64)") + '</option>' +
'<option value="password">' + Locale.tr("password") + '</option>' +
'<option value="number">' + Locale.tr("number") + '</option>' +
'<option value="number-float">'+Locale.tr("number (float)") + '</option>' +
'<option value="range">' + Locale.tr("range") + '</option>' +
'<option value="range-float">' +Locale.tr("range (float)") + '</option>' +
'<option value="list">' + Locale.tr("list") + '</option>' +
'</select>' +
'</label>' +
'</td>' +
'<td>' +
'<textarea class="user_input_description"/>' +
'<label>' + Locale.tr("Description") +
'<textarea class="user_input_description"/>' +
'</label>' +
'<div class="user_input_type_right number number-float">' +
'<label class="user_input_opt">' + Locale.tr("Default value") +
'<input type=text class="user_input_initial" placeholder="42"/>' +
'</label>' +
'</div>' +
'<div class="user_input_type_right range range-float">' +
'<label class="user_input_opt">' + Locale.tr("Options") +
'<input type=text class="user_input_params" placeholder="2..16"/>' +
'</label>' +
'<label class="user_input_opt">' + Locale.tr("Default value") +
'<input type=text class="user_input_initial" placeholder="8"/>' +
'</label>' +
'</div>' +
'<div class="user_input_type_right list">' +
'<label class="user_input_opt">' + Locale.tr("Options") +
'<input type=text class="user_input_params" placeholder="optA,optB,optC"/>' +
'</label>' +
'<label class="user_input_opt">' + Locale.tr("Default value") +
'<input type=text class="user_input_initial" placeholder="optB"/>' +
'</label>' +
'</div>' +
'</td>' +
'<td>' +
'</br>' +
'<a href="#"><i class="fa fa-times-circle remove-tab"></i></a>' +
'</td>' +
'</tr>');
})
$("select.user_input_type", context).change();
});
context.on("change", "select.user_input_type", function() {
var row = $(this).closest("tr");
$(".user_input_type_right", row).hide();
$(".user_input_type_right."+this.value, row).show();
});
context.on("click", ".service_custom_attrs i.remove-tab", function() {
var tr = $(this).closest('tr');
@ -241,11 +290,29 @@ define(function(require) {
var userInputsJSON = {};
$(".service_custom_attrs tbody tr", context).each(function() {
if ($(".user_input_name", $(this)).val()) {
var attr_name = $(".user_input_name", $(this)).val();
var attr_type = $(".user_input_type", $(this)).val();
var attr_desc = $(".user_input_description", $(this)).val();
userInputsJSON[attr_name] = "M|" + attr_type + "|" + attr_desc;
contextJSON[attr_name] = "$" + attr_name.toUpperCase();
var attr = {};
attr.name = $(".user_input_name", $(this)).val();
attr.mandatory = true;
attr.type = $(".user_input_type", $(this)).val();
attr.description = $(".user_input_description", $(this)).val();
switch(attr.type){
case "number":
case "number-float":
attr.initial = $("."+attr.type+" input.user_input_initial", $(this)).val();
break;
case "range":
case "range-float":
case "list":
attr.params = $("."+attr.type+" input.user_input_params", $(this)).val();
attr.initial = $("."+attr.type+" input.user_input_initial", $(this)).val();
break;
}
userInputsJSON[attr.name] = UserInputs.marshall(attr);
contextJSON[attr.name] = "$" + attr.name.toUpperCase();
}
});
@ -300,10 +367,27 @@ define(function(require) {
$(".add_service_custom_attr", context).trigger("click");
var context = $(".service_custom_attrs tbody tr", context).last();
var parts = value.split("|");
$(".user_input_name", context).val(key);
$(".user_input_type", context).val(parts[1]);
$(".user_input_description", context).val(TemplateUtils.escapeDoubleQuotes(TemplateUtils.htmlDecode(parts[2])));
var attr = UserInputs.unmarshall(value);
$(".user_input_type", context).val(attr.type).change();
$(".user_input_description", context).val(attr.description);
switch(attr.type){
case "number":
case "number-float":
$("."+attr.type+" input.user_input_initial", context).val(attr.initial);
break;
case "range":
case "range-float":
case "list":
$("."+attr.type+" input.user_input_params", context).val(attr.params);
$("."+attr.type+" input.user_input_initial", context).val(attr.initial);
break;
}
if (contextJSON) {
delete contextJSON[key];

View File

@ -112,13 +112,14 @@
</thead>
<thead>
<tr>
<th style="width:30%">{{tr "Name"}}</th>
<th style="width:20%">{{tr "Type"}}</th>
<th style="width:50%">{{tr "Description"}}</th>
<th style="width:30%"></th>
<th style="width:20%"></th>
<th style="width:50%"></th>
<th style="width:3%"></th>
</tr>
</thead>
<tbody></tbody>
<tbody style="vertical-align:top">
</tbody>
<tfoot>
<tr>
<td colspan="4">

View File

@ -21,7 +21,7 @@ define(function(require) {
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var CapacityInputs = require('./general/capacity-inputs');
var CapacityCreate = require('./general/capacity-create');
var WizardFields = require('utils/wizard-fields');
var Config = require('sunstone-config');
@ -62,7 +62,7 @@ define(function(require) {
function _html() {
return TemplateHTML({
'capacityInputsHTML': CapacityInputs.html(),
'capacityCreateHTML': CapacityCreate.html(),
'logos': Config.vmLogos
});
}
@ -103,7 +103,7 @@ define(function(require) {
// There is another listener in context.js setup
});
CapacityInputs.setup(context);
CapacityCreate.setup($("div.capacityCreate", context));
}
function _retrieve(context) {
@ -131,6 +131,8 @@ define(function(require) {
templateJSON['SUNSTONE'] = sunstone_template;
}
$.extend(templateJSON, CapacityCreate.retrieve($("div.capacityCreate", context)));
return templateJSON;
}
@ -182,6 +184,8 @@ define(function(require) {
delete templateJSON["HYPERVISOR"];
}
CapacityCreate.fill($("div.capacityCreate", context), templateJSON);
WizardFields.fill(context, templateJSON);
}
});

View File

@ -0,0 +1,246 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed 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. */
/* -------------------------------------------------------------------------- */
define(function(require) {
/*
DEPENDENCIES
*/
require('foundation.slider');
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var WizardFields = require('utils/wizard-fields');
var UserInputs = require('utils/user-inputs');
/*
TEMPLATES
*/
var TemplateHTML = require('hbs!./capacity-create/html');
/*
CONSTRUCTOR
*/
return {
'html': _html,
'setup': _setup,
'fill': _fill,
'retrieve': _retrieve
};
/*
FUNCTION DEFINITIONS
*/
function _html() {
return TemplateHTML();
}
function _setup(context) {
// MB to GB
context.on("input", "div.memory_input input", function(){
if (this.value && this.value >= 0) {
$("div.memory_gb_input input", context).val( this.value / 1024 );
} else {
$("div.memory_gb_input input", context).val("");
}
});
// MB to GB, range input
context.on("input", "div.memory_modify_opt.range input.mb_unit", function(){
var val = this.value.split("..").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return e / 1024;
}).join("..");
$("div.memory_modify_opt.range input.gb_unit", context).val(val);
});
// MB to GB, list input
context.on("input", "div.memory_modify_opt.list input.mb_unit", function(){
var val = this.value.split(",").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return e / 1024;
}).join(",");
$("div.memory_modify_opt.list input.gb_unit", context).val(val);
});
// GB to MB
context.on("input", "div.memory_gb_input input", function(){
if (this.value && this.value >= 0) {
$("div.memory_input input", context).val( Math.floor(this.value * 1024) );
} else {
$("div.memory_input input", context).val("");
}
});
// GB to MB, range input
context.on("input", "div.memory_modify_opt.range input.gb_unit", function(){
var val = this.value.split("..").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return Math.floor(e * 1024);
}).join("..");
$("div.memory_modify_opt.range input.mb_unit", context).val(val);
});
// GB to MB, list input
context.on("input", "div.memory_modify_opt.list input.gb_unit", function(){
var val = this.value.split(",").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return Math.floor(e * 1024);
}).join(",");
$("div.memory_modify_opt.list input.mb_unit", context).val(val);
});
// Unit select
$("#memory_unit", context).on('change', function() {
var memory_unit_val = $('#memory_unit :selected', context).val();
if (memory_unit_val == 'GB') {
$(".mb_unit", context).hide();
$(".gb_unit", context).show();
} else {
$(".mb_unit", context).show();
$(".gb_unit", context).hide();
}
$(".memory_modify_unit", context).text(memory_unit_val);
});
$("#memory_unit", context).change();
// Select for memory, cpu, vcpu modification on instantiate
$.each(["memory","cpu","vcpu"], function(i,classname){
$("."+classname+"_modify_type", context).on("change", function(){
$("."+classname+"_modify_opt", context).hide();
$("."+classname+"_modify_opt."+this.value, context).show();
$("#memory_unit", context).change();
});
$("."+classname+"_modify_type", context).change();
});
}
/**
* Fills the capacity inputs
* @param {Object} context JQuery selector
* @param {Object} template VM or VMTemplate object
*/
function _fill(context, element) {
var fields = $('[wizard_field]', context);
fields.each(function() {
var field_name = $(this).attr('wizard_field');
$(this).data("original_value", element[field_name]);
});
WizardFields.fill(context, element);
// Update memory_gb with the value set in memory
$("div.memory_input input", context).trigger("input");
if ($("div.memory_input input", context).val() && $("div.memory_input input", context).val() < 1024){
$("#memory_unit", context).val("MB").change();
} else {
$("#memory_unit", context).val("GB").change();
}
var userInputsJSON = element['USER_INPUTS'];
if (userInputsJSON) {
$.each(["memory","cpu","vcpu"], function(i,classname){
var name = classname.toUpperCase();
if (userInputsJSON[name] != undefined){
var attr = UserInputs.unmarshall(userInputsJSON[name]);
$("."+classname+"_modify_type", context).val(attr.type).change();
$("input."+classname+"_modify_opt."+attr.type, context).val(attr.params).trigger("input");
delete userInputsJSON[name];
} else {
$("."+classname+"_modify_type", context).val("fixed").change();
}
});
}
}
/**
* Retrieves the input values
* @param {Object} context JQuery selector
* @return {Object} If the input is not empty, returns:
* - CPU
* - MEMORY
* - VCPU
* - USER_INPUTS for cpu, memory, vcpu
*/
function _retrieve(context) {
var templateJSON = WizardFields.retrieve(context);
var userInputsJSON = {};
$.each(["memory","cpu","vcpu"], function(i,classname){
var attr = {};
attr.type = $("."+classname+"_modify_type", context).val();
if (attr.type == "fixed"){
// No user input, continue
return true;
}
attr.name = classname.toUpperCase();
attr.mandatory = true;
attr.description = "";
attr.initial = $('input[wizard_field="'+attr.name+'"]', context).val();
if (attr.type == "range" ||
attr.type == "range-float" ||
attr.type == "list"){
attr.params = $("input."+classname+"_modify_opt."+attr.type, context).val();
}
userInputsJSON[attr.name] = UserInputs.marshall(attr);
});
if (!$.isEmptyObject(userInputsJSON)) {
templateJSON['USER_INPUTS'] = userInputsJSON;
}
return templateJSON;
}
});

View File

@ -0,0 +1,148 @@
{{! -------------------------------------------------------------------------- }}
{{! Copyright 2002-2015, OpenNebula Project, OpenNebula Systems }}
{{! }}
{{! Licensed 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 class="row">
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label class="" for="MEMORY">
{{tr "Memory"}}
{{{tip (tr "Amount of RAM required for the VM, in Megabytes.")}}}
</label>
</div>
<div class="small-8 columns">
<div class="mb_unit memory_input">
<input type="number" min="0" step="256" wizard_field="MEMORY" id="MEMORY"/>
</div>
<div class="gb_unit memory_gb_input">
<input type="number" min="0" step="0.25" name="memory_gb"/>
</div>
</div>
<div class="small-4 columns">
<select id="memory_unit" name="MEMORY_UNIT">
<option value="MB">{{tr "MB"}}</option>
<option value="GB" selected>{{tr "GB"}}</option>
</select>
</div>
</div>
</div>
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label>
{{tr "Memory modification"}}
{{{tip (tr "Allow users to modify this template's memory on instantiate")}}}
</label>
</div>
<div class="small-4 columns">
<select class="memory_modify_type" >
<option value="fixed">{{tr "fixed"}}</option>
<option selected value="number">{{tr "number"}}</option>
<option value="range">{{tr "range"}}</option>
<option value="list">{{tr "list"}}</option>
</select>
</div>
<div class="small-6 columns">
<div class="memory_modify_opt range">
<input type=text class="mb_unit memory_modify_opt range" placeholder="512..4096"/>
<input type=text class="gb_unit" placeholder="0.5..4"/>
</div>
<div class="memory_modify_opt list">
<input type=text class="mb_unit memory_modify_opt list" placeholder="1024,4096,8192"/>
<input type=text class="gb_unit" placeholder="1,4,8"/>
</div>
</div>
<div class="small-2 columns">
<span class="memory_modify_opt range list memory_modify_unit">
</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label class="" for="CPU">
{{tr "CPU"}}
{{{tip (tr "Percentage of CPU divided by 100 required for the Virtual Machine. Half a processor is written 0.5.")}}}
</label>
<div class="cpu_input">
<input type="number" step="0.01" min="0" wizard_field="CPU" id="CPU"/>
</div>
</div>
</div>
</div>
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label>
{{tr "CPU modification"}}
{{{tip (tr "Allow users to modify this template's CPU on instantiate")}}}
</label>
</div>
<div class="small-4 columns">
<select class="cpu_modify_type" >
<option value="fixed">{{tr "fixed"}}</option>
<option selected value="number">{{tr "number"}}</option>
<option value="range">{{tr "range"}}</option>
<option value="list">{{tr "list"}}</option>
</select>
</div>
<div class="small-8 columns">
<input type=text class="cpu_modify_opt range" placeholder="0.5..8"/>
<input type=text class="cpu_modify_opt list" placeholder="0.5,1,4,16"/>
</div>
</div>
</div>
</div>
<div class="row">
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label class="" for="VCPU">
{{tr "VCPU"}}
{{{tip (tr "Number of virtual cpus. This value is optional, the default hypervisor behavior is used, usually one virtual CPU.")}}}
</label>
<div class="vcpu_input">
<input type="number" step="1" min="0" wizard_field="VCPU" id="VCPU"/>
</div>
</div>
</div>
</div>
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label>
{{tr "VCPU modification"}}
{{{tip (tr "Allow users to modify this template's VCPU on instantiate")}}}
</label>
</div>
<div class="small-4 columns">
<select class="vcpu_modify_type" >
<option value="fixed">{{tr "fixed"}}</option>
<option selected value="number">{{tr "number"}}</option>
<option value="range">{{tr "range"}}</option>
<option value="list">{{tr "list"}}</option>
</select>
</div>
<div class="small-8 columns">
<input type=text class="vcpu_modify_opt range" placeholder="1..8"/>
<input type=text class="vcpu_modify_opt list" placeholder="4,8,16"/>
</div>
</div>
</div>
</div>

View File

@ -23,6 +23,7 @@ define(function(require) {
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var WizardFields = require('utils/wizard-fields');
var UserInputs = require('utils/user-inputs');
/*
TEMPLATES
@ -40,7 +41,7 @@ define(function(require) {
'setCallback': _setCallback,
'fill': _fill,
'retrieve': _retrieve,
'retrieveResize': _retrieveResize
'retrieveChanges': _retrieveChanges
};
/*
@ -52,139 +53,38 @@ define(function(require) {
}
function _setup(context) {
// Define the cpu slider
var cpu_input = $("#CPU", context);
var cpu_slider = $("#cpu_slider", context)
context.foundation('slider', 'reflow');
//cpu_slider.attr('data-options', 'start: 0; end: 1600; step: 50;');
cpu_slider.on('change.fndtn.slider', function(){
if ($(this).attr('data-slider') >= 0) {
cpu_input.val($(this).attr('data-slider') / 100);
}
});
cpu_input.on('change', function() {
// MB to GB
context.on("input", "div.memory_input input", function(){
if (this.value && this.value >= 0) {
cpu_slider.foundation('slider', 'set_value', this.value * 100);
$("div.memory_gb_input input", context).val( this.value / 1024 );
} else {
cpu_slider.foundation('slider', 'set_value', -1);
$("div.memory_gb_input input", context).val("");
}
});
cpu_slider.foundation('slider', 'set_value', 100);
// Define the memory slider
var final_memory_input = $("#MEMORY", context);
var memory_input = $("#MEMORY_TMP", context);
var memory_unit = $("#memory_unit", context);
var current_memory_unit = memory_unit.val();
var update_final_memory_input = function() {
if (current_memory_unit == 'MB') {
final_memory_input.val(Math.floor(memory_input.val()));
} else {
final_memory_input.val(Math.floor(memory_input.val() * 1024));
}
}
memory_input.on('change', function() {
// GB to MB
context.on("input", "div.memory_gb_input input", function(){
if (this.value && this.value >= 0) {
$("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
update_final_memory_input();
$("div.memory_input input", context).val( Math.floor(this.value * 1024) );
} else {
$("#memory_slider", context).foundation('slider', 'set_value', -1);
final_memory_input.val("");
$("div.memory_input input", context).val("");
}
});
final_memory_input.on('change', function() {
if (this.value && this.value >= 0) {
$("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
memory_input.val(Math.floor(this.value));
} else {
$("#memory_slider", context).foundation('slider', 'set_value', -1);
memory_input.val("");
}
});
$("#memory_slider", context).on('change.fndtn.slider', function() {
if ($(this).attr('data-slider') >= 0) {
memory_input.val($(this).attr('data-slider') / 100);
update_final_memory_input();
}
});
memory_unit.on('change', function() {
// Unit select
$("#memory_unit", context).on('change', function() {
var memory_unit_val = $('#memory_unit :selected', context).val();
if (current_memory_unit != memory_unit_val) {
current_memory_unit = memory_unit_val
var new_val;
if (memory_unit_val == 'GB') {
$("#memory_slider", context).detach();
$(".memory_slider_container", context).html(
'<div id="memory_slider" class="range-slider radius" data-slider data-options="start: 0; end: 1600; step: 50;">'+
'<span class="range-slider-handle"></span>'+
'<span class="range-slider-active-segment"></span>'+
'<input type="hidden">'+
'</div>');
new_val = memory_input.val() / 1024;
} else if (memory_unit_val == 'MB') {
$("#memory_slider", context).detach();
$(".memory_slider_container", context).html(
'<div id="memory_slider" class="range-slider radius" data-slider data-options="start: 0; end: 409600; step: 12800;">'+
'<span class="range-slider-handle"></span>'+
'<span class="range-slider-active-segment"></span>'+
'<input type="hidden">'+
'</div>');
new_val = Math.floor(memory_input.val() * 1024);
}
$("#memory_slider", context).foundation('slider', 'reflow');
memory_input.val(new_val);
$("#memory_slider", context).foundation('slider', 'set_value', new_val * 100);
$("#memory_slider", context).on('change.fndtn.slider', function() {
if ($(this).attr('data-slider') >= 0) {
memory_input.val($(this).attr('data-slider') / 100);
update_final_memory_input();
}
});
update_final_memory_input();
}
});
// init::start is ignored for some reason
$("#memory_slider", context).foundation('slider', 'set_value', 51200);
// Define the vcpu slider
var vcpu_input = $("#VCPU", context);
var vcpu_slider = $("#vcpu_slider", context)
//vcpu_slider.attr('data-options', 'start: 0; end: 1600; step: 50;');
vcpu_slider.on('change.fndtn.slider', function(){
if ($(this).attr('data-slider') > 0) {
vcpu_input.val($(this).attr('data-slider') / 100);
}
});
vcpu_input.on('change', function() {
if (this.value && this.value > 0) {
vcpu_slider.foundation('slider', 'set_value', this.value * 100);
if (memory_unit_val == 'GB') {
$("div.memory_input", context).hide();
$("div.memory_gb_input", context).show();
} else {
vcpu_slider.foundation('slider', 'set_value', -1);
$("div.memory_input", context).show();
$("div.memory_gb_input", context).hide();
}
});
vcpu_slider.foundation('slider', 'set_value', 0);
$("#memory_unit", context).change();
}
/**
@ -201,6 +101,61 @@ define(function(require) {
});
WizardFields.fill(context, element.TEMPLATE);
var userInputs = element.TEMPLATE.USER_INPUTS;
if (userInputs != undefined){
if (userInputs.CPU != undefined){
var input = UserInputs.generateInputElement("CPU", userInputs.CPU);
$("div.cpu_input", context).html(input);
}
if (userInputs.VCPU != undefined){
var input = UserInputs.generateInputElement("VCPU", userInputs.VCPU);
$("div.vcpu_input", context).html(input);
}
if (userInputs.MEMORY != undefined){
// Normal input for MB
var attr = UserInputs.parse("MEMORY", userInputs.MEMORY);
attr.step = 256;
var input = UserInputs.attributeInput(attr);
$("div.memory_input", context).html(input);
// Modified input for GB
var attr_gb = UserInputs.parse("MEMORY", userInputs.MEMORY);
if (attr_gb.type == "range"){
attr_gb.type = "range-float";
attr_gb.min = (attr_gb.min / 1024);
attr_gb.max = (attr_gb.max / 1024);
attr_gb.initial = (attr_gb.initial / 1024);
attr_gb.step = (0.25);
} else if (attr_gb.type == "list"){
attr_gb.options = attr_gb.options.map(function(e){
return e / 1024;
});
attr_gb.initial = attr_gb.initial / 1024;
} else {
// TODO: error?
}
input = UserInputs.attributeInput(attr_gb);
$("div.memory_gb_input", context).html(input);
$("div.memory_gb_input input", context).removeAttr("wizard_field");
}
}
// Update memory_gb with the value set in memory
$("div.memory_input input", context).trigger("input");
if ($("div.memory_input input", context).val() >= 1024){
$("#memory_unit", context).val("GB").change();
}
}
/**
@ -209,9 +164,11 @@ define(function(require) {
* @param {Function} callback will be called as callback( retrieve(context) )
*/
function _setCallback(context, callback) {
context.on("change.fndtn.slider", function(){
context.on("input", function(){
callback( _retrieve(context) );
});
callback( _retrieve(context) );
}
/**
@ -235,7 +192,7 @@ define(function(require) {
* - MEMORY
* - VCPU
*/
function _retrieveResize(context) {
function _retrieveChanges(context) {
var templateJSON = WizardFields.retrieve(context);
var fields = $('[wizard_field]', context);

View File

@ -16,70 +16,45 @@
<div class="row">
<div class="large-12 columns">
<div class="">
<input type="hidden" wizard_field="MEMORY" id="MEMORY" name="memory" />
<label class="" for="MEMORY">
{{tr "Memory"}}
{{{tip (tr "Amount of RAM required for the VM, in Megabytes.")}}}
</label>
</div>
<div class="small-10 columns">
<div class="memory_input">
<input type="number" min="0" step="256" wizard_field="MEMORY" id="MEMORY" disabled/>
</div>
<div class="large-12 columns">
<label class="" for="MEMORY">
{{tr "Memory"}}
{{{tip (tr "Amount of RAM required for the VM, in Megabytes.")}}}
</label>
<div class="memory_gb_input">
<input type="number" min="0" step="0.25" name="memory_gb" disabled/>
</div>
<div class="medium-8 columns memory_slider_container">
<div id="memory_slider" class="range-slider radius" data-slider data-options="start: 0; end: 409600; step: 12800;">
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden">
</div>
</div>
<div class="medium-2 small-6 columns">
<input type="text" id="MEMORY_TMP" name="memory_tmp" size="4" />
</div>
<div class="medium-2 small-6 columns">
<select id="memory_unit" name="MEMORY_UNIT">
<option value="MB">{{tr "MB"}}</option>
<option value="GB">{{tr "GB"}}</option>
</select>
</div>
<div class="small-2 columns">
<select id="memory_unit" name="MEMORY_UNIT">
<option value="MB">{{tr "MB"}}</option>
<option value="GB" selected>{{tr "GB"}}</option>
</select>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<label class="" for="CPU">
{{tr "CPU"}}
{{{tip (tr "Percentage of CPU divided by 100 required for the Virtual Machine. Half a processor is written 0.5.")}}}
</label>
<div class="cpu_input">
<input type="number" step="0.01" min="0" wizard_field="CPU" id="CPU" disabled/>
</div>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<div class="large-12 columns">
<label class="" for="CPU">
{{tr "CPU"}}
{{{tip (tr "Percentage of CPU divided by 100 required for the Virtual Machine. Half a processor is written 0.5.")}}}
</label>
</div>
<div class="large-10 medium-10 columns">
<div id="cpu_slider" class="range-slider radius" data-slider data-options="start: 0; end: 1600; step: 50;">
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden">
</div>
</div>
<div class="large-2 medium-2 columns">
<input type="text" wizard_field="CPU" id="CPU" name="cpu"/>
<div class="small-12 columns">
<label class="" for="VCPU">
{{tr "VCPU"}}
{{{tip (tr "Number of virtual cpus. This value is optional, the default hypervisor behavior is used, usually one virtual CPU.")}}}
</label>
<div class="vcpu_input">
<input type="number" step="1" min="0" wizard_field="VCPU" id="VCPU" disabled/>
</div>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<div class="large-12 columns">
<label class="" for="VCPU">
{{tr "VCPU"}}
{{{tip (tr "Number of virtual cpus. This value is optional, the default hypervisor behavior is used, usually one virtual CPU.")}}}
</label>
</div>
<div class="large-10 medium-10 columns">
<div id="vcpu_slider" class="range-slider radius" data-slider data-options="start: 100; end: 1600; step: 100;">
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden">
</div>
</div>
<div class="large-2 medium-2 columns">
<input type="text" wizard_field="VCPU" id="VCPU" name="vcpu"/>
</div>
</div>
</div>
</div>

View File

@ -81,11 +81,13 @@
</div>
</div>
<div class="row">
<div class="large-7 columns">
{{{capacityInputsHTML}}}
<div class="capacityCreate large-12 columns">
{{{capacityCreateHTML}}}
</div>
<div class="large-5 columns">
{{#isFeatureEnabled "showback"}}
</div>
{{#isFeatureEnabled "showback"}}
<div class="row">
<div class="medium-6 columns">
<fieldset>
<legend>{{tr "Cost"}}</legend>
<div class="medium-6 columns">
@ -110,9 +112,9 @@
<input type="text" wizard_field="DISK_COST" id="DISK_COST" name="name"/>
</div>
</fieldset>
{{/isFeatureEnabled}}
</div>
</div>
{{/isFeatureEnabled}}
<div class="row">
<div class="large-6 columns">
<input type="checkbox" id="sunstone_capacity_select" name="name"/>

View File

@ -125,7 +125,7 @@ define(function(require) {
}
capacityContext = $(".capacityContext" + template_id, context);
$.extend(tmp_json, CapacityInputs.retrieveResize(capacityContext));
$.extend(tmp_json, CapacityInputs.retrieveChanges(capacityContext));
extra_info['template'] = tmp_json;
@ -209,20 +209,19 @@ define(function(require) {
}
if ((cpuCost != 0 || memoryCost != 0) && Config.isFeatureEnabled("showback")) {
var cost = 0;
var cpu = template_json.VMTEMPLATE.TEMPLATE.CPU;
var memory = template_json.VMTEMPLATE.TEMPLATE.MEMORY;
if (cpu != undefined && memory != undefined) {
cost = cpuCost * cpu + memoryCost * memory;
}
$(".cost_value", capacityContext).html(cost.toFixed(2));
$(".capacity_cost_div", capacityContext).show();
CapacityInputs.setCallback(capacityContext, function(values){
var cost = cpuCost * values.CPU + memoryCost * values.MEMORY;
var cost = 0;
if (values.CPU != undefined){
cost += cpuCost * values.CPU;
}
if (values.MEMORY != undefined){
cost += memoryCost * values.MEMORY;
}
$(".cost_value", capacityContext).html(cost.toFixed(2));
});
}

View File

@ -72,7 +72,7 @@ define(function(require) {
Tips.setup(context);
$('#' + DIALOG_ID + 'Form', context).submit(function() {
var templateJSON = CapacityInputs.retrieveResize(context);
var templateJSON = CapacityInputs.retrieveChanges(context);
var enforce = $("#enforce", this).is(":checked");

View File

@ -25,16 +25,27 @@ define(function(require) {
return {
'vmTemplateInsert': _generateVMTemplateUserInputs,
'serviceTemplateInsert': _generateServiceTemplateUserInputs
}
'serviceTemplateInsert': _generateServiceTemplateUserInputs,
'marshall': _marshall,
'unmarshall': _unmarshall,
'parse': _parse,
'generateInputElement': _generateInputElement,
'attributeInput': _attributeInput
};
// It will replace the div's html with a row for each USER_INPUTS
// opts.text_header: header text for the text & password inputs
// opts.network_header: header text for the network inputs
// returns true if at least one input was inserted
function _generateVMTemplateUserInputs(div, template_json, opts) {
return _generateInstantiateUserInputs(
div, template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS, opts);
// Delete the special user inputs for the capacity
var inputs = $.extend({}, template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS);
delete inputs["CPU"];
delete inputs["MEMORY"];
delete inputs["VCPU"];
return _generateInstantiateUserInputs(div, inputs, opts);
}
// It will replace the div's html with a row for each USER_INPUTS
@ -70,27 +81,15 @@ define(function(require) {
}
var network_attrs = [];
var text_attrs = [];
var input_attrs = [];
$.each(user_inputs, function(key, value) {
var parts = value.split("|");
// 0 mandatory; 1 type; 2 desc;
var attrs = {
"name": key,
"mandatory": parts[0],
"type": parts[1],
"description": parts[2],
}
var attrs = _parse(key, value);
switch (parts[1]) {
case "vnet_id":
network_attrs.push(attrs)
break;
case "text":
case "text64":
case "password":
text_attrs.push(attrs)
break;
if (attrs.type == "vnet_id"){
network_attrs.push(attrs);
} else {
input_attrs.push(attrs);
}
});
@ -137,7 +136,7 @@ define(function(require) {
});
}
if (text_attrs.length > 0) {
if (input_attrs.length > 0) {
if (opts.text_header.length > 0) {
div.append(
'<br>' +
@ -152,33 +151,229 @@ define(function(require) {
div.append('<div class="instantiate_user_inputs"/>');
$.each(text_attrs, function(index, custom_attr) {
var input;
switch (custom_attr.type) {
case "text":
input = '<textarea type="text" rows="1" wizard_field="' + custom_attr.name + '" required/>';
break;
case "text64":
input = '<textarea type="text" rows="1" wizard_field_64="true" wizard_field="' + custom_attr.name + '" required/>';
break;
case "password":
input = '<input type="password" wizard_field="' + custom_attr.name + '" required/>';
break;
}
$.each(input_attrs, function(index, custom_attr) {
$(".instantiate_user_inputs", div).append(
'<div class="row">' +
'<div class="large-12 large-centered columns">' +
'<label>' +
TemplateUtils.htmlDecode(custom_attr.description) +
input +
_attributeInput(custom_attr) +
'</label>' +
'</div>' +
'</div>');
});
}
return (network_attrs.length > 0 || text_attrs.length > 0);
return (network_attrs.length > 0 || input_attrs.length > 0);
}
})
/**
* Transforms a user input object to a string
* @param {object} attr user input object, e.g.
* { "name":
* "mandatory": true/false
* "type":
* "description":
* ["params":] "2..8" / "2,4,8"
* ["initial":] "3"
* }
* @return {string} String in the form "M|range|Description here|2..8|4"
*/
function _marshall(attr) {
var st = "";
st += (attr.mandatory ? "M" : "O") + "|" +
(attr.type != undefined ? attr.type : "text") + "|" +
(attr.description != undefined ? attr.description : "");
switch (attr.type) {
case "number":
case "number-float":
st += ("| |" + (attr.initial != undefined ? attr.initial : "") );
break;
case "range":
case "range-float":
case "list":
st += ("|" + (attr.params != undefined ? attr.params : "") +
"|" + (attr.initial != undefined ? attr.initial : "") );
break;
}
return st;
}
/**
* Transforms a user input string to an object
* @param {string} value String in the form "M|range|Description here|2..8|4"
* @return {object} user input object, e.g.
* { "mandatory": true/false
* "type":
* "description":
* ["params":] "2..8" / "2,4,8"
* ["initial":] "3"
* }
*/
function _unmarshall(value) {
var parts = value.split("|");
var attr = {
"mandatory": (parts[0] == "M"),
"type": parts[1],
"description": parts[2],
};
if (parts[3] != undefined){
attr.params = parts[3];
}
if (parts[4] != undefined){
attr.initial = parts[4];
}
return attr;
}
/**
* Returns a structure with the user input parameters
* @param {string} name Template Attribute name, e.g. USER_PASSWORD
* @param {string} value Template Attribute value,
* e.g. "M|range|Description here|2..8|4"
* @return {object} { "name":
"mandatory":
"type":
"description":
["params":] "2..8" / "2,4,8"
["initial":]
["min":]
["max":]
["step":]
["options":]
}
*/
function _parse(name, value) {
var attr = _unmarshall(value);
attr.name = name;
// TODO: error management (params undefined)
switch (attr.type) {
case "number":
attr.step = "1";
break;
case "number-float":
attr.step = "0.01";
break;
case "range":
var params = attr.params.split(".."); // "2..8"
attr.min = parseInt( params[0] );
attr.max = parseInt( params[1] );
attr.step = "1";
break;
case "range-float":
var params = attr.params.split(".."); // "2.4..8.75"
attr.min = parseFloat( params[0] );
attr.max = parseFloat( params[1] );
attr.step = "0.01";
break;
case "list":
attr.options = attr.params.split(","); // "2,4,16"
break;
}
return attr;
}
/**
* Returns an html <input> for the given user input attribute
* @param {object} attr structure as returned by parse
* @return {string} string containing an html <input> element
*/
function _attributeInput(attr) {
var input;
switch (attr.type) {
case "text":
input = '<textarea type="text" rows="1" wizard_field="' + attr.name + '" required/>';
break;
case "text64":
input = '<textarea type="text" rows="1" wizard_field_64="true" wizard_field="' + attr.name + '" required/>';
break;
case "password":
input = '<input type="password" wizard_field="' + attr.name + '" required/>';
break;
case "number":
case "number-float":
input = '<input type="number" step="'+attr.step+'" value="'+attr.initial+'" wizard_field="' + attr.name + '" required/>';
break;
case "range":
case "range-float":
input =
'<div class="row uinput-slider-container">'+
'<div class="small-8 columns">'+
'<input type="range" class="uinput-slider" style="width:100%"'+
'min="'+attr.min+'" max="'+attr.max+'" step="'+attr.step+'" '+
'value="'+attr.initial+'"/>'+
'</div>'+
'<div class="small-4 columns">'+
'<input type="number" class="uinput-slider-val" '+
'min="'+attr.min+'" max="'+attr.max+'" step="'+attr.step+'" '+
'value="'+attr.initial+'" wizard_field="' + attr.name + '" required/>'+
'</div>'+
'</div>';
$(document).off("input", "input.uinput-slider-val");
$(document).on("input", "input.uinput-slider-val", function(){
$("input[type=range]", $(this).closest('.uinput-slider-container')).val( this.value );
});
$(document).off("input", "input.uinput-slider");
$(document).on("input", "input.uinput-slider", function(){
$("input[type=number]", $(this).closest('.uinput-slider-container')).val( this.value );
});
break;
case "list":
input = '<select wizard_field="' + attr.name + '" required>';
$.each(attr.options, function(){
var selected = (attr.initial == this);
input += '<option value="'+this+'" '+
(selected? 'selected' : '')+'>'+
this+
'</option>';
});
input += '</select>';
break;
}
return input;
}
/**
* Returns an html <input> for the given USER_INPUT attribute
* @param {string} name Template Attribute name, e.g. USER_PASSWORD
* @param {string} value Template Attribute value,
* e.g. "M|range|Description here|2..8|4"
* @return {string} string containing an html <input> element
*/
function _generateInputElement(name, value) {
var attrs = _parse(name, value);
return _attributeInput(attrs);
}
});

View File

@ -1470,4 +1470,14 @@ div.vis-network-tooltip {
background: #bfbfbf;
}
}
}
// For abide validation
.error input {
border-bottom-color: $alert-color !important;
}
.error textarea {
border-bottom-color: $alert-color !important;
}