Commit ad1519f3 by Bach Dániel

Merge branch 'feature-indexview-fixes' into 'master'

Few fixes in index view

- fix vm list height
- permanent vm list button
- mark %d more buttons for translation (fixes #133)
parents e1827d58 c2b0ca67
...@@ -217,7 +217,7 @@ class AclBase(Model): ...@@ -217,7 +217,7 @@ class AclBase(Model):
clsfilter = Q(object_level_set__in=ols.all()) clsfilter = Q(object_level_set__in=ols.all())
if owner_also: if owner_also:
clsfilter |= Q(owner=user) clsfilter |= Q(owner=user)
return cls.objects.filter(clsfilter) return cls.objects.filter(clsfilter).distinct()
@classmethod @classmethod
def get_objects_with_group_level(cls, level, group): def get_objects_with_group_level(cls, level, group):
......
...@@ -608,6 +608,11 @@ footer a, footer a:hover, footer a:visited { ...@@ -608,6 +608,11 @@ footer a, footer a:hover, footer a:visited {
margin: 0; margin: 0;
} }
#dashboard-vm-list, #dashboard-node-list, #dashboard-group-list,
#dashboard-template-list {
min-height: 204px;
}
#group-detail-user-table td:first-child, #group-detail-user-table th:last-child, #group-detail-user-table td:first-child, #group-detail-user-table th:last-child,
#group-detail-user-table td:last-child, #group-detail-user-table td:last-child,
#group-detail-perm-table td:first-child, #group-detail-perm-table th:last-child, #group-detail-perm-table td:first-child, #group-detail-perm-table th:last-child,
...@@ -630,3 +635,22 @@ textarea[name="list-new-namelist"] { ...@@ -630,3 +635,22 @@ textarea[name="list-new-namelist"] {
.table thead>tr>th { .table thead>tr>th {
border-bottom: 1px; border-bottom: 1px;
} }
.badge-pulse {
-webkit-animation-name: 'pulse_animation';
-webkit-animation-duration: 1000ms;
-webkit-transform-origin: 70% 70%;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
@-webkit-keyframes pulse_animation {
0% { -webkit-transform: scale(1); }
30% { -webkit-transform: scale(1); }
40% { -webkit-transform: scale(1.18); }
50% { -webkit-transform: scale(1); }
60% { -webkit-transform: scale(1); }
70% { -webkit-transform: scale(1.08); }
80% { -webkit-transform: scale(1); }
100% { -webkit-transform: scale(1); }
}
...@@ -253,9 +253,10 @@ $(function () { ...@@ -253,9 +253,10 @@ $(function () {
for(var i=0; i<5 && i<search_result.length; i++) for(var i=0; i<5 && i<search_result.length; i++)
html += generateVmHTML(search_result[i].pk, search_result[i].name, html += generateVmHTML(search_result[i].pk, search_result[i].name,
search_result[i].host, search_result[i].icon, search_result[i].host, search_result[i].icon,
search_result[i].status, search_result[i].fav); search_result[i].status, search_result[i].fav,
(search_result.length < 5));
if(search_result.length == 0) if(search_result.length == 0)
html += '<div class="list-group-item">No result</div>'; html += '<div class="list-group-item list-group-item-last">' + gettext("No result") + '</div>';
$("#dashboard-vm-list").html(html); $("#dashboard-vm-list").html(html);
$('.title-favourite').tooltip({'placement': 'right'}); $('.title-favourite').tooltip({'placement': 'right'});
...@@ -268,6 +269,46 @@ $(function () { ...@@ -268,6 +269,46 @@ $(function () {
} }
}); });
/* search for groups */
var my_groups = []
$("#dashboard-group-search-input").keyup(function(e) {
// if my_groups is empty get a list of our groups
if(my_groups.length < 1) {
$.ajaxSetup( { "async": false } );
$.get("/dashboard/group/list/", function(result) {
for(var i in result) {
my_groups.push({
'url': result[i].url,
'name': result[i].name.toLowerCase(),
});
}
});
$.ajaxSetup( { "async": true } );
}
input = $("#dashboard-group-search-input").val().toLowerCase();
var search_result = []
var html = '';
for(var i in my_groups) {
if(my_groups[i].name.indexOf(input) != -1) {
search_result.push(my_groups[i]);
}
}
for(var i=0; i<5 && i<search_result.length; i++)
html += generateGroupHTML(search_result[i].url, search_result[i].name);
if(search_result.length == 0)
html += '<div class="list-group-item">No result</div>';
$("#dashboard-group-list").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/group/list/?s=" + input;
}
});
/* notification message toggle */ /* notification message toggle */
$(document).on('click', ".notification-message-subject", function() { $(document).on('click', ".notification-message-subject", function() {
$(".notification-message-text", $(this).parent()).slideToggle(); $(".notification-message-text", $(this).parent()).slideToggle();
...@@ -275,12 +316,14 @@ $(function () { ...@@ -275,12 +316,14 @@ $(function () {
}); });
$("#notification-button a").click(function() { $("#notification-button a").click(function() {
$('.notification-messages').load("/dashboard/notifications/"); $('.notification-messages').load("/dashboard/notifications/");
$('#notification-button a span[class*="badge-pulse"]').remove();
}); });
}); });
function generateVmHTML(pk, name, host, icon, _status, fav) { function generateVmHTML(pk, name, host, icon, _status, fav, is_last) {
return '<a href="/dashboard/vm/' + pk + '/" class="list-group-item">' + return '<a href="/dashboard/vm/' + pk + '/" class="list-group-item' +
(is_last ? ' list-group-item-last' : '') + '">' +
'<span class="index-vm-list-name">' + '<span class="index-vm-list-name">' +
'<i class="' + icon + '" title="' + _status + '"></i> ' + name + '<i class="' + icon + '" title="' + _status + '"></i> ' + name +
'</span>' + '</span>' +
...@@ -293,6 +336,12 @@ function generateVmHTML(pk, name, host, icon, _status, fav) { ...@@ -293,6 +336,12 @@ function generateVmHTML(pk, name, host, icon, _status, fav) {
'</a>'; '</a>';
} }
function generateGroupHTML(url, name) {
return '<a href="' + url + '" class="list-group-item real-link">'+
'<i class="icon-group"></i> '+ name +
'</a>';
}
/* copare vm-s by fav, pk order */ /* copare vm-s by fav, pk order */
function compareVmByFav(a, b) { function compareVmByFav(a, b) {
if(a.fav && b.fav) { if(a.fav && b.fav) {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<link rel="icon" type="image/png" href="{{ STATIC_URL}}dashboard/img/favicon.png"/>
<title>{% block title %}{% block title-page %}{% endblock %} | {% block title-site %}CIRCLE{% endblock %}{% endblock %}</title> <title>{% block title %}{% block title-page %}{% endblock %} | {% block title-site %}CIRCLE{% endblock %}{% endblock %}</title>
...@@ -39,7 +40,7 @@ ...@@ -39,7 +40,7 @@
<ul class="nav navbar-nav pull-right"> <ul class="nav navbar-nav pull-right">
<li class="dropdown" id="notification-button"> <li class="dropdown" id="notification-button">
<a href="{% url "dashboard.views.notifications" %}" style="color: white; font-size: 12px;" class="dropdown-toggle" data-toggle="dropdown"> <a href="{% url "dashboard.views.notifications" %}" style="color: white; font-size: 12px;" class="dropdown-toggle" data-toggle="dropdown">
{% trans "Notifications" %}{% if NEW_NOTIFICATIONS_COUNT > 0 %} <span class="badge">{{ NEW_NOTIFICATIONS_COUNT }}</span>{% endif %} {% trans "Notifications" %}{% if NEW_NOTIFICATIONS_COUNT > 0 %} <span class="badge badge-pulse">{{ NEW_NOTIFICATIONS_COUNT }}</span>{% endif %}
</a> </a>
<ul class="dropdown-menu notification-messages"> <ul class="dropdown-menu notification-messages">
<li>{% trans "Loading..." %}</li> <li>{% trans "Loading..." %}</li>
......
...@@ -2,31 +2,41 @@ ...@@ -2,31 +2,41 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<div class="pull-right toolbar"> <div class="pull-right toolbar">
<span class="btn btn-default btn-xs infobtn" title="{% trans "Help" %}"><i class="icon-info-sign"></i></span> <span class="btn btn-default btn-xs infobtn" title="{% trans "List of groups that you have access to." %}"><i class="icon-info-sign"></i></span>
</div> </div>
<h3 class="no-margin"><i class="icon-group"></i> {% trans "Groups" %}</h3> <h3 class="no-margin"><i class="icon-group"></i> {% trans "Groups" %}</h3>
</div> </div>
<div class="list-group" id="vm-list-view"> <div class="list-group" id="vm-list-view">
{% for i in groups %} <div id="dashboard-group-list">
<a href="{% url "dashboard.views.group-detail" pk=i.pk %}" class="list-group-item real-link"> {% for i in groups %}
<a href="{% url "dashboard.views.group-detail" pk=i.pk %}" class="list-group-item real-link
{% if forloop.last and groups|length < 5 %} list-group-item-last{% endif %}">
<i class="icon-group"></i> {{ i.name }} <i class="icon-group"></i> {{ i.name }}
</a> </a>
{% endfor %} {% endfor %}
</div>
<div href="#" class="list-group-item list-group-footer text-right"> <div href="#" class="list-group-item list-group-footer text-right">
<div class="row"> <div class="row">
<div class="col-sm-6 col-xs-6 input-group input-group-sm"> <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-group-search-input" type="text" class="form-control" placeholder="{% trans "Search..." %}" />
<div class="input-group-btn"> <div class="input-group-btn">
<button type="submit" class="form-control btn btn-primary" title="search"><i class="icon-search"></i></button> <button type="submit" class="form-control btn btn-primary"><i class="icon-search"></i></button>
</div> </div>
</div> </div>
<div class="col-sm-6 text-right"> <div class="col-sm-6 text-right">
{% if more_groups >= 0 %}
<a class="btn btn-primary btn-xs" href="{% url "dashboard.views.group-list" %}"> <a class="btn btn-primary btn-xs" href="{% url "dashboard.views.group-list" %}">
<i class="icon-chevron-sign-right"></i> <strong>{{ more_groups }}</strong> more <i class="icon-chevron-sign-right"></i>
{% if more_groups > 0 %}
{% blocktrans count more=more_groups %}
<strong>{{ more }}</strong> more
{% plural %}
<strong>{{ more }}</strong> more
{% endblocktrans %}
{% else %}
{% trans "list" %}
{% endif %}
</a> </a>
{% endif %} <a class="btn btn-success btn-xs group-create" href="{% url "dashboard.views.group-create" %}"><i class="icon-plus-sign"></i> {% trans "new" %} </a>
<a class="btn btn-success btn-xs group-create" href="{% url "dashboard.views.group-create" %}"><i class="icon-upload-alt"></i> {% trans "new" %} </a>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -14,11 +14,14 @@ ...@@ -14,11 +14,14 @@
</h3> </h3>
</div > </div >
<div class="list-group" id="node-list-view"> <div class="list-group" id="node-list-view">
{% for i in nodes %} <div id="dashboard-node-list">
<a href="{% url "dashboard.views.node-detail" pk=i.pk %}" class="list-group-item"> {% for i in nodes %}
<i class="icon-{% if i.enabled == True %}play-sign{% else %}pause{% endif %}"></i> {{ i.name }} <a href="{% url "dashboard.views.node-detail" pk=i.pk %}" class="list-group-item
</a> {% if forloop.last and nodes|length < 5 %} list-group-item-last{% endif %}">
{% endfor %} <i class="icon-{% if i.enabled == True %}play-sign{% else %}pause{% endif %}"></i> {{ i.name }}
</a>
{% endfor %}
</div>
<div href="#" class="list-group-item list-group-footer"> <div href="#" class="list-group-item list-group-footer">
<div class="row"> <div class="row">
<div class="col-sm-6 col-xs-6 input-group input-group-sm"> <div class="col-sm-6 col-xs-6 input-group input-group-sm">
......
{% load i18n %} {% load i18n %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<span class="btn btn-default btn-xs infobtn pull-right" title="{% trans "Help" %}"> <span class="btn btn-default btn-xs infobtn pull-right" title="{% trans "List of VM templates that are available for you. You can create new ones from scratch or customize existing ones (preferred)." %}">
<i class="icon-info-sign"></i> <i class="icon-info-sign"></i>
</span> </span>
<h3 class="no-margin"><i class="icon-puzzle-piece"></i> {% trans "Templates" %} <h3 class="no-margin"><i class="icon-puzzle-piece"></i> {% trans "Templates" %}
</h3> </h3>
</div> </div>
<div class="list-group" id="dashboard-template-list"> <div class="list-group" id="dashboard-template-list">
{% for t in templates %} <div id="dashboard-template-list">
<a href="{% url "dashboard.views.template-detail" pk=t.pk %}" class="list-group-item"> {% for t in templates %}
<span class="index-template-list-name"> <a href="{% url "dashboard.views.template-detail" pk=t.pk %}" class="list-group-item
<i class="icon-{{ t.os_type }}"></i> {{ t.name }} {% if forloop.last and nodes|length < 5 %} list-group-item-last{% endif %}">
</span> <span class="index-template-list-name">
<small class="text-muted index-template-list-system">{{ t.system }}</small> <i class="icon-{{ t.os_type }}"></i> {{ t.name }}
<div class="pull-right vm-create" data-template="{{ t.pk }}"><i title="{% trans "Start vm instance" %}" class="icon-play"></i></div> </span>
<div class="clearfix"></div> <small class="text-muted index-template-list-system">{{ t.system }}</small>
</a> <div class="pull-right vm-create" data-template="{{ t.pk }}"><i title="{% trans "Start vm instance" %}" class="icon-play"></i></div>
{% empty %} <div class="clearfix"></div>
<div class="alert alert-warning" style="margin: 10px;"> </a>
<p> {% empty %}
{% trans "You don't have any templates, however you can still start virtual machines and even save them as new templates!" %} <div class="alert alert-warning" style="margin: 10px;">
</p> <p>
</div> {% trans "You don't have any templates, however you can still start virtual machines and even save them as new templates!" %}
{% endfor %} </p>
</div>
{% endfor %}
</div>
<div href="#" class="list-group-item list-group-footer text-right"> <div href="#" class="list-group-item list-group-footer text-right">
<p> <p>
<a href="{% url "dashboard.views.template-list" %}" class="btn btn-primary btn-xs"> <a href="{% url "dashboard.views.template-list" %}" class="btn btn-primary btn-xs">
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<a href="#index-graph-view" data-index-box="vm" class="btn btn-default btn-xs"><i class="icon-dashboard"></i></a> <a href="#index-graph-view" data-index-box="vm" class="btn btn-default btn-xs"><i class="icon-dashboard"></i></a>
<a href="#index-list-view" data-index-box="vm" class="btn btn-default btn-xs disabled"><i class="icon-list"></i></a> <a href="#index-list-view" data-index-box="vm" class="btn btn-default btn-xs disabled"><i class="icon-list"></i></a>
</div> </div>
<span class="btn btn-default btn-xs infobtn" title="{% trans "Help" %}"><i class="icon-info-sign"></i></span> <span class="btn btn-default btn-xs infobtn" title="{% trans "List of your current virtual machines. Favourited ones are ahead of others." %}"><i class="icon-info-sign"></i></span>
</div> </div>
<h3 class="no-margin"> <h3 class="no-margin">
<i class="icon-desktop"></i> {% trans "Virtual machines" %} <i class="icon-desktop"></i> {% trans "Virtual machines" %}
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
<div class="list-group" id="vm-list-view"> <div class="list-group" id="vm-list-view">
<div id="dashboard-vm-list"> <div id="dashboard-vm-list">
{% for i in instances %} {% for i in instances %}
<a href="{{ i.get_absolute_url }}" class="list-group-item"> <a href="{{ i.get_absolute_url }}" class="list-group-item
{% if forloop.last and instances|length < 5 %} list-group-item-last{% endif %}">
<span class="index-vm-list-name"> <span class="index-vm-list-name">
<i class="{{ i.get_status_icon }}" title="{{ i.get_status_display }}"></i> <i class="{{ i.get_status_icon }}" title="{{ i.get_status_display }}"></i>
{{ i.name }} {{ i.name }}
...@@ -30,29 +31,47 @@ ...@@ -30,29 +31,47 @@
</div> </div>
<div style="clear: both;"></div> <div style="clear: both;"></div>
</a> </a>
{% empty %}
<div class="list-group-item list-group-item-last">
{% trans "You have no virtual machines." %}
</div>
{% endfor %} {% endfor %}
</div> </div>
<style>
.list-group-item-last {
border-bottom: 1px solid #ddd !important;
}
</style>
<div href="#" class="list-group-item list-group-footer"> <div href="#" class="list-group-item list-group-footer">
<div class="row"> <div class="row">
<div class="col-sm-6 col-xs-6 input-group input-group-sm"> <div class="col-sm-6 col-xs-6 input-group input-group-sm">
<input id="dashboard-vm-search-input" type="text" class="form-control" placeholder="{% trans "Search..." %}" /> <input id="dashboard-vm-search-input" type="text" class="form-control" placeholder="{% trans "Search..." %}" />
<div class="input-group-btn"> <div class="input-group-btn">
<button type="submit" class="form-control btn btn-primary" title="search"><i class="icon-search"></i></button> <button type="submit" class="form-control btn btn-primary"><i class="icon-search"></i></button>
</div> </div>
</div> </div>
<div class="col-sm-6 text-right"> <div class="col-sm-6 text-right">
{% if more_instances > 0 %}
<a class="btn btn-primary btn-xs" href="{% url "dashboard.views.vm-list" %}"> <a class="btn btn-primary btn-xs" href="{% url "dashboard.views.vm-list" %}">
<i class="icon-chevron-sign-right"></i> {% blocktrans with count=more_instances %}<strong>{{ count }}</strong> more{% endblocktrans %} <i class="icon-chevron-sign-right"></i>
{% if more_instances > 0 %}
{% blocktrans count counter=more_instances %}
<strong>{{ counter }}</strong> more
{% plural %}
<strong>{{ counter }}</strong> more
{% endblocktrans %}
{% else %}
{% trans "list" %}
{% endif %}
</a> </a>
{% endif %}
<a class="btn btn-success btn-xs vm-create" href="{% url "dashboard.views.vm-create" %}"><i class="icon-plus-sign"></i> {% trans "new" %}</a> <a class="btn btn-success btn-xs vm-create" href="{% url "dashboard.views.vm-create" %}"><i class="icon-plus-sign"></i> {% trans "new" %}</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="panel-body" id="vm-graph-view" style="display: none"> <div class="panel-body" id="vm-graph-view" style="display: none">
<p class="pull-right"> <input class="knob" data-fgColor="chartreuse" data-thickness=".4" data-max="{{ request.user.profile.instance_limit }}" data-width="100" data-height="100" data-readOnly="true" value="{{ instances|length|add:more_instances }}"></p> <p class="pull-right">
<input class="knob" data-fgColor="chartreuse" data-thickness=".4" data-max="{{ request.user.profile.instance_limit }}" data-width="100" data-height="100" data-readOnly="true" value="{{ instances|length|add:more_instances }}">
</p>
<p><span class="bigbig">{% blocktrans with count=running_vm_num %}<big>{{ count }}</big> running{% endblocktrans %}</span> <p><span class="bigbig">{% blocktrans with count=running_vm_num %}<big>{{ count }}</big> running{% endblocktrans %}</span>
<ul class="list-inline" style="max-height: 95px; overflow: hidden;"> <ul class="list-inline" style="max-height: 95px; overflow: hidden;">
{% for vm in running_vms %} {% for vm in running_vms %}
...@@ -69,7 +88,11 @@ ...@@ -69,7 +88,11 @@
<div> <div>
<a style="float: right; margin-top: 17px;" href="{% url "dashboard.views.vm-list" %}" class="btn btn-primary btn-xs"> <a style="float: right; margin-top: 17px;" href="{% url "dashboard.views.vm-list" %}" class="btn btn-primary btn-xs">
<i class="icon-chevron-sign-right"></i> <i class="icon-chevron-sign-right"></i>
<strong>{{ instances|length|add:more_instances }}</strong> machines total {% blocktrans count counter=instances|length|add:more_instances %}
<strong>{{ counter }}</strong> machine total
{% plural %}
<strong>{{ counter }}</strong> machines total
{% endblocktrans %}
</a> </a>
<p class="big text-warning">{% blocktrans with count=stopped_vm_num %}<big>{{ count }}</big> stopped{% endblocktrans %}</p> <p class="big text-warning">{% blocktrans with count=stopped_vm_num %}<big>{{ count }}</big> stopped{% endblocktrans %}</p>
</div> </div>
......
...@@ -1476,6 +1476,49 @@ class GroupDetailTest(LoginMixin, TestCase): ...@@ -1476,6 +1476,49 @@ class GroupDetailTest(LoginMixin, TestCase):
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
class GroupListTest(LoginMixin, TestCase):
fixtures = ['test-vm-fixture.json', 'node.json']
def setUp(self):
self.u1 = User.objects.create(username='user1')
self.u1.set_password('password')
self.u1.save()
permlist = Permission.objects.all()
self.u1.user_permissions.add(
filter(lambda element: 'group' in element.name and
'add' in element.name, permlist)[0])
self.u2 = User.objects.create(username='user2')
self.u2.set_password('password')
self.u2.save()
self.g1 = Group.objects.create(name='group1')
self.g1.profile.set_user_level(self.u1, 'owner')
self.g1.save()
self.g2 = Group.objects.create(name='group2')
self.g2.profile.set_user_level(self.u1, 'owner')
self.g2.save()
self.g3 = Group.objects.create(name='group3')
self.g3.profile.set_user_level(self.u1, 'owner')
self.g3.save()
def test_anon_filter(self):
c = Client()
response = c.get('/dashboard/group/list/?s="3"')
self.assertEqual(response.status_code, 302)
def test_permitteduser_filter(self):
c = Client()
self.login(c, 'user1')
response = c.get('/dashboard/group/list/?s="3"')
self.assertEqual(response.status_code, 200)
def tearDown(self):
super(GroupListTest, self).tearDown()
self.u1.delete()
self.u2.delete()
self.g1.delete()
self.g2.delete()
class VmDetailVncTest(LoginMixin, TestCase): class VmDetailVncTest(LoginMixin, TestCase):
fixtures = ['test-vm-fixture.json', 'node.json'] fixtures = ['test-vm-fixture.json', 'node.json']
......
...@@ -41,6 +41,7 @@ from django.views.generic import (TemplateView, DetailView, View, DeleteView, ...@@ -41,6 +41,7 @@ from django.views.generic import (TemplateView, DetailView, View, DeleteView,
UpdateView, CreateView, ListView) UpdateView, CreateView, ListView)
from django.contrib import messages from django.contrib import messages
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils.translation import ungettext as __
from django.template.defaultfilters import title as title_filter from django.template.defaultfilters import title as title_filter
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.template import RequestContext from django.template import RequestContext
...@@ -273,9 +274,9 @@ class VmDetailView(CheckedDetailView): ...@@ -273,9 +274,9 @@ class VmDetailView(CheckedDetailView):
raise PermissionDenied() raise PermissionDenied()
self.object.change_password(user=request.user) self.object.change_password(user=request.user)
messages.success(request, _("Password changed!")) messages.success(request, _("Password changed."))
if request.is_ajax(): if request.is_ajax():
return HttpResponse("Success!") return HttpResponse("Success.")
else: else:
return redirect(reverse_lazy("dashboard.views.detail", return redirect(reverse_lazy("dashboard.views.detail",
kwargs={'pk': self.object.pk})) kwargs={'pk': self.object.pk}))
...@@ -295,7 +296,7 @@ class VmDetailView(CheckedDetailView): ...@@ -295,7 +296,7 @@ class VmDetailView(CheckedDetailView):
} }
Instance.objects.filter(pk=self.object.pk).update(**resources) Instance.objects.filter(pk=self.object.pk).update(**resources)
success_message = _("Resources successfully updated!") success_message = _("Resources successfully updated.")
if request.is_ajax(): if request.is_ajax():
response = {'message': success_message} response = {'message': success_message}
return HttpResponse( return HttpResponse(
...@@ -315,7 +316,7 @@ class VmDetailView(CheckedDetailView): ...@@ -315,7 +316,7 @@ class VmDetailView(CheckedDetailView):
Instance.objects.filter(pk=self.object.pk).update( Instance.objects.filter(pk=self.object.pk).update(
**{'name': new_name}) **{'name': new_name})
success_message = _("VM successfully renamed!") success_message = _("VM successfully renamed.")
if request.is_ajax(): if request.is_ajax():
response = { response = {
'message': success_message, 'message': success_message,
...@@ -339,7 +340,7 @@ class VmDetailView(CheckedDetailView): ...@@ -339,7 +340,7 @@ class VmDetailView(CheckedDetailView):
Instance.objects.filter(pk=self.object.pk).update( Instance.objects.filter(pk=self.object.pk).update(
**{'description': new_description}) **{'description': new_description})
success_message = _("VM description successfully updated!") success_message = _("VM description successfully updated.")
if request.is_ajax(): if request.is_ajax():
response = { response = {
'message': success_message, 'message': success_message,
...@@ -360,9 +361,9 @@ class VmDetailView(CheckedDetailView): ...@@ -360,9 +361,9 @@ class VmDetailView(CheckedDetailView):
raise PermissionDenied() raise PermissionDenied()
if len(new_tag) < 1: if len(new_tag) < 1:
message = u"Please input something!" message = u"Please input something."
elif len(new_tag) > 20: elif len(new_tag) > 20:
message = u"Tag name is too long!" message = u"Tag name is too long."
else: else:
self.object.tags.add(new_tag) self.object.tags.add(new_tag)
...@@ -416,7 +417,7 @@ class VmDetailView(CheckedDetailView): ...@@ -416,7 +417,7 @@ class VmDetailView(CheckedDetailView):
unicode(request.user), object) unicode(request.user), object)
raise PermissionDenied() raise PermissionDenied()
except ValueError: except ValueError:
error = _("There is a problem with your input!") error = _("There is a problem with your input.")
except Exception as e: except Exception as e:
error = _("Unknown error.") error = _("Unknown error.")
logger.error(e) logger.error(e)
...@@ -439,7 +440,7 @@ class VmDetailView(CheckedDetailView): ...@@ -439,7 +440,7 @@ class VmDetailView(CheckedDetailView):
raise PermissionDenied() raise PermissionDenied()
try: try:
self.object.add_interface(vlan=vlan, user=request.user) self.object.add_interface(vlan=vlan, user=request.user)
messages.success(request, _("Successfully added new interface!")) messages.success(request, _("Successfully added new interface."))
except Exception, e: except Exception, e:
error = u' '.join(e.messages) error = u' '.join(e.messages)
messages.error(request, error) messages.error(request, error)
...@@ -640,7 +641,7 @@ class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView): ...@@ -640,7 +641,7 @@ class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView):
Node.objects.filter(pk=self.object.pk).update( Node.objects.filter(pk=self.object.pk).update(
**{'name': new_name}) **{'name': new_name})
success_message = _("Node successfully renamed!") success_message = _("Node successfully renamed.")
if request.is_ajax(): if request.is_ajax():
response = { response = {
'message': success_message, 'message': success_message,
...@@ -733,7 +734,7 @@ class GroupDetailView(CheckedDetailView): ...@@ -733,7 +734,7 @@ class GroupDetailView(CheckedDetailView):
Group.objects.filter(pk=self.object.pk).update( Group.objects.filter(pk=self.object.pk).update(
**{'name': new_name}) **{'name': new_name})
success_message = _("Group successfully renamed!") success_message = _("Group successfully renamed.")
if request.is_ajax(): if request.is_ajax():
response = { response = {
'message': success_message, 'message': success_message,
...@@ -789,7 +790,7 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin): ...@@ -789,7 +790,7 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
logger.info("Tried to remove owner from %s by %s.", logger.info("Tried to remove owner from %s by %s.",
unicode(instance), unicode(request.user)) unicode(instance), unicode(request.user))
msg = _("The original owner cannot be removed, however " msg = _("The original owner cannot be removed, however "
"you can transfer ownership!") "you can transfer ownership.")
messages.warning(request, msg) messages.warning(request, msg)
continue continue
instance.set_level(entity, None) instance.set_level(entity, None)
...@@ -898,7 +899,7 @@ class TemplateChoose(TemplateView): ...@@ -898,7 +899,7 @@ class TemplateChoose(TemplateView):
if template == "base_vm": if template == "base_vm":
return redirect(reverse("dashboard.views.template-create")) return redirect(reverse("dashboard.views.template-create"))
elif template is None: elif template is None:
messages.warning(request, _("Select an option to proceed!")) messages.warning(request, _("Select an option to proceed."))
return redirect(reverse("dashboard.views.template-choose")) return redirect(reverse("dashboard.views.template-choose"))
else: else:
template = get_object_or_404(InstanceTemplate, pk=template) template = get_object_or_404(InstanceTemplate, pk=template)
...@@ -981,7 +982,7 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView): ...@@ -981,7 +982,7 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
model = InstanceTemplate model = InstanceTemplate
template_name = "dashboard/template-edit.html" template_name = "dashboard/template-edit.html"
form_class = TemplateForm form_class = TemplateForm
success_message = _("Successfully modified template!") success_message = _("Successfully modified template.")
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
template = self.get_object() template = self.get_object()
...@@ -1083,7 +1084,7 @@ class TemplateDelete(LoginRequiredMixin, DeleteView): ...@@ -1083,7 +1084,7 @@ class TemplateDelete(LoginRequiredMixin, DeleteView):
object.delete() object.delete()
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Template successfully deleted!") success_message = _("Template successfully deleted.")
if request.is_ajax(): if request.is_ajax():
return HttpResponse( return HttpResponse(
...@@ -1159,7 +1160,7 @@ class GroupList(LoginRequiredMixin, SingleTableView): ...@@ -1159,7 +1160,7 @@ class GroupList(LoginRequiredMixin, SingleTableView):
groups = [{ groups = [{
'url': reverse("dashboard.views.group-detail", 'url': reverse("dashboard.views.group-detail",
kwargs={'pk': i.pk}), kwargs={'pk': i.pk}),
'name': i.name} for i in self.queryset] 'name': i.name} for i in self.get_queryset()]
return HttpResponse( return HttpResponse(
json.dumps(list(groups)), json.dumps(list(groups)),
content_type="application/json", content_type="application/json",
...@@ -1219,7 +1220,7 @@ class GroupRemoveUserView(CheckedDetailView, DeleteView): ...@@ -1219,7 +1220,7 @@ class GroupRemoveUserView(CheckedDetailView, DeleteView):
container.user_set.remove(User.objects.get(pk=pk)) container.user_set.remove(User.objects.get(pk=pk))
def get_success_message(self): def get_success_message(self):
return _("Member successfully removed from group!") return _("Member successfully removed from group.")
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
object = self.get_object() object = self.get_object()
...@@ -1245,7 +1246,7 @@ class GroupRemoveAclUserView(GroupRemoveUserView): ...@@ -1245,7 +1246,7 @@ class GroupRemoveAclUserView(GroupRemoveUserView):
container.set_level(User.objects.get(pk=pk), None) container.set_level(User.objects.get(pk=pk), None)
def get_success_message(self): def get_success_message(self):
return _("Acl user successfully removed from group!") return _("Acl user successfully removed from group.")
class GroupRemoveAclGroupView(GroupRemoveUserView): class GroupRemoveAclGroupView(GroupRemoveUserView):
...@@ -1263,7 +1264,7 @@ class GroupRemoveAclGroupView(GroupRemoveUserView): ...@@ -1263,7 +1264,7 @@ class GroupRemoveAclGroupView(GroupRemoveUserView):
container.set_level(Group.objects.get(pk=pk), None) container.set_level(Group.objects.get(pk=pk), None)
def get_success_message(self): def get_success_message(self):
return _("Acl group successfully removed from group!") return _("Acl group successfully removed from group.")
class GroupDelete(CheckedDetailView, DeleteView): class GroupDelete(CheckedDetailView, DeleteView):
...@@ -1290,7 +1291,7 @@ class GroupDelete(CheckedDetailView, DeleteView): ...@@ -1290,7 +1291,7 @@ class GroupDelete(CheckedDetailView, DeleteView):
raise PermissionDenied() raise PermissionDenied()
object.delete() object.delete()
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Group successfully deleted!") success_message = _("Group successfully deleted.")
if request.is_ajax(): if request.is_ajax():
if request.POST.get('redirect').lower() == "true": if request.POST.get('redirect').lower() == "true":
...@@ -1410,11 +1411,13 @@ class VmCreate(LoginRequiredMixin, TemplateView): ...@@ -1410,11 +1411,13 @@ class VmCreate(LoginRequiredMixin, TemplateView):
i.deploy.async(user=request.user) i.deploy.async(user=request.user)
if len(instances) > 1: if len(instances) > 1:
messages.success(request, _("Successfully created %d VMs!" % messages.success(request, __(
len(instances))) "Successfully created %(count)d VM.", # this should not happen
"Successfully created %(count)d VMs.", len(instances)) % {
'count': len(instances)})
path = reverse("dashboard.index") path = reverse("dashboard.index")
else: else:
messages.success(request, _("VM successfully created!")) messages.success(request, _("VM successfully created."))
path = instances[0].get_absolute_url() path = instances[0].get_absolute_url()
if request.is_ajax(): if request.is_ajax():
...@@ -1504,7 +1507,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView): ...@@ -1504,7 +1507,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
savedform.save() savedform.save()
nodemodel = formset.save() nodemodel = formset.save()
messages.success(request, _('Node successfully created!')) messages.success(request, _('Node successfully created.'))
path = nodemodel[0].get_absolute_url() path = nodemodel[0].get_absolute_url()
if request.is_ajax(): if request.is_ajax():
return HttpResponse(json.dumps({'redirect': path}), return HttpResponse(json.dumps({'redirect': path}),
...@@ -1547,7 +1550,7 @@ class GroupCreate(LoginRequiredMixin, TemplateView): ...@@ -1547,7 +1550,7 @@ class GroupCreate(LoginRequiredMixin, TemplateView):
form.cleaned_data form.cleaned_data
savedform = form.save() savedform = form.save()
savedform.profile.set_level(request.user, 'owner') savedform.profile.set_level(request.user, 'owner')
messages.success(request, _('Group successfully created!')) messages.success(request, _('Group successfully created.'))
if request.is_ajax(): if request.is_ajax():
return HttpResponse(json.dumps({'redirect': return HttpResponse(json.dumps({'redirect':
savedform.profile.get_absolute_url()}), savedform.profile.get_absolute_url()}),
...@@ -1590,7 +1593,7 @@ class VmDelete(LoginRequiredMixin, DeleteView): ...@@ -1590,7 +1593,7 @@ class VmDelete(LoginRequiredMixin, DeleteView):
object.destroy.async(user=request.user) object.destroy.async(user=request.user)
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("VM successfully deleted!") success_message = _("VM successfully deleted.")
if request.is_ajax(): if request.is_ajax():
if request.POST.get('redirect').lower() == "true": if request.POST.get('redirect').lower() == "true":
...@@ -1629,7 +1632,7 @@ class NodeDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView): ...@@ -1629,7 +1632,7 @@ class NodeDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
object.delete() object.delete()
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Node successfully deleted!") success_message = _("Node successfully deleted.")
if request.is_ajax(): if request.is_ajax():
if request.POST.get('redirect').lower() == "true": if request.POST.get('redirect').lower() == "true":
...@@ -1721,7 +1724,7 @@ class NodeStatus(LoginRequiredMixin, SuperuserRequiredMixin, DetailView): ...@@ -1721,7 +1724,7 @@ class NodeStatus(LoginRequiredMixin, SuperuserRequiredMixin, DetailView):
self.object.enable(user=request.user) self.object.enable(user=request.user)
else: else:
self.object.disable(user=request.user) self.object.disable(user=request.user)
success_message = _("Node successfully changed status!") success_message = _("Node successfully changed status.")
if request.is_ajax(): if request.is_ajax():
response = { response = {
...@@ -1768,7 +1771,7 @@ class NodeFlushView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView): ...@@ -1768,7 +1771,7 @@ class NodeFlushView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView):
def __flush(self, request): def __flush(self, request):
self.object = self.get_object() self.object = self.get_object()
self.object.flush.async(user=request.user) self.object.flush.async(user=request.user)
success_message = _("Node successfully flushed!") success_message = _("Node successfully flushed.")
messages.success(request, success_message) messages.success(request, success_message)
return redirect(self.get_success_url()) return redirect(self.get_success_url())
...@@ -1803,7 +1806,7 @@ class PortDelete(LoginRequiredMixin, DeleteView): ...@@ -1803,7 +1806,7 @@ class PortDelete(LoginRequiredMixin, DeleteView):
super(PortDelete, self).delete(request, *args, **kwargs) super(PortDelete, self).delete(request, *args, **kwargs)
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Port successfully removed!") success_message = _("Port successfully removed.")
if request.is_ajax(): if request.is_ajax():
return HttpResponse( return HttpResponse(
...@@ -1844,8 +1847,10 @@ class VmMassDelete(LoginRequiredMixin, View): ...@@ -1844,8 +1847,10 @@ class VmMassDelete(LoginRequiredMixin, View):
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
success_message = _("Mass delete complete, the following VMs were " success_message = __(
"deleted: %s!") % u', '.join(names) "Mass delete complete, the following VM was deleted: %s.",
"Mass delete complete, the following VMs were deleted: %s.",
len(names)) % u', '.join(names)
# we can get this only via AJAX ... # we can get this only via AJAX ...
if request.is_ajax(): if request.is_ajax():
...@@ -1864,7 +1869,7 @@ class LeaseCreate(LoginRequiredMixin, SuperuserRequiredMixin, ...@@ -1864,7 +1869,7 @@ class LeaseCreate(LoginRequiredMixin, SuperuserRequiredMixin,
model = Lease model = Lease
form_class = LeaseForm form_class = LeaseForm
template_name = "dashboard/lease-create.html" template_name = "dashboard/lease-create.html"
success_message = _("Successfully created a new lease!") success_message = _("Successfully created a new lease.")
def get_success_url(self): def get_success_url(self):
return reverse_lazy("dashboard.views.template-list") return reverse_lazy("dashboard.views.template-list")
...@@ -1875,7 +1880,7 @@ class LeaseDetail(LoginRequiredMixin, SuperuserRequiredMixin, ...@@ -1875,7 +1880,7 @@ class LeaseDetail(LoginRequiredMixin, SuperuserRequiredMixin,
model = Lease model = Lease
form_class = LeaseForm form_class = LeaseForm
template_name = "dashboard/lease-edit.html" template_name = "dashboard/lease-edit.html"
success_message = _("Successfully modified lease!") success_message = _("Successfully modified lease.")
def get_success_url(self): def get_success_url(self):
return reverse_lazy("dashboard.views.lease-detail", kwargs=self.kwargs) return reverse_lazy("dashboard.views.lease-detail", kwargs=self.kwargs)
...@@ -1915,7 +1920,7 @@ class LeaseDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView): ...@@ -1915,7 +1920,7 @@ class LeaseDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
object.delete() object.delete()
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Lease successfully deleted!") success_message = _("Lease successfully deleted.")
if request.is_ajax(): if request.is_ajax():
return HttpResponse( return HttpResponse(
...@@ -1968,10 +1973,10 @@ class FavouriteView(TemplateView): ...@@ -1968,10 +1973,10 @@ class FavouriteView(TemplateView):
vm = Instance.objects.get(pk=self.request.POST.get("vm")) vm = Instance.objects.get(pk=self.request.POST.get("vm"))
try: try:
Favourite.objects.get(instance=vm, user=user).delete() Favourite.objects.get(instance=vm, user=user).delete()
return HttpResponse("Deleted!") return HttpResponse("Deleted.")
except Favourite.DoesNotExist: except Favourite.DoesNotExist:
Favourite(instance=vm, user=user).save() Favourite(instance=vm, user=user).save()
return HttpResponse("Added!") return HttpResponse("Added.")
class TransferOwnershipView(LoginRequiredMixin, DetailView): class TransferOwnershipView(LoginRequiredMixin, DetailView):
...@@ -2397,9 +2402,9 @@ class DiskAddView(TemplateView): ...@@ -2397,9 +2402,9 @@ class DiskAddView(TemplateView):
if form.is_valid(): if form.is_valid():
if form.cleaned_data.get("size"): if form.cleaned_data.get("size"):
messages.success(self.request, _("Disk successfully added!")) messages.success(self.request, _("Disk successfully added."))
else: else:
messages.success(self.request, _("Disk download started!")) messages.success(self.request, _("Disk download started."))
form.save() form.save()
else: else:
error = "<br /> ".join(["<strong>%s</strong>: %s" % error = "<br /> ".join(["<strong>%s</strong>: %s" %
...@@ -2513,7 +2518,7 @@ class DiskRemoveView(DeleteView): ...@@ -2513,7 +2518,7 @@ class DiskRemoveView(DeleteView):
next_url = request.POST.get("next") next_url = request.POST.get("next")
success_url = next_url if next_url else app.get_absolute_url() success_url = next_url if next_url else app.get_absolute_url()
success_message = _("Disk successfully removed!") success_message = _("Disk successfully removed.")
if request.is_ajax(): if request.is_ajax():
return HttpResponse( return HttpResponse(
...@@ -2578,7 +2583,7 @@ class InterfaceDeleteView(DeleteView): ...@@ -2578,7 +2583,7 @@ class InterfaceDeleteView(DeleteView):
instance.remove_interface(interface=self.object, user=request.user) instance.remove_interface(interface=self.object, user=request.user)
success_url = self.get_success_url() success_url = self.get_success_url()
success_message = _("Interface successfully deleted!") success_message = _("Interface successfully deleted.")
if request.is_ajax(): if request.is_ajax():
return HttpResponse( return HttpResponse(
......
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