Allow users to specify the order of VNICs of an instance.
Enable to order VNICs. It allows to choose your preferred network to eth0, eth1 and so on. Added jQuery UI for implementing drag and drop sort function. implements bp quantum-vnic-ordering Change-Id: I29cba9004d7170af2be3a6645c2217d7a5b0f6ae
This commit is contained in:
parent
1d99475ef9
commit
3a84686ae3
@ -4,6 +4,8 @@ horizon.projects = {
|
||||
current_membership: [],
|
||||
users: [],
|
||||
roles: [],
|
||||
networks_selected: [],
|
||||
networks_available: [],
|
||||
default_role_id: "",
|
||||
workflow_loaded: false,
|
||||
no_project_members: gettext('This project currently has no members.'),
|
||||
@ -26,6 +28,14 @@ horizon.projects = {
|
||||
get_role_element: function(role_id) {
|
||||
return $('select[id^="id_role_' + role_id + '"]');
|
||||
},
|
||||
/*
|
||||
|
||||
* Gets the html select element associated with a given
|
||||
* network id for network_id.
|
||||
**/
|
||||
get_network_element: function(network_id) {
|
||||
return $('li > label[for^="id_network_' + network_id + '"]');
|
||||
},
|
||||
|
||||
/*
|
||||
* Initializes all of the horizon.projects lists with
|
||||
@ -82,6 +92,28 @@ horizon.projects = {
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Initializes an associative array of lists of the current
|
||||
* networks.
|
||||
**/
|
||||
init_network_list: function() {
|
||||
horizon.projects.networks_selected = [];
|
||||
horizon.projects.networks_available = [];
|
||||
$(this.get_network_element("")).each(function(){
|
||||
var $this = $(this);
|
||||
var $input = $this.children("input");
|
||||
var network_property = {
|
||||
name:$this.text().replace(/^\s+/,""),
|
||||
id:$input.attr("id"),
|
||||
value:$input.attr("value")
|
||||
};
|
||||
if($input.is(':checked')) {
|
||||
horizon.projects.networks_selected.push(network_property);
|
||||
} else {
|
||||
horizon.projects.networks_available.push(network_property);
|
||||
}
|
||||
});
|
||||
},
|
||||
/*
|
||||
* Checks to see whether a user is a member of the current project.
|
||||
* If they are, returns the id of their primary role.
|
||||
@ -171,6 +203,16 @@ horizon.projects = {
|
||||
return $(user_el);
|
||||
},
|
||||
|
||||
/*
|
||||
* Generates the HTML structure for a network that will be displayed
|
||||
* as a list item in the project network list.
|
||||
**/
|
||||
generate_network_element: function(name, id, value) {
|
||||
var $li = $('<li>');
|
||||
$li.attr('name', value).html(name + '<em class="network_id">(' + value + ')</em><a href="#" class="btn btn-primary"></a>');
|
||||
return $li;
|
||||
},
|
||||
|
||||
set_selected_role: function(selected_el, role_id) {
|
||||
$(selected_el).text(horizon.projects.roles[role_id]);
|
||||
$(selected_el).attr('data-role-id', role_id);
|
||||
@ -197,6 +239,72 @@ horizon.projects = {
|
||||
horizon.projects.detect_no_results();
|
||||
},
|
||||
|
||||
/*
|
||||
* Generates the HTML structure for the project Network List.
|
||||
**/
|
||||
generate_networklist_html: function() {
|
||||
var self = this;
|
||||
var updateForm = function() {
|
||||
var lists = $("#networkListId div.input li").attr('data-index',100);
|
||||
var active_networks = $("#selected_network > li").map(function(){
|
||||
return $(this).attr("name");
|
||||
});
|
||||
$("#networkListId div.input input:checkbox").removeAttr('checked');
|
||||
active_networks.each(function(index, value){
|
||||
$("#networkListId div.input input:checkbox[value=" + value + "]")
|
||||
.attr('checked','checked')
|
||||
.parents("li").attr('data-index',index);
|
||||
});
|
||||
$("#networkListId div.input ul").html(
|
||||
lists.sort(function(a,b){
|
||||
if( $(a).data("index") < $(b).data("index")) return -1;
|
||||
if( $(a).data("index") > $(b).data("index")) return 1;
|
||||
return 0;
|
||||
})
|
||||
);
|
||||
};
|
||||
$("#networkListSortContainer").show();
|
||||
$("#networkListIdContainer").hide();
|
||||
self.init_network_list();
|
||||
$.each(self.networks_available, function(index, value){
|
||||
$("#available_network").append(self.generate_network_element(value.name, value.id, value.value));
|
||||
});
|
||||
$.each(self.networks_selected, function(index, value){
|
||||
$("#selected_network").append(self.generate_network_element(value.name, value.id, value.value));
|
||||
});
|
||||
// $(".networklist > li").click(function(){
|
||||
// $(this).toggleClass("ui-selected");
|
||||
// });
|
||||
$(".networklist > li > a.btn").click(function(e){
|
||||
var $this = $(this);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if($this.parents("ul#available_network").length > 0) {
|
||||
$this.parent().appendTo($("#selected_network"));
|
||||
} else if ($this.parents("ul#selected_network").length > 0) {
|
||||
$this.parent().appendTo($("#available_network"));
|
||||
}
|
||||
updateForm();
|
||||
});
|
||||
if ($("#networkListId > div.control-group.error").length > 0) {
|
||||
var errortext = $("#networkListId > div.control-group.error").find("span.help-inline").text();
|
||||
$("#selected_network_h4").before($('<div class="dynamic-error">').html(errortext));
|
||||
}
|
||||
$(".networklist").sortable({
|
||||
connectWith: "ul.networklist",
|
||||
placeholder: "ui-state-highlight",
|
||||
distance: 5,
|
||||
start:function(e,info){
|
||||
$("#selected_network").addClass("dragging");
|
||||
},
|
||||
stop:function(e,info){
|
||||
$("#selected_network").removeClass("dragging");
|
||||
updateForm();
|
||||
}
|
||||
}).disableSelection();
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Triggers on click of link to add/remove member from the project.
|
||||
**/
|
||||
@ -395,6 +503,7 @@ horizon.projects = {
|
||||
* Calls set-up functions upon loading the workflow.
|
||||
**/
|
||||
workflow_init: function(modal) {
|
||||
horizon.projects.generate_networklist_html();
|
||||
if (!horizon.projects.workflow_loaded) {
|
||||
$(modal).find('form').each( function () {
|
||||
// call the initalization functions
|
||||
@ -438,6 +547,7 @@ horizon.projects = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
horizon.addInitFunction(function() {
|
||||
$('.btn').on('click', function (evt) {
|
||||
horizon.projects.workflow_loaded = false;
|
||||
|
@ -256,7 +256,7 @@ horizon.datatables.set_table_filter = function (parent) {
|
||||
$(parent).find('table').each(function (index, elm) {
|
||||
var input = $($(elm).find('div.table_search input')),
|
||||
table_selector;
|
||||
if (input) {
|
||||
if (input.length > 0) {
|
||||
// Disable server-side searcing if we have client-side searching since
|
||||
// (for now) the client-side is actually superior. Server-side filtering
|
||||
// remains as a noscript fallback.
|
||||
|
6
horizon/static/horizon/lib/jquery/jquery-ui-1.9.2.custom.min.js
vendored
Executable file
6
horizon/static/horizon/lib/jquery/jquery-ui-1.9.2.custom.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
@ -13,6 +13,7 @@
|
||||
<script src="{{ STATIC_URL }}horizon/lib/spin.jquery.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src='{{ STATIC_URL }}horizon/lib/json2.js' type='text/javascript' charset="utf-8"></script>
|
||||
<script src="{{ STATIC_URL }}horizon/lib/underscore/underscore-min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ STATIC_URL }}horizon/lib/jquery/jquery-ui-1.9.2.custom.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
<script src="{{ STATIC_URL }}bootstrap/js/bootstrap.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
{% load i18n horizon %}
|
||||
|
||||
<p>{% blocktrans %}Choose network from Available networks to Selected Networks by push button or drag and drop, you may change nic order by drag and drop as well. {% endblocktrans %}</p>
|
@ -0,0 +1,35 @@
|
||||
{% load i18n %}
|
||||
|
||||
<noscript><h3>{{ step }}</h3></noscript>
|
||||
<table class="table-fixed" id="networkListSortContainer">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="actions">
|
||||
<h4 id="selected_network_h4">{% trans "Selected Networks" %}</h4>
|
||||
<ul id="selected_network" class="networklist">
|
||||
</ul>
|
||||
<h4>{% trans "Available networks" %}</h4>
|
||||
<ul id="available_network" class="networklist">
|
||||
</ul>
|
||||
</td>
|
||||
<td class="help_text">
|
||||
{% include "project/instances/_launch_network_help.html" %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="table-fixed" id="networkListIdContainer">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="actions">
|
||||
<div id="networkListId">
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</div>
|
||||
</td>
|
||||
<td class="help_text">
|
||||
{{ step.get_help_text }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@ -415,6 +415,10 @@ class SetNetworkAction(workflows.Action):
|
||||
network = forms.MultipleChoiceField(label=_("Networks"),
|
||||
required=True,
|
||||
widget=forms.CheckboxSelectMultiple(),
|
||||
error_messages={
|
||||
'required': _(
|
||||
"At least one network must"
|
||||
" be specified.")},
|
||||
help_text=_("Launch instance with"
|
||||
"these networks"))
|
||||
|
||||
@ -439,6 +443,7 @@ class SetNetworkAction(workflows.Action):
|
||||
|
||||
class SetNetwork(workflows.Step):
|
||||
action_class = SetNetworkAction
|
||||
template_name = "project/instances/_update_networks.html"
|
||||
contributes = ("network_id",)
|
||||
|
||||
def contribute(self, data, context):
|
||||
|
BIN
openstack_dashboard/static/dashboard/img/drag.png
Normal file
BIN
openstack_dashboard/static/dashboard/img/drag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1023 B |
@ -1175,12 +1175,16 @@ div .flavor_table {
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
.error .help-inline {
|
||||
.error .help-inline, .dynamic-error {
|
||||
background: #efdfdf;
|
||||
border: 1px solid #ead5d8;
|
||||
padding: 10px;
|
||||
display: block;
|
||||
}
|
||||
.dynamic-error {
|
||||
color: #b94a48;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
label.log-length {
|
||||
line-height: 28px;
|
||||
@ -1568,3 +1572,120 @@ label.log-length {
|
||||
width: 275px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
/* Styling for draged network object */
|
||||
#networkListSortContainer {
|
||||
display: none;
|
||||
}
|
||||
.networklist {
|
||||
padding: 6px;
|
||||
background: #eee;
|
||||
border: 1px solid #ccc;
|
||||
min-height: 2em;
|
||||
width: auto !important;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
li {
|
||||
width: 226px;
|
||||
list-style-type: none;
|
||||
margin: 6px auto;
|
||||
padding: 3px;
|
||||
background: #fff;
|
||||
border: 1px solid #aaa;
|
||||
line-height: 18px;
|
||||
border-radius: 3px;
|
||||
cursor: move;
|
||||
padding-left: 23px;
|
||||
background: white url(/static/dashboard/img/drag.png) no-repeat 11px 50%;
|
||||
em {
|
||||
font-size: 0.5em;
|
||||
line-height: 1em;
|
||||
color:#999;
|
||||
font-style: normal;
|
||||
margin-left: 0.8em;
|
||||
}
|
||||
i {
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
a.btn {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
line-height: 12px;
|
||||
padding: 2px 5px 3px;
|
||||
margin-right: 1px;
|
||||
width: 18px;
|
||||
text-align: center;
|
||||
//position: absolute;
|
||||
right:5px;
|
||||
vertical-align: middle;
|
||||
float: right;
|
||||
&:before {
|
||||
content: "+";
|
||||
}
|
||||
}
|
||||
}
|
||||
li.ui-sortable-helper {
|
||||
background-color: #def;
|
||||
}
|
||||
li.ui-state-highlight {
|
||||
border: 1px dotted #ccc;
|
||||
background: #efefef;
|
||||
height: 0.5em;
|
||||
}
|
||||
li:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
#selected_network {
|
||||
margin-bottom: 1.5em;
|
||||
counter-reset:v1 0;
|
||||
background: #edf9ff;
|
||||
border:1px solid #c0d9e4;
|
||||
li {
|
||||
position: relative;
|
||||
a.btn {
|
||||
&:before {
|
||||
content: "-";
|
||||
}
|
||||
}
|
||||
}
|
||||
li:before {
|
||||
content:"nic:"counter(v1);
|
||||
counter-increment:v1;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
background: #666;
|
||||
color:#fff;
|
||||
font-size: 90%;
|
||||
padding: 0px 4px;
|
||||
vertical-align: middle;
|
||||
border-radius: 2px;
|
||||
position: absolute;
|
||||
left: -2em;
|
||||
}
|
||||
&.dragging {
|
||||
li:before {
|
||||
content:"nic:";
|
||||
background-color:rgba(102,102,102,0.5);
|
||||
padding-right: 10px;
|
||||
}
|
||||
li.ui-state-highlight:before {
|
||||
content:"";
|
||||
background:transparent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user