Hi Bianca,
Some comments:
1) I have no feedback when the operation is done. The dialog keeps open.
2) I am not able to un-check an option. Instead of that, I need to use
the 'Remove' button.
Is it possible to make un-check option the same as 'Remove' so we
can remove the 'Remove' button and only let the user works on check box?
2.1) On each "Remove" button click a new request is made. The UI should
only expose the data and get the result on "Save" button and a single
request will be made.
3) I am not able to remove an option recently checked.
4) I was not able to get a screenshot but when I click on Edit the
dialog opens very tiny and the loading appears outside it.
Something like:
------------------------------------------------------------------
| |
| Tiny dialog without content (only with buttons) |
------------------------------------------------------------------
<loading icon> Loading...
The dialog should be open completely and the loading message should
appear in the center of the dialog.
5) All the 3 options are being sent to backend.
Example, try to update a guest which has only 'hd' as boot order. I
selected 'cdrom' and moved 'cdrom' to the first place.
After clicking on Save, all the 3 options got saved (but I haven't
checked 'network')
6) The 'Save' button does not work always.
Open Edit dialog, select a new option => The Save button does not
make any request
7) When I select "Edit" 2 requests to GET /vms/*name* are made. Only one
should be enough.
On 01/30/2017 05:28 PM, bianca(a)linux.vnet.ibm.com wrote:
From: Bianca Carvalho <bianca(a)linux.vnet.ibm.com>
This patch adds the UI portion for supporting changing the guest boot order
via edit guest panel. This was based off of what Samuel had prototyped.
Issue found in backend during test:
When updating the VM even with just changing the name, the bootorder gets reset to
'hd' only.
I tested this using the curl command and confirmed that indeed it does get reset to one
entry only.
Issue written to address this:
https://github.com/kimchi-project/kimchi/issues/1012
Signed-off-by: Bianca Carvalho <bianca(a)linux.vnet.ibm.com>
---
ui/css/kimchi.css | 61 ++++++++++++++++++++++-
ui/css/src/modules/_edit-guests.scss | 60 +++++++++++++++++++++-
ui/js/src/kimchi.guest_edit_main.js | 97 +++++++++++++++++++++++++++++++++++-
ui/pages/guest-edit.html.tmpl | 26 ++++++++--
4 files changed, 238 insertions(+), 6 deletions(-)
diff --git a/ui/css/kimchi.css b/ui/css/kimchi.css
index fff3279..dec47fa 100644
--- a/ui/css/kimchi.css
+++ b/ui/css/kimchi.css
@@ -1,7 +1,7 @@
/*
* Project Kimchi
*
- * Copyright IBM Corp, 2015-2016
+ * Copyright IBM Corp, 2015-2017
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1557,6 +1557,65 @@ body.wok-gallery {
overflow: visible;
}
+ul {
+ cursor: default;
+}
+
+.boot-order {
+ display: block;
+ width: 85%;
+ font-size: 14px;
+ line-height: 1.42857;
+ color: #444;
+ overflow: hidden;
+ background-color: #fff;
+ background-image: none;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+ -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+ transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+}
+
+.boot-order:focus,
+.boot-order.focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233,
0.6);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.boot-order > li {
+ cursor: move;
+ /* fallback if grab cursor is unsupported */
+ cursor: grab;
+ cursor: -moz-grab;
+ cursor: -webkit-grab;
+ border-left: 0;
+ border-right: 0;
+}
+
+.boot-order > li:first-child {
+ border-top: 0;
+}
+
+.boot-order > li:last-child {
+ border-bottom: 0;
+}
+
+.boot-order > li.ui-sortable-helper {
+ cursor: grabbing;
+ cursor: -moz-grabbing;
+ cursor: -webkit-grabbing;
+ border: 1px solid #ccc !important;
+}
+
+.boot-order li i {
+ text-align: right;
+}
+
/* Add Template Modal Window */
.templates-modal .modal-dialog {
width: 1100px;
diff --git a/ui/css/src/modules/_edit-guests.scss b/ui/css/src/modules/_edit-guests.scss
index 25d4d65..c8cc122 100644
--- a/ui/css/src/modules/_edit-guests.scss
+++ b/ui/css/src/modules/_edit-guests.scss
@@ -1,7 +1,7 @@
//
// Project Kimchi
//
-// Copyright IBM Corp, 2015-2016
+// Copyright IBM Corp, 2015-2017
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -429,3 +429,61 @@
#form-guest-storage-add .form-section .field {
overflow: visible;
}
+
+ul {
+ cursor: default;
+}
+
+.boot-order {
+ display: block;
+ width: 85%;
+ font-size: 14px;
+ line-height: 1.42857;
+ color: #444;
+ overflow: hidden;
+ background-color: #fff;
+ background-image: none;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+ -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+ transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+}
+
+.boot-order:focus,
+.boot-order.focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233,
0.6);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.boot-order > li {
+ cursor: move; /* fallback if grab cursor is unsupported */
+ cursor: grab;
+ cursor: -moz-grab;
+ cursor: -webkit-grab;
+ border-left: 0;
+ border-right: 0;
+}
+
+.boot-order > li:first-child {
+ border-top: 0;
+}
+
+.boot-order > li:last-child {
+ border-bottom: 0;
+}
+
+.boot-order > li.ui-sortable-helper {
+ cursor: grabbing;
+ cursor: -moz-grabbing;
+ cursor: -webkit-grabbing;
+ border: 1px solid #ccc !important;
+}
+
+.boot-order li i {
+ text-align: right;
+}
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index b47d293..dfb2ca3 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
kimchi.guest_edit_main = function() {
var authType;
var formTargetId;
@@ -26,6 +27,7 @@ kimchi.guest_edit_main = function() {
var networkOptions = "";
clearTimeout(kimchi.vmTimeout);
+ var bootOrderOptions = [];
$('#modalWindow').on('hidden.bs.modal', function() {
kimchi.setListVMAutoTimeout();
@@ -45,7 +47,6 @@ kimchi.guest_edit_main = function() {
var submitForm = function(event) {
- // tap map, "general": 0, "storage": 1,
"interface": 2, "permission": 3, "password": 4
var submit_map = {
0: generalSubmit,
3: permissionSubmit,
@@ -963,6 +964,85 @@ kimchi.guest_edit_main = function() {
});
};
+ var setupBootOrder = function(guest) {
+ var guestBootOrder = guest['bootorder'];
+ var dev = ["cdrom", "hd", "network"];
+ var excludedDev = dev.filter(function(e){return
this.indexOf(e)<0;},guestBootOrder);
+
+ $('#myList button').prop('disabled', true);
+ $('#myList').empty();
+ $.each(guestBootOrder, function(index, value) {
+ item = $.parseHTML("<li class='list-group-item'
data-value=" + value + "><input type='checkbox'
class='wok-checkbox' id='checkbox-" + value + "'
value='" + value + "'> <label class='check-all'
for='checkbox-" + value + "'>" + value +
"</label><button id='button-" + value + "' class='btn
btn-link deleteBootOrderElem' style='float:right; margin-top: 3px; padding:
0;'><i class='fa fa-minus-circle'></i>
Remove</button></li>");
+ $('#myList').append(item);
+ $('#checkbox-' + value).prop('disabled', true);
+ $('#checkbox-' + value).prop('checked', true);
+ $('#button-' + value).prop('disabled', false);
+ });
+ if (excludedDev) {
+ $.each(excludedDev, function(index, value) {
+ item = $.parseHTML("<li class='list-group-item'
data-value=" + value + "><input type='checkbox'
class='wok-checkbox' id='checkbox-" + value + "'
value='" + value + "'> <label class='check-all'
for='checkbox-" + value + "'>" + value +
"</label><button id='button-" + value + "' class='btn
btn-link deleteBootOrderElem' style='float:right; margin-top: 3px; padding:
0;'><i class='fa fa-minus-circle'></i>
Remove</button></li>");
+ $('#myList').append(item);
+ });
+ }
+
+ if (guestBootOrder.length == 1) {
+ $('#myList button').prop('disabled', true);
+ }
+
+ $('.boot-order').sortable({
+ items: 'li',
+ cursor: 'move',
+ opacity: 0.6,
+ containment: "parent",
+ start: function(event, ui) {
+ $(this).addClass('focus');
+ },
+ stop: function(event, ui) {
+ $(this).removeClass('focus');
+ },
+ change: function(event, ui) {
+ // callback once started changing order
+ },
+ update: function(event, ui) {
+ // callback once finished order
+ $(saveButton).prop('disabled', false);
+ bootOrderOptions = [];
+ $("#myList li").each(function() {
+
bootOrderOptions.push($(this).attr("data-value").toLowerCase())
+ });
+ bootOrderOptions.forEach(function(entry) {
+ console.log(entry);
+ });
+ var data = {
+ bootorder: bootOrderOptions
+ };
+ kimchi.updateVM(kimchi.selectedGuest, data, function() {
+ // wok.window.close();
+ }, function(err) {
+
wok.message.error(err.responseJSON.reason,'#alert-modal-container');
+ });
+ }
+ });
+
+ $(".deleteBootOrderElem").on('click', function(evt) {
+ evt.preventDefault();
+ var item = $(this).parent().attr("data-value").toLowerCase();
+ $("#checkbox-" + item).prop('disabled', false);
+ $("#checkbox-" + item).prop('checked', false);
+ var index = guestBootOrder.indexOf(item);
+ if (index !== -1) {
+ guestBootOrder.splice(index, 1);
+ }
+ if (guestBootOrder.length == 1) {
+ $('#myList button').prop('disabled', true);
+ }
+ var data = {
+ bootorder: guestBootOrder
+ };
+ kimchi.updateVM(kimchi.selectedGuest, data, function() {});
+ });
+ };
+
var initContent = function(guest) {
guest['icon'] = guest['icon'] ||
'plugins/kimchi/images/icon-vm.png';
$('#form-guest-edit-general').fillWithObject(guest);
@@ -1028,6 +1108,7 @@ kimchi.guest_edit_main = function() {
setupPermission();
setupPCIDevice();
setupSnapshot();
+ setupBootOrder(guest);
kimchi.init_processor_tab(guest.cpu_info, $(saveButton));
if ((kimchi.thisVMState === "running") || (kimchi.thisVMState ===
"paused")) {
@@ -1051,6 +1132,13 @@ kimchi.guest_edit_main = function() {
};
};
+ $('#form-guest-edit-general').removeClass('active');
+ $('#guest-edit-tabs > .wok-mask').show();
+ setTimeout(function() {
+ $('#form-guest-edit-general').addClass('active');
+ $('#guest-edit-tabs > .wok-mask').hide();
+ }, 500);
+
kimchi.retrieveVM(kimchi.selectedGuest, initContent);
var generalSubmit = function(event) {
@@ -1115,6 +1203,13 @@ kimchi.guest_edit_main = function() {
delete changedFields.memory.current;
}
}
+ console.log(changedFields);
+
+ checkedValue = [];
+ $("#myList input:checked").each(function() {
+ checkedValue.push($(this).attr("value"));
+ });
+ changedFields.bootorder = checkedValue;
kimchi.updateVM(kimchi.selectedGuest, changedFields, function() {
kimchi.listVmsAuto();
diff --git a/ui/pages/guest-edit.html.tmpl b/ui/pages/guest-edit.html.tmpl
index d8a482c..d67627a 100644
--- a/ui/pages/guest-edit.html.tmpl
+++ b/ui/pages/guest-edit.html.tmpl
@@ -1,7 +1,7 @@
#*
* Project Kimchi
*
- * Copyright IBM Corp, 2013-2016
+ * Copyright IBM Corp, 2013-2017
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
</div>
<div class="modal-body">
<span id="alert-modal-container"></span>
-<ul class="nav nav-tabs" role="tablist">
+ <ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a
href="#form-guest-edit-general"
aria-controls="form-guest-edit-general" role="tab"
data-id="form-guest-edit-general"
data-toggle="tab">$_("General")</a></li>
<li role="presentation"><a
href="#form-guest-edit-storage"
aria-controls="form-guest-edit-storage" role="tab"
data-id="form-guest-edit-storage"
data-toggle="tab">$_("Storage")</a></li>
<li role="presentation"><a
href="#form-guest-edit-interface"
aria-controls="form-guest-edit-interface" role="tab"
data-id="form-guest-edit-interface"
data-toggle="tab">$_("Interface")</a></li>
@@ -40,6 +40,14 @@
<li role="presentation"><a href="#form-edit-processor"
aria-controls="form-edit-processor" role="tab"
data-id="form-edit-processor"
data-toggle="tab">$_("Processor")</a></li>
</ul>
<div class="tab-content" id="guest-edit-tabs">
+ <div class="wok-mask" role="presentation"
class="hidden">
+ <div class="wok-mask-loader-container">
+ <div class="wok-mask-loading">
+ <div class="wok-mask-loading-icon"></div>
+ <div
class="wok-mask-loading-text">$_("Loading")...</div>
+ </div>
+ </div>
+ </div>
<form role="tabpanel" class="tab-pane active"
id="form-guest-edit-general">
<div class="form-group">
<label
for="guest-edit-id-textbox">$_("Name")</label>
@@ -68,6 +76,19 @@
<option
value="virtio">$_("virtio")</option>
</select>
</div>
+ <div class="guest-edit-bootorder tab-pane"
id="form-guest-edit-bootorder">
+ <div id="bootOrder">
+ <label for="guest-edit-boot-order-textbox">Boot
Order</label>
+ <ul id="myList" class="list-group
boot-order">
+ <li class="list-group-item"
data-value="CDROM"><input type="checkbox"
id="checkbox-cdrom" value="cdrom"> CD-ROM <button
id="button-cdrom" class="btn btn-link deleteBootOrderElem"><i
class="fa fa-minus-circle"></i> Remove</button></li>
+ <li class="list-group-item"
data-value="HD"><input type="checkbox"
id="checkbox-hd" value="hd"> HD <button id="button-hd"
class="btn btn-link deleteBootOrderElem"><i class="fa
fa-minus-circle"></i> Remove</button></li>
+ <li class="list-group-item"
data-value="Network"><input type="checkbox"
id="checkbox-network" value="network"> Network <button
id="button-network" class="btn btn-link deleteBootOrderElem"><i
class="fa fa-minus-circle"></i> Remove</button></li>
+ </ul>
+ <p class="help-block">
+ <i class="fa fa-info-circle"></i>
$_("Select which items for boot order and grad them when needed to order them. At
least one option must be selected.")</p>
+ </p>
+ </div>
+ </div>
</form>
<form role="tabpanel" class="tab-pane"
id="form-guest-edit-storage">
<div class="btn-group action-area">
@@ -197,7 +218,6 @@
$_("Current CPU must be equal or lower than the
Maximum CPU value. If a topology is set, it must be also be a multiple of the
'threads' value.")
</p>
</div>
-
<div id="guest-max-processor-panel"
class="form-group">
<label
for="guest-edit-max-processor-textbox">$_("Max CPU")</label>
<p id="settings-readonly-help"
class="hidden">$_("Unable to edit maximum CPU or CPU topology when
editing a running or paused virtual machine.")</p>