diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create.js
index 413eafa9fa..db9f0e3390 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create.js
@@ -76,7 +76,7 @@ define(function(require) {
var wizardTabInstance;
$.each(WIZARD_TABS, function(index, wizardTab) {
try {
- wizardTabInstance = new wizardTab();
+ wizardTabInstance = new wizardTab({listener: that});
wizardTabInstance.contentHTML = wizardTabInstance.html();
that.wizardTabs.push(wizardTabInstance);
} catch (err) {
@@ -97,6 +97,8 @@ define(function(require) {
FormPanel.prototype.submitWizard = _submitWizard;
FormPanel.prototype.submitAdvanced = _submitAdvanced;
FormPanel.prototype.fill = _fill;
+ FormPanel.prototype.notify = _notify;
+ FormPanel.prototype.retrieve = _retrieve;
return FormPanel;
@@ -134,7 +136,7 @@ define(function(require) {
});
}
- function _submitWizard(context) {
+ function _retrieve(context) {
var templateJSON = {}
$.each(this.wizardTabs, function(index, wizardTab) {
$.extend(true, templateJSON, wizardTab.retrieve($('#' + wizardTab.wizardTabId, context)));
@@ -154,6 +156,12 @@ define(function(require) {
delete templateJSON["VCENTER_PUBLIC_CLOUD"];
}
+ return templateJSON;
+ }
+
+ function _submitWizard(context) {
+ var templateJSON = this.retrieve(context);
+
if (this.action == "create") {
Sunstone.runAction("Template.create", {'vmtemplate': templateJSON});
return false;
@@ -188,5 +196,34 @@ define(function(require) {
$.each(this.wizardTabs, function(index, wizardTab) {
wizardTab.fill($('#' + wizardTab.wizardTabId, context), templateJSON);
});
+
+ // After all tabs have been filled, perform a notify
+ this.notify();
+ }
+
+ var in_progress = false;
+
+ function _notify() {
+ var that = this;
+
+ // Avoid lots of calls (debounce)
+ if(in_progress){
+ return;
+ }
+
+ in_progress = true;
+
+ setTimeout(function(){
+ var context = that.formContext;
+ var templateJSON = that.retrieve(context);
+
+ $.each(that.wizardTabs, function(index, wizardTab) {
+ if (wizardTab.notify != undefined){
+ wizardTab.notify($('#' + wizardTab.wizardTabId, context), templateJSON);
+ }
+ });
+
+ in_progress = false;
+ }, 500);
}
});
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js
index 180915779e..ea670a1cdd 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js
@@ -45,7 +45,7 @@ define(function(require) {
CONSTRUCTOR
*/
- function WizardTab() {
+ function WizardTab(opts) {
if (!Config.isTemplateCreationTabEnabled('network')) {
throw "Wizard Tab not enabled";
}
@@ -54,6 +54,10 @@ define(function(require) {
this.icon = 'fa-globe';
this.title = Locale.tr("Network");
this.classes = "hypervisor only_kvm only_vcenter"
+
+ if(opts.listener != undefined){
+ this.listener = opts.listener;
+ }
}
WizardTab.prototype.constructor = WizardTab;
@@ -98,6 +102,12 @@ define(function(require) {
});
that.addNicTab(context);
+
+ if(that.listener != undefined){
+ $(context).on("change", "input", function(){
+ that.listener.notify();
+ });
+ }
}
function _retrieve(context) {
@@ -202,5 +212,9 @@ define(function(require) {
$("#" + LINKS_CONTAINER_ID + " li", context).each(function(index) {
$("a", this).html(Locale.tr("NIC") + ' ' + index + " ");
})
+
+ if(this.listener != undefined){
+ this.listener.notify();
+ }
}
});
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os.js
index 3bdbe999c0..977c29efaf 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os.js
@@ -169,6 +169,7 @@ define(function(require) {
WizardTab.prototype.onShow = _onShow;
WizardTab.prototype.retrieve = _retrieve;
WizardTab.prototype.fill = _fill;
+ WizardTab.prototype.notify = _notify;
return WizardTab;
@@ -192,6 +193,28 @@ define(function(require) {
var that = this;
Foundation.reflow(context, 'tabs');
+ context.on("click", "button.boot-order-up", function(){
+ var tr = $(this).closest("tr");
+ tr.prev().before(tr);
+
+ _refreshBootValue(context);
+
+ return false;
+ });
+
+ context.on("click", "button.boot-order-down", function(){
+ var tr = $(this).closest("tr");
+ tr.next().after(tr);
+
+ _refreshBootValue(context);
+
+ return false;
+ });
+
+ $("table.boot-order tbody", context).on("change", "input", function(){
+ _refreshBootValue(context);
+ });
+
var kernelDSContext = $(".kernel_ds", context);
var kernelDSInputsContext = $("#kernel_path_inputs", context);
$("input[name='kernel_type']", context).change(function() {
@@ -251,15 +274,7 @@ define(function(require) {
$.extend(osJSON, WizardFields.retrieve('.kernelTab', context));
$.extend(osJSON, WizardFields.retrieve('.ramdiskTab', context));
- var boot = "";
- var val;
- for (var i = 0; i < 3; i++) {
- val = $('#BOOT_' + i, context).val();
- if (val != undefined && val.length > 0) {
- if (boot.length > 0) {boot += ","}
- boot += val;
- }
- }
+ var boot = _retrieveBootValue(context);
if (boot.length > 0) {
osJSON["BOOT"] = boot;
@@ -288,11 +303,7 @@ define(function(require) {
WizardFields.fill(context, osJSON);
if (osJSON && osJSON['BOOT']) {
- var boot_vals = osJSON['BOOT'].split(",");
-
- for (var i = 0; i < 3 && i < boot_vals.length; i++) {
- $('#BOOT_' + i, context).val(boot_vals[i]);
- }
+ _fillBootValue(context, osJSON['BOOT']);
}
delete templateJSON['OS'];
@@ -304,4 +315,108 @@ define(function(require) {
delete templateJSON['FEATURES'];
}
}
+
+ //----------------------------------------------------------------------------
+ // Boot order
+ //----------------------------------------------------------------------------
+
+ function _retrieveBootValue(context) {
+ return $("table.boot-order", context).attr("value");
+ }
+
+ function _fillBootValue(context, value) {
+ return $("table.boot-order", context).attr("value", value);
+ }
+
+ function _refreshBootValue(context) {
+ var table = $("table.boot-order", context);
+
+ var devices = [];
+
+ $.each($("tr", table), function(){
+ if ($("input", this).is(":checked")){
+ devices.push( $(this).attr("value") );
+ }
+ });
+
+ table.attr("value", devices.join(','));
+ }
+
+ function _addBootRow(context, value, label) {
+ $("table.boot-order tbody", context).append(
+ '
'+
+ ' | '+
+ ''+value+' | '+
+ ' | '+
+ ''+
+ ''+
+ ''+
+ ' | '+
+ '
');
+ }
+
+ function _notify(context, templateJSON) {
+ var table = $("table.boot-order", context);
+ var prev_value = $(table).attr("value");
+
+ $("table.boot-order tbody", context).html("");
+
+ if (templateJSON.DISK != undefined){
+ var disks = templateJSON.DISK;
+
+ if (!$.isArray(disks)){
+ disks = [disks];
+ }
+
+ $.each(disks, function(i,disk){
+ var label = ' ';
+
+ if (disk.IMAGE != undefined){
+ label += disk.IMAGE;
+ } else if (disk.IMAGE_ID != undefined){
+ label += Locale.tr("Image ID") + " " + disk.IMAGE_ID;
+ } else {
+ label += Locale.tr("Volatile");
+ }
+
+ _addBootRow(context, 'disk'+i, label);
+ });
+ }
+
+ if (templateJSON.NIC != undefined){
+ var nics = templateJSON.NIC;
+
+ if (!$.isArray(nics)){
+ nics = [nics];
+ }
+ $.each(nics, function(i,nic){
+ var label = ' ';
+
+ if (nic.NETWORK != undefined){
+ label += nic.NETWORK;
+ } else if (nic.NETWORK_ID != undefined){
+ label += Locale.tr("Network ID") + " " + nic.NETWORK_ID;
+ } else {
+ label += Locale.tr("Manual settings");
+ }
+
+ _addBootRow(context, 'nic'+i, label);
+ });
+ }
+
+ if (prev_value.length > 0){
+ var pos = 0;
+
+ $.each(prev_value.split(','), function(i,device){
+ var tr = $('tr[value="'+device+'"]', table);
+
+ if(tr.length > 0){
+ $($("tr", table)[pos]).before(tr);
+ $("input", tr).click();
+
+ pos += 1;
+ }
+ });
+ }
+ }
});
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os/html.hbs b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os/html.hbs
index e7e24e5c76..bb8aaeab8a 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os/html.hbs
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/os/html.hbs
@@ -62,46 +62,16 @@
-
-
+
-
-
-
-
-
-
+
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage.js
index 7bd07255e7..78a22523d9 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/storage.js
@@ -45,7 +45,7 @@ define(function(require) {
CONSTRUCTOR
*/
- function WizardTab() {
+ function WizardTab(opts) {
if (!Config.isTemplateCreationTabEnabled('storage')) {
throw "Wizard Tab not enabled";
}
@@ -54,6 +54,10 @@ define(function(require) {
this.icon = 'fa-tasks';
this.title = Locale.tr("Storage");
this.classes = "hypervisor only_kvm only_vcenter"
+
+ if(opts.listener != undefined){
+ this.listener = opts.listener;
+ }
}
WizardTab.prototype.constructor = WizardTab;
@@ -98,6 +102,12 @@ define(function(require) {
});
that.addDiskTab(context);
+
+ if(that.listener != undefined){
+ $(context).on("change", "input", function(){
+ that.listener.notify();
+ });
+ }
}
function _retrieve(context) {
@@ -186,5 +196,9 @@ define(function(require) {
$("#" + LINKS_CONTAINER_ID + " li", context).each(function(index) {
$("a", this).html(Locale.tr("Disk") + ' ' + index + "
");
})
+
+ if(this.listener != undefined){
+ this.listener.notify();
+ }
}
});
diff --git a/src/sunstone/public/app/tabs/vms-tab/form-panels/updateconf.js b/src/sunstone/public/app/tabs/vms-tab/form-panels/updateconf.js
index d993d604b0..2131639b00 100644
--- a/src/sunstone/public/app/tabs/vms-tab/form-panels/updateconf.js
+++ b/src/sunstone/public/app/tabs/vms-tab/form-panels/updateconf.js
@@ -153,5 +153,14 @@ define(function(require) {
$.each(this.wizardTabs, function(index, wizardTab) {
wizardTab.fill($('#' + wizardTab.wizardTabId, context), templateJSON);
});
+
+ // After all tabs have been filled, perform a notify.
+ // There isn't a proper listener because this wizard does not allow to edit
+ // the disks and nics
+ $.each(this.wizardTabs, function(index, wizardTab) {
+ if (wizardTab.notify != undefined){
+ wizardTab.notify($('#' + wizardTab.wizardTabId, context), templateJSON);
+ }
+ });
}
});
diff --git a/src/sunstone/public/app/tabs/vms-tab/panels/conf.js b/src/sunstone/public/app/tabs/vms-tab/panels/conf.js
index 276e228801..0f0d06548b 100644
--- a/src/sunstone/public/app/tabs/vms-tab/panels/conf.js
+++ b/src/sunstone/public/app/tabs/vms-tab/panels/conf.js
@@ -97,7 +97,7 @@ define(function(require) {
Sunstone.showFormPanel(TAB_ID, UPDATECONF_FORM_ID, "updateconf",
function(formPanelInstance, context) {
- formPanelInstance.fill(context, that.element.ID, that.conf);
+ formPanelInstance.fill(context, that.element.ID, that.element.TEMPLATE);
});
return false;
diff --git a/src/sunstone/public/app/tabs/vms-tab/panels/conf/html.hbs b/src/sunstone/public/app/tabs/vms-tab/panels/conf/html.hbs
index 2281a7e250..80e7ad2072 100644
--- a/src/sunstone/public/app/tabs/vms-tab/panels/conf/html.hbs
+++ b/src/sunstone/public/app/tabs/vms-tab/panels/conf/html.hbs
@@ -18,7 +18,7 @@
{{#isTabActionEnabled "vms-tab" "VM.updateconf"}}
-
diff --git a/src/sunstone/public/app/tabs/vms-tab/panels/storage.js b/src/sunstone/public/app/tabs/vms-tab/panels/storage.js
index 6c5e2accca..7ef96f04b1 100644
--- a/src/sunstone/public/app/tabs/vms-tab/panels/storage.js
+++ b/src/sunstone/public/app/tabs/vms-tab/panels/storage.js
@@ -149,7 +149,7 @@ define(function(require) {
var disks = [];
if ($.isArray(that.element.TEMPLATE.DISK))
- disks = that.element.TEMPLATE.DISK;
+ disks = that.element.TEMPLATE.DISK.slice(0); // clone
else if (!$.isEmptyObject(that.element.TEMPLATE.DISK))
disks = [that.element.TEMPLATE.DISK];
diff --git a/src/sunstone/public/app/utils/form-panels/form-panel.js b/src/sunstone/public/app/utils/form-panels/form-panel.js
index 518c0f5bd5..2d16cfec74 100644
--- a/src/sunstone/public/app/utils/form-panels/form-panel.js
+++ b/src/sunstone/public/app/utils/form-panels/form-panel.js
@@ -22,6 +22,8 @@ define(function(require) {
var Sunstone = require('sunstone');
function BaseFormPanel() {
+ this.formContext = $("#" + this.tabId+" div[form-panel-id="+this.formPanelId+"]");
+
return this;
}
diff --git a/src/sunstone/public/app/utils/tab-datatable.js b/src/sunstone/public/app/utils/tab-datatable.js
index 32df58f4aa..31671a0a7c 100644
--- a/src/sunstone/public/app/utils/tab-datatable.js
+++ b/src/sunstone/public/app/utils/tab-datatable.js
@@ -765,9 +765,9 @@ define(function(require) {
$('#select_resource_' + that.dataTableId, section).hide();
$('.label', section).hide();
- $('#selected_resource_id_' + that.dataTableId, section).val(aData[that.selectOptions.id_index]).change();
+ $('#selected_resource_id_' + that.dataTableId, section).val(aData[that.selectOptions.id_index]).trigger("change");
- $('#selected_resource_name_' + that.dataTableId, section).text(aData[that.selectOptions.name_index]).change();
+ $('#selected_resource_name_' + that.dataTableId, section).text(aData[that.selectOptions.name_index]).trigger("change");
$('#selected_resource_name_' + that.dataTableId, section).show();
that.selectOptions.select_callback(aData, that.selectOptions);
@@ -937,10 +937,10 @@ define(function(require) {
// $('input.check_item', this).prop('checked', true);
if (row_id !== undefined) {
- $('#selected_resource_id_' + that.dataTableId, section).val(row_id).change();
+ $('#selected_resource_id_' + that.dataTableId, section).val(row_id).trigger("change");
}
- $('#selected_resource_name_' + that.dataTableId, section).text(row_name).change();
+ $('#selected_resource_name_' + that.dataTableId, section).text(row_name).trigger("change");
$('#selected_resource_name_' + that.dataTableId, section).show();
that.refreshResourceTableSelect(section, that.dataTableId);