[PATCH] Edit Template redefined

From: Wen Wang <wenwang@linux.vnet.ibm.com> This patch redesigned "Edit Template" diaguage in "Templates". New "Edit Template" will display all the related information into tabs of "General", "Storage" and "Interface". Due to unfinished back-end work, functions are not fully supported, which will be finished in the future work. Temporary disabled functions: 1) Multiple disk operation with multiple storage pools edit in template for which reason the add button in "Storage" tab is disabled. 2) iSCSI and SCSI storage pool add is removed since we are going to allow this kind of operation in the process of creating a VM. Signed-off-by: Wen Wang <wenwang@linux.vnet.ibm.com> --- ui/css/theme-default/template-edit.css | 84 +++++++- ui/js/src/kimchi.template_edit_main.js | 336 ++++++++++++++++++++++---------- ui/pages/template-edit.html.tmpl | 169 +++++++++------- 3 files changed, 402 insertions(+), 187 deletions(-) diff --git a/ui/css/theme-default/template-edit.css b/ui/css/theme-default/template-edit.css index 4975f1b..302c488 100644 --- a/ui/css/theme-default/template-edit.css +++ b/ui/css/theme-default/template-edit.css @@ -17,24 +17,33 @@ */ #template-edit-window { font-size: 13px; - height: 600px; - width: 1000px; + height: 500px; + width: 800px; } -.template-edit-fieldset { - float: left; - padding: 1em; +#edit-template-tabs { + background: none repeat scroll 0 0 transparent; + border: medium none; + height: 100%; + padding: 0; } -.template-edit-wrapper-label, .template-edit-wrapper-controls { +#edit-template-tabs .form-template-inline-wrapper { + display: inline-block; vertical-align: top; - width: 470px; } .template-edit-wrapper-label { - height: 18px; - line-height: 18px; - margin-top: 8px; + vertical-align: top; + min-width: 100px; + height: 35px; + line-height: 35px; + margin: 7px 0 8px; +} + +.template-edit-wrapper-controls { + vertical-align: top; + width: 400px; } .template-edit-wrapper-controls input[type="text"] { @@ -56,7 +65,7 @@ .template-edit-wrapper-controls > .dropdown { margin: 5px 0 0 1px; - width: 440px; + width: 372px; } .template-edit-wrapper-controls input[type="text"][disabled] { @@ -103,3 +112,56 @@ input[type="checkbox"]:CHECKED+.item { background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat 10px center; } + +#edit-template-tabs .template-tab-header { + margin-bottom: 8px; + padding-bottom: 2px; + font-weight: bold; + border-bottom: 1px solid #999999; + overflow: hidden; +} + +#edit-template-tabs .template-tab-header .action-area { + float: right; + height: 20px; + width: 20px; +} + +#edit-template-tabs .template-storage-cell{ + display: inline-block; + width: 230px; +} + +#edit-template-tabs .template-interface-cell { + display: inline-block; + width: 250px; +} + +#form-template-storage .template-tab-body select { + width: 140px; +} + +#form-template-storage .template-tab-body input { + width: 56px; +} + +#edit-template-tabs .template-tab-body .item { + margin: 5px 0; +} + +#form-template-interface .template-tab-body select { + width: 180px; +} + +#edit-template-tabs .template-tab-body .action-area { + float: right; +} + +#edit-template-tabs .template-tab-body .action-area button { + width: 20px; + height: 20px; +} + +#edit-template-tabs .template-tab-body .hide { + display: none; +} \ No newline at end of file diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js index 2f4cc9a..ac6cff8 100644 --- a/ui/js/src/kimchi.template_edit_main.js +++ b/ui/js/src/kimchi.template_edit_main.js @@ -16,14 +16,18 @@ * limitations under the License. */ kimchi.template_edit_main = function() { - var templateEditForm = $('#form-template-edit'); + var templateEditMain = $('#edit-template-tabs'); var origDisks; var origPool; + var origNetworks; var templateDiskSize; - $('#template-name', templateEditForm).val(kimchi.selectedTemplate); - kimchi.retrieveTemplate(kimchi.selectedTemplate, function(template) { + $('#template-name', templateEditMain).val(kimchi.selectedTemplate); + templateEditMain.tabs(); + + var initGeneral = function(template) { origDisks = template.disks; origPool = template.storagepool; + origNetworks = template.networks; for(var i=0;i<template.disks.length;i++){ if(template.disks[i].base){ template["vm-image"] = template.disks[i].base; @@ -37,18 +41,12 @@ kimchi.template_edit_main = function() { if (prop == 'graphics') { value = value["type"]; } - $('input[name="' + prop + '"]', templateEditForm).val(value); - } - var disks = template.disks; - $('input[name="disks"]').val(disks[0].size); - templateDiskSize = $('input[name="disks"]').val(); - if (disks[0].volume) { - var spool_value = $('#form-template-edit [name="storagepool"]').val(); - $('input[name="storagepool"]', templateEditForm).val(spool_value + '/' + disks[0].volume); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); + $('input[name="' + prop + '"]', templateEditMain).val(value); } var vncOpt = [{label: 'VNC', value: 'vnc'}]; + $('#template-edit-graphics').append('<option selected>VNC</option>'); + $('#template-edit-graphics').append('<option>Spice</option>'); kimchi.select('template-edit-graphics-list', vncOpt); var enableSpice = function() { if (kimchi.capabilities == undefined) { @@ -61,85 +59,215 @@ kimchi.template_edit_main = function() { } }; enableSpice(); - + }; + var initStorage = function(result) { var scsipools = {}; - kimchi.listStoragePools(function(result) { - var options = []; - if (result && result.length) { - $.each(result, function(index, storagePool) { - if ((storagePool.state=="active") && (storagePool.type !== 'kimchi-iso')) { - if ((storagePool.type == 'iscsi') || (storagePool.type == 'scsi')){ - scsipools[storagePool.name] = []; - kimchi.listStorageVolumes(storagePool.name, function(result) { - if (result && result.length) { - $.each(result, function(index, storageVolume) { - options.push({ - label: storagePool.name + '/' + storageVolume.name, - value: '/storagepools/' + storagePool.name + '/' + storageVolume.name - }); - scsipools[storagePool.name].push(storageVolume) - }); - } - kimchi.select('template-edit-storagePool-list', options); - }); - } - else { - options.push({ - label: storagePool.name, - value: '/storagepools/' + storagePool.name - }); - } + var addStorageItem = function(storageData) { + var nodeStorage = $.parseHTML(kimchi.substitute($("#template-storage-pool-tmpl").html(), storageData)); + $('.template-tab-body', '#form-template-storage').append(nodeStorage); + $('.edit', '#form-template-storage').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.template-storage-name', storageItem).hide(); + var currentName = $('.template-storage-name', storageItem).text(); + $('.template-storage-disk', storageItem).hide(); + var currentDisk = $('.template-storage-disk', storageItem).text(); + $('input', storageItem).val(currentDisk).show(); + $('select', storageItem).show(); + if (currentName === 'iscsi' || currentName === 'scsi') { + $('input', storageItem).attr('disabled', true); + } else { + $('input', storageItem).attr('disabled', false); + } + $('.save', storageItem).parent().show(); + $('.delete', storageItem).parent().hide(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).hide(); + $('select', storageItem).show(); + }); + $('.delete', '#form-template-storage').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-storage').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var cancelEntity = $(this).parent().parent(); + if($('.template-storage-disk', cancelEntity).text() === '') { + cancelEntity.remove(); + } else { + $('label', cancelEntity).show(); + $('input', cancelEntity).hide(); + $('select', cancelEntity).hide(); + $('.cancel', cancelEntity).parent().hide(); + $('.edit', cancelEntity).parent().show(); + } + }); + $('.save', '#form-template-storage').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.save', storageItem).parent().hide(); + $('.delete', storageItem).parent().show(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).show(); + $('.template-storage-disk', storageItem).text($('input', storageItem).val()).show(); + $('select', storageItem).hide(); + $('input', storageItem).hide(); + }); + var storageOptions = ''; + $.each(result, function(index, storageEntities) { + if((storageEntities.state === 'active') && (storageEntities.type != 'kimchi-iso') + && (storageEntities.type != 'iscsi') && (storageEntities.type != 'scsi')){ + var isSlected = storageEntities.name === 'default' ? ' selected' : ''; + storageOptions += '<option' + isSlected + '>' + result[index].name + '</option>'; + } + }); + $('select', '#form-template-storage').find('option').remove(); + $('select', '#form-template-storage').append(storageOptions); + $('select', '#form-template-storage').change(function() { + var selectedItem = $(this).parent().parent(); + var tempStorageName = $(this).val(); + if (tempStorageName === 'iscsi' || tempStorageName === 'scsi') { + $('input', selectedItem).attr('disabled', true); + } else { + $('input', selectedItem).attr('disabled', false); + } + $.each(result, function(index, storageEntities) { + if (tempStorageName === storageEntities.name) { + selectedItem.find('.template-storage-type').text(storageEntities.type); } - }); - } - if ($.isEmptyObject(scsipools)) { - kimchi.select('template-edit-storagePool-list', options); + }) + }); + }; + + if ((origDisks && origDisks.length) && (origPool && origPool)) { + splitPool = origPool.split('/'); + var defaultPool; + var defaultType; + $.each(result, function(index, poolEntities) { + if (poolEntities.name === splitPool[splitPool.length-1]) { + defaultType = poolEntities.type; + defaultPool = splitPool[splitPool.length-1] + } + }); + $.each(origDisks, function(index, diskEntities) { + var storageNodeData = { + viewMode : '', + editMode : 'hide', + storageName : defaultPool, + storageType : defaultType, + storageDisk : diskEntities.size + } + addStorageItem(storageNodeData); + }); + } + + $('#template-edit-storage-add-button').button({ + icons: { + primary: "ui-icon-plusthick" + }, + text: false, + disabled: true + }).click(function(event) { + event.preventDefault(); + var storageNodeData = { + viewMode : 'hide', + editMode : '', + storageName : 'default', + storageType : 'dir', + storageDisk : '' } + addStorageItem(storageNodeData); }); - kimchi.listNetworks(function(result) { - if(result && result.length > 0) { - var html = ''; - var tmpl = $('#tmpl-network').html(); - $.each(result, function(index, network) { - if (result[index].state === 'active') - html += kimchi.substitute(tmpl, network); - }); - $('#template-edit-network-list').html(html).show(); - if(template.networks && template.networks.length > 0) { - $('input[name="networks"]', templateEditForm).each(function(index, element) { - var value = $(element).val(); - if(template.networks.indexOf(value) >= 0) { - $(element).prop('checked', true); - } - }); + }; + var initInterface = function(result) { + var addInterfaceItem = function(networkData) { + var nodeInterface = $.parseHTML(kimchi.substitute($('#template-interface-tmpl').html(), networkData)); + $('.template-tab-body', '#form-template-interface').append(nodeInterface); + $('.edit', '#form-template-interface').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false, + disabled : true + }); + $('.delete', '#form-template-interface').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-interface').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.save', '#form-template-interface').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var interItem = $(this).parent().parent(); + $('.save', interItem).parent().hide(); + $('.delete', interItem).parent().show(); + var selectedInterface = $('select', interItem).val(); + $('label', interItem).text(selectedInterface).show(); + $('select', interItem).hide(); + }); + var networkOptions = ''; + for(var i=0;i<result.length;i++){ + if(result[i].state === "active") { + var isSlected = i==0 ? ' selected' : ''; + networkOptions += '<option' + isSlected + '>' + result[i].name + '</option>'; } - } else { - $('#template-edit-network-list').hide(); } - }); - }); - - $('#template-edit-storagePool').change(function() { - storagepool = $(this).val(); - var storageArray = storagepool.split("/"); - if (storageArray.length > 3) { - volumeName = storageArray.pop(); - poolName = storageArray.pop(); - kimchi.getStoragePoolVolume(poolName, volumeName, function(result) { - $('input[name="disks"]', templateEditForm).val(result.capacity / Math.pow(1024,3)); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); - return false; - }, function (err) { - kimchi.message.error(err.responseJSON.reason); + $('select', '#form-template-interface').find('option').remove(); + $('select', '#form-template-interface').append(networkOptions); + }; + if(result && result.length > 0) { + $.each(result, function(index, data) { + if($.inArray(data.name, origNetworks) > -1) { + addInterfaceItem({ + mac : '', + network : data.name, + type : 'network', + viewMode : '', + editMode : 'hide' + }); + } }); - } else { - $('input[name="disks"]', templateEditForm).removeAttr('disabled'); - $('input[name="disks"]', templateEditForm).val(templateDiskSize); } - }); - $('input[name="disks"]', templateEditForm).keyup(function() { - templateDiskSize = $('input[name="disks"]', templateEditForm).val(); - }); + $('#template-edit-interface-add-button').button({ + icons: { + primary: 'ui-icon-plusthick' + }, + text: false + }).click(function(evt) { + evt.preventDefault(); + addInterfaceItem({ + mac : '', + network : '', + type : 'network', + viewMode : 'hide', + editMode : '' + }); + }); + }; + kimchi.retrieveTemplate(kimchi.selectedTemplate, initGeneral); + kimchi.listNetworks(initInterface); + kimchi.listStoragePools(initStorage); $('#tmpl-edit-button-save').on('click', function() { var editableFields = [ 'name', 'cpus', 'memory', 'storagepool', 'disks', 'graphics']; @@ -147,33 +275,41 @@ kimchi.template_edit_main = function() { $.each(editableFields, function(i, field) { /* Support only 1 disk at this moment */ if (field == 'disks') { - origDisks[0].size = Number($('#form-template-edit [name="' + field + '"]').val()); + $.each($('#form-template-storage .item'), function(index, diskEntities) { + origDisks[index].size = Number($(this).find('.template-storage-disk').text()); + }) data[field] = origDisks; } else if (field == 'graphics') { - var type = $('#form-template-edit [name="' + field + '"]').val(); + var type = $('#form-template-general [name="' + field + '"]').val(); data[field] = {'type': type}; } else { - data[field] = $('#form-template-edit [name="' + field + '"]').val(); + data[field] = $('#form-template-general [name="' + field + '"]').val(); } }); data['memory'] = Number(data['memory']); data['cpus'] = Number(data['cpus']); - storagepool = data['storagepool']; - storageArray = storagepool.split("/"); - if (storageArray.length > 3){ - /* Support only 1 disk at this moment */ - data["disks"][0].volume = storageArray.pop(); - data['storagepool'] = storageArray.join("/"); - } else if (data["disks"][0].volume) { - delete data["disks"][0].volume; - } - var networks = templateEditForm.serializeObject().networks; - if (networks instanceof Array) { - data.networks = networks; - } else if (networks != null) { - data.networks = [networks]; + + //Fix me: Only support one storage pool now + var storages = $('.template-tab-body .item', '#form-template-storage'); + var storageForUpdate = new Array(); + $.each(storages, function(index, storageEntities) { + var tempName = $('.template-storage-name', storageEntities).text() + tempName = '/storagepools/' + tempName; + storageForUpdate.push(tempName); + }) + data['storagepool'] = storageForUpdate[0]; + + var networks = $('.template-tab-body .item', '#form-template-interface'); + var networkForUpdate = new Array(); + $.each(networks, function(index, networkEntities) { + networkForUpdate.push($('.template-interface-name', networkEntities).text()); + }); + if (networkForUpdate instanceof Array) { + data.networks = networkForUpdate; + } else if (networkForUpdate != null) { + data.networks = [networkForUpdate]; } else { data.networks = []; } diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl index 5a71d91..d5d2be1 100644 --- a/ui/pages/template-edit.html.tmpl +++ b/ui/pages/template-edit.html.tmpl @@ -28,74 +28,67 @@ <div class="close">X</div> </header> <div class="content"> - <form id="form-template-edit"> + <div id="edit-template-tabs"> <input type="hidden" id="template-name" name="templateName" /> - <fieldset class="template-edit-fieldset"> - <div> + <ul> + <li> + <a href="#form-template-general">$_("General")</a> + </li> + <li> + <a href="#form-template-storage">$_("storage")</a> + </li> + <li> + <a href="#form-template-interface">$_("Interface")</a> + </li> + </ul> + <form id="form-template-general"> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-label"> <label for="template-edit-id-textbox">$_("Name")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-id-textbox" name="name" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-vendor-textbox">$_("Vendor")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-version-textbox">$_("Version")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-cpu-textbox">$_("CPU Number")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-cpu-textbox" name="cpus" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-memory-textbox">$_("Memory (MB)")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-memory-textbox" name="memory" type="text" /> + <div class="template-edit-wrapper-label templ-edit-cdrom"> + <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + </div> + <div class="template-edit-wrapper-label templ-edit-vm-image hide-content"> + <label for="template-edit-vmimage-textbox">$_("Image File")</label> </div> - </div> - <div> <div class="template-edit-wrapper-label"> - <label for="template-edit-disk-textbox">$_("Disk (GB)")</label> + <label>$_("Graphics")</label> </div> + </div> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-controls"> - <input id="template-edit-disk-textbox" name="disks" type="text" /> + <input id="template-edit-id-textbox" name="name" type="text" /> </div> - </div> - </fieldset> - <fieldset class="template-edit-fieldset"> - <div id="templ-edit-cdrom"> - <div class="template-edit-wrapper-label"> - <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> - <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled"/> + <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> </div> - </div> - <div id="templ-edit-vm-image" class="hide-content"> - <div class="template-edit-wrapper-label">$_("Image File")</div> - <div class="template-edit-wrapper-controls"><input name="vm-image" type="text" disabled/></div> - </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Graphics")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-cpu-textbox" name="cpus" type="text" /> + </div> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-memory-textbox" name="memory" type="text" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-cdrom"> + <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-vm-image hide-content"> + <input id="template-edit-vmimage-textbox" name="vm-image" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> <div class="btn dropdown popable"> @@ -108,40 +101,26 @@ </div> </div> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Storage Pool")</label> - </div> - <div class="template-edit-wrapper-controls"> - <div class="btn dropdown popable"> - <input id="template-edit-storagePool" name="storagepool" type="hidden" /> - <span class="text" id="template-edit-storage-label"></span><span class="arrow"></span> - <div class="popover" style="width: 100%"> - <ul class="select-list" id="template-edit-storagePool-list" data-target="template-edit-storagePool" data-label="template-edit-storage-label"> - </ul> - </div> - </div> - </div> + </form> + <form id="form-template-storage"> + <div class="template-tab-header"> + <span class="template-storage-cell">$_("Storage Pool")</span> + <span class="template-storage-cell">$_("Type")</span> + <span class="template-storage-cell">$_("Disk(GB)")</span> + <button type="button" id="template-edit-storage-add-button" class="action-area"></button> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Network")</label> - </div> - <div class="template-edit-wrapper-controls"> - <ul class="select-list-box" id="template-edit-network-list"> - </ul> - <script id="tmpl-network" type="text/html"> - <li> - <label> - <input name="networks" type="checkbox" value="{name}" /> - <span class="item">{name}</span> - </label> - </li> - </script> - </div> + <div class="template-tab-body"> </div> - </fieldset> - </form> + </form> + <form id="form-template-interface"> + <div class="template-tab-header"> + <span class="template-interface-cell">$_("Network")</span> + <span class="template-interface-cell">$_("Type")</span> + <button type="button" id="template-edit-interface-add-button" class="action-area"></button> + </div> + <div class="template-tab-body"></div> + </form> + </div> </div> <footer> <div class="btn-group"> @@ -152,3 +131,41 @@ <script> kimchi.template_edit_main(); </script> +<script id="template-storage-pool-tmpl" type="text/html"> + <div class='item'> + <span class="template-storage-cell"> + <label class="template-storage-name {viewMode}">{storageName}</label> + <select class="{editMode}"></select> + </span> + <span class="template-storage-cell"> + <label class="template-storage-type">{storageType}</label> + </span> + <span class="template-storage-cell"> + <label class="template-storage-disk {viewMode}">{storageDisk}</label> + <input class="{editMode}" /> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> +<script id="template-interface-tmpl" type="text/html"> + <div class="item"> + <span class="template-interface-cell"> + <label class="template-interface-name {viewMode}">{network}</label> + <select class="{editMode}"></select> + </span> + <span class="template-interface-cell"> + <span>{type}</span> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> \ No newline at end of file -- 1.7.1

