From 07a464231d541203c9baef9dd0e13b95f79a60eb Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Thu, 14 Sep 2017 02:24:10 +0530
Subject: [PATCH] animation added to vm termination

---
 hosting/static/hosting/css/landing-page.css   |   3 +
 .../static/hosting/css/virtual-machine.css    |  33 ++++++++
 hosting/static/hosting/img/ajax-loader.gif    | Bin 0 -> 404 bytes
 .../hosting/js/virtual_machine_detail.js      |  38 ++++++++-
 .../hosting/includes/_navbar_user.html        |   5 --
 .../hosting/virtual_machine_detail.html       |  35 ++++----
 hosting/urls.py                               |   2 +
 hosting/views.py                              |  76 +++++++++++-------
 8 files changed, 141 insertions(+), 51 deletions(-)
 create mode 100644 hosting/static/hosting/img/ajax-loader.gif

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 0000000000000000000000000000000000000000..a7c3f2bacbe630950c16f53e3c27dd840f2e8622
GIT binary patch
literal 404
zcmZ?wbhEHb)Mnsj_{hNU?%lhzw6s;LRsl)He^Smxsfi`2DGKG8B^e5dS&0=n`H3ld
znR#jX42nNl7`PZ17!?0=`?-b$J39ur8tEA@GXjNlfS3VfAOn+8OCQJSX*X{)e?H13
zeJ||u>DC8kZ4r?R)6{G4&Dyt|CtcU`diyE8Uq?3owA-;j!N^AxXd>8TMr31bj{uEP
z;7?56IIHFOnwrlu67PNQNtrQY{;7pt&RzvNJJ_?&Ze06Pg>MsMs)$s6#HZT6Q+}5p
z&C*E<I=&ueA`^;<Acq+MO<XxEEBa3UBYrO7?UfHJdzM^TuwobAGVVjKeUi;OpPxMU
z@@LSj8EZ_>81%TGdiiN4(8Lw%U?wsno9F=b>WnG7*rn?>{@R)9v%+M)yIi1FiTcrX
vD}VECG@HG3ZvWp+k0+)$$G&~0?NxTdRajt8g3>tw(O*m=3=Gzwa03GXAUBr*

literal 0
HcmV?d00001

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 @@
                 </li>
                 <li>
                     {% get_current_language as LANGUAGE_CODE %}
-                    {% if LANGUAGE_CODE == 'en-us'%}
-                        <a href="{% change_lang 'de' %}"><i class="fa fa-fw fa-globe" aria-hidden="true"></i>&nbsp;&nbsp;Deutsch</a>
-                    {% else %}
-                        <a href="{% change_lang 'en-us' %}"><i class="fa fa-fw fa-globe" aria-hidden="true"></i>&nbsp;&nbsp;English</a>
-                    {% endif %}
                 </li>
             </ul>
         </div>
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 @@
 				<div class="vm-vmid">
 					<div class="vm-item-subtitle">{% trans "Current Pricing" %}</div>
 					<div class="vm-item-lg">{{virtual_machine.price|floatformat}} CHF/{% trans "Month" %}</div>
-					<a class="btn btn-vm-invoice" href="{% url 'hosting:orders' order.pk %}">{% trans "See Invoice" %}</a>
+					<a class="btn btn-vm-invoice" href="{% url 'hosting:orders' 2 %}">{% trans "See Invoice" %}</a>
 				</div>
 			</div>
 			<div class="vm-detail-item">
 				<h2 class="vm-detail-title">{% trans "Status" %} <img src="{% static 'hosting/img/connected.svg' %}" class="un-icon"></h2>
 				<div class="vm-vmid">
 					<div class="vm-item-subtitle">{% trans "Your VM is" %}</div>
-					{% if virtual_machine.state == 'PENDING' %}
-						<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div>
-					{% elif  virtual_machine.state == 'ACTIVE' %}
-						<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div>
-					{% elif  virtual_machine.state == 'FAILED'%}
-						<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div>
-					{% endif %}
-					{% if not virtual_machine.status == 'canceled' %}
-						<form method="POST" id="virtual_machine_cancel_form" class="cancel-form" action="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}">
-							{% csrf_token %}
-						</form>
-						<button data-href="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}" data-toggle="modal" data-target="#confirm-cancel" class="btn btn-vm-term">{% trans "Terminate VM" %}</button>
-					{% endif %}
+						<div id="terminate-VM" data-alt="{% trans 'Terminating' %}">
+							{% if virtual_machine.state == 'PENDING' %}
+								<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div>
+							{% elif  virtual_machine.state == 'ACTIVE' %}
+								<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div>
+							{% elif  virtual_machine.state == 'FAILED'%}
+								<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div>
+							{% else %}
+								<div class="vm-item-lg"></div>
+							{% endif %}
+							{% if not virtual_machine.status == 'canceled' %}
+								<form method="POST" id="virtual_machine_cancel_form" class="cancel-form" action="{% url 'hosting:virtual_machines' 2 %}">
+									{% csrf_token %}
+								</form>
+								<button data-toggle="modal" data-target="#confirm-cancel" class="btn btn-vm-term">{% trans "Terminate VM" %}</button>
+								<div class="alert alert-danger hide">
+									{% trans "Sorry, there was an unexpected error. Kindly retry." %}
+								</div>
+							{% endif %}
+						</div>
 				</div>
 			</div>
 		</div>
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):