Commit 3aaf7e00 by Kálmán Viktor Committed by Guba Sándor

dashboard: call save as async

dashboard: remove disks
dashboard: handle None disk sizes
dashboard: disk list design
dashboard: create diskless vm from new template

Conflicts:

	circle/dashboard/templates/dashboard/_disk-list-element.html
	circle/dashboard/urls.py
	circle/dashboard/views.py
parent f6e1dcbe
...@@ -123,6 +123,18 @@ $(function () { ...@@ -123,6 +123,18 @@ $(function () {
return false; return false;
}); });
/* for disk remove buttons */
$('.disk-remove').click(function() {
var disk_pk = $(this).data('disk-pk');
addModalConfirmation(deleteObject,
{ 'url': '/dashboard/disk/' + disk_pk + '/remove/',
'data': [],
'pk': disk_pk,
'type': "disk",
});
return false;
});
/* for Node removes buttons */ /* for Node removes buttons */
$('.node-delete').click(function() { $('.node-delete').click(function() {
var node_pk = $(this).data('node-pk'); var node_pk = $(this).data('node-pk');
...@@ -258,9 +270,15 @@ function deleteObject(data) { ...@@ -258,9 +270,15 @@ function deleteObject(data) {
if(!data['redirect']) { if(!data['redirect']) {
selected = []; selected = [];
addMessage(re['message'], 'success'); addMessage(re['message'], 'success');
if(data.type === "disk") {
// no need to remove them from DOM
$('a[data-disk-pk="' + data.pk + '"]').parent("li").fadeOut();
$('a[data-disk-pk="' + data.pk + '"]').parent("h4").fadeOut();
} else {
$('a[data-'+data['type']+'-pk="' + data['pk'] + '"]').closest('tr').fadeOut(function() { $('a[data-'+data['type']+'-pk="' + data['pk'] + '"]').closest('tr').fadeOut(function() {
$(this).remove(); $(this).remove();
}); });
}
} else { } else {
window.location.replace('/dashboard'); window.location.replace('/dashboard');
} }
......
...@@ -10,5 +10,8 @@ ...@@ -10,5 +10,8 @@
<div class="label label-danger">failed</div> <div class="label label-danger">failed</div>
{% endif %} {% endif %}
{% else %}<span class="disk-list-disk-percentage" data-disk-pk="{{ d.pk }}">{{ d.get_download_percentage }}</span>%{% endif %} {% else %}<span class="disk-list-disk-percentage" data-disk-pk="{{ d.pk }}">{{ d.get_download_percentage }}</span>%{% endif %}
<a href="{% url "dashboard.views.disk-remove" pk=d.pk %}?next={{ request.path }}"
<div class="btn btn-xs btn-danger pull-right"><i class="icon-remove"></i> Remove</div> data-disk-pk="{{ d.pk }}" class="btn btn-xs btn-danger pull-right disk-remove">
<i class="icon-remove"></i>{% if long_remove %} Remove{% endif %}
</a>
<div style="clear: both;"></div>
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
{% if text %} {% if text %}
{{ text }} {{ text|safe }}
{% else %} {% else %}
{%blocktrans with object=object%} {%blocktrans with object=object%}
Are you sure you want to delete <strong>{{ object }}</strong>? Are you sure you want to delete <strong>{{ object }}</strong>?
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
{% if text %} {% if text %}
{{ text }} {{ text|safe }}
{% else %} {% else %}
{%blocktrans with object=object%} {%blocktrans with object=object%}
Are you sure you want to delete <strong>{{ object }}</strong>? Are you sure you want to delete <strong>{{ object }}</strong>?
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
{% csrf_token %} {% csrf_token %}
<a class="btn btn-default">Back</a> <a class="btn btn-default">Back</a>
<input type="hidden" name="next" value="{{ request.GET.next }}"/> <input type="hidden" name="next" value="{{ request.GET.next }}"/>
<button class="btn btn-danger">Yes, delete</button> <button class="btn btn-danger">Yes</button>
</form> </form>
</div> </div>
</div> </div>
......
...@@ -10,7 +10,7 @@ from .views import ( ...@@ -10,7 +10,7 @@ from .views import (
TemplateDelete, TemplateDetail, TemplateList, TransferOwnershipConfirmView, TemplateDelete, TemplateDetail, TemplateList, TransferOwnershipConfirmView,
TransferOwnershipView, vm_activity, VmCreate, VmDelete, VmDetailView, TransferOwnershipView, vm_activity, VmCreate, VmDelete, VmDetailView,
VmDetailVncTokenView, VmGraphView, VmList, VmMassDelete, VmMigrateView, VmDetailVncTokenView, VmGraphView, VmList, VmMassDelete, VmMigrateView,
VmRenewView, VmRenewView, DiskRemoveView
) )
urlpatterns = patterns( urlpatterns = patterns(
...@@ -99,4 +99,6 @@ urlpatterns = patterns( ...@@ -99,4 +99,6 @@ urlpatterns = patterns(
name="dashboard.views.disk-add"), name="dashboard.views.disk-add"),
url(r'^profile/$', MyPreferencesView.as_view(), url(r'^profile/$', MyPreferencesView.as_view(),
name="dashboard.views.profile"), name="dashboard.views.profile"),
url(r'^disk/(?P<pk>\d+)/remove/$', DiskRemoveView.as_view(),
name="dashboard.views.disk-remove"),
) )
...@@ -43,6 +43,7 @@ from vm.models import ( ...@@ -43,6 +43,7 @@ from vm.models import (
Instance, instance_activity, InstanceActivity, InstanceTemplate, Interface, Instance, instance_activity, InstanceActivity, InstanceTemplate, Interface,
InterfaceTemplate, Lease, Node, NodeActivity, Trait, InterfaceTemplate, Lease, Node, NodeActivity, Trait,
) )
from storage.models import Disk
from firewall.models import Vlan, Host, Rule from firewall.models import Vlan, Host, Rule
from dashboard.models import Favourite, Profile from dashboard.models import Favourite, Profile
...@@ -2082,3 +2083,49 @@ def set_language_cookie(request, response, lang=None): ...@@ -2082,3 +2083,49 @@ def set_language_cookie(request, response, lang=None):
cname = getattr(settings, 'LANGUAGE_COOKIE_NAME', 'django_language') cname = getattr(settings, 'LANGUAGE_COOKIE_NAME', 'django_language')
response.set_cookie(cname, lang, 365 * 86400) response.set_cookie(cname, lang, 365 * 86400)
class DiskRemoveView(DeleteView):
model = Disk
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def get_context_data(self, **kwargs):
context = super(DiskRemoveView, self).get_context_data(**kwargs)
disk = self.get_object()
app = disk.get_appliance()
context['title'] = _("Disk remove confirmation")
context['text'] = _("Are you sure you want to remove "
"<strong>%(disk)s</strong> from "
"<strong>%(app)s</strong>?" % {'disk': disk,
'app': app}
)
return context
def delete(self, request, *args, **kwargs):
disk = self.get_object()
if not disk.has_level(request.user, 'owner'):
raise PermissionDenied()
disk = self.get_object()
app = disk.get_appliance()
app.disks.remove(disk)
disk.destroy()
next_url = request.POST.get("next")
success_url = next_url if next_url else app.get_absolute_url()
success_message = _("Disk successfully removed!")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect("%s#resources" % success_url)
...@@ -204,6 +204,17 @@ class Disk(AclBase, TimeStampedModel): ...@@ -204,6 +204,17 @@ class Disk(AclBase, TimeStampedModel):
""" """
return any(i.state != 'STOPPED' for i in self.instance_set.all()) return any(i.state != 'STOPPED' for i in self.instance_set.all())
def get_appliance(self):
"""Return an Instance or InstanceTemplate object where the disk is used
"""
instance = self.instance_set.all()
template = self.template_set.all()
app = list(instance) + list(template)
if len(app) > 0:
return app[0]
else:
return None
def get_exclusive(self): def get_exclusive(self):
"""Get an instance of the disk for exclusive usage. """Get an instance of the disk for exclusive usage.
......
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