On 10/31/2014 08:40 AM, Wen Wang wrote:
From: Wen Wang <wenwang@linux.vnet.ibm.com>
This patch redesigned "Edit Template" diaguage in "Templates". New "Edit Template" will display all the related information into tabs of "General", "Storage" and "Interface". Due to unfinished back-end work, functions are not fully supported, which will be finished in the future work.
Temporary disabled functions: 1) Multiple disk operation with multiple storage pools edit in template for which reason the add button in "Storage" tab is disabled.
2) iSCSI and SCSI storage pool add is removed since we are going to allow this kind of operation in the process of creating a VM.
This patch is just an UI redefinition so it must not remove any functionality. And also we need to continue allowing user to create a template using a SCSI or iSCSI pool. So for this UI redefinition, we need to continue listing all the active pools and on SCSI or iSCSI pool selection the user will choose a volume instead of the disk size. And also during some offline chats, I figured out we need to discuss more about the idea to move the SCSI and iSCSI disk selection to VM creation: 1) The VM creation process may not lead user to errors Which means, on SCSI or iSCSI pool selection the user must be able to create a VM. If we move the volume selection to VM creation and only display the free volumes there will be one case the user will not be able to create a VM using a SCSI/iSCSI volume. 2) I should be able to share the same SCSI/iSCSI volume among VMs. Let's say a iSCSI volume contains shared data needed for some VMs. How do I do it? Based on those points, we should keep the iSCSI/SCSI volume selection on Template and use the "shareable" option when creating the VM.
Signed-off-by: Wen Wang <wenwang@linux.vnet.ibm.com> --- ui/css/theme-default/template-edit.css | 84 +++++++- ui/js/src/kimchi.template_edit_main.js | 336 ++++++++++++++++++++++---------- ui/pages/template-edit.html.tmpl | 169 +++++++++------- 3 files changed, 402 insertions(+), 187 deletions(-)
diff --git a/ui/css/theme-default/template-edit.css b/ui/css/theme-default/template-edit.css index 4975f1b..302c488 100644 --- a/ui/css/theme-default/template-edit.css +++ b/ui/css/theme-default/template-edit.css @@ -17,24 +17,33 @@ */ #template-edit-window { font-size: 13px; - height: 600px; - width: 1000px; + height: 500px; + width: 800px; }
-.template-edit-fieldset { - float: left; - padding: 1em; +#edit-template-tabs { + background: none repeat scroll 0 0 transparent; + border: medium none; + height: 100%; + padding: 0; }
-.template-edit-wrapper-label, .template-edit-wrapper-controls { +#edit-template-tabs .form-template-inline-wrapper { + display: inline-block; vertical-align: top; - width: 470px; }
.template-edit-wrapper-label { - height: 18px; - line-height: 18px; - margin-top: 8px; + vertical-align: top; + min-width: 100px; + height: 35px; + line-height: 35px; + margin: 7px 0 8px; +} + +.template-edit-wrapper-controls { + vertical-align: top; + width: 400px; }
.template-edit-wrapper-controls input[type="text"] { @@ -56,7 +65,7 @@
.template-edit-wrapper-controls > .dropdown { margin: 5px 0 0 1px; - width: 440px; + width: 372px; }
.template-edit-wrapper-controls input[type="text"][disabled] { @@ -103,3 +112,56 @@ input[type="checkbox"]:CHECKED+.item { background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat 10px center; } + +#edit-template-tabs .template-tab-header { + margin-bottom: 8px; + padding-bottom: 2px; + font-weight: bold; + border-bottom: 1px solid #999999; + overflow: hidden; +} + +#edit-template-tabs .template-tab-header .action-area { + float: right; + height: 20px; + width: 20px; +} + +#edit-template-tabs .template-storage-cell{ + display: inline-block; + width: 230px; +} + +#edit-template-tabs .template-interface-cell { + display: inline-block; + width: 250px; +} + +#form-template-storage .template-tab-body select { + width: 140px; +} + +#form-template-storage .template-tab-body input { + width: 56px; +} + +#edit-template-tabs .template-tab-body .item { + margin: 5px 0; +} + +#form-template-interface .template-tab-body select { + width: 180px; +} + +#edit-template-tabs .template-tab-body .action-area { + float: right; +} + +#edit-template-tabs .template-tab-body .action-area button { + width: 20px; + height: 20px; +} + +#edit-template-tabs .template-tab-body .hide { + display: none; +} \ No newline at end of file diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js index 2f4cc9a..ac6cff8 100644 --- a/ui/js/src/kimchi.template_edit_main.js +++ b/ui/js/src/kimchi.template_edit_main.js @@ -16,14 +16,18 @@ * limitations under the License. */ kimchi.template_edit_main = function() { - var templateEditForm = $('#form-template-edit'); + var templateEditMain = $('#edit-template-tabs'); var origDisks; var origPool; + var origNetworks; var templateDiskSize; - $('#template-name', templateEditForm).val(kimchi.selectedTemplate); - kimchi.retrieveTemplate(kimchi.selectedTemplate, function(template) { + $('#template-name', templateEditMain).val(kimchi.selectedTemplate); + templateEditMain.tabs(); + + var initGeneral = function(template) { origDisks = template.disks; origPool = template.storagepool; + origNetworks = template.networks; for(var i=0;i<template.disks.length;i++){ if(template.disks[i].base){ template["vm-image"] = template.disks[i].base; @@ -37,18 +41,12 @@ kimchi.template_edit_main = function() { if (prop == 'graphics') { value = value["type"]; } - $('input[name="' + prop + '"]', templateEditForm).val(value); - } - var disks = template.disks; - $('input[name="disks"]').val(disks[0].size); - templateDiskSize = $('input[name="disks"]').val(); - if (disks[0].volume) { - var spool_value = $('#form-template-edit [name="storagepool"]').val(); - $('input[name="storagepool"]', templateEditForm).val(spool_value + '/' + disks[0].volume); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); + $('input[name="' + prop + '"]', templateEditMain).val(value); }
var vncOpt = [{label: 'VNC', value: 'vnc'}]; + $('#template-edit-graphics').append('<option selected>VNC</option>'); + $('#template-edit-graphics').append('<option>Spice</option>'); kimchi.select('template-edit-graphics-list', vncOpt); var enableSpice = function() { if (kimchi.capabilities == undefined) { @@ -61,85 +59,215 @@ kimchi.template_edit_main = function() { } }; enableSpice(); - + }; + var initStorage = function(result) { var scsipools = {}; - kimchi.listStoragePools(function(result) { - var options = []; - if (result && result.length) { - $.each(result, function(index, storagePool) { - if ((storagePool.state=="active") && (storagePool.type !== 'kimchi-iso')) { - if ((storagePool.type == 'iscsi') || (storagePool.type == 'scsi')){ - scsipools[storagePool.name] = []; - kimchi.listStorageVolumes(storagePool.name, function(result) { - if (result && result.length) { - $.each(result, function(index, storageVolume) { - options.push({ - label: storagePool.name + '/' + storageVolume.name, - value: '/storagepools/' + storagePool.name + '/' + storageVolume.name - }); - scsipools[storagePool.name].push(storageVolume) - }); - } - kimchi.select('template-edit-storagePool-list', options); - }); - } - else { - options.push({ - label: storagePool.name, - value: '/storagepools/' + storagePool.name - }); - } + var addStorageItem = function(storageData) { + var nodeStorage = $.parseHTML(kimchi.substitute($("#template-storage-pool-tmpl").html(), storageData)); + $('.template-tab-body', '#form-template-storage').append(nodeStorage); + $('.edit', '#form-template-storage').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.template-storage-name', storageItem).hide(); + var currentName = $('.template-storage-name', storageItem).text(); + $('.template-storage-disk', storageItem).hide(); + var currentDisk = $('.template-storage-disk', storageItem).text(); + $('input', storageItem).val(currentDisk).show(); + $('select', storageItem).show(); + if (currentName === 'iscsi' || currentName === 'scsi') { + $('input', storageItem).attr('disabled', true); + } else { + $('input', storageItem).attr('disabled', false); + } + $('.save', storageItem).parent().show(); + $('.delete', storageItem).parent().hide(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).hide(); + $('select', storageItem).show(); + }); + $('.delete', '#form-template-storage').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-storage').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var cancelEntity = $(this).parent().parent(); + if($('.template-storage-disk', cancelEntity).text() === '') { + cancelEntity.remove(); + } else { + $('label', cancelEntity).show(); + $('input', cancelEntity).hide(); + $('select', cancelEntity).hide(); + $('.cancel', cancelEntity).parent().hide(); + $('.edit', cancelEntity).parent().show(); + } + }); + $('.save', '#form-template-storage').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.save', storageItem).parent().hide(); + $('.delete', storageItem).parent().show(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).show(); + $('.template-storage-disk', storageItem).text($('input', storageItem).val()).show(); + $('select', storageItem).hide(); + $('input', storageItem).hide(); + }); + var storageOptions = ''; + $.each(result, function(index, storageEntities) { + if((storageEntities.state === 'active') && (storageEntities.type != 'kimchi-iso') + && (storageEntities.type != 'iscsi') && (storageEntities.type != 'scsi')){ + var isSlected = storageEntities.name === 'default' ? ' selected' : ''; + storageOptions += '<option' + isSlected + '>' + result[index].name + '</option>'; + } + }); + $('select', '#form-template-storage').find('option').remove(); + $('select', '#form-template-storage').append(storageOptions); + $('select', '#form-template-storage').change(function() { + var selectedItem = $(this).parent().parent(); + var tempStorageName = $(this).val(); + if (tempStorageName === 'iscsi' || tempStorageName === 'scsi') { + $('input', selectedItem).attr('disabled', true); + } else { + $('input', selectedItem).attr('disabled', false); + } + $.each(result, function(index, storageEntities) { + if (tempStorageName === storageEntities.name) { + selectedItem.find('.template-storage-type').text(storageEntities.type); } - }); - } - if ($.isEmptyObject(scsipools)) { - kimchi.select('template-edit-storagePool-list', options); + }) + }); + }; + + if ((origDisks && origDisks.length) && (origPool && origPool)) { + splitPool = origPool.split('/'); + var defaultPool; + var defaultType; + $.each(result, function(index, poolEntities) { + if (poolEntities.name === splitPool[splitPool.length-1]) { + defaultType = poolEntities.type; + defaultPool = splitPool[splitPool.length-1] + } + }); + $.each(origDisks, function(index, diskEntities) { + var storageNodeData = { + viewMode : '', + editMode : 'hide', + storageName : defaultPool, + storageType : defaultType, + storageDisk : diskEntities.size + } + addStorageItem(storageNodeData); + }); + } + + $('#template-edit-storage-add-button').button({ + icons: { + primary: "ui-icon-plusthick" + }, + text: false, + disabled: true + }).click(function(event) { + event.preventDefault(); + var storageNodeData = { + viewMode : 'hide', + editMode : '', + storageName : 'default', + storageType : 'dir', + storageDisk : '' } + addStorageItem(storageNodeData); }); - kimchi.listNetworks(function(result) { - if(result && result.length > 0) { - var html = ''; - var tmpl = $('#tmpl-network').html(); - $.each(result, function(index, network) { - if (result[index].state === 'active') - html += kimchi.substitute(tmpl, network); - }); - $('#template-edit-network-list').html(html).show(); - if(template.networks && template.networks.length > 0) { - $('input[name="networks"]', templateEditForm).each(function(index, element) { - var value = $(element).val(); - if(template.networks.indexOf(value) >= 0) { - $(element).prop('checked', true); - } - }); + }; + var initInterface = function(result) { + var addInterfaceItem = function(networkData) { + var nodeInterface = $.parseHTML(kimchi.substitute($('#template-interface-tmpl').html(), networkData)); + $('.template-tab-body', '#form-template-interface').append(nodeInterface); + $('.edit', '#form-template-interface').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false, + disabled : true + }); + $('.delete', '#form-template-interface').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-interface').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.save', '#form-template-interface').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var interItem = $(this).parent().parent(); + $('.save', interItem).parent().hide(); + $('.delete', interItem).parent().show(); + var selectedInterface = $('select', interItem).val(); + $('label', interItem).text(selectedInterface).show(); + $('select', interItem).hide(); + }); + var networkOptions = ''; + for(var i=0;i<result.length;i++){ + if(result[i].state === "active") { + var isSlected = i==0 ? ' selected' : ''; + networkOptions += '<option' + isSlected + '>' + result[i].name + '</option>'; } - } else { - $('#template-edit-network-list').hide(); } - }); - }); - - $('#template-edit-storagePool').change(function() { - storagepool = $(this).val(); - var storageArray = storagepool.split("/"); - if (storageArray.length > 3) { - volumeName = storageArray.pop(); - poolName = storageArray.pop(); - kimchi.getStoragePoolVolume(poolName, volumeName, function(result) { - $('input[name="disks"]', templateEditForm).val(result.capacity / Math.pow(1024,3)); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); - return false; - }, function (err) { - kimchi.message.error(err.responseJSON.reason); + $('select', '#form-template-interface').find('option').remove(); + $('select', '#form-template-interface').append(networkOptions); + }; + if(result && result.length > 0) { + $.each(result, function(index, data) { + if($.inArray(data.name, origNetworks) > -1) { + addInterfaceItem({ + mac : '', + network : data.name, + type : 'network', + viewMode : '', + editMode : 'hide' + }); + } }); - } else { - $('input[name="disks"]', templateEditForm).removeAttr('disabled'); - $('input[name="disks"]', templateEditForm).val(templateDiskSize); } - }); - $('input[name="disks"]', templateEditForm).keyup(function() { - templateDiskSize = $('input[name="disks"]', templateEditForm).val(); - }); + $('#template-edit-interface-add-button').button({ + icons: { + primary: 'ui-icon-plusthick' + }, + text: false + }).click(function(evt) { + evt.preventDefault(); + addInterfaceItem({ + mac : '', + network : '', + type : 'network', + viewMode : 'hide', + editMode : '' + }); + }); + }; + kimchi.retrieveTemplate(kimchi.selectedTemplate, initGeneral); + kimchi.listNetworks(initInterface); + kimchi.listStoragePools(initStorage);
$('#tmpl-edit-button-save').on('click', function() { var editableFields = [ 'name', 'cpus', 'memory', 'storagepool', 'disks', 'graphics']; @@ -147,33 +275,41 @@ kimchi.template_edit_main = function() { $.each(editableFields, function(i, field) { /* Support only 1 disk at this moment */ if (field == 'disks') { - origDisks[0].size = Number($('#form-template-edit [name="' + field + '"]').val()); + $.each($('#form-template-storage .item'), function(index, diskEntities) { + origDisks[index].size = Number($(this).find('.template-storage-disk').text()); + }) data[field] = origDisks; } else if (field == 'graphics') { - var type = $('#form-template-edit [name="' + field + '"]').val(); + var type = $('#form-template-general [name="' + field + '"]').val(); data[field] = {'type': type}; } else { - data[field] = $('#form-template-edit [name="' + field + '"]').val(); + data[field] = $('#form-template-general [name="' + field + '"]').val(); } }); data['memory'] = Number(data['memory']); data['cpus'] = Number(data['cpus']); - storagepool = data['storagepool']; - storageArray = storagepool.split("/"); - if (storageArray.length > 3){ - /* Support only 1 disk at this moment */ - data["disks"][0].volume = storageArray.pop(); - data['storagepool'] = storageArray.join("/"); - } else if (data["disks"][0].volume) { - delete data["disks"][0].volume; - } - var networks = templateEditForm.serializeObject().networks; - if (networks instanceof Array) { - data.networks = networks; - } else if (networks != null) { - data.networks = [networks]; + + //Fix me: Only support one storage pool now + var storages = $('.template-tab-body .item', '#form-template-storage'); + var storageForUpdate = new Array(); + $.each(storages, function(index, storageEntities) { + var tempName = $('.template-storage-name', storageEntities).text() + tempName = '/storagepools/' + tempName; + storageForUpdate.push(tempName); + }) + data['storagepool'] = storageForUpdate[0]; + + var networks = $('.template-tab-body .item', '#form-template-interface'); + var networkForUpdate = new Array(); + $.each(networks, function(index, networkEntities) { + networkForUpdate.push($('.template-interface-name', networkEntities).text()); + }); + if (networkForUpdate instanceof Array) { + data.networks = networkForUpdate; + } else if (networkForUpdate != null) { + data.networks = [networkForUpdate]; } else { data.networks = []; } diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl index 5a71d91..d5d2be1 100644 --- a/ui/pages/template-edit.html.tmpl +++ b/ui/pages/template-edit.html.tmpl @@ -28,74 +28,67 @@ <div class="close">X</div> </header> <div class="content"> - <form id="form-template-edit"> + <div id="edit-template-tabs"> <input type="hidden" id="template-name" name="templateName" /> - <fieldset class="template-edit-fieldset"> - <div> + <ul> + <li> + <a href="#form-template-general">$_("General")</a> + </li> + <li> + <a href="#form-template-storage">$_("storage")</a> + </li> + <li> + <a href="#form-template-interface">$_("Interface")</a> + </li> + </ul> + <form id="form-template-general"> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-label"> <label for="template-edit-id-textbox">$_("Name")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-id-textbox" name="name" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-vendor-textbox">$_("Vendor")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-version-textbox">$_("Version")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-cpu-textbox">$_("CPU Number")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-cpu-textbox" name="cpus" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-memory-textbox">$_("Memory (MB)")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-memory-textbox" name="memory" type="text" /> + <div class="template-edit-wrapper-label templ-edit-cdrom"> + <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + </div> + <div class="template-edit-wrapper-label templ-edit-vm-image hide-content"> + <label for="template-edit-vmimage-textbox">$_("Image File")</label> </div> - </div> - <div> <div class="template-edit-wrapper-label"> - <label for="template-edit-disk-textbox">$_("Disk (GB)")</label> + <label>$_("Graphics")</label> </div> + </div> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-controls"> - <input id="template-edit-disk-textbox" name="disks" type="text" /> + <input id="template-edit-id-textbox" name="name" type="text" /> </div> - </div> - </fieldset> - <fieldset class="template-edit-fieldset"> - <div id="templ-edit-cdrom"> - <div class="template-edit-wrapper-label"> - <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> - <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled"/> + <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> </div> - </div> - <div id="templ-edit-vm-image" class="hide-content"> - <div class="template-edit-wrapper-label">$_("Image File")</div> - <div class="template-edit-wrapper-controls"><input name="vm-image" type="text" disabled/></div> - </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Graphics")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-cpu-textbox" name="cpus" type="text" /> + </div> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-memory-textbox" name="memory" type="text" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-cdrom"> + <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-vm-image hide-content"> + <input id="template-edit-vmimage-textbox" name="vm-image" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> <div class="btn dropdown popable"> @@ -108,40 +101,26 @@ </div> </div> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Storage Pool")</label> - </div> - <div class="template-edit-wrapper-controls"> - <div class="btn dropdown popable"> - <input id="template-edit-storagePool" name="storagepool" type="hidden" /> - <span class="text" id="template-edit-storage-label"></span><span class="arrow"></span> - <div class="popover" style="width: 100%"> - <ul class="select-list" id="template-edit-storagePool-list" data-target="template-edit-storagePool" data-label="template-edit-storage-label"> - </ul> - </div> - </div> - </div> + </form> + <form id="form-template-storage"> + <div class="template-tab-header"> + <span class="template-storage-cell">$_("Storage Pool")</span> + <span class="template-storage-cell">$_("Type")</span> + <span class="template-storage-cell">$_("Disk(GB)")</span> + <button type="button" id="template-edit-storage-add-button" class="action-area"></button> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Network")</label> - </div> - <div class="template-edit-wrapper-controls"> - <ul class="select-list-box" id="template-edit-network-list"> - </ul> - <script id="tmpl-network" type="text/html"> - <li> - <label> - <input name="networks" type="checkbox" value="{name}" /> - <span class="item">{name}</span> - </label> - </li> - </script> - </div> + <div class="template-tab-body"> </div> - </fieldset> - </form> + </form> + <form id="form-template-interface"> + <div class="template-tab-header"> + <span class="template-interface-cell">$_("Network")</span> + <span class="template-interface-cell">$_("Type")</span> + <button type="button" id="template-edit-interface-add-button" class="action-area"></button> + </div> + <div class="template-tab-body"></div> + </form> + </div> </div> <footer> <div class="btn-group"> @@ -152,3 +131,41 @@ <script> kimchi.template_edit_main(); </script> +<script id="template-storage-pool-tmpl" type="text/html"> + <div class='item'> + <span class="template-storage-cell"> + <label class="template-storage-name {viewMode}">{storageName}</label> + <select class="{editMode}"></select> + </span> + <span class="template-storage-cell"> + <label class="template-storage-type">{storageType}</label> + </span> + <span class="template-storage-cell"> + <label class="template-storage-disk {viewMode}">{storageDisk}</label> + <input class="{editMode}" /> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> +<script id="template-interface-tmpl" type="text/html"> + <div class="item"> + <span class="template-interface-cell"> + <label class="template-interface-name {viewMode}">{network}</label> + <select class="{editMode}"></select> + </span> + <span class="template-interface-cell"> + <span>{type}</span> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> \ No newline at end of file

On 11/2/2014 9:00 PM, Aline Manera wrote:
On 10/31/2014 08:40 AM, Wen Wang wrote:
From: Wen Wang <wenwang@linux.vnet.ibm.com>
This patch redesigned "Edit Template" diaguage in "Templates". New "Edit Template" will display all the related information into tabs of "General", "Storage" and "Interface". Due to unfinished back-end work, functions are not fully supported, which will be finished in the future work.
Temporary disabled functions: 1) Multiple disk operation with multiple storage pools edit in template for which reason the add button in "Storage" tab is disabled.
2) iSCSI and SCSI storage pool add is removed since we are going to allow this kind of operation in the process of creating a VM.
This patch is just an UI redefinition so it must not remove any functionality.
And also we need to continue allowing user to create a template using a SCSI or iSCSI pool.
So for this UI redefinition, we need to continue listing all the active pools and on SCSI or iSCSI pool selection the user will choose a volume instead of the disk size.
And also during some offline chats, I figured out we need to discuss more about the idea to move the SCSI and iSCSI disk selection to VM creation:
1) The VM creation process may not lead user to errors Which means, on SCSI or iSCSI pool selection the user must be able to create a VM. If we move the volume selection to VM creation and only display the free volumes there will be one case the user will not be able to create a VM using a SCSI/iSCSI volume.
2) I should be able to share the same SCSI/iSCSI volume among VMs. Let's say a iSCSI volume contains shared data needed for some VMs. How do I do it?
Based on those points, we should keep the iSCSI/SCSI volume selection on Template and use the "shareable" option when creating the VM.
I got your point. So we should keep the iSCSI and SCSI function as what we had before and I will just have the format changed which should function the same as before. Due to unfinished back-end multi-disk from different storage pools support, I will make adding disk in "Storage" tab disabled temporarily as well as we should talk about what is the best way to move the iSCSI as well as SCSI disk selection to VM creation. I will send a V2 for your comments Best
Signed-off-by: Wen Wang <wenwang@linux.vnet.ibm.com> --- ui/css/theme-default/template-edit.css | 84 +++++++- ui/js/src/kimchi.template_edit_main.js | 336 ++++++++++++++++++++++---------- ui/pages/template-edit.html.tmpl | 169 +++++++++------- 3 files changed, 402 insertions(+), 187 deletions(-)
diff --git a/ui/css/theme-default/template-edit.css b/ui/css/theme-default/template-edit.css index 4975f1b..302c488 100644 --- a/ui/css/theme-default/template-edit.css +++ b/ui/css/theme-default/template-edit.css @@ -17,24 +17,33 @@ */ #template-edit-window { font-size: 13px; - height: 600px; - width: 1000px; + height: 500px; + width: 800px; }
-.template-edit-fieldset { - float: left; - padding: 1em; +#edit-template-tabs { + background: none repeat scroll 0 0 transparent; + border: medium none; + height: 100%; + padding: 0; }
-.template-edit-wrapper-label, .template-edit-wrapper-controls { +#edit-template-tabs .form-template-inline-wrapper { + display: inline-block; vertical-align: top; - width: 470px; }
.template-edit-wrapper-label { - height: 18px; - line-height: 18px; - margin-top: 8px; + vertical-align: top; + min-width: 100px; + height: 35px; + line-height: 35px; + margin: 7px 0 8px; +} + +.template-edit-wrapper-controls { + vertical-align: top; + width: 400px; }
.template-edit-wrapper-controls input[type="text"] { @@ -56,7 +65,7 @@
.template-edit-wrapper-controls > .dropdown { margin: 5px 0 0 1px; - width: 440px; + width: 372px; }
.template-edit-wrapper-controls input[type="text"][disabled] { @@ -103,3 +112,56 @@ input[type="checkbox"]:CHECKED+.item { background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat 10px center; } + +#edit-template-tabs .template-tab-header { + margin-bottom: 8px; + padding-bottom: 2px; + font-weight: bold; + border-bottom: 1px solid #999999; + overflow: hidden; +} + +#edit-template-tabs .template-tab-header .action-area { + float: right; + height: 20px; + width: 20px; +} + +#edit-template-tabs .template-storage-cell{ + display: inline-block; + width: 230px; +} + +#edit-template-tabs .template-interface-cell { + display: inline-block; + width: 250px; +} + +#form-template-storage .template-tab-body select { + width: 140px; +} + +#form-template-storage .template-tab-body input { + width: 56px; +} + +#edit-template-tabs .template-tab-body .item { + margin: 5px 0; +} + +#form-template-interface .template-tab-body select { + width: 180px; +} + +#edit-template-tabs .template-tab-body .action-area { + float: right; +} + +#edit-template-tabs .template-tab-body .action-area button { + width: 20px; + height: 20px; +} + +#edit-template-tabs .template-tab-body .hide { + display: none; +} \ No newline at end of file diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js index 2f4cc9a..ac6cff8 100644 --- a/ui/js/src/kimchi.template_edit_main.js +++ b/ui/js/src/kimchi.template_edit_main.js @@ -16,14 +16,18 @@ * limitations under the License. */ kimchi.template_edit_main = function() { - var templateEditForm = $('#form-template-edit'); + var templateEditMain = $('#edit-template-tabs'); var origDisks; var origPool; + var origNetworks; var templateDiskSize; - $('#template-name', templateEditForm).val(kimchi.selectedTemplate); - kimchi.retrieveTemplate(kimchi.selectedTemplate, function(template) { + $('#template-name', templateEditMain).val(kimchi.selectedTemplate); + templateEditMain.tabs(); + + var initGeneral = function(template) { origDisks = template.disks; origPool = template.storagepool; + origNetworks = template.networks; for(var i=0;i<template.disks.length;i++){ if(template.disks[i].base){ template["vm-image"] = template.disks[i].base; @@ -37,18 +41,12 @@ kimchi.template_edit_main = function() { if (prop == 'graphics') { value = value["type"]; } - $('input[name="' + prop + '"]', templateEditForm).val(value); - } - var disks = template.disks; - $('input[name="disks"]').val(disks[0].size); - templateDiskSize = $('input[name="disks"]').val(); - if (disks[0].volume) { - var spool_value = $('#form-template-edit [name="storagepool"]').val(); - $('input[name="storagepool"]', templateEditForm).val(spool_value + '/' + disks[0].volume); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); + $('input[name="' + prop + '"]', templateEditMain).val(value); }
var vncOpt = [{label: 'VNC', value: 'vnc'}]; + $('#template-edit-graphics').append('<option selected>VNC</option>'); + $('#template-edit-graphics').append('<option>Spice</option>'); kimchi.select('template-edit-graphics-list', vncOpt); var enableSpice = function() { if (kimchi.capabilities == undefined) { @@ -61,85 +59,215 @@ kimchi.template_edit_main = function() { } }; enableSpice(); - + }; + var initStorage = function(result) { var scsipools = {}; - kimchi.listStoragePools(function(result) { - var options = []; - if (result && result.length) { - $.each(result, function(index, storagePool) { - if ((storagePool.state=="active") && (storagePool.type !== 'kimchi-iso')) { - if ((storagePool.type == 'iscsi') || (storagePool.type == 'scsi')){ - scsipools[storagePool.name] = []; - kimchi.listStorageVolumes(storagePool.name, function(result) { - if (result && result.length) { - $.each(result, function(index, storageVolume) { - options.push({ - label: storagePool.name + '/' + storageVolume.name, - value: '/storagepools/' + storagePool.name + '/' + storageVolume.name - }); - scsipools[storagePool.name].push(storageVolume) - }); - } - kimchi.select('template-edit-storagePool-list', options); - }); - } - else { - options.push({ - label: storagePool.name, - value: '/storagepools/' + storagePool.name - }); - } + var addStorageItem = function(storageData) { + var nodeStorage = $.parseHTML(kimchi.substitute($("#template-storage-pool-tmpl").html(), storageData));
+ $('.template-tab-body', '#form-template-storage').append(nodeStorage); + $('.edit', '#form-template-storage').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.template-storage-name', storageItem).hide(); + var currentName = $('.template-storage-name', storageItem).text(); + $('.template-storage-disk', storageItem).hide(); + var currentDisk = $('.template-storage-disk', storageItem).text(); + $('input', storageItem).val(currentDisk).show(); + $('select', storageItem).show(); + if (currentName === 'iscsi' || currentName === 'scsi') { + $('input', storageItem).attr('disabled', true); + } else { + $('input', storageItem).attr('disabled', false); + } + $('.save', storageItem).parent().show(); + $('.delete', storageItem).parent().hide(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).hide(); + $('select', storageItem).show(); + }); + $('.delete', '#form-template-storage').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-storage').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var cancelEntity = $(this).parent().parent(); + if($('.template-storage-disk', cancelEntity).text() === '') { + cancelEntity.remove(); + } else { + $('label', cancelEntity).show(); + $('input', cancelEntity).hide(); + $('select', cancelEntity).hide(); + $('.cancel', cancelEntity).parent().hide(); + $('.edit', cancelEntity).parent().show(); + } + }); + $('.save', '#form-template-storage').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.save', storageItem).parent().hide(); + $('.delete', storageItem).parent().show(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).show(); + $('.template-storage-disk', storageItem).text($('input', storageItem).val()).show(); + $('select', storageItem).hide(); + $('input', storageItem).hide(); + }); + var storageOptions = ''; + $.each(result, function(index, storageEntities) { + if((storageEntities.state === 'active') && (storageEntities.type != 'kimchi-iso') + && (storageEntities.type != 'iscsi') && (storageEntities.type != 'scsi')){ + var isSlected = storageEntities.name === 'default' ? ' selected' : ''; + storageOptions += '<option' + isSlected + '>' + result[index].name + '</option>'; + } + }); + $('select', '#form-template-storage').find('option').remove(); + $('select', '#form-template-storage').append(storageOptions); + $('select', '#form-template-storage').change(function() { + var selectedItem = $(this).parent().parent(); + var tempStorageName = $(this).val(); + if (tempStorageName === 'iscsi' || tempStorageName === 'scsi') { + $('input', selectedItem).attr('disabled', true); + } else { + $('input', selectedItem).attr('disabled', false); + } + $.each(result, function(index, storageEntities) { + if (tempStorageName === storageEntities.name) { + selectedItem.find('.template-storage-type').text(storageEntities.type); } - }); - } - if ($.isEmptyObject(scsipools)) { - kimchi.select('template-edit-storagePool-list', options); + }) + }); + }; + + if ((origDisks && origDisks.length) && (origPool && origPool)) { + splitPool = origPool.split('/'); + var defaultPool; + var defaultType; + $.each(result, function(index, poolEntities) { + if (poolEntities.name === splitPool[splitPool.length-1]) { + defaultType = poolEntities.type; + defaultPool = splitPool[splitPool.length-1] + } + }); + $.each(origDisks, function(index, diskEntities) { + var storageNodeData = { + viewMode : '', + editMode : 'hide', + storageName : defaultPool, + storageType : defaultType, + storageDisk : diskEntities.size + } + addStorageItem(storageNodeData); + }); + } + + $('#template-edit-storage-add-button').button({ + icons: { + primary: "ui-icon-plusthick" + }, + text: false, + disabled: true + }).click(function(event) { + event.preventDefault(); + var storageNodeData = { + viewMode : 'hide', + editMode : '', + storageName : 'default', + storageType : 'dir', + storageDisk : '' } + addStorageItem(storageNodeData); }); - kimchi.listNetworks(function(result) { - if(result && result.length > 0) { - var html = ''; - var tmpl = $('#tmpl-network').html(); - $.each(result, function(index, network) { - if (result[index].state === 'active') - html += kimchi.substitute(tmpl, network); - }); - $('#template-edit-network-list').html(html).show(); - if(template.networks && template.networks.length > 0) { - $('input[name="networks"]', templateEditForm).each(function(index, element) { - var value = $(element).val(); - if(template.networks.indexOf(value) >= 0) { - $(element).prop('checked', true); - } - }); + }; + var initInterface = function(result) { + var addInterfaceItem = function(networkData) { + var nodeInterface = $.parseHTML(kimchi.substitute($('#template-interface-tmpl').html(), networkData)); + $('.template-tab-body', '#form-template-interface').append(nodeInterface); + $('.edit', '#form-template-interface').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false, + disabled : true + }); + $('.delete', '#form-template-interface').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-interface').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.save', '#form-template-interface').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var interItem = $(this).parent().parent(); + $('.save', interItem).parent().hide(); + $('.delete', interItem).parent().show(); + var selectedInterface = $('select', interItem).val(); + $('label', interItem).text(selectedInterface).show(); + $('select', interItem).hide(); + }); + var networkOptions = ''; + for(var i=0;i<result.length;i++){ + if(result[i].state === "active") { + var isSlected = i==0 ? ' selected' : ''; + networkOptions += '<option' + isSlected + '>' + result[i].name + '</option>'; } - } else { - $('#template-edit-network-list').hide(); } - }); - }); - - $('#template-edit-storagePool').change(function() { - storagepool = $(this).val(); - var storageArray = storagepool.split("/"); - if (storageArray.length > 3) { - volumeName = storageArray.pop(); - poolName = storageArray.pop(); - kimchi.getStoragePoolVolume(poolName, volumeName, function(result) { - $('input[name="disks"]', templateEditForm).val(result.capacity / Math.pow(1024,3)); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); - return false; - }, function (err) { - kimchi.message.error(err.responseJSON.reason); + $('select', '#form-template-interface').find('option').remove(); + $('select', '#form-template-interface').append(networkOptions); + }; + if(result && result.length > 0) { + $.each(result, function(index, data) { + if($.inArray(data.name, origNetworks) > -1) { + addInterfaceItem({ + mac : '', + network : data.name, + type : 'network', + viewMode : '', + editMode : 'hide' + }); + } }); - } else { - $('input[name="disks"]', templateEditForm).removeAttr('disabled'); - $('input[name="disks"]', templateEditForm).val(templateDiskSize); } - }); - $('input[name="disks"]', templateEditForm).keyup(function() { - templateDiskSize = $('input[name="disks"]', templateEditForm).val(); - }); + $('#template-edit-interface-add-button').button({ + icons: { + primary: 'ui-icon-plusthick' + }, + text: false + }).click(function(evt) { + evt.preventDefault(); + addInterfaceItem({ + mac : '', + network : '', + type : 'network', + viewMode : 'hide', + editMode : '' + }); + }); + }; + kimchi.retrieveTemplate(kimchi.selectedTemplate, initGeneral); + kimchi.listNetworks(initInterface); + kimchi.listStoragePools(initStorage);
$('#tmpl-edit-button-save').on('click', function() { var editableFields = [ 'name', 'cpus', 'memory', 'storagepool', 'disks', 'graphics']; @@ -147,33 +275,41 @@ kimchi.template_edit_main = function() { $.each(editableFields, function(i, field) { /* Support only 1 disk at this moment */ if (field == 'disks') { - origDisks[0].size = Number($('#form-template-edit [name="' + field + '"]').val()); + $.each($('#form-template-storage .item'), function(index, diskEntities) { + origDisks[index].size = Number($(this).find('.template-storage-disk').text()); + }) data[field] = origDisks; } else if (field == 'graphics') { - var type = $('#form-template-edit [name="' + field + '"]').val(); + var type = $('#form-template-general [name="' + field + '"]').val(); data[field] = {'type': type}; } else { - data[field] = $('#form-template-edit [name="' + field + '"]').val(); + data[field] = $('#form-template-general [name="' + field + '"]').val(); } }); data['memory'] = Number(data['memory']); data['cpus'] = Number(data['cpus']); - storagepool = data['storagepool']; - storageArray = storagepool.split("/"); - if (storageArray.length > 3){ - /* Support only 1 disk at this moment */ - data["disks"][0].volume = storageArray.pop(); - data['storagepool'] = storageArray.join("/"); - } else if (data["disks"][0].volume) { - delete data["disks"][0].volume; - } - var networks = templateEditForm.serializeObject().networks; - if (networks instanceof Array) { - data.networks = networks; - } else if (networks != null) { - data.networks = [networks]; + + //Fix me: Only support one storage pool now + var storages = $('.template-tab-body .item', '#form-template-storage'); + var storageForUpdate = new Array(); + $.each(storages, function(index, storageEntities) { + var tempName = $('.template-storage-name', storageEntities).text() + tempName = '/storagepools/' + tempName; + storageForUpdate.push(tempName); + }) + data['storagepool'] = storageForUpdate[0]; + + var networks = $('.template-tab-body .item', '#form-template-interface'); + var networkForUpdate = new Array(); + $.each(networks, function(index, networkEntities) { + networkForUpdate.push($('.template-interface-name', networkEntities).text()); + }); + if (networkForUpdate instanceof Array) { + data.networks = networkForUpdate; + } else if (networkForUpdate != null) { + data.networks = [networkForUpdate]; } else { data.networks = []; } diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl index 5a71d91..d5d2be1 100644 --- a/ui/pages/template-edit.html.tmpl +++ b/ui/pages/template-edit.html.tmpl @@ -28,74 +28,67 @@ <div class="close">X</div> </header> <div class="content"> - <form id="form-template-edit"> + <div id="edit-template-tabs"> <input type="hidden" id="template-name" name="templateName" /> - <fieldset class="template-edit-fieldset"> - <div> + <ul> + <li> + <a href="#form-template-general">$_("General")</a> + </li> + <li> + <a href="#form-template-storage">$_("storage")</a> + </li> + <li> + <a href="#form-template-interface">$_("Interface")</a> + </li> + </ul> + <form id="form-template-general"> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-label"> <label for="template-edit-id-textbox">$_("Name")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-id-textbox" name="name" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-vendor-textbox">$_("Vendor")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-version-textbox">$_("Version")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-cpu-textbox">$_("CPU Number")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-cpu-textbox" name="cpus" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-memory-textbox">$_("Memory (MB)")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-memory-textbox" name="memory" type="text" /> + <div class="template-edit-wrapper-label templ-edit-cdrom"> + <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + </div> + <div class="template-edit-wrapper-label templ-edit-vm-image hide-content"> + <label for="template-edit-vmimage-textbox">$_("Image File")</label> </div> - </div> - <div> <div class="template-edit-wrapper-label"> - <label for="template-edit-disk-textbox">$_("Disk (GB)")</label> + <label>$_("Graphics")</label> </div> + </div> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-controls"> - <input id="template-edit-disk-textbox" name="disks" type="text" /> + <input id="template-edit-id-textbox" name="name" type="text" /> </div> - </div> - </fieldset> - <fieldset class="template-edit-fieldset"> - <div id="templ-edit-cdrom"> - <div class="template-edit-wrapper-label"> - <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> - <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled"/> + <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> </div> - </div> - <div id="templ-edit-vm-image" class="hide-content"> - <div class="template-edit-wrapper-label">$_("Image File")</div> - <div class="template-edit-wrapper-controls"><input name="vm-image" type="text" disabled/></div> - </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Graphics")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-cpu-textbox" name="cpus" type="text" /> + </div> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-memory-textbox" name="memory" type="text" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-cdrom"> + <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-vm-image hide-content"> + <input id="template-edit-vmimage-textbox" name="vm-image" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> <div class="btn dropdown popable"> @@ -108,40 +101,26 @@ </div> </div> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Storage Pool")</label> - </div> - <div class="template-edit-wrapper-controls"> - <div class="btn dropdown popable"> - <input id="template-edit-storagePool" name="storagepool" type="hidden" /> - <span class="text" id="template-edit-storage-label"></span><span class="arrow"></span> - <div class="popover" style="width: 100%"> - <ul class="select-list" id="template-edit-storagePool-list" data-target="template-edit-storagePool" data-label="template-edit-storage-label"> - </ul> - </div> - </div> - </div> + </form> + <form id="form-template-storage"> + <div class="template-tab-header"> + <span class="template-storage-cell">$_("Storage Pool")</span> + <span class="template-storage-cell">$_("Type")</span> + <span class="template-storage-cell">$_("Disk(GB)")</span> + <button type="button" id="template-edit-storage-add-button" class="action-area"></button> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Network")</label> - </div> - <div class="template-edit-wrapper-controls"> - <ul class="select-list-box" id="template-edit-network-list"> - </ul> - <script id="tmpl-network" type="text/html"> - <li> - <label> - <input name="networks" type="checkbox" value="{name}" /> - <span class="item">{name}</span> - </label> - </li> - </script> - </div> + <div class="template-tab-body"> </div> - </fieldset> - </form> + </form> + <form id="form-template-interface"> + <div class="template-tab-header"> + <span class="template-interface-cell">$_("Network")</span> + <span class="template-interface-cell">$_("Type")</span> + <button type="button" id="template-edit-interface-add-button" class="action-area"></button> + </div> + <div class="template-tab-body"></div> + </form> + </div> </div> <footer> <div class="btn-group"> @@ -152,3 +131,41 @@ <script> kimchi.template_edit_main(); </script> +<script id="template-storage-pool-tmpl" type="text/html"> + <div class='item'> + <span class="template-storage-cell"> + <label class="template-storage-name {viewMode}">{storageName}</label> + <select class="{editMode}"></select> + </span> + <span class="template-storage-cell"> + <label class="template-storage-type">{storageType}</label> + </span> + <span class="template-storage-cell"> + <label class="template-storage-disk {viewMode}">{storageDisk}</label> + <input class="{editMode}" /> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> +<script id="template-interface-tmpl" type="text/html"> + <div class="item"> + <span class="template-interface-cell"> + <label class="template-interface-name {viewMode}">{network}</label> + <select class="{editMode}"></select> + </span> + <span class="template-interface-cell"> + <span>{type}</span> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> \ No newline at end of file

Some comments about the patch: 1) The storage tab is named as "storage", use "Storage" (the S is in upper case) 2) On Storage and Network tabs, when I add a new resource and save it, the line moves up. 3) With a Remote ISO, the Storage and Network tabs appears without any information. 4) Template from Image file, the CDROM field appears in blank and there is no info about the image file. On 10/31/2014 08:40 AM, Wen Wang wrote:
From: Wen Wang <wenwang@linux.vnet.ibm.com>
This patch redesigned "Edit Template" diaguage in "Templates". New "Edit Template" will display all the related information into tabs of "General", "Storage" and "Interface". Due to unfinished back-end work, functions are not fully supported, which will be finished in the future work.
Temporary disabled functions: 1) Multiple disk operation with multiple storage pools edit in template for which reason the add button in "Storage" tab is disabled. 2) iSCSI and SCSI storage pool add is removed since we are going to allow this kind of operation in the process of creating a VM.
Signed-off-by: Wen Wang <wenwang@linux.vnet.ibm.com> --- ui/css/theme-default/template-edit.css | 84 +++++++- ui/js/src/kimchi.template_edit_main.js | 336 ++++++++++++++++++++++---------- ui/pages/template-edit.html.tmpl | 169 +++++++++------- 3 files changed, 402 insertions(+), 187 deletions(-)
diff --git a/ui/css/theme-default/template-edit.css b/ui/css/theme-default/template-edit.css index 4975f1b..302c488 100644 --- a/ui/css/theme-default/template-edit.css +++ b/ui/css/theme-default/template-edit.css @@ -17,24 +17,33 @@ */ #template-edit-window { font-size: 13px; - height: 600px; - width: 1000px; + height: 500px; + width: 800px; }
-.template-edit-fieldset { - float: left; - padding: 1em; +#edit-template-tabs { + background: none repeat scroll 0 0 transparent; + border: medium none; + height: 100%; + padding: 0; }
-.template-edit-wrapper-label, .template-edit-wrapper-controls { +#edit-template-tabs .form-template-inline-wrapper { + display: inline-block; vertical-align: top; - width: 470px; }
.template-edit-wrapper-label { - height: 18px; - line-height: 18px; - margin-top: 8px; + vertical-align: top; + min-width: 100px; + height: 35px; + line-height: 35px; + margin: 7px 0 8px; +} + +.template-edit-wrapper-controls { + vertical-align: top; + width: 400px; }
.template-edit-wrapper-controls input[type="text"] { @@ -56,7 +65,7 @@
.template-edit-wrapper-controls > .dropdown { margin: 5px 0 0 1px; - width: 440px; + width: 372px; }
.template-edit-wrapper-controls input[type="text"][disabled] { @@ -103,3 +112,56 @@ input[type="checkbox"]:CHECKED+.item { background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat 10px center; } + +#edit-template-tabs .template-tab-header { + margin-bottom: 8px; + padding-bottom: 2px; + font-weight: bold; + border-bottom: 1px solid #999999; + overflow: hidden; +} + +#edit-template-tabs .template-tab-header .action-area { + float: right; + height: 20px; + width: 20px; +} + +#edit-template-tabs .template-storage-cell{ + display: inline-block; + width: 230px; +} + +#edit-template-tabs .template-interface-cell { + display: inline-block; + width: 250px; +} + +#form-template-storage .template-tab-body select { + width: 140px; +} + +#form-template-storage .template-tab-body input { + width: 56px; +} + +#edit-template-tabs .template-tab-body .item { + margin: 5px 0; +} + +#form-template-interface .template-tab-body select { + width: 180px; +} + +#edit-template-tabs .template-tab-body .action-area { + float: right; +} + +#edit-template-tabs .template-tab-body .action-area button { + width: 20px; + height: 20px; +} + +#edit-template-tabs .template-tab-body .hide { + display: none; +} \ No newline at end of file diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js index 2f4cc9a..ac6cff8 100644 --- a/ui/js/src/kimchi.template_edit_main.js +++ b/ui/js/src/kimchi.template_edit_main.js @@ -16,14 +16,18 @@ * limitations under the License. */ kimchi.template_edit_main = function() { - var templateEditForm = $('#form-template-edit'); + var templateEditMain = $('#edit-template-tabs'); var origDisks; var origPool; + var origNetworks; var templateDiskSize; - $('#template-name', templateEditForm).val(kimchi.selectedTemplate); - kimchi.retrieveTemplate(kimchi.selectedTemplate, function(template) { + $('#template-name', templateEditMain).val(kimchi.selectedTemplate); + templateEditMain.tabs(); + + var initGeneral = function(template) { origDisks = template.disks; origPool = template.storagepool; + origNetworks = template.networks; for(var i=0;i<template.disks.length;i++){ if(template.disks[i].base){ template["vm-image"] = template.disks[i].base; @@ -37,18 +41,12 @@ kimchi.template_edit_main = function() { if (prop == 'graphics') { value = value["type"]; } - $('input[name="' + prop + '"]', templateEditForm).val(value); - } - var disks = template.disks; - $('input[name="disks"]').val(disks[0].size); - templateDiskSize = $('input[name="disks"]').val(); - if (disks[0].volume) { - var spool_value = $('#form-template-edit [name="storagepool"]').val(); - $('input[name="storagepool"]', templateEditForm).val(spool_value + '/' + disks[0].volume); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); + $('input[name="' + prop + '"]', templateEditMain).val(value); }
var vncOpt = [{label: 'VNC', value: 'vnc'}]; + $('#template-edit-graphics').append('<option selected>VNC</option>'); + $('#template-edit-graphics').append('<option>Spice</option>'); kimchi.select('template-edit-graphics-list', vncOpt); var enableSpice = function() { if (kimchi.capabilities == undefined) { @@ -61,85 +59,215 @@ kimchi.template_edit_main = function() { } }; enableSpice(); - + }; + var initStorage = function(result) { var scsipools = {}; - kimchi.listStoragePools(function(result) { - var options = []; - if (result && result.length) { - $.each(result, function(index, storagePool) { - if ((storagePool.state=="active") && (storagePool.type !== 'kimchi-iso')) { - if ((storagePool.type == 'iscsi') || (storagePool.type == 'scsi')){ - scsipools[storagePool.name] = []; - kimchi.listStorageVolumes(storagePool.name, function(result) { - if (result && result.length) { - $.each(result, function(index, storageVolume) { - options.push({ - label: storagePool.name + '/' + storageVolume.name, - value: '/storagepools/' + storagePool.name + '/' + storageVolume.name - }); - scsipools[storagePool.name].push(storageVolume) - }); - } - kimchi.select('template-edit-storagePool-list', options); - }); - } - else { - options.push({ - label: storagePool.name, - value: '/storagepools/' + storagePool.name - }); - } + var addStorageItem = function(storageData) { + var nodeStorage = $.parseHTML(kimchi.substitute($("#template-storage-pool-tmpl").html(), storageData)); + $('.template-tab-body', '#form-template-storage').append(nodeStorage); + $('.edit', '#form-template-storage').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.template-storage-name', storageItem).hide(); + var currentName = $('.template-storage-name', storageItem).text(); + $('.template-storage-disk', storageItem).hide(); + var currentDisk = $('.template-storage-disk', storageItem).text(); + $('input', storageItem).val(currentDisk).show(); + $('select', storageItem).show(); + if (currentName === 'iscsi' || currentName === 'scsi') { + $('input', storageItem).attr('disabled', true); + } else { + $('input', storageItem).attr('disabled', false); + } + $('.save', storageItem).parent().show(); + $('.delete', storageItem).parent().hide(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).hide(); + $('select', storageItem).show(); + }); + $('.delete', '#form-template-storage').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-storage').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var cancelEntity = $(this).parent().parent(); + if($('.template-storage-disk', cancelEntity).text() === '') { + cancelEntity.remove(); + } else { + $('label', cancelEntity).show(); + $('input', cancelEntity).hide(); + $('select', cancelEntity).hide(); + $('.cancel', cancelEntity).parent().hide(); + $('.edit', cancelEntity).parent().show(); + } + }); + $('.save', '#form-template-storage').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.save', storageItem).parent().hide(); + $('.delete', storageItem).parent().show(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).show(); + $('.template-storage-disk', storageItem).text($('input', storageItem).val()).show(); + $('select', storageItem).hide(); + $('input', storageItem).hide(); + }); + var storageOptions = ''; + $.each(result, function(index, storageEntities) { + if((storageEntities.state === 'active') && (storageEntities.type != 'kimchi-iso') + && (storageEntities.type != 'iscsi') && (storageEntities.type != 'scsi')){ + var isSlected = storageEntities.name === 'default' ? ' selected' : ''; + storageOptions += '<option' + isSlected + '>' + result[index].name + '</option>'; + } + }); + $('select', '#form-template-storage').find('option').remove(); + $('select', '#form-template-storage').append(storageOptions); + $('select', '#form-template-storage').change(function() { + var selectedItem = $(this).parent().parent(); + var tempStorageName = $(this).val(); + if (tempStorageName === 'iscsi' || tempStorageName === 'scsi') { + $('input', selectedItem).attr('disabled', true); + } else { + $('input', selectedItem).attr('disabled', false); + } + $.each(result, function(index, storageEntities) { + if (tempStorageName === storageEntities.name) { + selectedItem.find('.template-storage-type').text(storageEntities.type); } - }); - } - if ($.isEmptyObject(scsipools)) { - kimchi.select('template-edit-storagePool-list', options); + }) + }); + }; + + if ((origDisks && origDisks.length) && (origPool && origPool)) { + splitPool = origPool.split('/'); + var defaultPool; + var defaultType; + $.each(result, function(index, poolEntities) { + if (poolEntities.name === splitPool[splitPool.length-1]) { + defaultType = poolEntities.type; + defaultPool = splitPool[splitPool.length-1] + } + }); + $.each(origDisks, function(index, diskEntities) { + var storageNodeData = { + viewMode : '', + editMode : 'hide', + storageName : defaultPool, + storageType : defaultType, + storageDisk : diskEntities.size + } + addStorageItem(storageNodeData); + }); + } + + $('#template-edit-storage-add-button').button({ + icons: { + primary: "ui-icon-plusthick" + }, + text: false, + disabled: true + }).click(function(event) { + event.preventDefault(); + var storageNodeData = { + viewMode : 'hide', + editMode : '', + storageName : 'default', + storageType : 'dir', + storageDisk : '' } + addStorageItem(storageNodeData); }); - kimchi.listNetworks(function(result) { - if(result && result.length > 0) { - var html = ''; - var tmpl = $('#tmpl-network').html(); - $.each(result, function(index, network) { - if (result[index].state === 'active') - html += kimchi.substitute(tmpl, network); - }); - $('#template-edit-network-list').html(html).show(); - if(template.networks && template.networks.length > 0) { - $('input[name="networks"]', templateEditForm).each(function(index, element) { - var value = $(element).val(); - if(template.networks.indexOf(value) >= 0) { - $(element).prop('checked', true); - } - }); + }; + var initInterface = function(result) { + var addInterfaceItem = function(networkData) { + var nodeInterface = $.parseHTML(kimchi.substitute($('#template-interface-tmpl').html(), networkData)); + $('.template-tab-body', '#form-template-interface').append(nodeInterface); + $('.edit', '#form-template-interface').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false, + disabled : true + }); + $('.delete', '#form-template-interface').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-interface').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.save', '#form-template-interface').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var interItem = $(this).parent().parent(); + $('.save', interItem).parent().hide(); + $('.delete', interItem).parent().show(); + var selectedInterface = $('select', interItem).val(); + $('label', interItem).text(selectedInterface).show(); + $('select', interItem).hide(); + }); + var networkOptions = ''; + for(var i=0;i<result.length;i++){ + if(result[i].state === "active") { + var isSlected = i==0 ? ' selected' : ''; + networkOptions += '<option' + isSlected + '>' + result[i].name + '</option>'; } - } else { - $('#template-edit-network-list').hide(); } - }); - }); - - $('#template-edit-storagePool').change(function() { - storagepool = $(this).val(); - var storageArray = storagepool.split("/"); - if (storageArray.length > 3) { - volumeName = storageArray.pop(); - poolName = storageArray.pop(); - kimchi.getStoragePoolVolume(poolName, volumeName, function(result) { - $('input[name="disks"]', templateEditForm).val(result.capacity / Math.pow(1024,3)); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); - return false; - }, function (err) { - kimchi.message.error(err.responseJSON.reason); + $('select', '#form-template-interface').find('option').remove(); + $('select', '#form-template-interface').append(networkOptions); + }; + if(result && result.length > 0) { + $.each(result, function(index, data) { + if($.inArray(data.name, origNetworks) > -1) { + addInterfaceItem({ + mac : '', + network : data.name, + type : 'network', + viewMode : '', + editMode : 'hide' + }); + } }); - } else { - $('input[name="disks"]', templateEditForm).removeAttr('disabled'); - $('input[name="disks"]', templateEditForm).val(templateDiskSize); } - }); - $('input[name="disks"]', templateEditForm).keyup(function() { - templateDiskSize = $('input[name="disks"]', templateEditForm).val(); - }); + $('#template-edit-interface-add-button').button({ + icons: { + primary: 'ui-icon-plusthick' + }, + text: false + }).click(function(evt) { + evt.preventDefault(); + addInterfaceItem({ + mac : '', + network : '', + type : 'network', + viewMode : 'hide', + editMode : '' + }); + }); + }; + kimchi.retrieveTemplate(kimchi.selectedTemplate, initGeneral); + kimchi.listNetworks(initInterface); + kimchi.listStoragePools(initStorage);
$('#tmpl-edit-button-save').on('click', function() { var editableFields = [ 'name', 'cpus', 'memory', 'storagepool', 'disks', 'graphics']; @@ -147,33 +275,41 @@ kimchi.template_edit_main = function() { $.each(editableFields, function(i, field) { /* Support only 1 disk at this moment */ if (field == 'disks') { - origDisks[0].size = Number($('#form-template-edit [name="' + field + '"]').val()); + $.each($('#form-template-storage .item'), function(index, diskEntities) { + origDisks[index].size = Number($(this).find('.template-storage-disk').text()); + }) data[field] = origDisks; } else if (field == 'graphics') { - var type = $('#form-template-edit [name="' + field + '"]').val(); + var type = $('#form-template-general [name="' + field + '"]').val(); data[field] = {'type': type}; } else { - data[field] = $('#form-template-edit [name="' + field + '"]').val(); + data[field] = $('#form-template-general [name="' + field + '"]').val(); } }); data['memory'] = Number(data['memory']); data['cpus'] = Number(data['cpus']); - storagepool = data['storagepool']; - storageArray = storagepool.split("/"); - if (storageArray.length > 3){ - /* Support only 1 disk at this moment */ - data["disks"][0].volume = storageArray.pop(); - data['storagepool'] = storageArray.join("/"); - } else if (data["disks"][0].volume) { - delete data["disks"][0].volume; - } - var networks = templateEditForm.serializeObject().networks; - if (networks instanceof Array) { - data.networks = networks; - } else if (networks != null) { - data.networks = [networks]; + + //Fix me: Only support one storage pool now + var storages = $('.template-tab-body .item', '#form-template-storage'); + var storageForUpdate = new Array(); + $.each(storages, function(index, storageEntities) { + var tempName = $('.template-storage-name', storageEntities).text() + tempName = '/storagepools/' + tempName; + storageForUpdate.push(tempName); + }) + data['storagepool'] = storageForUpdate[0]; + + var networks = $('.template-tab-body .item', '#form-template-interface'); + var networkForUpdate = new Array(); + $.each(networks, function(index, networkEntities) { + networkForUpdate.push($('.template-interface-name', networkEntities).text()); + }); + if (networkForUpdate instanceof Array) { + data.networks = networkForUpdate; + } else if (networkForUpdate != null) { + data.networks = [networkForUpdate]; } else { data.networks = []; } diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl index 5a71d91..d5d2be1 100644 --- a/ui/pages/template-edit.html.tmpl +++ b/ui/pages/template-edit.html.tmpl @@ -28,74 +28,67 @@ <div class="close">X</div> </header> <div class="content"> - <form id="form-template-edit"> + <div id="edit-template-tabs"> <input type="hidden" id="template-name" name="templateName" /> - <fieldset class="template-edit-fieldset"> - <div> + <ul> + <li> + <a href="#form-template-general">$_("General")</a> + </li> + <li> + <a href="#form-template-storage">$_("storage")</a> + </li> + <li> + <a href="#form-template-interface">$_("Interface")</a> + </li> + </ul> + <form id="form-template-general"> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-label"> <label for="template-edit-id-textbox">$_("Name")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-id-textbox" name="name" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-vendor-textbox">$_("Vendor")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-version-textbox">$_("Version")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-cpu-textbox">$_("CPU Number")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-cpu-textbox" name="cpus" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-memory-textbox">$_("Memory (MB)")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-memory-textbox" name="memory" type="text" /> + <div class="template-edit-wrapper-label templ-edit-cdrom"> + <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + </div> + <div class="template-edit-wrapper-label templ-edit-vm-image hide-content"> + <label for="template-edit-vmimage-textbox">$_("Image File")</label> </div> - </div> - <div> <div class="template-edit-wrapper-label"> - <label for="template-edit-disk-textbox">$_("Disk (GB)")</label> + <label>$_("Graphics")</label> </div> + </div> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-controls"> - <input id="template-edit-disk-textbox" name="disks" type="text" /> + <input id="template-edit-id-textbox" name="name" type="text" /> </div> - </div> - </fieldset> - <fieldset class="template-edit-fieldset"> - <div id="templ-edit-cdrom"> - <div class="template-edit-wrapper-label"> - <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> - <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled"/> + <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> </div> - </div> - <div id="templ-edit-vm-image" class="hide-content"> - <div class="template-edit-wrapper-label">$_("Image File")</div> - <div class="template-edit-wrapper-controls"><input name="vm-image" type="text" disabled/></div> - </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Graphics")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-cpu-textbox" name="cpus" type="text" /> + </div> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-memory-textbox" name="memory" type="text" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-cdrom"> + <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-vm-image hide-content"> + <input id="template-edit-vmimage-textbox" name="vm-image" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> <div class="btn dropdown popable"> @@ -108,40 +101,26 @@ </div> </div> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Storage Pool")</label> - </div> - <div class="template-edit-wrapper-controls"> - <div class="btn dropdown popable"> - <input id="template-edit-storagePool" name="storagepool" type="hidden" /> - <span class="text" id="template-edit-storage-label"></span><span class="arrow"></span> - <div class="popover" style="width: 100%"> - <ul class="select-list" id="template-edit-storagePool-list" data-target="template-edit-storagePool" data-label="template-edit-storage-label"> - </ul> - </div> - </div> - </div> + </form> + <form id="form-template-storage"> + <div class="template-tab-header"> + <span class="template-storage-cell">$_("Storage Pool")</span> + <span class="template-storage-cell">$_("Type")</span> + <span class="template-storage-cell">$_("Disk(GB)")</span> + <button type="button" id="template-edit-storage-add-button" class="action-area"></button> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Network")</label> - </div> - <div class="template-edit-wrapper-controls"> - <ul class="select-list-box" id="template-edit-network-list"> - </ul> - <script id="tmpl-network" type="text/html"> - <li> - <label> - <input name="networks" type="checkbox" value="{name}" /> - <span class="item">{name}</span> - </label> - </li> - </script> - </div> + <div class="template-tab-body"> </div> - </fieldset> - </form> + </form> + <form id="form-template-interface"> + <div class="template-tab-header"> + <span class="template-interface-cell">$_("Network")</span> + <span class="template-interface-cell">$_("Type")</span> + <button type="button" id="template-edit-interface-add-button" class="action-area"></button> + </div> + <div class="template-tab-body"></div> + </form> + </div> </div> <footer> <div class="btn-group"> @@ -152,3 +131,41 @@ <script> kimchi.template_edit_main(); </script> +<script id="template-storage-pool-tmpl" type="text/html"> + <div class='item'> + <span class="template-storage-cell"> + <label class="template-storage-name {viewMode}">{storageName}</label> + <select class="{editMode}"></select> + </span> + <span class="template-storage-cell"> + <label class="template-storage-type">{storageType}</label> + </span> + <span class="template-storage-cell"> + <label class="template-storage-disk {viewMode}">{storageDisk}</label> + <input class="{editMode}" /> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> +<script id="template-interface-tmpl" type="text/html"> + <div class="item"> + <span class="template-interface-cell"> + <label class="template-interface-name {viewMode}">{network}</label> + <select class="{editMode}"></select> + </span> + <span class="template-interface-cell"> + <span>{type}</span> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> \ No newline at end of file

Hi Aline, I did the investigation, please refer to the inline comments On 11/2/2014 9:10 PM, Aline Manera wrote:
Some comments about the patch:
1) The storage tab is named as "storage", use "Storage" (the S is in upper case)
ACK
2) On Storage and Network tabs, when I add a new resource and save it, the line moves up. ACK 3) With a Remote ISO, the Storage and Network tabs appears without any information. After checking the response of the server, when creating a template with Remote ISO, "network" of the response is empty which should be "default" if not changed, and this this working using either local img or local iso. I have done fixing the not showing the network and storage problem. I think server should return a "default" value of the "network" just the same as local iso template creation. And you can always added more network. 4) Template from Image file, the CDROM field appears in blank and there is no info about the image file. ACK
On 10/31/2014 08:40 AM, Wen Wang wrote:
From: Wen Wang <wenwang@linux.vnet.ibm.com>
This patch redesigned "Edit Template" diaguage in "Templates". New "Edit Template" will display all the related information into tabs of "General", "Storage" and "Interface". Due to unfinished back-end work, functions are not fully supported, which will be finished in the future work.
Temporary disabled functions: 1) Multiple disk operation with multiple storage pools edit in template for which reason the add button in "Storage" tab is disabled. 2) iSCSI and SCSI storage pool add is removed since we are going to allow this kind of operation in the process of creating a VM.
Signed-off-by: Wen Wang <wenwang@linux.vnet.ibm.com> --- ui/css/theme-default/template-edit.css | 84 +++++++- ui/js/src/kimchi.template_edit_main.js | 336 ++++++++++++++++++++++---------- ui/pages/template-edit.html.tmpl | 169 +++++++++------- 3 files changed, 402 insertions(+), 187 deletions(-)
diff --git a/ui/css/theme-default/template-edit.css b/ui/css/theme-default/template-edit.css index 4975f1b..302c488 100644 --- a/ui/css/theme-default/template-edit.css +++ b/ui/css/theme-default/template-edit.css @@ -17,24 +17,33 @@ */ #template-edit-window { font-size: 13px; - height: 600px; - width: 1000px; + height: 500px; + width: 800px; }
-.template-edit-fieldset { - float: left; - padding: 1em; +#edit-template-tabs { + background: none repeat scroll 0 0 transparent; + border: medium none; + height: 100%; + padding: 0; }
-.template-edit-wrapper-label, .template-edit-wrapper-controls { +#edit-template-tabs .form-template-inline-wrapper { + display: inline-block; vertical-align: top; - width: 470px; }
.template-edit-wrapper-label { - height: 18px; - line-height: 18px; - margin-top: 8px; + vertical-align: top; + min-width: 100px; + height: 35px; + line-height: 35px; + margin: 7px 0 8px; +} + +.template-edit-wrapper-controls { + vertical-align: top; + width: 400px; }
.template-edit-wrapper-controls input[type="text"] { @@ -56,7 +65,7 @@
.template-edit-wrapper-controls > .dropdown { margin: 5px 0 0 1px; - width: 440px; + width: 372px; }
.template-edit-wrapper-controls input[type="text"][disabled] { @@ -103,3 +112,56 @@ input[type="checkbox"]:CHECKED+.item { background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat 10px center; } + +#edit-template-tabs .template-tab-header { + margin-bottom: 8px; + padding-bottom: 2px; + font-weight: bold; + border-bottom: 1px solid #999999; + overflow: hidden; +} + +#edit-template-tabs .template-tab-header .action-area { + float: right; + height: 20px; + width: 20px; +} + +#edit-template-tabs .template-storage-cell{ + display: inline-block; + width: 230px; +} + +#edit-template-tabs .template-interface-cell { + display: inline-block; + width: 250px; +} + +#form-template-storage .template-tab-body select { + width: 140px; +} + +#form-template-storage .template-tab-body input { + width: 56px; +} + +#edit-template-tabs .template-tab-body .item { + margin: 5px 0; +} + +#form-template-interface .template-tab-body select { + width: 180px; +} + +#edit-template-tabs .template-tab-body .action-area { + float: right; +} + +#edit-template-tabs .template-tab-body .action-area button { + width: 20px; + height: 20px; +} + +#edit-template-tabs .template-tab-body .hide { + display: none; +} \ No newline at end of file diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js index 2f4cc9a..ac6cff8 100644 --- a/ui/js/src/kimchi.template_edit_main.js +++ b/ui/js/src/kimchi.template_edit_main.js @@ -16,14 +16,18 @@ * limitations under the License. */ kimchi.template_edit_main = function() { - var templateEditForm = $('#form-template-edit'); + var templateEditMain = $('#edit-template-tabs'); var origDisks; var origPool; + var origNetworks; var templateDiskSize; - $('#template-name', templateEditForm).val(kimchi.selectedTemplate); - kimchi.retrieveTemplate(kimchi.selectedTemplate, function(template) { + $('#template-name', templateEditMain).val(kimchi.selectedTemplate); + templateEditMain.tabs(); + + var initGeneral = function(template) { origDisks = template.disks; origPool = template.storagepool; + origNetworks = template.networks; for(var i=0;i<template.disks.length;i++){ if(template.disks[i].base){ template["vm-image"] = template.disks[i].base; @@ -37,18 +41,12 @@ kimchi.template_edit_main = function() { if (prop == 'graphics') { value = value["type"]; } - $('input[name="' + prop + '"]', templateEditForm).val(value); - } - var disks = template.disks; - $('input[name="disks"]').val(disks[0].size); - templateDiskSize = $('input[name="disks"]').val(); - if (disks[0].volume) { - var spool_value = $('#form-template-edit [name="storagepool"]').val(); - $('input[name="storagepool"]', templateEditForm).val(spool_value + '/' + disks[0].volume); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); + $('input[name="' + prop + '"]', templateEditMain).val(value); }
var vncOpt = [{label: 'VNC', value: 'vnc'}]; + $('#template-edit-graphics').append('<option selected>VNC</option>'); + $('#template-edit-graphics').append('<option>Spice</option>'); kimchi.select('template-edit-graphics-list', vncOpt); var enableSpice = function() { if (kimchi.capabilities == undefined) { @@ -61,85 +59,215 @@ kimchi.template_edit_main = function() { } }; enableSpice(); - + }; + var initStorage = function(result) { var scsipools = {}; - kimchi.listStoragePools(function(result) { - var options = []; - if (result && result.length) { - $.each(result, function(index, storagePool) { - if ((storagePool.state=="active") && (storagePool.type !== 'kimchi-iso')) { - if ((storagePool.type == 'iscsi') || (storagePool.type == 'scsi')){ - scsipools[storagePool.name] = []; - kimchi.listStorageVolumes(storagePool.name, function(result) { - if (result && result.length) { - $.each(result, function(index, storageVolume) { - options.push({ - label: storagePool.name + '/' + storageVolume.name, - value: '/storagepools/' + storagePool.name + '/' + storageVolume.name - }); - scsipools[storagePool.name].push(storageVolume) - }); - } - kimchi.select('template-edit-storagePool-list', options); - }); - } - else { - options.push({ - label: storagePool.name, - value: '/storagepools/' + storagePool.name - }); - } + var addStorageItem = function(storageData) { + var nodeStorage = $.parseHTML(kimchi.substitute($("#template-storage-pool-tmpl").html(), storageData));
+ $('.template-tab-body', '#form-template-storage').append(nodeStorage); + $('.edit', '#form-template-storage').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.template-storage-name', storageItem).hide(); + var currentName = $('.template-storage-name', storageItem).text(); + $('.template-storage-disk', storageItem).hide(); + var currentDisk = $('.template-storage-disk', storageItem).text(); + $('input', storageItem).val(currentDisk).show(); + $('select', storageItem).show(); + if (currentName === 'iscsi' || currentName === 'scsi') { + $('input', storageItem).attr('disabled', true); + } else { + $('input', storageItem).attr('disabled', false); + } + $('.save', storageItem).parent().show(); + $('.delete', storageItem).parent().hide(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).hide(); + $('select', storageItem).show(); + }); + $('.delete', '#form-template-storage').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-storage').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var cancelEntity = $(this).parent().parent(); + if($('.template-storage-disk', cancelEntity).text() === '') { + cancelEntity.remove(); + } else { + $('label', cancelEntity).show(); + $('input', cancelEntity).hide(); + $('select', cancelEntity).hide(); + $('.cancel', cancelEntity).parent().hide(); + $('.edit', cancelEntity).parent().show(); + } + }); + $('.save', '#form-template-storage').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var storageItem = $(this).parent().parent(); + $('.save', storageItem).parent().hide(); + $('.delete', storageItem).parent().show(); + var selectedStorage = $('select', storageItem).val(); + $('.template-storage-name', storageItem).text(selectedStorage).show(); + $('.template-storage-disk', storageItem).text($('input', storageItem).val()).show(); + $('select', storageItem).hide(); + $('input', storageItem).hide(); + }); + var storageOptions = ''; + $.each(result, function(index, storageEntities) { + if((storageEntities.state === 'active') && (storageEntities.type != 'kimchi-iso') + && (storageEntities.type != 'iscsi') && (storageEntities.type != 'scsi')){ + var isSlected = storageEntities.name === 'default' ? ' selected' : ''; + storageOptions += '<option' + isSlected + '>' + result[index].name + '</option>'; + } + }); + $('select', '#form-template-storage').find('option').remove(); + $('select', '#form-template-storage').append(storageOptions); + $('select', '#form-template-storage').change(function() { + var selectedItem = $(this).parent().parent(); + var tempStorageName = $(this).val(); + if (tempStorageName === 'iscsi' || tempStorageName === 'scsi') { + $('input', selectedItem).attr('disabled', true); + } else { + $('input', selectedItem).attr('disabled', false); + } + $.each(result, function(index, storageEntities) { + if (tempStorageName === storageEntities.name) { + selectedItem.find('.template-storage-type').text(storageEntities.type); } - }); - } - if ($.isEmptyObject(scsipools)) { - kimchi.select('template-edit-storagePool-list', options); + }) + }); + }; + + if ((origDisks && origDisks.length) && (origPool && origPool)) { + splitPool = origPool.split('/'); + var defaultPool; + var defaultType; + $.each(result, function(index, poolEntities) { + if (poolEntities.name === splitPool[splitPool.length-1]) { + defaultType = poolEntities.type; + defaultPool = splitPool[splitPool.length-1] + } + }); + $.each(origDisks, function(index, diskEntities) { + var storageNodeData = { + viewMode : '', + editMode : 'hide', + storageName : defaultPool, + storageType : defaultType, + storageDisk : diskEntities.size + } + addStorageItem(storageNodeData); + }); + } + + $('#template-edit-storage-add-button').button({ + icons: { + primary: "ui-icon-plusthick" + }, + text: false, + disabled: true + }).click(function(event) { + event.preventDefault(); + var storageNodeData = { + viewMode : 'hide', + editMode : '', + storageName : 'default', + storageType : 'dir', + storageDisk : '' } + addStorageItem(storageNodeData); }); - kimchi.listNetworks(function(result) { - if(result && result.length > 0) { - var html = ''; - var tmpl = $('#tmpl-network').html(); - $.each(result, function(index, network) { - if (result[index].state === 'active') - html += kimchi.substitute(tmpl, network); - }); - $('#template-edit-network-list').html(html).show(); - if(template.networks && template.networks.length > 0) { - $('input[name="networks"]', templateEditForm).each(function(index, element) { - var value = $(element).val(); - if(template.networks.indexOf(value) >= 0) { - $(element).prop('checked', true); - } - }); + }; + var initInterface = function(result) { + var addInterfaceItem = function(networkData) { + var nodeInterface = $.parseHTML(kimchi.substitute($('#template-interface-tmpl').html(), networkData)); + $('.template-tab-body', '#form-template-interface').append(nodeInterface); + $('.edit', '#form-template-interface').button({ + icons : {primary : 'ui-icon-pencil'}, + text : false, + disabled : true + }); + $('.delete', '#form-template-interface').button({ + icons : {primary : 'ui-icon-trash'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.cancel', '#form-template-interface').button({ + icons : {primary : 'ui-icon-arrowreturnthick-1-w'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + $(this).parent().parent().remove(); + }); + $('.save', '#form-template-interface').button({ + icons : {primary : 'ui-icon-disk'}, + text : false + }).click(function(evt) { + evt.preventDefault(); + var interItem = $(this).parent().parent(); + $('.save', interItem).parent().hide(); + $('.delete', interItem).parent().show(); + var selectedInterface = $('select', interItem).val(); + $('label', interItem).text(selectedInterface).show(); + $('select', interItem).hide(); + }); + var networkOptions = ''; + for(var i=0;i<result.length;i++){ + if(result[i].state === "active") { + var isSlected = i==0 ? ' selected' : ''; + networkOptions += '<option' + isSlected + '>' + result[i].name + '</option>'; } - } else { - $('#template-edit-network-list').hide(); } - }); - }); - - $('#template-edit-storagePool').change(function() { - storagepool = $(this).val(); - var storageArray = storagepool.split("/"); - if (storageArray.length > 3) { - volumeName = storageArray.pop(); - poolName = storageArray.pop(); - kimchi.getStoragePoolVolume(poolName, volumeName, function(result) { - $('input[name="disks"]', templateEditForm).val(result.capacity / Math.pow(1024,3)); - $('input[name="disks"]', templateEditForm).attr('disabled','disabled'); - return false; - }, function (err) { - kimchi.message.error(err.responseJSON.reason); + $('select', '#form-template-interface').find('option').remove(); + $('select', '#form-template-interface').append(networkOptions); + }; + if(result && result.length > 0) { + $.each(result, function(index, data) { + if($.inArray(data.name, origNetworks) > -1) { + addInterfaceItem({ + mac : '', + network : data.name, + type : 'network', + viewMode : '', + editMode : 'hide' + }); + } }); - } else { - $('input[name="disks"]', templateEditForm).removeAttr('disabled'); - $('input[name="disks"]', templateEditForm).val(templateDiskSize); } - }); - $('input[name="disks"]', templateEditForm).keyup(function() { - templateDiskSize = $('input[name="disks"]', templateEditForm).val(); - }); + $('#template-edit-interface-add-button').button({ + icons: { + primary: 'ui-icon-plusthick' + }, + text: false + }).click(function(evt) { + evt.preventDefault(); + addInterfaceItem({ + mac : '', + network : '', + type : 'network', + viewMode : 'hide', + editMode : '' + }); + }); + }; + kimchi.retrieveTemplate(kimchi.selectedTemplate, initGeneral); + kimchi.listNetworks(initInterface); + kimchi.listStoragePools(initStorage);
$('#tmpl-edit-button-save').on('click', function() { var editableFields = [ 'name', 'cpus', 'memory', 'storagepool', 'disks', 'graphics']; @@ -147,33 +275,41 @@ kimchi.template_edit_main = function() { $.each(editableFields, function(i, field) { /* Support only 1 disk at this moment */ if (field == 'disks') { - origDisks[0].size = Number($('#form-template-edit [name="' + field + '"]').val()); + $.each($('#form-template-storage .item'), function(index, diskEntities) { + origDisks[index].size = Number($(this).find('.template-storage-disk').text()); + }) data[field] = origDisks; } else if (field == 'graphics') { - var type = $('#form-template-edit [name="' + field + '"]').val(); + var type = $('#form-template-general [name="' + field + '"]').val(); data[field] = {'type': type}; } else { - data[field] = $('#form-template-edit [name="' + field + '"]').val(); + data[field] = $('#form-template-general [name="' + field + '"]').val(); } }); data['memory'] = Number(data['memory']); data['cpus'] = Number(data['cpus']); - storagepool = data['storagepool']; - storageArray = storagepool.split("/"); - if (storageArray.length > 3){ - /* Support only 1 disk at this moment */ - data["disks"][0].volume = storageArray.pop(); - data['storagepool'] = storageArray.join("/"); - } else if (data["disks"][0].volume) { - delete data["disks"][0].volume; - } - var networks = templateEditForm.serializeObject().networks; - if (networks instanceof Array) { - data.networks = networks; - } else if (networks != null) { - data.networks = [networks]; + + //Fix me: Only support one storage pool now + var storages = $('.template-tab-body .item', '#form-template-storage'); + var storageForUpdate = new Array(); + $.each(storages, function(index, storageEntities) { + var tempName = $('.template-storage-name', storageEntities).text() + tempName = '/storagepools/' + tempName; + storageForUpdate.push(tempName); + }) + data['storagepool'] = storageForUpdate[0]; + + var networks = $('.template-tab-body .item', '#form-template-interface'); + var networkForUpdate = new Array(); + $.each(networks, function(index, networkEntities) { + networkForUpdate.push($('.template-interface-name', networkEntities).text()); + }); + if (networkForUpdate instanceof Array) { + data.networks = networkForUpdate; + } else if (networkForUpdate != null) { + data.networks = [networkForUpdate]; } else { data.networks = []; } diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl index 5a71d91..d5d2be1 100644 --- a/ui/pages/template-edit.html.tmpl +++ b/ui/pages/template-edit.html.tmpl @@ -28,74 +28,67 @@ <div class="close">X</div> </header> <div class="content"> - <form id="form-template-edit"> + <div id="edit-template-tabs"> <input type="hidden" id="template-name" name="templateName" /> - <fieldset class="template-edit-fieldset"> - <div> + <ul> + <li> + <a href="#form-template-general">$_("General")</a> + </li> + <li> + <a href="#form-template-storage">$_("storage")</a> + </li> + <li> + <a href="#form-template-interface">$_("Interface")</a> + </li> + </ul> + <form id="form-template-general"> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-label"> <label for="template-edit-id-textbox">$_("Name")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-id-textbox" name="name" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-vendor-textbox">$_("Vendor")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-version-textbox">$_("Version")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-cpu-textbox">$_("CPU Number")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-cpu-textbox" name="cpus" type="text" /> - </div> - </div> - <div> <div class="template-edit-wrapper-label"> <label for="template-edit-memory-textbox">$_("Memory (MB)")</label> </div> - <div class="template-edit-wrapper-controls"> - <input id="template-edit-memory-textbox" name="memory" type="text" /> + <div class="template-edit-wrapper-label templ-edit-cdrom"> + <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + </div> + <div class="template-edit-wrapper-label templ-edit-vm-image hide-content"> + <label for="template-edit-vmimage-textbox">$_("Image File")</label> </div> - </div> - <div> <div class="template-edit-wrapper-label"> - <label for="template-edit-disk-textbox">$_("Disk (GB)")</label> + <label>$_("Graphics")</label> </div> + </div> + <div class="form-template-inline-wrapper"> <div class="template-edit-wrapper-controls"> - <input id="template-edit-disk-textbox" name="disks" type="text" /> + <input id="template-edit-id-textbox" name="name" type="text" /> </div> - </div> - </fieldset> - <fieldset class="template-edit-fieldset"> - <div id="templ-edit-cdrom"> - <div class="template-edit-wrapper-label"> - <label for="template-edit-cdrom-textbox">$_("CDROM")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> - <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled"/> + <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" /> </div> - </div> - <div id="templ-edit-vm-image" class="hide-content"> - <div class="template-edit-wrapper-label">$_("Image File")</div> - <div class="template-edit-wrapper-controls"><input name="vm-image" type="text" disabled/></div> - </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Graphics")</label> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-cpu-textbox" name="cpus" type="text" /> + </div> + <div class="template-edit-wrapper-controls"> + <input id="template-edit-memory-textbox" name="memory" type="text" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-cdrom"> + <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled" /> + </div> + <div class="template-edit-wrapper-controls templ-edit-vm-image hide-content"> + <input id="template-edit-vmimage-textbox" name="vm-image" type="text" disabled="disabled" /> </div> <div class="template-edit-wrapper-controls"> <div class="btn dropdown popable"> @@ -108,40 +101,26 @@ </div> </div> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Storage Pool")</label> - </div> - <div class="template-edit-wrapper-controls"> - <div class="btn dropdown popable"> - <input id="template-edit-storagePool" name="storagepool" type="hidden" /> - <span class="text" id="template-edit-storage-label"></span><span class="arrow"></span> - <div class="popover" style="width: 100%"> - <ul class="select-list" id="template-edit-storagePool-list" data-target="template-edit-storagePool" data-label="template-edit-storage-label"> - </ul> - </div> - </div> - </div> + </form> + <form id="form-template-storage"> + <div class="template-tab-header"> + <span class="template-storage-cell">$_("Storage Pool")</span> + <span class="template-storage-cell">$_("Type")</span> + <span class="template-storage-cell">$_("Disk(GB)")</span> + <button type="button" id="template-edit-storage-add-button" class="action-area"></button> </div> - <div> - <div class="template-edit-wrapper-label"> - <label>$_("Network")</label> - </div> - <div class="template-edit-wrapper-controls"> - <ul class="select-list-box" id="template-edit-network-list"> - </ul> - <script id="tmpl-network" type="text/html"> - <li> - <label> - <input name="networks" type="checkbox" value="{name}" /> - <span class="item">{name}</span> - </label> - </li> - </script> - </div> + <div class="template-tab-body"> </div> - </fieldset> - </form> + </form> + <form id="form-template-interface"> + <div class="template-tab-header"> + <span class="template-interface-cell">$_("Network")</span> + <span class="template-interface-cell">$_("Type")</span> + <button type="button" id="template-edit-interface-add-button" class="action-area"></button> + </div> + <div class="template-tab-body"></div> + </form> + </div> </div> <footer> <div class="btn-group"> @@ -152,3 +131,41 @@ <script> kimchi.template_edit_main(); </script> +<script id="template-storage-pool-tmpl" type="text/html"> + <div class='item'> + <span class="template-storage-cell"> + <label class="template-storage-name {viewMode}">{storageName}</label> + <select class="{editMode}"></select> + </span> + <span class="template-storage-cell"> + <label class="template-storage-type">{storageType}</label> + </span> + <span class="template-storage-cell"> + <label class="template-storage-disk {viewMode}">{storageDisk}</label> + <input class="{editMode}" /> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> +<script id="template-interface-tmpl" type="text/html"> + <div class="item"> + <span class="template-interface-cell"> + <label class="template-interface-name {viewMode}">{network}</label> + <select class="{editMode}"></select> + </span> + <span class="template-interface-cell"> + <span>{type}</span> + </span> + <span class="action-area {editMode}"> + <button class="save"></button><button class="cancel"></button> + </span> + <span class="action-area {viewMode}"> + <button class="edit"></button><button class="delete"></button> + </span> + </div> +</script> \ No newline at end of file
participants (2)
-
Aline Manera
-
Wen Wang