Commit e559618a by Kálmán Viktor

dashboard: mark favourite vms

parent a16d972b
# Create your models here. from django.contrib.auth.models import User
from django.db.models import Model, ForeignKey
from vm.models import Instance
class Favourite(Model):
instance = ForeignKey(Instance)
user = ForeignKey(User)
...@@ -50,7 +50,8 @@ $(function () { ...@@ -50,7 +50,8 @@ $(function () {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}); });
$('[title]').tooltip(); $('[title]:not(.title-favourite)').tooltip();
$('.title-favourite').tooltip({'placement': 'right'});
$(':input[title]').tooltip({trigger: 'focus', placement: 'auto right'}); $(':input[title]').tooltip({trigger: 'focus', placement: 'auto right'});
$(".knob").knob(); $(".knob").knob();
...@@ -64,6 +65,34 @@ $(function () { ...@@ -64,6 +65,34 @@ $(function () {
$("a[href=" + window.location.hash +"]").tab('show'); $("a[href=" + window.location.hash +"]").tab('show');
} }
/* favourite star */
$("#dashboard-vm-list").on('click', '.dashboard-vm-favourite', function(e) {
var star = $(this).children("i");
var pk = $(this).data("vm");
if(star.hasClass("icon-star-empty")) {
star.removeClass("icon-star-empty").addClass("icon-star");
star.prop("title", "Unfavourite");
} else {
star.removeClass("icon-star").addClass("icon-star-empty");
star.prop("title", "Mark as favourite");
}
$.ajax({
url: "/dashboard/favourite/",
type: "POST",
data: {'vm': pk},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
// success
},
error: function(xhr, textStatus, error) {
console.log("oh babám");
}
});
$(star).tooltip('destroy').tooltip({'placement': 'right'});
my_vms = [];
return false;
});
/* scroll to top if there is a message */ /* scroll to top if there is a message */
if($(".messagelist").children(".alert").length > 0) if($(".messagelist").children(".alert").length > 0)
$('body').animate({scrollTop: 0}); $('body').animate({scrollTop: 0});
...@@ -106,8 +135,9 @@ $(function () { ...@@ -106,8 +135,9 @@ $(function () {
for(var i in result) { for(var i in result) {
my_vms.push({ my_vms.push({
'pk': result[i].pk, 'pk': result[i].pk,
'name': result[i].fields.name, 'name': result[i].name,
'state': result[i].fields.state, 'state': result[i].state,
'fav': result[i].fav,
}); });
} }
}); });
...@@ -122,24 +152,34 @@ $(function () { ...@@ -122,24 +152,34 @@ $(function () {
search_result.push(my_vms[i]); search_result.push(my_vms[i]);
} }
} }
search_result.sort(compareVmByFav);
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].fav);
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">No result</div>';
$("#dashboard-vm-list").html(html); $("#dashboard-vm-list").html(html);
$('.title-favourite').tooltip({'placement': 'right'});
}); });
}); });
function generateVmHTML(pk, name) { function generateVmHTML(pk, name, fav) {
return '<a href="/dashboard/vm/' + pk + '/" class="list-group-item">' + return '<a href="/dashboard/vm/' + pk + '/" class="list-group-item">' +
'<i class="icon-play-sign"></i> ' + name + '<i class="icon-play-sign"></i> ' + name +
'<div class="pull-right">' + '<div class="pull-right dashboard-vm-favourite" data-vm="' + pk +'">' +
'<i class="icon-star text-primary" title="" data-original-title="Mark as favorite."></i>' + '<i class="title-favourite icon-star' + (fav ? "" : "-empty") + ' text-primary" title="" data-original-title="' +
(fav ? "Un": "Mark as ") + 'favourite"></i>' +
'</div>' + '</div>' +
'</a>'; '</a>';
} }
function compareVmByFav(a, b) {
if(a.fav)
return -1;
else
return 1;
}
function addSliderMiscs() { function addSliderMiscs() {
$('.vm-slider').each(function() { $('.vm-slider').each(function() {
$("<span>").addClass("output").html($(this).val()).insertAfter($(this)); $("<span>").addClass("output").html($(this).val()).insertAfter($(this));
......
...@@ -16,7 +16,14 @@ ...@@ -16,7 +16,14 @@
<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">
<i class="icon-{% if i.state == "RUNNING" %}play-sign{% else %}pause{% endif %}"></i> {{ i.name }} <div class="pull-right"><i class="icon-star text-primary" title="Mark as favorite."></i></div> <i class="icon-{% if i.state == "RUNNING" %}play-sign{% else %}pause{% endif %}"></i> {{ i.name }}
<div class="pull-right dashboard-vm-favourite" data-vm="{{ i.pk }}">
{% if i.fav %}
<i class="icon-star text-primary title-favourite" title="Unfavourite"></i>
{% else %}
<i class="icon-star-empty text-primary title-favourite" title="Mark as favorite"></i>
{% endif %}
</div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
......
...@@ -6,6 +6,7 @@ from .views import ( ...@@ -6,6 +6,7 @@ from .views import (
VmDelete, VmMassDelete, vm_activity, NodeList, NodeDetailView, PortDelete, VmDelete, VmMassDelete, vm_activity, NodeList, NodeDetailView, PortDelete,
TransferOwnershipView, TransferOwnershipConfirmView, NodeDelete, TransferOwnershipView, TransferOwnershipConfirmView, NodeDelete,
TemplateList, LeaseDetail, NodeCreate, LeaseCreate, TemplateCreate, TemplateList, LeaseDetail, NodeCreate, LeaseCreate, TemplateCreate,
FavouriteView,
) )
urlpatterns = patterns( urlpatterns = patterns(
...@@ -46,4 +47,6 @@ urlpatterns = patterns( ...@@ -46,4 +47,6 @@ urlpatterns = patterns(
name="dashboard.views.delete-node"), name="dashboard.views.delete-node"),
url(r'^node/create/$', NodeCreate.as_view(), url(r'^node/create/$', NodeCreate.as_view(),
name='dashboard.views.node-create'), name='dashboard.views.node-create'),
url(r'^favourite/$', FavouriteView.as_view(),
name='dashboard.views.favourite'),
) )
...@@ -17,7 +17,6 @@ from django.views.generic.detail import SingleObjectMixin ...@@ -17,7 +17,6 @@ from django.views.generic.detail import SingleObjectMixin
from django.views.generic import (TemplateView, DetailView, View, DeleteView, from django.views.generic import (TemplateView, DetailView, View, DeleteView,
UpdateView, CreateView) UpdateView, CreateView)
from django.contrib import messages from django.contrib import messages
from django.core import serializers
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.forms.models import inlineformset_factory from django.forms.models import inlineformset_factory
...@@ -31,6 +30,7 @@ from vm.models import (Instance, InstanceTemplate, InterfaceTemplate, ...@@ -31,6 +30,7 @@ from vm.models import (Instance, InstanceTemplate, InterfaceTemplate,
InstanceActivity, Node, instance_activity, Lease) InstanceActivity, Node, instance_activity, Lease)
from firewall.models import Vlan, Host, Rule from firewall.models import Vlan, Host, Rule
from storage.models import Disk from storage.models import Disk
from dashboard.models import Favourite
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -61,13 +61,16 @@ class IndexView(LoginRequiredMixin, TemplateView): ...@@ -61,13 +61,16 @@ class IndexView(LoginRequiredMixin, TemplateView):
user = self.request.user user = self.request.user
else: else:
user = None user = None
context = super(IndexView, self).get_context_data(**kwargs)
favs = Instance.objects.filter(favourite__user=self.request.user)
instances = Instance.get_objects_with_level( instances = Instance.get_objects_with_level(
'user', user).filter(destroyed=None) 'user', user).filter(destroyed=None)
display = list(favs) + list(set(instances) - set(favs))
context = super(IndexView, self).get_context_data(**kwargs) for d in display:
d.fav = True if d in favs else False
context.update({ context.update({
'instances': instances[:5], 'instances': display[:5],
'more_instances': instances.count() - len(instances[:5]) 'more_instances': instances.count() - len(instances[:5])
}) })
...@@ -464,10 +467,15 @@ class VmList(LoginRequiredMixin, SingleTableView): ...@@ -464,10 +467,15 @@ class VmList(LoginRequiredMixin, SingleTableView):
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
if self.request.is_ajax(): if self.request.is_ajax():
vms = serializers.serialize('json', self.get_queryset(), favs = Instance.objects.filter(
fields=('pk', 'name', 'state')) favourite__user=self.request.user).values_list('pk', flat=True)
instances = Instance.get_objects_with_level(
'user', self.request.user).filter(
destroyed=None).values('pk', 'name', 'state')
for i in instances:
i['fav'] = True if i['pk'] in favs else False
return HttpResponse( return HttpResponse(
vms, json.dumps(list(instances)), # instances is ValuesQuerySet
content_type="application/json", content_type="application/json",
) )
else: else:
...@@ -859,6 +867,19 @@ def vm_activity(request, pk): ...@@ -859,6 +867,19 @@ def vm_activity(request, pk):
) )
class FavouriteView(TemplateView):
def post(self, *args, **kwargs):
user = self.request.user
vm = Instance.objects.get(pk=self.request.POST.get("vm"))
try:
Favourite.objects.get(instance=vm, user=user).delete()
return HttpResponse("Deleted!")
except Favourite.DoesNotExist:
Favourite(instance=vm, user=user).save()
return HttpResponse("Added!")
class TransferOwnershipView(LoginRequiredMixin, DetailView): class TransferOwnershipView(LoginRequiredMixin, DetailView):
model = Instance model = Instance
template_name = 'dashboard/vm-detail/tx-owner.html' template_name = 'dashboard/vm-detail/tx-owner.html'
......
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