From: Samuel Guimarães <sguimaraes943(a)gmail.com>
Added a warning icon when a template has invalid parameters in Templates list and when
editing a template.
Signed-off-by: peterpennings <peterpnns(a)gmail.com>
Signed-off-by: Samuel Guimarães <sguimaraes943(a)gmail.com>
---
ui/css/kimchi.css | 97 ++++++++++++++++++++++++++++++++--
ui/css/src/modules/_guests.scss | 6 +++
ui/css/src/modules/_iso-list.scss | 22 +++++++-
ui/css/src/modules/_templates.scss | 53 +++++++++++++++++--
ui/js/src/kimchi.guest_add_main.js | 7 +++
ui/js/src/kimchi.template_edit_main.js | 52 ++++++++++++++----
ui/js/src/kimchi.template_main.js | 9 +++-
ui/pages/guest-add.html.tmpl | 11 ++--
ui/pages/i18n.json.tmpl | 1 +
ui/pages/tabs/templates.html.tmpl | 24 +++++----
ui/pages/template-edit.html.tmpl | 6 ++-
11 files changed, 255 insertions(+), 33 deletions(-)
diff --git a/ui/css/kimchi.css b/ui/css/kimchi.css
index 1d33d45..e7bed2e 100644
--- a/ui/css/kimchi.css
+++ b/ui/css/kimchi.css
@@ -121,6 +121,38 @@
transition: all .1s ease-in-out;
}
+#template-add-window.modal-content label.box-iso-outer span.box-iso-inner
.tooltip-inner,
+#guest-add-window.modal-content label.box-iso-outer span.box-iso-inner .tooltip-inner {
+ font-size: 10pt;
+ padding: 6px 8px;
+}
+
+#template-add-window.modal-content label.box-iso-outer span.box-iso-inner
.tooltip-inner,
+#guest-add-window.modal-content label.box-iso-outer span.box-iso-inner .tooltip-inner {
+ max-width: 300px;
+}
+
+#template-add-window.modal-content label.box-iso-outer span.box-iso-inner
.tooltip[style],
+#guest-add-window.modal-content label.box-iso-outer span.box-iso-inner .tooltip[style] {
+ left: 7px !important;
+ right: 7px !important;
+}
+
+#template-add-window.modal-content label.box-iso-outer span.box-iso-inner
.tooltip-arrow[style],
+#guest-add-window.modal-content label.box-iso-outer span.box-iso-inner
.tooltip-arrow[style] {
+ left: 216px !important;
+}
+
+#template-add-window.modal-content li[data-invalid="invalid"]
label.box-iso-outer,
+#guest-add-window.modal-content li[data-invalid="invalid"] label.box-iso-outer
{
+ color: #999 !important;
+}
+
+#template-add-window.modal-content li[data-invalid="invalid"]
label.box-iso-outer span.box-iso-inner,
+#guest-add-window.modal-content li[data-invalid="invalid"] label.box-iso-outer
span.box-iso-inner {
+ background: rgba(255, 255, 255, 0.4);
+}
+
#template-add-window.modal-content ul.list-template,
#template-add-window.modal-content ul.list-iso,
#guest-add-window.modal-content ul.list-template,
@@ -255,6 +287,13 @@
padding: 10px 30px;
}
+.guests-modal .template-status {
+ position: absolute;
+ right: 15px;
+ bottom: 15px;
+ font-size: 32px;
+}
+
#guest-add-window .modal-body {
margin: 0;
padding: 0;
@@ -1807,16 +1846,20 @@ body.wok-gallery {
}
#templates-root-container .wok-vm-list .column-version {
- width: 14.2435%;
+ width: 12.2435%;
font-weight: bold;
}
#templates-root-container .wok-vm-list .column-processors {
- width: 12.8413%;
+ width: 10.8413%;
}
#templates-root-container .wok-vm-list .column-memory {
- width: 7.3800%;
+ width: 9.6900%;
+}
+
+#templates-root-container .wok-vm-list .column-status {
+ width: 1.6900%;
}
#templates-root-container .wok-vm-list .column-action {
@@ -1875,6 +1918,7 @@ body.wok-gallery {
}
#templates-root-container .wok-vm-gallery .wok-vm-body {
+ position: relative;
padding: 0 20px 0 20px;
width: 240px;
display: inline-block;
@@ -1911,6 +1955,19 @@ body.wok-gallery {
cursor: default;
}
+#templates-root-container .wok-vm-gallery span.template-status {
+ position: absolute;
+ bottom: 10px;
+ right: 10px;
+ width: 32px;
+ height: 32px;
+}
+
+#templates-root-container .wok-vm-gallery .invalid-icon {
+ position: absolute;
+ font-size: 32px;
+}
+
#templates-root-container .wok-vm-gallery .item-hidden.column-type,
#templates-root-container .wok-vm-gallery .item-hidden.column-version,
#templates-root-container .wok-vm-gallery .item-hidden.column-processors {
padding-bottom: 11px;
}
@@ -1979,6 +2036,40 @@ body.wok-gallery {
background-image: url("/images/theme-default/icon-unknown.png");
}
+#templates-root-container span.template-status {
+ color: #999;
+}
+
+#templates-root-container .tooltip-inner {
+ font-size: 10pt;
+ padding: 6px 8px;
+}
+
+#templates-root-container .wok-vm-list .tooltip-inner {
+ max-width: 300px;
+}
+
+#templates-root-container .wok-vm-list .tooltip[style] {
+ left: 79px !important;
+}
+
+#templates-root-container .wok-vm-list .tooltip-arrow[style] {
+ left: 10px !important;
+}
+
+#templates-root-container .wok-vm-gallery .tooltip-inner {
+ max-width: 320px;
+}
+
+#templates-root-container .wok-vm-gallery .tooltip[style] {
+ left: 7px !important;
+ right: 7px !important;
+}
+
+#templates-root-container .wok-vm-gallery .tooltip-arrow[style] {
+ left: 207px !important;
+}
+
.network-config input.invalid-field[type="text"] {
border-color: #FF4444;
}
diff --git a/ui/css/src/modules/_guests.scss b/ui/css/src/modules/_guests.scss
index 6f5dbf0..6c24800 100644
--- a/ui/css/src/modules/_guests.scss
+++ b/ui/css/src/modules/_guests.scss
@@ -38,6 +38,12 @@
overflow: auto;
padding: 10px 30px;
}
+ .template-status {
+ position: absolute;
+ right: 15px;
+ bottom: 15px;
+ font-size: 32px;
+ }
}
#guest-add-window {
diff --git a/ui/css/src/modules/_iso-list.scss b/ui/css/src/modules/_iso-list.scss
index 222dcdb..355f590 100644
--- a/ui/css/src/modules/_iso-list.scss
+++ b/ui/css/src/modules/_iso-list.scss
@@ -46,9 +46,29 @@
label.box-iso-outer span.box-iso-inner {
display: block;
border: 1px solid transparent;
- background: $gray-lighter;
+ background: $body-bg;
transition: all .1s ease-in-out;
}
+ label.box-iso-outer span.box-iso-inner .tooltip-inner {
+ font-size: 10pt;
+ padding: 6px 8px;
+ }
+ label.box-iso-outer span.box-iso-inner .tooltip-inner {
+ max-width: 300px;
+ }
+ label.box-iso-outer span.box-iso-inner .tooltip[style] {
+ left: 7px !important;
+ right: 7px !important;
+ }
+ label.box-iso-outer span.box-iso-inner .tooltip-arrow[style] {
+ left: 216px !important;
+ }
+ li[data-invalid="invalid"] label.box-iso-outer {
+ color: $gray-light !important;
+ }
+ li[data-invalid="invalid"] label.box-iso-outer span.box-iso-inner {
+ background: rgba($body-bg, 0.4);
+ }
ul.list-template,
ul.list-iso {
display: block;
diff --git a/ui/css/src/modules/_templates.scss b/ui/css/src/modules/_templates.scss
index a9f0e8f..ad76d0f 100644
--- a/ui/css/src/modules/_templates.scss
+++ b/ui/css/src/modules/_templates.scss
@@ -370,14 +370,17 @@
font-weight: bold;
}
.column-version {
- width: 14.2435%;
+ width: 12.2435%;
font-weight: bold;
}
.column-processors {
- width: 12.8413%;
+ width: 10.8413%;
}
.column-memory {
- width: 7.3800%;
+ width: 9.6900%;
+ }
+ .column-status {
+ width: 1.6900%;
}
.column-action {
width: 33.8000%;
@@ -423,6 +426,7 @@
display: none;
}
.wok-vm-body {
+ position: relative;;
padding: 0 20px 0 20px;
width: 240px;
display: inline-block;
@@ -455,6 +459,17 @@
white-space: nowrap;
cursor: default;
}
+ span.template-status {
+ position: absolute;
+ bottom: 10px;
+ right: 10px;
+ width: 32px;
+ height: 32px;
+ }
+ .invalid-icon {
+ position: absolute;
+ font-size: 32px;
+ }
.item-hidden {
&.column-type,
&.column-version,
@@ -515,4 +530,36 @@
}
}
}
+ span.template-status {
+ color: #999;
+ }
+ .tooltip-inner {
+ font-size: 10pt;
+ padding: 6px 8px;
+ }
+
+ .wok-vm-list .tooltip-inner {
+ max-width: 300px;
+ }
+
+ .wok-vm-list .tooltip[style] {
+ left: 79px !important;
+ }
+
+ .wok-vm-list .tooltip-arrow[style] {
+ left: 10px !important;
+ }
+
+ .wok-vm-gallery .tooltip-inner {
+ max-width: 320px;
+ }
+
+ .wok-vm-gallery .tooltip[style] {
+ left: 7px !important;
+ right: 7px !important;
+ }
+
+ .wok-vm-gallery .tooltip-arrow[style] {
+ left: 207px !important;
+ }
}
diff --git a/ui/js/src/kimchi.guest_add_main.js b/ui/js/src/kimchi.guest_add_main.js
index 87ad6fa..2b311fc 100644
--- a/ui/js/src/kimchi.guest_add_main.js
+++ b/ui/js/src/kimchi.guest_add_main.js
@@ -29,9 +29,16 @@ kimchi.guest_add_main = function() {
var html = '';
var tmpl = $('#tmpl-template').html();
$.each(result, function(index, value) {
+ value.invalid_indicator = "invalid";
+ if ($.isEmptyObject(value.invalid)) {
+ value.invalid_indicator = "valid";
+ }
html += wok.substitute(tmpl, value);
});
$('#templateTile').html(html);
+
$('.iso-radio-hidden[data-invalid="invalid"]').attr("disabled",
true);
+ $('.template-status[data-invalid="valid"]').hide();
+ $('[data-toggle="tooltip"]').tooltip();
return;
}
diff --git a/ui/js/src/kimchi.template_edit_main.js
b/ui/js/src/kimchi.template_edit_main.js
index bc3c2ef..f639e0a 100644
--- a/ui/js/src/kimchi.template_edit_main.js
+++ b/ui/js/src/kimchi.template_edit_main.js
@@ -133,9 +133,14 @@ kimchi.template_edit_main = function() {
storageOptions += '<option value="' + poolName +
'">' + poolName + '</option>';
});
- $(storageRow + ' #selectStorageName').append(storageOptions);
- $(storageRow + '
#selectStorageName').val(storageData.storageName);
- $(storageRow + ' #selectStorageName').selectpicker();
+ $(storageRow + ' .selectStorageName').append(storageOptions);
+ if(!$(storageRow + ' .selectStorageName
option[value="'+storageData.storageName+'"]').length){
+ var invalidOption = '<option disabled="disabled"
selected="selected" value="' + storageData.storageName +
'">' + storageData.storageName + '</option>';
+ $(storageRow + '
.selectStorageName').prepend(invalidOption);
+ $(storageRow + '
.selectStorageName').parent().addClass('has-error')
+ }
+ $(storageRow + '
.selectStorageName').val(storageData.storageName);
+ $(storageRow + ' .selectStorageName').selectpicker();
if (storageData.storageType === 'iscsi' ||
storageData.storageType === 'scsi') {
$(storageRow + '
.template-storage-disk').attr('readonly', true).prop('disabled',
true);
@@ -164,7 +169,8 @@ kimchi.template_edit_main = function() {
$(this).parent().parent().remove();
});
- $(storageRow + ' #selectStorageName').change(function() {
+ $(storageRow + ' select.selectStorageName').change(function() {
+ $(this).parent().parent().removeClass('has-error');
var poolType = storagePoolsInfo[$(this).val()].type;
$(storageRow + '
.template-storage-name').val($(this).val());
$(storageRow + ' .template-storage-type').val(poolType);
@@ -319,9 +325,24 @@ kimchi.template_edit_main = function() {
$('#guest-show-max-processor
i.fa').toggleClass('fa-plus-circle fa-minus-circle');
});
};
+
+ var checkInvalids = function(){
+ $.each(template.invalid, function(key, value) {
+ if(key === 'cdrom' || key === 'vm-image'){
+ $('.tab-content
input[name="'+key+'"]').attr('disabled',false).parent().addClass('has-error
has-feedback');
+ return true;
+ }else if(key === 'storagepools'){
+ return true;
+ }else {
+ return false;
+ }
+ });
+ }
+
kimchi.listNetworks(initInterface);
kimchi.listStoragePools(initStorage);
initProcessor();
+ checkInvalids();
};
kimchi.retrieveTemplate(kimchi.selectedTemplate, initTemplate);
@@ -415,16 +436,27 @@ kimchi.template_edit_main = function() {
data.networks = [];
}
- kimchi.updateTemplate($('#template-name').val(), data, function() {
- kimchi.doListTemplates();
- wok.window.close();
- }, function(err) {
+ if($('.has-error', '#form-template-storage').length){
+ // Workaround to check if invalid storage wasn't changed
+
$('a[href="#storage"]','#edit-template-tabs').tab('show');
$button.html(i18n['KCHAPI6007M']);
$('.modal input[type="text"]').prop('disabled',
false);
$('.modal input[type="checkbox"]').prop('disabled',
false);
$('.modal select').prop('disabled', false);
$('.modal .selectpicker').removeClass('disabled');
- wok.message.error(err.responseJSON.reason,'#alert-modal-container');
- });
+
wok.message.error(i18n['KCHTMPL6007M'],'#alert-modal-container');
+ }else {
+ kimchi.updateTemplate($('#template-name').val(), data, function() {
+ kimchi.doListTemplates();
+ wok.window.close();
+ }, function(err) {
+ $button.html(i18n['KCHAPI6007M']);
+ $('.modal input[type="text"]').prop('disabled',
false);
+ $('.modal
input[type="checkbox"]').prop('disabled', false);
+ $('.modal select').prop('disabled', false);
+ $('.modal .selectpicker').removeClass('disabled');
+
wok.message.error(err.responseJSON.reason,'#alert-modal-container');
+ });
+ }
});
};
diff --git a/ui/js/src/kimchi.template_main.js b/ui/js/src/kimchi.template_main.js
index 5787d77..22a3509 100644
--- a/ui/js/src/kimchi.template_main.js
+++ b/ui/js/src/kimchi.template_main.js
@@ -7,7 +7,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- *
http://www.apache.org/licenses/LICENSE-2.0
+ *
http://www.apache.org/licenses/LICENSE-2.0invalid_indicator_template
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,6 +24,10 @@ kimchi.doListTemplates = function() {
var listHtml = '';
var templateHtml = $('#templateTmpl').html();
$.each(result, function(index, value) {
+ value.invalid_indicator = "invalid";
+ if ($.isEmptyObject(value.invalid)) {
+ value.invalid_indicator = "valid";
+ }
listHtml += wok.substitute(templateHtml, value);
});
$('.wok-vm-list').removeClass('hidden');
@@ -31,6 +35,7 @@ kimchi.doListTemplates = function() {
$('#templateList').html(listHtml);
kimchi.templateBindClick();
$('.wok-mask').fadeOut(300, function() {});
+ $('.template-status[data-invalid="valid"]').hide();
} else {
$('#templateList').html('');
$('#noTemplates').show();
@@ -43,7 +48,7 @@ kimchi.doListTemplates = function() {
valueNames: ['name-filter', 'os-type-filter',
'os-version-filter', 'cpus-filter', 'memory-filter']
};
var templatesList = new List('templates-container', options);
-
+
$('[data-invalid="invalid"][data-toggle="tooltip"]').tooltip();
}, function(err) {
wok.message.error(err.responseJSON.reason);
$('.wok-mask').fadeOut(300, function() {
diff --git a/ui/pages/guest-add.html.tmpl b/ui/pages/guest-add.html.tmpl
index 33472ce..8289a7f 100644
--- a/ui/pages/guest-add.html.tmpl
+++ b/ui/pages/guest-add.html.tmpl
@@ -51,12 +51,17 @@
<ul id="templateTile" class="list-template
tile-check tile-template">
</ul>
<script type="html/text"
id="tmpl-template" class="tmpl-html">
- <li class="col-md-3">
+ <li class="col-md-3 template-opacity"
data-invalid="{invalid_indicator}">
<label class="box-iso-outer">
- <input type="radio"
name="template" value="/plugins/kimchi/templates/{name}"
class="iso-radio-hidden">
+ <input type="radio"
name="template" value="/plugins/kimchi/templates/{name}"
class="iso-radio-hidden" data-invalid="{invalid_indicator}">
<span
class="box-iso-border">
<span
class="box-iso-inner">
- <h3 class="iso-title
{os_distro}" title="{name}">{name}</h3>
+
+ <h3 class="iso-title
{os_distro}" title="{name}">
+ <span
data-invalid="{invalid_indicator}" data-placement="top"
class="template-status" data-toggle="tooltip"
title="$_("This template has invalid parameters.")">
+ <i
role="presentation" class="fa fa-exclamation-triangle
invalid-icon"></i>
+ <span
class="sr-only">$_("This template has invalid
parameters")</span>
+ </span>{name}</h3>
<dl
class="iso-info">
<dt>{os_distro}</dt>
<dd>$_("OS")</dd>
diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl
index 8da568a..95c5600 100644
--- a/ui/pages/i18n.json.tmpl
+++ b/ui/pages/i18n.json.tmpl
@@ -51,6 +51,7 @@
"KCHTMPL6004M": "$_("View Table")",
"KCHTMPL6005M": "$_("View Gallery")",
"KCHTMPL6006M": "$_("Not Available")",
+ "KCHTMPL6007M": "$_("Please check the invalid Storage
Pools")",
"KCHVM6001M": "$_("This will delete the virtual machine and its
virtual disks. This operation cannot be undone. Would you like to continue?")",
"KCHVM6002M": "$_("Power off Confirmation")",
diff --git a/ui/pages/tabs/templates.html.tmpl b/ui/pages/tabs/templates.html.tmpl
index 50e2b22..7616796 100644
--- a/ui/pages/tabs/templates.html.tmpl
+++ b/ui/pages/tabs/templates.html.tmpl
@@ -60,11 +60,11 @@
<button type="button" class="btn
dropdown-toggle form-control selectpicker btn-default sort-button"
data-toggle="dropdown" title="Status"
aria-expanded="false"><span class="filter-option
pull-left">$_("Status")</span> <span
class="caret"></span></button>
<div class="dropdown-menu open"
style="max-height: 668px; overflow: hidden; min-height: 0px;padding: 0px;">
<ul class="dropdown-menu inner selectpicker"
role="menu" style="max-height: 656px; overflow-y: auto; min-height:
0px;">
- <li role="presentation"
nwAct="sort"><a href="#" class="sort"
data-sort="name-filter">$_("Name")</a></li>
- <li role="presentation"
nwAct="clone"><a href="#" class="sort"
data-sort="os-type-filter">$_("OS")</a></li>
- <li role="presentation"
nwAct="clone"><a href="#" class="sort"
data-sort="os-version-filter">$_("Version")</a></li>
- <li role="presentation"
nwAct="clone"><a href="#" class="sort"
data-sort="cpus-filter">$_("Current CPUs")</a></li>
- <li role="presentation"
nwAct="clone"><a href="#" class="sort"
data-sort="memory-filter">$_("Memory")</a></li>
+ <li nwAct="sort"><a href="#"
class="sort"
data-sort="name-filter">$_("Name")</a></li>
+ <li nwAct="clone"><a
href="#" class="sort"
data-sort="os-type-filter">$_("OS")</a></li>
+ <li nwAct="clone"><a
href="#" class="sort"
data-sort="os-version-filter">$_("Version")</a></li>
+ <li nwAct="clone"><a
href="#" class="sort"
data-sort="cpus-filter">$_("Current CPUs")</a></li>
+ <li nwAct="clone"><a
href="#" class="sort"
data-sort="memory-filter">$_("Memory")</a></li>
</ul>
</div>
</div>
@@ -108,17 +108,21 @@
kimchi.template_main();
</script>
<script id="templateTmpl" type="html/text">
- <li class="wok-vm-body">
- <span class='column-name name-filter name-distro-icon
icon-{os_distro}' title="{name}"
val="{name}">{name}</span><!--
+ <li class="wok-vm-body"
data-invalid="{invalid_indicator}">
+ <span class='column-name name-filter name-distro-icon
icon-{os_distro}' title="{name}" val="{name}">
+ <span class="template-status"
data-invalid="{invalid_indicator}" data-toggle="tooltip"
title="$_("This template has invalid parameters.")">
+ <i role="presentation" class="fa
fa-exclamation-triangle invalid-icon"></i>
+ <span class="sr-only">$_("This template has
invalid parameters")</span>
+ </span>{name}</span><!--
--><span class='column-action pull-right'>
<span class="pull-right">
<div class="dropdown menu-flat">
<button class="btn btn-primary dropdown-toggle"
type="button" data-toggle="dropdown"
aria-expanded="false"><span
class="edit-alt"></span>$_("Actions")<span
class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
- <li role="presentation" nwAct="edit"
class='template-edit'><a href="#"
data-template='{name}'><i class="fa
fa-pencil"></i>$_("Edit")</a></li>
- <li role="presentation" nwAct="clone"
class='template-clone'><a href="#"
data-template='{name}'><i class="fa
fa-files-o"></i>$_("Clone")</a></li>
- <li role="presentation" nwAct="delete"
class='critical template-delete'><a href="#"
data-template='{name}'><i class="fa
fa-minus-circle"></i>$_("Delete")</a></li>
+ <li nwAct="edit"
class='template-edit'><a href="#"
data-template='{name}'><i class="fa
fa-pencil"></i>$_("Edit")</a></li>
+ <li nwAct="clone"
class='template-clone'><a href="#"
data-template='{name}'><i class="fa
fa-files-o"></i>$_("Clone")</a></li>
+ <li nwAct="delete" class='critical
template-delete'><a href="#" data-template='{name}'><i
class="fa
fa-minus-circle"></i>$_("Delete")</a></li>
</ul>
</div>
</span>
diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl
index d094e66..8fb4a56 100644
--- a/ui/pages/template-edit.html.tmpl
+++ b/ui/pages/template-edit.html.tmpl
@@ -93,9 +93,13 @@
</div>
<div class="template-edit-wrapper-controls
templ-edit-cdrom">
<input
id="template-edit-cdrom-textbox" class="form-control"
name="cdrom" type="text" disabled="disabled" />
+ <span
class="form-control-feedback">
+ <i class="fa
fa-times"></i>
+ </span>
</div>
<div class="template-edit-wrapper-controls
templ-edit-vm-image hide">
<input
id="template-edit-vmimage-textbox" class="form-control"
name="vm-image" type="text" disabled="disabled" />
+ <span class="fa fa-times
form-control-feedback"></span>
</div>
<div
class="template-edit-wrapper-controls">
<select
id="template-edit-graphics" name="graphics"
class="form-control" />
@@ -172,7 +176,7 @@
<div id="storageRow{storageIndex}" class='item'>
<span class="template-storage-cell storage-pool">
<input class="template-storage-name" value={storageName}
type="text" style="display:none" />
- <select id="selectStorageName"></select>
+ <select id="selectStorageName-{storageIndex}"
class="selectStorageName"></select>
</span>
<span class="template-storage-cell type">
<input class="template-storage-type form-control"
value={storageType} readonly=true type="text" />
--
1.9.3