Commit e559618a by Kálmán Viktor

dashboard: mark favourite vms

parent a16d972b
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Favourite'
db.create_table(u'dashboard_favourite', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('instance', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['vm.Instance'])),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
))
db.send_create_signal(u'dashboard', ['Favourite'])
def backwards(self, orm):
# Deleting model 'Favourite'
db.delete_table(u'dashboard_favourite')
models = {
u'acl.level': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Level'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
},
u'acl.objectlevel': {
'Meta': {'unique_together': "(('content_type', 'object_id', 'level'),)", 'object_name': 'ObjectLevel'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['acl.Level']"}),
'object_id': ('django.db.models.fields.IntegerField', [], {}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'dashboard.favourite': {
'Meta': {'object_name': 'Favourite'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'instance': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Instance']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
u'firewall.domain': {
'Meta': {'object_name': 'Domain'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
},
u'firewall.group': {
'Meta': {'object_name': 'Group'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
u'firewall.host': {
'Meta': {'object_name': 'Host'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('firewall.fields.IPAddressField', [], {'unique': 'True', 'max_length': '100'}),
'ipv6': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'pub_ipv4': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Vlan']"})
},
u'firewall.vlan': {
'Meta': {'object_name': 'Vlan'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Domain']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'network4': ('firewall.fields.IPNetworkField', [], {'max_length': '100'}),
'network6': ('firewall.fields.IPNetworkField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'network_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'reverse_domain': ('django.db.models.fields.TextField', [], {'default': "'%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa'"}),
'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
},
u'storage.datastore': {
'Meta': {'ordering': "['name']", 'object_name': 'DataStore'},
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
},
u'storage.disk': {
'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
'base': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'derivatives'", 'null': 'True', 'to': u"orm['storage.Disk']"}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'datastore': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['storage.DataStore']"}),
'destroyed': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'dev_num': ('django.db.models.fields.CharField', [], {'default': "'a'", 'max_length': '1'}),
'filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'ready': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'size': ('sizefield.models.FileSizeField', [], {}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
},
u'taggit.tag': {
'Meta': {'object_name': 'Tag'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
},
u'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
},
u'vm.instance': {
'Meta': {'ordering': "[u'pk']", 'object_name': 'Instance'},
'access_method': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'active_since': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'arch': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'boot_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'destroyed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'disks': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "u'instance_set'", 'symmetrical': 'False', 'to': u"orm['storage.Disk']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lease': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Lease']"}),
'max_ram_size': ('django.db.models.fields.IntegerField', [], {}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'node': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'instance_set'", 'null': 'True', 'to': u"orm['vm.Node']"}),
'num_cores': ('django.db.models.fields.IntegerField', [], {}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'pw': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'ram_size': ('django.db.models.fields.IntegerField', [], {}),
'raw_data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'req_traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'default': "u'NOSTATE'", 'max_length': '20'}),
'template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'instance_set'", 'null': 'True', 'to': u"orm['vm.InstanceTemplate']"}),
'time_of_delete': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'time_of_suspend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'vnc_port': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'})
},
u'vm.instancetemplate': {
'Meta': {'ordering': "[u'name']", 'object_name': 'InstanceTemplate'},
'access_method': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'arch': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'boot_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'disks': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "u'template_set'", 'symmetrical': 'False', 'to': u"orm['storage.Disk']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lease': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Lease']"}),
'max_ram_size': ('django.db.models.fields.IntegerField', [], {}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'num_cores': ('django.db.models.fields.IntegerField', [], {}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.InstanceTemplate']", 'null': 'True', 'blank': 'True'}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'ram_size': ('django.db.models.fields.IntegerField', [], {}),
'raw_data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'req_traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'default': "u'NEW'", 'max_length': '10'}),
'system': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
u'vm.lease': {
'Meta': {'ordering': "[u'name']", 'object_name': 'Lease'},
'delete_interval_seconds': ('django.db.models.fields.IntegerField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'suspend_interval_seconds': ('django.db.models.fields.IntegerField', [], {})
},
u'vm.node': {
'Meta': {'object_name': 'Node'},
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Host']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}),
'overcommit': ('django.db.models.fields.FloatField', [], {'default': '1.0'}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'})
},
u'vm.trait': {
'Meta': {'object_name': 'Trait'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['dashboard']
\ No newline at end of file
# 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