animation added to vm termination
This commit is contained in:
		
					parent
					
						
							
								821f854fc9
							
						
					
				
			
			
				commit
				
					
						07a464231d
					
				
			
		
					 8 changed files with 141 additions and 51 deletions
				
			
		|  | @ -853,6 +853,9 @@ a.list-group-item-danger:focus, | ||||||
| .panel-danger > .panel-heading { | .panel-danger > .panel-heading { | ||||||
|     color: #eb4d5c; |     color: #eb4d5c; | ||||||
| } | } | ||||||
|  | .alert-danger{ | ||||||
|  |     background: rgba(235, 204, 209, 0.2); | ||||||
|  | } | ||||||
| .has-error .form-control, | .has-error .form-control, | ||||||
| .has-error .input-group-addon { | .has-error .input-group-addon { | ||||||
|     color: #eb4d5c; |     color: #eb4d5c; | ||||||
|  |  | ||||||
|  | @ -290,6 +290,11 @@ | ||||||
|   text-align: center; |   text-align: center; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .vm-vmid .alert { | ||||||
|  |   margin-top: 15px; | ||||||
|  |   margin-bottom: -60px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .vm-item-lg { | .vm-item-lg { | ||||||
|   font-size: 22px; |   font-size: 22px; | ||||||
|   margin-top: 5px; |   margin-top: 5px; | ||||||
|  | @ -305,6 +310,10 @@ | ||||||
|   color: #e47f2f; |   color: #e47f2f; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .vm-color-failed { | ||||||
|  |   color: #eb4d5c; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .vm-detail-item .value{ | .vm-detail-item .value{ | ||||||
|   font-weight: 400; |   font-weight: 400; | ||||||
| } | } | ||||||
|  | @ -627,4 +636,28 @@ | ||||||
|     left: auto; |     left: auto; | ||||||
|     right: 8px; |     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; | ||||||
| } | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								hosting/static/hosting/img/ajax-loader.gif
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								hosting/static/hosting/img/ajax-loader.gif
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 404 B | 
|  | @ -2,7 +2,43 @@ | ||||||
| $( document ).ready(function() { | $( document ).ready(function() { | ||||||
| 
 | 
 | ||||||
| 	$('#confirm-cancel').on('click', '.btn-ok', function(e) { | 	$('#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; |   var hash = window.location.hash; | ||||||
|  |  | ||||||
|  | @ -37,11 +37,6 @@ | ||||||
|                 </li> |                 </li> | ||||||
|                 <li> |                 <li> | ||||||
|                     {% get_current_language as LANGUAGE_CODE %} |                     {% 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>  Deutsch</a> |  | ||||||
|                     {% else %} |  | ||||||
|                         <a href="{% change_lang 'en-us' %}"><i class="fa fa-fw fa-globe" aria-hidden="true"></i>  English</a> |  | ||||||
|                     {% endif %} |  | ||||||
|                 </li> |                 </li> | ||||||
|             </ul> |             </ul> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  | @ -46,26 +46,33 @@ | ||||||
| 				<div class="vm-vmid"> | 				<div class="vm-vmid"> | ||||||
| 					<div class="vm-item-subtitle">{% trans "Current Pricing" %}</div> | 					<div class="vm-item-subtitle">{% trans "Current Pricing" %}</div> | ||||||
| 					<div class="vm-item-lg">{{virtual_machine.price|floatformat}} CHF/{% trans "Month" %}</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> | 			</div> | ||||||
| 			<div class="vm-detail-item"> | 			<div class="vm-detail-item"> | ||||||
| 				<h2 class="vm-detail-title">{% trans "Status" %} <img src="{% static 'hosting/img/connected.svg' %}" class="un-icon"></h2> | 				<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-vmid"> | ||||||
| 					<div class="vm-item-subtitle">{% trans "Your VM is" %}</div> | 					<div class="vm-item-subtitle">{% trans "Your VM is" %}</div> | ||||||
| 					{% if virtual_machine.state == 'PENDING' %} | 						<div id="terminate-VM" data-alt="{% trans 'Terminating' %}"> | ||||||
| 						<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div> | 							{% if virtual_machine.state == 'PENDING' %} | ||||||
| 					{% elif  virtual_machine.state == 'ACTIVE' %} | 								<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div> | ||||||
| 						<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div> | 							{% elif  virtual_machine.state == 'ACTIVE' %} | ||||||
| 					{% elif  virtual_machine.state == 'FAILED'%} | 								<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div> | ||||||
| 						<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div> | 							{% elif  virtual_machine.state == 'FAILED'%} | ||||||
| 					{% endif %} | 								<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div> | ||||||
| 					{% if not virtual_machine.status == 'canceled' %} | 							{% else %} | ||||||
| 						<form method="POST" id="virtual_machine_cancel_form" class="cancel-form" action="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}"> | 								<div class="vm-item-lg"></div> | ||||||
| 							{% csrf_token %} | 							{% endif %} | ||||||
| 						</form> | 							{% if not virtual_machine.status == 'canceled' %} | ||||||
| 						<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> | 								<form method="POST" id="virtual_machine_cancel_form" class="cancel-form" action="{% url 'hosting:virtual_machines' 2 %}"> | ||||||
| 					{% endif %} | 									{% 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> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
|  |  | ||||||
|  | @ -10,9 +10,11 @@ from .views import ( | ||||||
|     HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, |     HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, | ||||||
|     SSHKeyChoiceView, DashboardView, SettingsView) |     SSHKeyChoiceView, DashboardView, SettingsView) | ||||||
| 
 | 
 | ||||||
|  | from django.views.generic import TemplateView | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|  |     url(r'test/?$', TemplateView.as_view(template_name='hosting/virtual_machine_detail.html')), | ||||||
|     url(r'index/?$', IndexView.as_view(), name='index'), |     url(r'index/?$', IndexView.as_view(), name='index'), | ||||||
|     url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'), |     url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'), | ||||||
|     url(r'dashboard/?$', DashboardView.as_view(), name='dashboard'), |     url(r'dashboard/?$', DashboardView.as_view(), name='dashboard'), | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| import uuid | import uuid | ||||||
|  | import json | ||||||
|  | from time import sleep | ||||||
| 
 | 
 | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.contrib import messages | 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.contrib.auth.tokens import default_token_generator | ||||||
| from django.core.files.base import ContentFile | from django.core.files.base import ContentFile | ||||||
| from django.core.urlresolvers import reverse_lazy, reverse | from django.core.urlresolvers import reverse_lazy, reverse | ||||||
| from django.http import Http404 | from django.http import Http404, HttpResponseRedirect, HttpResponse | ||||||
| from django.http import HttpResponseRedirect | from django.shortcuts import redirect, render | ||||||
| from django.shortcuts import redirect |  | ||||||
| from django.shortcuts import render |  | ||||||
| from django.utils.http import urlsafe_base64_decode | from django.utils.http import urlsafe_base64_decode | ||||||
| from django.utils.safestring import mark_safe | from django.utils.safestring import mark_safe | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
|  | from django.utils.translation import ugettext | ||||||
| from django.views.generic import View, CreateView, FormView, ListView, \ | from django.views.generic import View, CreateView, FormView, ListView, \ | ||||||
|     DetailView, \ |     DetailView, \ | ||||||
|     DeleteView, TemplateView, UpdateView |     DeleteView, TemplateView, UpdateView | ||||||
|  | @ -711,7 +712,7 @@ class PaymentVMView(LoginRequiredMixin, FormView): | ||||||
|                                                request.get_host()), |                                                request.get_host()), | ||||||
|                 'page_header': _( |                 'page_header': _( | ||||||
|                     'Your New VM %(vm_name)s at Data Center Light') % { |                     'Your New VM %(vm_name)s at Data Center Light') % { | ||||||
|                                    'vm_name': vm.get('name')} |                     'vm_name': vm.get('name')} | ||||||
|             } |             } | ||||||
|             email_data = { |             email_data = { | ||||||
|                 'subject': context.get('page_header'), |                 'subject': context.get('page_header'), | ||||||
|  | @ -924,6 +925,7 @@ class VirtualMachineView(LoginRequiredMixin, View): | ||||||
|         return render(request, self.template_name, context) |         return render(request, self.template_name, context) | ||||||
| 
 | 
 | ||||||
|     def post(self, request, *args, **kwargs): |     def post(self, request, *args, **kwargs): | ||||||
|  |         response = {} | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         vm = self.get_object() |         vm = self.get_object() | ||||||
| 
 | 
 | ||||||
|  | @ -934,41 +936,53 @@ class VirtualMachineView(LoginRequiredMixin, View): | ||||||
|             password=owner.password |             password=owner.password | ||||||
|         ) |         ) | ||||||
|         vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data |         vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data | ||||||
|         terminated = manager.delete_vm( | 
 | ||||||
|             vm.id |         terminated = manager.delete_vm(vm.id) | ||||||
|         ) |  | ||||||
| 
 | 
 | ||||||
|         if not terminated: |         if not terminated: | ||||||
|             messages.error( |             messages.error( | ||||||
|                 request, |                 request, | ||||||
|                 'Error terminating VM %s' % (opennebula_vm_id) |                 'Error terminating VM %s' % (opennebula_vm_id) | ||||||
|             ) |             ) | ||||||
|             return HttpResponseRedirect(self.get_success_url()) |             response['status'] = False | ||||||
|         context = { |         else: | ||||||
|             'vm': vm_data, |             context = { | ||||||
|             'base_url': "{0}://{1}".format(self.request.scheme, |                 'vm': vm_data, | ||||||
|                                            self.request.get_host()), |                 'base_url': "{0}://{1}".format(self.request.scheme, | ||||||
|             'page_header': _('Virtual Machine Cancellation') |                                                self.request.get_host()), | ||||||
|         } |                 'page_header': _('Virtual Machine Cancellation') | ||||||
|         email_data = { |             } | ||||||
|             'subject': context['page_header'], |             email_data = { | ||||||
|             'to': self.request.user.email, |                 'subject': context['page_header'], | ||||||
|             'context': context, |                 'to': self.request.user.email, | ||||||
|             'template_name': 'vm_canceled', |                 'context': context, | ||||||
|             'template_path': 'hosting/emails/', |                 'template_name': 'vm_canceled', | ||||||
|             'from_address': settings.DCL_SUPPORT_FROM_ADDRESS, |                 'template_path': 'hosting/emails/', | ||||||
|         } |                 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS, | ||||||
|         email = BaseEmail(**email_data) |             } | ||||||
|         email.send() |             email = BaseEmail(**email_data) | ||||||
|  |             email.send() | ||||||
| 
 | 
 | ||||||
|         messages.error( |             # messages.error( | ||||||
|             request, |             #     request, | ||||||
|             _('VM %(VM_ID)s terminated successfully') % { |             #     _('VM %(VM_ID)s terminated successfully') % { | ||||||
|                 'VM_ID': opennebula_vm_id} |             #         '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, | class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin, | ||||||
|                           ListView): |                           ListView): | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue