diff --git a/hosting/static/hosting/css/landing-page.css b/hosting/static/hosting/css/landing-page.css index 71b7a33d..9d067b3c 100644 --- a/hosting/static/hosting/css/landing-page.css +++ b/hosting/static/hosting/css/landing-page.css @@ -853,6 +853,9 @@ a.list-group-item-danger:focus, .panel-danger > .panel-heading { color: #eb4d5c; } +.alert-danger{ + background: rgba(235, 204, 209, 0.2); +} .has-error .form-control, .has-error .input-group-addon { color: #eb4d5c; diff --git a/hosting/static/hosting/css/virtual-machine.css b/hosting/static/hosting/css/virtual-machine.css index b4916da0..b6afe4ef 100644 --- a/hosting/static/hosting/css/virtual-machine.css +++ b/hosting/static/hosting/css/virtual-machine.css @@ -290,6 +290,11 @@ text-align: center; } +.vm-vmid .alert { + margin-top: 15px; + margin-bottom: -60px; +} + .vm-item-lg { font-size: 22px; margin-top: 5px; @@ -305,6 +310,10 @@ color: #e47f2f; } +.vm-color-failed { + color: #eb4d5c; +} + .vm-detail-item .value{ font-weight: 400; } @@ -627,4 +636,28 @@ left: auto; right: 8px; } +} + +.processing > .btn { + position: relative; + border-color: #eee; +} +.processing > .btn:hover, +.processing > .btn:focus, +.processing > .btn:active { + border-color: #eee; +} + +.processing > .btn:after { + content: ' '; + display: block; + position: absolute; + background-image: url('/static/hosting/img/ajax-loader.gif'); + background-repeat: no-repeat; + background-position: center; + background-color: #eee; + width: 100%; + top: 0; + height: 100%; + left: 0; } \ No newline at end of file diff --git a/hosting/static/hosting/img/ajax-loader.gif b/hosting/static/hosting/img/ajax-loader.gif new file mode 100644 index 00000000..a7c3f2ba Binary files /dev/null and b/hosting/static/hosting/img/ajax-loader.gif differ diff --git a/hosting/static/hosting/js/virtual_machine_detail.js b/hosting/static/hosting/js/virtual_machine_detail.js index 303f95ca..ce97d44e 100644 --- a/hosting/static/hosting/js/virtual_machine_detail.js +++ b/hosting/static/hosting/js/virtual_machine_detail.js @@ -2,7 +2,43 @@ $( document ).ready(function() { $('#confirm-cancel').on('click', '.btn-ok', function(e) { - $('#virtual_machine_cancel_form').trigger('submit'); + var url = $('#virtual_machine_cancel_form').attr('action'); + var $container = $('#terminate-VM'); + var $btn = $container.find('.btn'); + var text = $container.find('.vm-item-lg').text(); + var altText = $container.attr('data-alt'); + $container.find('.alert-danger').addClass('hide'); + $container.addClass('processing') + .find('.vm-item-lg').attr('class', '') + .addClass('vm-item-lg vm-color-failed') + .text(altText); + $btn.prop('disabled', true); + $('#confirm-cancel').modal('hide'); + $.post(url) + .done(function(data) { + console.log( "success" , data); + if (data.status == true) { + $container.addClass('terminate-success') + .find('.vm-item-lg').text(data.text); + $btn.remove(); + // window.location = data.redirect; + } + else { + $container.addClass('terminate-fail') + .find('.vm-item-lg').text(text); + $container.find('.btn').prop('disabled', false); + $container.find('.alert-danger').text(data.text).removeClass('hide'); + } + }) + .fail(function(data) { + $container.addClass('terminate-fail') + .find('.vm-item-lg').text(text); + $container.find('.btn').prop('disabled', false); + $container.find('.alert-danger').removeClass('hide'); + }) + .always(function(data) { + $container.removeClass('processing'); + }); }); var hash = window.location.hash; diff --git a/hosting/templates/hosting/includes/_navbar_user.html b/hosting/templates/hosting/includes/_navbar_user.html index d06477ca..37c01109 100644 --- a/hosting/templates/hosting/includes/_navbar_user.html +++ b/hosting/templates/hosting/includes/_navbar_user.html @@ -37,11 +37,6 @@
  • {% get_current_language as LANGUAGE_CODE %} - {% if LANGUAGE_CODE == 'en-us'%} -   Deutsch - {% else %} -   English - {% endif %}
  • diff --git a/hosting/templates/hosting/virtual_machine_detail.html b/hosting/templates/hosting/virtual_machine_detail.html index 6243c309..a5c82e90 100644 --- a/hosting/templates/hosting/virtual_machine_detail.html +++ b/hosting/templates/hosting/virtual_machine_detail.html @@ -46,26 +46,33 @@
    {% trans "Current Pricing" %}
    {{virtual_machine.price|floatformat}} CHF/{% trans "Month" %}
    - {% trans "See Invoice" %} + {% trans "See Invoice" %}

    {% trans "Status" %}

    {% trans "Your VM is" %}
    - {% if virtual_machine.state == 'PENDING' %} -
    {% trans "Pending" %}
    - {% elif virtual_machine.state == 'ACTIVE' %} -
    {% trans "Online" %}
    - {% elif virtual_machine.state == 'FAILED'%} -
    {% trans "Failed" %}
    - {% endif %} - {% if not virtual_machine.status == 'canceled' %} -
    - {% csrf_token %} -
    - - {% endif %} +
    + {% if virtual_machine.state == 'PENDING' %} +
    {% trans "Pending" %}
    + {% elif virtual_machine.state == 'ACTIVE' %} +
    {% trans "Online" %}
    + {% elif virtual_machine.state == 'FAILED'%} +
    {% trans "Failed" %}
    + {% else %} +
    + {% endif %} + {% if not virtual_machine.status == 'canceled' %} +
    + {% csrf_token %} +
    + +
    + {% trans "Sorry, there was an unexpected error. Kindly retry." %} +
    + {% endif %} +
    diff --git a/hosting/urls.py b/hosting/urls.py index 10e09dd0..c3b982cb 100644 --- a/hosting/urls.py +++ b/hosting/urls.py @@ -10,9 +10,11 @@ from .views import ( HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, SSHKeyChoiceView, DashboardView, SettingsView) +from django.views.generic import TemplateView urlpatterns = [ + url(r'test/?$', TemplateView.as_view(template_name='hosting/virtual_machine_detail.html')), url(r'index/?$', IndexView.as_view(), name='index'), url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'), url(r'dashboard/?$', DashboardView.as_view(), name='dashboard'), diff --git a/hosting/views.py b/hosting/views.py index f7d6e414..df6e6100 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -1,4 +1,6 @@ import uuid +import json +from time import sleep from django.conf import settings from django.contrib import messages @@ -6,13 +8,12 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.tokens import default_token_generator from django.core.files.base import ContentFile from django.core.urlresolvers import reverse_lazy, reverse -from django.http import Http404 -from django.http import HttpResponseRedirect -from django.shortcuts import redirect -from django.shortcuts import render +from django.http import Http404, HttpResponseRedirect, HttpResponse +from django.shortcuts import redirect, render from django.utils.http import urlsafe_base64_decode from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext from django.views.generic import View, CreateView, FormView, ListView, \ DetailView, \ DeleteView, TemplateView, UpdateView @@ -711,7 +712,7 @@ class PaymentVMView(LoginRequiredMixin, FormView): request.get_host()), 'page_header': _( 'Your New VM %(vm_name)s at Data Center Light') % { - 'vm_name': vm.get('name')} + 'vm_name': vm.get('name')} } email_data = { 'subject': context.get('page_header'), @@ -924,6 +925,7 @@ class VirtualMachineView(LoginRequiredMixin, View): return render(request, self.template_name, context) def post(self, request, *args, **kwargs): + response = {} owner = self.request.user vm = self.get_object() @@ -934,41 +936,53 @@ class VirtualMachineView(LoginRequiredMixin, View): password=owner.password ) vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data - terminated = manager.delete_vm( - vm.id - ) + + terminated = manager.delete_vm(vm.id) if not terminated: messages.error( request, 'Error terminating VM %s' % (opennebula_vm_id) ) - return HttpResponseRedirect(self.get_success_url()) - context = { - 'vm': vm_data, - 'base_url': "{0}://{1}".format(self.request.scheme, - self.request.get_host()), - 'page_header': _('Virtual Machine Cancellation') - } - email_data = { - 'subject': context['page_header'], - 'to': self.request.user.email, - 'context': context, - 'template_name': 'vm_canceled', - 'template_path': 'hosting/emails/', - 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS, - } - email = BaseEmail(**email_data) - email.send() + response['status'] = False + else: + context = { + 'vm': vm_data, + 'base_url': "{0}://{1}".format(self.request.scheme, + self.request.get_host()), + 'page_header': _('Virtual Machine Cancellation') + } + email_data = { + 'subject': context['page_header'], + 'to': self.request.user.email, + 'context': context, + 'template_name': 'vm_canceled', + 'template_path': 'hosting/emails/', + 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS, + } + email = BaseEmail(**email_data) + email.send() - messages.error( - request, - _('VM %(VM_ID)s terminated successfully') % { - 'VM_ID': opennebula_vm_id} + # messages.error( + # request, + # _('VM %(VM_ID)s terminated successfully') % { + # 'VM_ID': opennebula_vm_id} + # ) + deleting = True + t = 0 + while deleting: + if t < 150 and manager.get_vm(self.kwargs.get('pk')): + sleep(2) + else: + deleting = False + response['status'] = True + response['redirect'] = self.get_success_url() + response['text'] = ugettext('Terminated') + return HttpResponse( + json.dumps(response), + content_type="application/json" ) - return HttpResponseRedirect(self.get_success_url()) - class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin, ListView):