Update guests.html.template to manipulate the VM List my DOM manipulation
rather than by string manipulation. Also update the tile to function as a start
when the VM is stopped, or as a console connection when it is running.
Signed-off-by: Adam King <rak(a)linux.vnet.ibm.com>
---
ui/css/theme-default/list.css | 2 +
ui/js/src/kimchi.guest_main.js | 366 +++++++++++++++++++++++------------------
ui/pages/tabs/guests.html.tmpl | 2 +-
3 files changed, 207 insertions(+), 163 deletions(-)
diff --git a/ui/css/theme-default/list.css b/ui/css/theme-default/list.css
index 57ad610..af7ac1f 100644
--- a/ui/css/theme-default/list.css
+++ b/ui/css/theme-default/list.css
@@ -101,6 +101,7 @@ max-height: 110px;
width: auto;
display:inline;
border: none;
+ position: relative;
}
.list-vm .tile.running .imgactive{
@@ -249,6 +250,7 @@ max-height: 110px;
.list-vm .shutoff {
+ position: relative;
box-shadow: none !important;
}
diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
index 99cb84a..15354a4 100644
--- a/ui/js/src/kimchi.guest_main.js
+++ b/ui/js/src/kimchi.guest_main.js
@@ -5,6 +5,7 @@
*
* Authors:
* Hongliang Wang <hlwanghl(a)cn.ibm.com>
+ * Adam King <rak(a)us.ibm.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,164 +19,111 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-kimchi.initVmButtonsAction = function() {
-
- var vmstart = function(event) {
- if (!$(this).hasClass('loading')) {
- $(this).addClass('loading');
- kimchi.startVM($(this).data('vm'), function(result) {
- kimchi.listVmsAuto();
- }, function(err) {
- kimchi.message.error(err.responseJSON.reason);
- });
- } else {
- event.preventDefault();
- event.stopPropagation();
- return;
- }
- };
-
- var vmstop = function(event) {
- if (!$(this).hasClass('loading')) {
- $(this).addClass('loading');
- kimchi.stopVM($(this).data('vm'), function(result) {
- kimchi.listVmsAuto();
- }, function(err) {
- kimchi.message.error(err.responseJSON.reason);
- });
- } else {
- event.preventDefault();
- event.stopPropagation();
- }
- };
-
- $('.circle').circle();
-
- $(".vm-start").each(function(index) {
- if ('running' === $(this).data('vmstate')) {
- $(this).hide();
- } else {
- $(this).show();
- }
- });
-
- $(".vm-stop").each(function(index) {
- if ('running' === $(this).data('vmstate')) {
- $(this).show();
- } else {
- $(this).hide();
- }
- });
-
- $(".vm-start").on({
- click : vmstart,
- });
-
- $(".vm-stop").on({
- click : vmstop,
- });
-
- $(".vm-reset").on("click", function(event) {
- if ('running' === $(this).data('vmstate')) {
- kimchi.resetVM($(this).data('vm'), function(result) {
- kimchi.listVmsAuto();
- }, function(err) {
- kimchi.message.error(err.responseJSON.reason);
- });
- } else {
- kimchi.startVM($(this).data('vm'), function(result) {
- kimchi.listVmsAuto();
- }, function(err) {
- kimchi.message.error(err.responseJSON.reason);
- });
- }
- });
-
- $(".vm-delete").on("click", function(event) {
- var vm = $(this);
- var settings = {
- title : i18n['KCHAPI6001M'],
- content : i18n['KCHVM6001M'],
- confirm : i18n['KCHAPI6002M'],
- cancel : i18n['KCHAPI6003M']
- };
- kimchi.confirm(settings, function() {
- kimchi.deleteVM(vm.data('vm'), function(result) {
- kimchi.listVmsAuto();
- }, function(err) {
- kimchi.message.error(err.responseJSON.reason);
- });
- }, function() {
- });
- });
-
- $(".vm-edit").on("click", function(event) {
- var vmName = $(this).data('vm');
- kimchi.selectedGuest = vmName;
- kimchi.window.open("guest-edit.html");
- });
- $(".vm-vnc").on("click", function(event) {
- kimchi.vncToVM($(this).data('vm'));
- });
+kimchi.vmstart = function(event) {
+ var button=$(this);
+ if (!button.hasClass('loading')) {
+ button.addClass('loading');
+ var vm=$(this).closest('li[name=guest]');
+ var vm_id=vm.attr("id");
+ kimchi.startVM(vm_id, function(result) {
+ button.removeClass('loading');
+ kimchi.listVmsAuto();
+ }, function() {
+ startButton.removeClass('loading');
+ kimchi.message.error(i18n['msg.fail.start']);
+ }
+ );
+ } else {
+ event.preventDefault();
+ event.stopPropagation();
+ return;
+ }
+};
- $(".vm-spice").on("click", function(event) {
- kimchi.spiceToVM($(this).data('vm'));
- });
+kimchi.vmstop = function(event) {
+ var button=$(this);
+ if (!button.hasClass('loading')) {
+ button.addClass('loading');
+ var vm=button.closest('li[name=guest]');
+ var vm_id=vm.attr("id");
+ kimchi.stopVM(vm_id, function(result) {
+ button.removeClass('loading');
+ kimchi.listVmsAuto();
+ }, function() {
+ kimchi.message.error(i18n['msg.fail.stop']);
+ });
+ } else {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+};
- kimchi.init_button_stat();
+kimchi.vmreset = function(event){
+ var vm=$(this).closest('li[name=guest]');
+ var vm_id=vm.attr("id");
+ kimchi.resetVM(vm_id, function(result) {
+ kimchi.listVmsAuto();
+ }, function() {
+ kimchi.message.error(i18n['msg.fail.reset']);
+ }
+ );
+};
+kimchi.vmdelete = function(event) {
+ var vm = $(this).closest('li[name=guest]');
+ var vm_id=vm.attr("id");
+ var settings = {
+ title : i18n['msg.confirm.delete.title'],
+ content : i18n['msg.vm.confirm.delete'],
+ confirm : i18n['msg.confirm.delete.confirm'],
+ cancel : i18n['msg.confirm.delete.cancel']
+ };
+ kimchi.confirm(settings, function() {
+ kimchi.deleteVM(vm_id, function(result) {
+ kimchi.listVmsAuto();
+ }, function() {
+ kimchi.message.error(i18n['msg.fail.delete']);
+ });
+ }, function() {
+ });
};
-kimchi.init_button_stat = function() {
- $('.vm-action').each(function() {
- var vm_action = $(this);
- var vm_vnc = vm_action.find('.vm-vnc');
- var vm_spice = vm_action.find('.vm-spice');
- var vm_graphics;
- if (vm_action.data('graphics') === 'vnc') {
- vm_spice.hide();
- vm_graphics = vm_vnc;
- } else if (vm_action.data('graphics') === 'spice') {
- vm_vnc.hide();
- vm_graphics = vm_spice;
- } else {
- vm_vnc.hide();
- vm_spice.hide();
- vm_graphics = null;
- }
+kimchi.vmedit = function(event) {
+ var vm = $(this).closest('li[name=guest]');
+ var vm_id=vm.attr("id");
+ kimchi.selectedGuest = vm_id;
+ kimchi.window.open("guest-edit.html");
+};
- if (vm_graphics !== null) {
- if (vm_action.data('vmstate') === 'running') {
- vm_graphics.removeAttr('disabled');
- } else {
- vm_graphics.attr('disabled', 'disabled');
- }
- }
+kimchi.openVmConsole = function(event) {
+ var vm=$(this).closest('li[name=guest]');
+ var vmObject=vm.data();
+ if (vmObject.graphics['type'] == 'vnc') {
+ kimchi.vncToVM(vm.attr('id'));
+ }
+ else if (vmObject.graphics['type'] == 'spice') {
+ kimchi.spiceToVM(vm.attr('id'));
+ }
- var editButton = vm_action.find('.vm-edit');
- editButton.prop('disabled', vm_action.data('vmstate') !==
'shutoff');
- })
};
-kimchi.getVmsOldImg = function() {
+kimchi.getVmsCurrentConsoleImgs = function() {
var res = new Object();
$('#guestList').children().each(function() {
- res[$(this).attr('id')] =
$(this).find('img').attr('src');
+ res[$(this).attr('id')] =
$(this).find('img.imgactive').attr('src');
})
return res;
};
-kimchi.getVmsOldPopStats = function() {
- var oldSettings = new Object();
- $('#guestList').children().each(function() {
- if ($(this).find('.popable').hasClass('open')) {
- oldSettings[$(this).attr('id')] = true;
- } else {
- oldSettings[$(this).attr('id')] = false;
- }
- })
- return oldSettings;
+kimchi.getOpenMenuVmId = function() {
+ var result;
+ var openMenu = $('#guestList .open:first')
+ if(openMenu) {
+ var li_element=openMenu.closest('li');
+ result=li_element.attr('id');
+ }
+ return result;
};
kimchi.listVmsAuto = function() {
@@ -185,28 +133,18 @@ kimchi.listVmsAuto = function() {
kimchi.listVMs(function(result, textStatus, jqXHR) {
if (result && textStatus=="success") {
if(result.length) {
- $('#guestListField').show();
- $('#noGuests').hide();
var listHtml = '';
var guestTemplate = kimchi.guestTemplate;
- var oldImages = kimchi.getVmsOldImg();
- var oldSettings = kimchi.getVmsOldPopStats();
- $.each(result, function(index, value) {
- var oldImg = oldImages[value.name];
- curImg = value.state == 'running' ? value.screenshot :
value.icon;
- value['load-src'] = curImg || 'images/icon-vm.png';
- value['tile-src'] = oldImg || value['load-src'];
- var statusTemplate = kimchi.editTemplate(guestTemplate,
oldSettings[value.name]);
- listHtml += kimchi.template(statusTemplate, value);
- });
- $('#guestList').html(listHtml);
- $('#guestList').find('.imgload').each(function() {
- this.onload = function() {
- $(this).prev('.imgactive').remove();
- $(this).show();
- }
+ var currentConsoleImages = kimchi.getVmsCurrentConsoleImgs();
+ var openMenuGuest = kimchi.getOpenMenuVmId();
+ $('#guestList').html('');
+ $('#guestListField').show();
+ $('#noGuests').hide();
+
+ $.each(result, function(index, vm) {
+ var guestLI = kimchi.createGuestLi(vm, currentConsoleImages[vm.name],
vm.name==openMenuGuest);
+ $('#guestList').append(guestLI);
});
- kimchi.initVmButtonsAction();
} else {
$('#guestListField').hide();
$('#noGuests').show();
@@ -220,6 +158,109 @@ kimchi.listVmsAuto = function() {
});
};
+kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
+ var result=kimchi.guestElem.clone();
+
+ //Setup the VM list entry
+ var vmRunningBool=(vmObject.state=="running");
+ result.attr('id',vmObject.name);
+ result.data(vmObject);
+
+ //Add the Name
+ var guestTitle=result.find('.title').attr('title',vmObject.name);
+ guestTitle.html(vmObject.name);
+
+ //Setup the VM console thumbnail display
+ var curImg = vmObject.state == 'running' ? vmObject.screenshot :
vmObject.icon;
+ var load_src = curImg || 'images/icon-vm.png';
+ var tile_src = prevScreenImage || vmObject['load-src'];
+ var liveTile=result.find('div[name=guest-tile] > .tile');
+ liveTile.addClass(vmObject.state);
+ liveTile.find('.imgactive').attr('src',tile_src);
+ var imgLoad=liveTile.find('.imgload');
+ imgLoad.on('load', function() {
+ var oldImg=$(this).parent().find('.imgactive');
+ oldImg.removeClass("imgactive").addClass("imgload");
+ oldImg.attr("src","");
+ $(this).addClass("imgactive").removeClass("imgload");
+ $(this).off('load');
+ });
+ imgLoad.attr('src',load_src);
+
+ //Link the stopped tile to the start action, the running tile to open the console
+ if (vmRunningBool) {
+ liveTile.off("click", kimchi.vmstart);
+ liveTile.on("click", kimchi.openVmConsole);
+ }
+ else {
+ liveTile.off("click", kimchi.openVmConsole);
+ liveTile.on("click", kimchi.vmstart);
+ liveTile.hover(function(event){$(this).find('.overlay').show()},
function(event){$(this).find('.overlay').hide()});
+ }
+
+
+ //Setup the gauges
+ var stats=vmObject.stats;
+ var gaugeValue=0;
+ gaugeValue=parseInt(stats.net_throughput);
+ kimchi.circleGaugeInit(result,
"net_throughput",gaugeValue,(gaugeValue*100/stats.net_throughput_peak));
+ gaugeValue=parseInt(stats.io_throughput);
+ kimchi.circleGaugeInit(result,
"io_throughput",gaugeValue,(gaugeValue*100/stats.io_throughput_peak));
+ gaugeValue=parseInt(stats.cpu_utilization);
+ kimchi.circleGaugeInit(result,
"cpu_utilization",gaugeValue+"%",gaugeValue);
+
+ //Setup the VM Actions
+ var guestActions=result.find("div[name=guest-actions]");
+ guestActions.find(".shutoff-disabled").prop('disabled', !vmRunningBool
);
+ guestActions.find(".running-disabled").prop('disabled', vmRunningBool
);
+
+ if (vmRunningBool) {
+ guestActions.find(".running-hidden").hide();
+ }
+ else {
+ guestActions.find(".shutoff-hidden").hide();
+ }
+
+ var consoleActions=guestActions.find("[name=vm-console]");
+
+ if ((vmObject.graphics['type'] == 'vnc') ||
(vmObject.graphics['type'] == 'spice')) {
+ consoleActions.on("click", kimchi.openVmConsole);
+ consoleActions.show();
+ } else { //we don't recognize the VMs supported graphics, so hide the menu choice
+ consoleActions.hide();
+ consoleActions.off("click",kimchi.openVmConsole);
+ }
+
+ //Setup action event handlers
+ guestActions.find("[name=vm-start]").on({click : kimchi.vmstart});
+ guestActions.find("[name=vm-stop]").on({click : kimchi.vmstop});
+ if (vmRunningBool) { //If the guest is not running, do not enable reset
+ guestActions.find("[name=vm-reset]").on({click : kimchi.vmreset});
+ }
+ guestActions.find("[name=vm-edit]").on({click : kimchi.vmedit});
+ guestActions.find("[name=vm-delete]").on({click : kimchi.vmdelete});
+
+ //Maintain menu open state
+ var actionMenu=guestActions.find("div[name=actionmenu]");
+ if (openMenu) {
+ actionMenu.addClass("open");
+ }
+
+ return result;
+};
+
+kimchi.circleGaugeInit = function(topElement, divName, display, percentage){
+ var gauge=topElement.find('div[name="' + divName + '"]
.circleGauge');
+ if(gauge) {
+ var data=Object();
+ data.percentage = percentage;
+ data.display = display;
+ gauge.data(data);
+ }
+ gauge.circleGauge();
+ return(gauge);
+};
+
kimchi.guestSetRequestHeader = function(xhr) {
xhr.setRequestHeader('Accept', 'text/html');
};
@@ -229,6 +270,7 @@ kimchi.guest_main = function() {
kimchi.window.open('guest-add.html');
});
kimchi.guestTemplate = $('#guest-tmpl').html();
+
kimchi.guestElem=$('<div/>').html(kimchi.guestTemplate).find('li');
$('#guests-root-container').on('remove', function() {
kimchi.vmTimeout && clearTimeout(kimchi.vmTimeout);
});
@@ -236,7 +278,7 @@ kimchi.guest_main = function() {
};
kimchi.editTemplate = function(guestTemplate, oldPopStat) {
- if (oldPopStat != null && oldPopStat) {
+ if (oldPopStat) {
return guestTemplate.replace("vm-action", "vm-action open");
}
return guestTemplate;
diff --git a/ui/pages/tabs/guests.html.tmpl b/ui/pages/tabs/guests.html.tmpl
index 8b530c7..e86718b 100644
--- a/ui/pages/tabs/guests.html.tmpl
+++ b/ui/pages/tabs/guests.html.tmpl
@@ -40,8 +40,8 @@
<ul class="list-title">
<li class="guest-type">$_("Name")</li>
<li class="guest-cpu">$_("CPU")</li>
- <li class="guest-network">$_("Network
I/O")</li>
<li class="guest-storage">$_("Disk
I/O")</li>
+ <li class="guest-network">$_("Network
I/O")</li>
<li class="guest-tile">$_("Livetile")</li>
<li class="guest-actions">$_("Actions")</li>
</ul>
--
1.8.1.4