Commit 53386bcc by Bach Dániel

Merge branch 'box-search'

Conflicts:
	circle/dashboard/static/dashboard/dashboard.js
	circle/dashboard/templates/dashboard/index-nodes.html
parents 5034085b 05eac66d
......@@ -159,8 +159,8 @@ $(function () {
{ 'url': '/dashboard/vm/delete/' + vm_pk + '/',
'data': [],
'pk': vm_pk,
'type': "vm",
'redirect': dir});
'type': "vm",
'redirect': dir});
return false;
});
......@@ -171,7 +171,7 @@ $(function () {
{ 'url': '/dashboard/disk/' + disk_pk + '/remove/',
'data': [],
'pk': disk_pk,
'type': "disk",
'type': "disk",
});
return false;
});
......@@ -184,7 +184,7 @@ $(function () {
{ 'url': '/dashboard/node/delete/' + node_pk + '/',
'data': [],
'pk': node_pk,
'type': "node",
'type': "node",
'redirect': dir});
return false;
......@@ -212,7 +212,7 @@ $(function () {
addModalConfirmation(deleteObject,
{ 'url': '/dashboard/group/delete/' + group_pk + '/',
'data': [],
'type': "group",
'type': "group",
'pk': group_pk,
'redirect': dir});
......@@ -269,6 +269,62 @@ $(function () {
}
});
/* search for nodes */
var my_nodes = []
$("#dashboard-node-search-input").keyup(function(e) {
// if my_nodes is empty get a list of our nodes
if(my_nodes.length < 1) {
$.ajaxSetup( { "async": false } );
$.get("/dashboard/node/list/", function(result) {
for(var i in result) {
my_nodes.push({
'name': result[i].name.toLowerCase(),
'icon': result[i].icon,
'status': result[i].status,
'label': result[i].label,
'url': result[i].url,
});
}
});
$.ajaxSetup( { "async": true } );
}
input = $("#dashboard-node-search-input").val().toLowerCase();
var search_result = []
var html = '';
for(var i in my_nodes) {
if(my_nodes[i].name.indexOf(input) != -1) {
search_result.push(my_nodes[i]);
}
}
for(var i=0; i<5 && i<search_result.length; i++)
html += generateNodeHTML(search_result[i].name,
search_result[i].icon, search_result[i].status,
search_result[i].url,
(search_result.length < 5));
if(search_result.length == 0)
html += '<div class="list-group-item list-group-item-last">' + gettext("No result") + '</div>';
$("#dashboard-node-list").html(html);
html = '';
for(var i=0; i<5 && i<search_result.length; i++)
html += generateNodeTagHTML(search_result[i].name,
search_result[i].icon, search_result[i].status,
search_result[i].label, search_result[i].url);
if(search_result.length == 0)
html += '<div class="list-group-item list-group-item-last">' + gettext("No result") + '</div>';
$("#dashboard-node-taglist").html(html);
// if there is only one result and ENTER is pressed redirect
if(e.keyCode == 13 && search_result.length == 1) {
window.location.href = search_result[0].url;
}
if(e.keyCode == 13 && search_result.length > 1 && input.length > 0) {
window.location.href = "/dashboard/node/list/?s=" + input;
}
});
/* search for groups */
var my_groups = []
$("#dashboard-group-search-input").keyup(function(e) {
......@@ -342,6 +398,21 @@ function generateGroupHTML(url, name) {
'</a>';
}
function generateNodeHTML(name, icon, _status, url, is_last) {
return '<a href="' + url + '" class="list-group-item real-link' + (is_last ? ' list-group-item-last' : '') + '">' +
'<span class="index-node-list-name">' +
'<i class="' + icon + '" title="' + _status + '"></i> ' + name +
'</span>' +
'<div style="clear: both;"></div>' +
'</a>';
}
function generateNodeTagHTML(name, icon, _status, label , url) {
return '<a href="' + url + '" class="label ' + label + '" >' +
'<i class="' + icon + '" title="' + _status + '"></i> ' + name +
'</a> ';
}
/* copare vm-s by fav, pk order */
function compareVmByFav(a, b) {
if(a.fav && b.fav) {
......
......@@ -16,26 +16,33 @@
<div class="list-group" id="node-list-view">
<div id="dashboard-node-list">
{% for i in nodes %}
<a href="{% url "dashboard.views.node-detail" pk=i.pk %}" class="list-group-item
<a href="{{ i.get_absolute_url }}" class="list-group-item real-link
{% if forloop.last and nodes|length < 5 %} list-group-item-last{% endif %}">
<i class="icon-{% if i.enabled == True %}play-sign{% else %}pause{% endif %}"></i> {{ i.name }}
</a>
<span class="index-node-list-name">
<i class="{{ i.get_status_icon }}" title="{{ i.get_status_display }}"></i>
{{ i.name }}
</span>
<div style="clear: both;"></div>
</a>
{% endfor %}
</div>
<div href="#" class="list-group-item list-group-footer">
<div class="row">
<div class="col-sm-6 col-xs-6 input-group input-group-sm">
<input type="text" class="form-control" placeholder="{% trans "Search..." %}" />
<input id="dashboard-node-search-input" type="text" class="form-control" placeholder="{% trans "Search..." %}" />
<div class="input-group-btn">
<button type="submit" class="form-control btn btn-primary" title="search"><i class="icon-search"></i></button>
</div>
</div>
<div class="col-sm-6 text-right">
{% if more_nodes > 0 %}
<a class="btn btn-primary btn-xs" href="{% url "dashboard.views.node-list" %}">
<i class="icon-chevron-sign-right"></i> <strong>{{ more_nodes }}</strong> more
<i class="icon-chevron-sign-right"></i>
{% if more_nodes > 0 %}
{% blocktrans with count=more_nodes %}<strong>{{count}}</strong> more{% endblocktrans %}
{% else %}
{% trans "list" %}
{% endif %}
</a>
{% endif %}
<a class="btn btn-success btn-xs node-create" href="{% url "dashboard.views.node-create" %}"><i class="icon-plus-sign"></i> {% trans "new" %}</a>
</div>
</div>
......@@ -43,35 +50,26 @@
</div>
<div class="panel-body" id="node-graph-view" style="display: none">
<p class="pull-right"> <input class="knob" data-fgColor="chartreuse" data-thickness=".4" data-width="60" data-height="60" data-readOnly="true" value="{% widthratio node_num.running sum_node_num 100 %}"></p>
<p class="pull-right"> <input class="knob" data-fgColor="chartreuse" data-thickness=".4" data-width="60" data-height="60" data-readOnly="true" value="{% widthratio node_num.running sum_node_num 100 %}"></p>
<p><span class="big"><big>{{ node_num.running }}</big> running </span>
+ <big>{{ node_num.missing }}</big> missing + <br><big>{{ node_num.disabled }}</big> disabled + <big>{{ node_num.offline }}</big> offline</p>
<ul class="list-inline">
{% for i in nodes %}
<a class="label {% if i.state == 'ONLINE' %}label-success
{% elif i.state == 'MISSING' %}label-danger
{% elif i.state == 'DISABLED' %}label-warning
{% elif i.state == 'OFFLINE' %}label-warning
{% endif %}" href="{% url "dashboard.views.node-detail" pk=i.pk %}"><i class="icon-{% if i.enabled == True %}play-sign{% else %}pause{% endif %}"></i> {{ i.name}}</a>
{% endfor %}
</ul>
<ul class="list-inline" id="dashboard-node-taglist">
{% for i in nodes %}
<a href="{{ i.get_absolute_url }}" class="label {{i.get_status_label}}" >
<i class="{{ i.get_status_icon }}" title="{{ i.get_status_display }}"></i> {{ i.name }}</a>
{% endfor %}
</ul>
<div class="clearfix"></div>
<div class="row">
<div class="col-sm-6 col-xs-6 input-group input-group-sm">
<input type="text" class="form-control" placeholder="{% trans "Search..." %}" />
<div class="input-group-btn">
<button type="submit" class="form-control btn btn-primary" title="search"><i class="icon-search"></i></button>
</div>
</div>
<div class="col-sm-6 text-right">
{% if more_nodes >= 0 %}
<div class="col-sm-6 text-right pull-right">
{% if more_nodes >= 0 %}
<a class="btn btn-primary btn-xs" href="{% url "dashboard.views.node-list" %}">
<i class="icon-chevron-sign-right"></i> {% blocktrans with count=more_nodes %}<strong>{{count}}</strong> more{% endblocktrans %}
</a>
{% endif %}
<a class="btn btn-success btn-xs node-create" href="{% url "dashboard.views.node-create" %}"><i class="icon-plus-sign"></i> {% trans "new" %}</a>
</div>
</div>
</div>
</div>
</div>
......@@ -1144,6 +1144,23 @@ class NodeList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
table_class = NodeListTable
table_pagination = False
def get(self, *args, **kwargs):
if self.request.is_ajax():
nodes = Node.objects.all()
nodes = [{
'name': i.name,
'icon': i.get_status_icon(),
'url': i.get_absolute_url(),
'label': i.get_status_label(),
'status': i.state.lower()} for i in nodes]
return HttpResponse(
json.dumps(list(nodes)),
content_type="application/json",
)
else:
return super(NodeList, self).get(*args, **kwargs)
def get_queryset(self):
return Node.objects.annotate(
number_of_VMs=Count('instance_set')).select_related('host')
......
......@@ -285,6 +285,22 @@ class Node(OperatedMixin, TimeStampedModel):
def byte_ram_usage(self):
return self.ram_usage * self.ram_size
def get_status_icon(self):
return {
'OFFLINE': 'icon-minus-sign',
'DISABLED': 'icon-moon',
'MISSING': 'icon-warning-sign',
'ONLINE': 'icon-play-sign'}.get(self.get_state(),
'icon-question-sign')
def get_status_label(self):
return {
'OFFLINE': 'label-warning',
'DISABLED': 'label-warning',
'MISSING': 'label-danger',
'ONLINE': 'label-success'}.get(self.get_state(),
'label-danger')
@node_available
def update_vm_states(self):
"""Update state of Instances running on this Node.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment