[Kimchi-devel] [PATCH v2 4/4] Change guests tab to update the VM List by DOM manipulation

Adam King rak at linux.vnet.ibm.com
Fri Feb 21 01:59:35 UTC 2014


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 at 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 at cn.ibm.com>
+ *  Adam King <rak at 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




More information about the Kimchi-devel mailing list