merged master

This commit is contained in:
Arvind Tiwari 2017-10-03 18:42:00 +05:30
commit 734a41a371
25 changed files with 330 additions and 370 deletions

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-24 12:34+0000\n"
"POT-Creation-Date: 2017-10-01 22:12+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -331,12 +331,15 @@ msgstr "Alle Benachrichtigungen"
msgid "%(page_header_text)s"
msgstr ""
msgid "Invoice Date"
msgstr "Rechnung Datum"
msgid "Date"
msgstr "Datum"
msgid "Status"
msgstr ""
msgid "Terminated"
msgstr "Beendet"
msgid "Approved"
msgstr "Akzeptiert"
@ -352,12 +355,18 @@ msgstr "Bezahlmethode"
msgid "ending in"
msgstr "endend in"
msgid "Credit Card"
msgstr "Kreditkarte"
msgid "Order summary"
msgstr "Bestellungsübersicht"
msgid "Product"
msgstr "Produkt"
msgid "Period"
msgstr "Periode"
msgid "Cores"
msgstr "Prozessorkerne"
@ -390,15 +399,18 @@ msgstr "Abarbeitung..."
msgid "Hold tight, we are processing your request"
msgstr "Bitte warten - wir bearbeiten Deine Anfrage gerade"
msgid "OK"
msgstr ""
msgid "Close"
msgstr "Schliessen"
msgid "Some problem encountered. Please try again later."
msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal."
msgid "Order Nr."
msgstr "Bestellung Nr."
msgid "Date"
msgstr "Datum"
msgid "Amount"
msgstr "Betrag"
@ -423,9 +435,6 @@ msgstr "inkl. Mehrwertsteuer"
msgid "Billing Address"
msgstr "Rechnungsadresse"
msgid "Credit Card"
msgstr "Kreditkarte"
msgid ""
"\n"
" Please fill in your credit card information "
@ -599,16 +608,13 @@ msgstr "Deine Virtuelle Maschine beenden"
msgid "Do you want to cancel your Virtual Machine"
msgstr "Bist Du sicher, dass Du Deine virtuelle Maschine beenden willst"
msgid "OK"
msgstr ""
#, python-format
msgid ""
"Your Virtual Machine <strong>%(machine_name)s</strong> is successfully "
"terminated!"
msgstr ""
"Deine Virtuelle Machine (VM) <strong>%(machine_name)s</strong> wurde erfolgreich "
"beendet!"
"Deine Virtuelle Machine (VM) <strong>%(machine_name)s</strong> wurde "
"erfolgreich beendet!"
msgid "Virtual Machines"
msgstr "Virtuelle Maschinen"
@ -616,6 +622,13 @@ msgstr "Virtuelle Maschinen"
msgid "To create a new virtual machine, click \"Create VM\""
msgstr "Um eine neue VM zu erzeugen, klicke \"Neue VM erzeugen\""
#, python-format
msgid ""
"To access your VM, <a href=\"%(create_ssh_url)s\">add your SSH key here</a>"
msgstr ""
"Um auf Deine VM zuzugreifen, <a href=\"%(create_ssh_url)s\">füge Deinen SSH-"
"Key hinzu</a>"
msgid "CREATE VM"
msgstr "NEUE VM"
@ -673,6 +686,16 @@ msgid "In order to create a VM, you need to create/upload your SSH KEY first."
msgstr ""
"Um eine VM zu erstellen musst du zuerst einen SSH-Key erstellen / hochladen."
msgid "Error."
msgstr "Fehler"
msgid ""
"There was a payment related error. On close of this popup, you will be "
"redirected back to the payment page."
msgstr ""
"Es ist ein Fehler bei der Zahlung betreten. Du wirst nach dem Schliessen vom "
"Popup zur Bezahlseite weitergeleitet"
msgid "Thank you for the order."
msgstr "Danke für Deine Bestellung."
@ -697,8 +720,11 @@ msgid ""
"contact Data Center Light Support."
msgstr "Kontaktiere den Data Center Light Support."
msgid "Terminated"
msgstr "Beendet"
msgid ""
"We could not find the requested VM. Please contact Data Center Light Support."
msgstr ""
"Wir konnten die gesucht VM nicht finden. Kontaktiere den Data Center Light "
"Support."
msgid "Error terminating VM"
msgstr "Fehler beenden VM"
@ -706,8 +732,13 @@ msgstr "Fehler beenden VM"
msgid "Virtual Machine Cancellation"
msgstr "VM Kündigung"
#~ msgid "Close"
#~ msgstr "Schliessen"
msgid "There was an error processing your request. Please try again."
msgstr ""
"Es gab einen Fehler bei der Bearbeitung Deine Anfrage. Bitte versuche es "
"noch einmal."
#~ msgid "Invoice Date"
#~ msgstr "Rechnung Datum"
#~ msgid "VM %(VM_ID)s terminated successfully"
#~ msgstr "VM %(VM_ID)s erfolgreich beendet"
@ -842,5 +873,5 @@ msgstr "VM Kündigung"
#~ "Your SSH private key was already generated and downloaded, if you lost "
#~ "it, contact us. "
#~ msgstr ""
#~ "Dein privater SSH Key wurde bereits generiert und heruntergeladen. "
#~ "Falls Du ihn verloren hast, kontaktiere uns."
#~ "Dein privater SSH Key wurde bereits generiert und heruntergeladen. Falls "
#~ "Du ihn verloren hast, kontaktiere uns."

View file

@ -90,19 +90,19 @@ class HostingOrder(AssignPermissionsMixin, models.Model):
self.cc_brand = stripe_charge.source.brand
self.save()
def set_subscription_id(self, subscription_object, cc_details):
def set_subscription_id(self, subscription_id, cc_details):
"""
When creating a Stripe subscription, we have subscription id.
We store this in the subscription_id field.
This method sets the subscription id from subscription_object
and also the last4 and credit card brands used for this order.
This method sets the subscription id
and the last4 and credit card brands used for this order.
:param subscription_object: Stripe's subscription object
:param subscription_id: Stripe's subscription id
:param cc_details: A dict containing card details
{last4, brand}
:return:
"""
self.subscription_id = subscription_object.id
self.subscription_id = subscription_id
self.last4 = cc_details.get('last4')
self.cc_brand = cc_details.get('brand')
self.save()

View file

@ -86,23 +86,31 @@ $(document).ready(function() {
url: create_vm_form.attr('action'),
type: 'POST',
data: create_vm_form.serialize(),
init: function(){
ok_btn = $('#createvm-modal-done-btn');
close_btn = $('#createvm-modal-close-btn');
ok_btn.addClass('btn btn-success btn-ok btn-wide hide');
close_btn.addClass('btn btn-danger btn-ok btn-wide hide');
},
success: function (data) {
fa_icon = $('.modal-icon > .fa');
modal_btn = $('#createvm-modal-done-btn');
$('#createvm-modal-title').text(data.msg_title);
$('#createvm-modal-body').html(data.msg_body);
modal_btn.attr('href', data.redirect)
.removeClass('hide');
if (data.status === true) {
fa_icon = $('.modal-icon > .fa');
fa_icon.attr('class', 'checkmark');
// $('.modal-header > .close').removeClass('hidden');
$('#createvm-modal-title').text(data.msg_title);
$('#createvm-modal-body').text(data.msg_body);
$('#createvm-modal-done-btn')
.attr('href', data.redirect)
.removeClass('hide');
} else {
fa_icon.attr('class', 'fa fa-close');
modal_btn.attr('class', '').addClass('btn btn-danger btn-ok btn-wide');
}
},
error: function (xmlhttprequest, textstatus, message) {
fa_icon = $('.modal-icon > .fa');
fa_icon.attr('class', 'fa fa-close');
if (typeof(create_vm_error_message) !== 'undefined') {
$('#createvm-modal-text').text(create_vm_error_message);
$('#createvm-modal-body').text(create_vm_error_message);
}
$('#btn-create-vm').prop('disabled', false);
$('#createvm-modal-close-btn').removeClass('hide');

View file

@ -0,0 +1,8 @@
{% if messages %}
<ul class="list-unstyled msg-list">
{% for message in messages %}
<div
class="alert {% if message.tags and message.tags == 'error' %} alert-danger {% else %} alert-{{message.tags}} {% endif %}">{{ message|safe }}</div>
{% endfor %}
</ul>
{% endif %}

View file

@ -16,13 +16,7 @@
<div class="auth-content">
<div class="intro-message auth-box">
<h2 class="section-heading">{% trans "Login"%}</h2>
{% if messages %}
<ul class="list-unstyled msg-list">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% include 'hosting/includes/_messages.html' %}
<form action="{% url 'hosting:login' %}" method="post" class="form" novalidated>
{% csrf_token %}
{% for field in form %}

View file

@ -17,10 +17,12 @@
<h1 class="dashboard-title-thin">
<img src="{% static 'hosting/img/billing.svg' %}" class="un-icon">{% blocktrans with page_header_text=page_header_text|default:"Invoice" %}{{page_header_text}}{% endblocktrans %}
</h1>
<div class="dashboard-container-options">
<button type="button" class="btn-plain btn-pdf" data-target="#order-detail{{order.pk}}"><img src="{% static 'hosting/img/icon-pdf.svg' %}" class="svg-img"></button>
<button type="button" class="btn-plain btn-print"><img src="{% static 'hosting/img/icon-print.svg' %}" class="svg-img"></button>
</div>
{% if order %}
<div class="dashboard-container-options">
<button type="button" class="btn-plain btn-pdf" data-target="#order-detail{{order.pk}}"><img src="{% static 'hosting/img/icon-pdf.svg' %}" class="svg-img"></button>
<button type="button" class="btn-plain btn-print"><img src="{% static 'hosting/img/icon-print.svg' %}" class="svg-img"></button>
</div>
{% endif %}
</div>
<div class="order-details">
{% if order %}
@ -29,7 +31,7 @@
</p>
{% endif %}
<p>
<strong>{% trans "Invoice Date" %}:</strong>
<strong>{% trans "Date" %}:</strong>
<span id="order-created_at">
{% if order %}
{{order.created_at|date:'Y-m-d H:i'}}
@ -80,8 +82,7 @@
{{order.last4}}<br>
{{user.email}}
{% else %}
{{cc_brand|default:'Card'}} {% trans "ending in" %} ****
{{cc_last4}}<br>
{{cc_brand|default:_('Credit Card')}} {% trans "ending in" %} ****{{cc_last4}}<br>
{% if request.user.is_authenticated %}
{{request.user.email}}
{% else %}
@ -94,7 +95,12 @@
<div>
<h4>{% trans "Order summary" %}</h4>
<p>
<strong>{% trans "Product" %}:</strong> {{vm.name}}
<strong>{% trans "Product" %}:</strong>&nbsp;
{% if vm.name %}
{{ vm.name }}
{% else %}
{{ request.session.template.name }}
{% endif %}
</p>
<div class="row">
<div class="col-sm-6">
@ -132,19 +138,21 @@
{% endif %}
</div>
{% if not order %}
<form method="post" id="virtual_machine_create_form">
{% csrf_token %}
<div class="row">
<div class="col-sm-8">
<div class="dcl-place-order-text">{% blocktrans with vm_price=request.session.specs.price %}By clicking "Place order" this plan will charge your credit card account with the fee of {{ vm_price }}CHF/month{% endblocktrans %}.</div>
{% block submit_btn %}
<form method="post" id="virtual_machine_create_form">
{% csrf_token %}
<div class="row">
<div class="col-sm-8">
<div class="dcl-place-order-text">{% blocktrans with vm_price=request.session.specs.price %}By clicking "Place order" this plan will charge your credit card account with the fee of {{ vm_price }}CHF/month{% endblocktrans %}.</div>
</div>
<div class="col-sm-4 order-confirm-btn text-right">
<button class="btn choice-btn" id="btn-create-vm" data-href="{% url 'hosting:order-confirmation' %}" data-toggle="modal" data-target="#createvm-modal">
{% trans "Place order" %}
</button>
</div>
</div>
<div class="col-sm-4 order-confirm-btn text-right">
<button class="btn choice-btn" id="btn-create-vm" data-href="{% url 'hosting:order-confirmation' %}" data-toggle="modal" data-target="#createvm-modal">
{% trans "Place order" %}
</button>
</div>
</div>
</form>
</form>
{% endblock submit_btn %}
{% endif %}
{% endif %}
</div>
@ -197,8 +205,10 @@
{%endblock%}
{% block js_extra %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="{% static 'hosting/js/html2pdf.js' %}"></script>
<script src="{% static 'hosting/js/order.js' %}"></script>
{% if order %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="{% static 'hosting/js/html2pdf.js' %}"></script>
<script src="{% static 'hosting/js/order.js' %}"></script>
{% endif %}
{% endblock js_extra %}

View file

@ -17,6 +17,7 @@
<div class="auth-content">
<div class="intro-message auth-box sign-up">
<h2 class="section-heading">{% trans "Resend activation link"%}</h2>
{% include 'hosting/includes/_messages.html' %}
<form action="{% url 'hosting:resend_activation_link' %}" method="post" class="form" novalidate>
{% csrf_token %}
{% for field in form %}

View file

@ -17,6 +17,7 @@
<div class="auth-content">
<div class="intro-message auth-box sign-up">
<h2 class="section-heading">{% trans "Reset your password"%}</h2>
{% include 'hosting/includes/_messages.html' %}
<form action="{% url 'hosting:reset_password' %}" method="post" class="form" novalidate>
{% csrf_token %}
{% for field in form %}

View file

@ -15,6 +15,7 @@
<div class="auth-content">
<div class="intro-message auth-box sign-up">
<h2 class="section-heading">{% trans "Sign up"%}</h2>
{% include 'hosting/includes/_messages.html' %}
<form action="{% url 'hosting:signup' %}" method="post" class="form" novalidate>
{% csrf_token %}
{% for field in form %}

View file

@ -11,6 +11,7 @@
<div class="auth-center">
<div class="auth-title">
<h2>{% trans "Your VM hosted in Switzerland"%}</h2>
{% include 'hosting/includes/_messages.html' %}
</div>
<div class="auth-content">
<div class="intro-message auth-box sign-up">

View file

@ -16,7 +16,7 @@
<p>{% trans 'To create a new virtual machine, click "Create VM"' %}
{% if show_create_ssh_key_msg %}
{% url 'hosting:create_ssh_key' as create_ssh_url %}
<br/>{% blocktrans %}To access your VM, add your SSH key <a href="{{create_ssh_url}}">here</a>{% endblocktrans %}
<br/>{% blocktrans %}To access your VM, <a href="{{create_ssh_url}}">add your SSH key here</a>{% endblocktrans %}
{% endif %}
</p>
<div class="text-right">

View file

@ -60,8 +60,9 @@ CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \
minutes."
class DashboardView(View):
class DashboardView(LoginRequiredMixin, View):
template_name = "hosting/dashboard.html"
login_url = reverse_lazy('hosting:login')
def get_context_data(self, **kwargs):
context = {}
@ -80,8 +81,6 @@ class DjangoHostingView(ProcessVMSelectionMixin, View):
templates = OpenNebulaManager().get_templates()
data = VirtualMachineTemplateSerializer(templates, many=True).data
configuration_options = HostingPlan.get_serialized_configs()
# configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING)
context = {
'hosting': HOSTING,
'hosting_long': "Django",
@ -134,7 +133,6 @@ class NodeJSHostingView(ProcessVMSelectionMixin, View):
def get_context_data(self, **kwargs):
HOSTING = 'nodejs'
# configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING)
templates = OpenNebulaManager().get_templates()
configuration_options = HostingPlan.get_serialized_configs()
@ -249,7 +247,8 @@ class SignupValidateView(TemplateView):
<br />{go_back} {hurl}.'.format(
signup_success_message=_(
'Thank you for signing up. We have sent an email to you. '
'Please follow the instructions in it to activate your account. Once activated, you can login using'),
'Please follow the instructions in it to activate your '
'account. Once activated, you can login using'),
go_back=_('Go back to'),
lurl=login_url,
hurl=home_url
@ -269,7 +268,8 @@ class SignupValidatedView(SignupValidateView):
reverse('hosting:login') + '">' + str(_('login')) + '</a>'
section_title = _('Account activation')
if validated:
message = '{account_activation_string} <br /> {login_string} {lurl}.'.format(
message = ('{account_activation_string} <br />'
' {login_string} {lurl}.').format(
account_activation_string=_(
"Your account has been activated."),
login_string=_("You can now"),
@ -636,10 +636,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
return HttpResponseRedirect(
reverse('hosting:payment') + '#payment_error')
# Create Billing Address
billing_address = form.save()
request.session['billing_address_data'] = billing_address_data
request.session['billing_address'] = billing_address.id
request.session['token'] = token
request.session['customer'] = customer.id
return HttpResponseRedirect("{url}?{query_params}".format(
@ -687,10 +684,12 @@ class OrdersHostingDetailView(LoginRequiredMixin,
try:
vm_detail = VMDetail.objects.get(vm_id=obj.vm_id)
context['vm'] = vm_detail.__dict__
context['vm']['name'] = (
'{}-{}'.format(
context['vm']['configuration'], context['vm']['vm_id']
)
context['vm']['name'] = '{}-{}'.format(
context['vm']['configuration'], context['vm']['vm_id'])
context['vm']['price'] = get_vm_price(
cpu=context['vm']['cores'],
disk_size=context['vm']['disk_size'],
memory=context['vm']['memory']
)
context['subscription_end_date'] = vm_detail.end_date()
except VMDetail.DoesNotExist:
@ -755,7 +754,6 @@ class OrdersHostingDetailView(LoginRequiredMixin,
stripe_customer_id = request.session.get('customer')
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
billing_address_data = request.session.get('billing_address_data')
billing_address_id = request.session.get('billing_address')
vm_template_id = template.get('id', 1)
# Make stripe charge to a customer
@ -773,8 +771,7 @@ class OrdersHostingDetailView(LoginRequiredMixin,
cpu = specs.get('cpu')
memory = specs.get('memory')
disk_size = specs.get('disk_size')
amount_to_be_charged = get_vm_price(cpu=cpu, memory=memory,
disk_size=disk_size)
amount_to_be_charged = specs.get('price')
plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu,
memory=memory,
disk_size=disk_size)
@ -793,12 +790,24 @@ class OrdersHostingDetailView(LoginRequiredMixin,
'response_object').stripe_plan_id}])
stripe_subscription_obj = subscription_result.get('response_object')
# Check if the subscription was approved and is active
if stripe_subscription_obj is None or stripe_subscription_obj.status != 'active':
if (stripe_subscription_obj is None or
stripe_subscription_obj.status != 'active'):
msg = subscription_result.get('error')
messages.add_message(self.request, messages.ERROR, msg,
extra_tags='failed_payment')
return HttpResponseRedirect(
reverse('hosting:payment') + '#payment_error')
response = {
'status': False,
'redirect': "{url}#{section}".format(
url=reverse('hosting:payment'),
section='payment_error'),
'msg_title': str(_('Error.')),
'msg_body': str(
_('There was a payment related error.'
' On close of this popup, you will be redirected back to'
' the payment page.'))
}
return HttpResponse(json.dumps(response),
content_type="application/json")
user = {
'name': self.request.user.name,
'email': self.request.user.email,
@ -809,8 +818,7 @@ class OrdersHostingDetailView(LoginRequiredMixin,
}
create_vm_task.delay(vm_template_id, user, specs, template,
stripe_customer_id, billing_address_data,
billing_address_id,
stripe_subscription_obj, card_details_dict)
stripe_subscription_obj.id, card_details_dict)
for session_var in ['specs', 'template', 'billing_address',
'billing_address_data',
@ -1013,6 +1021,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
return redirect(reverse('hosting:virtual_machines'))
elif self.request.is_ajax():
return HttpResponse()
context = None
try:
serializer = VirtualMachineSerializer(vm)
context = {
@ -1022,7 +1031,11 @@ class VirtualMachineView(LoginRequiredMixin, View):
}
except Exception as ex:
logger.debug("Exception generated {}".format(str(ex)))
pass
messages.error(self.request,
_('We could not find the requested VM. Please '
'contact Data Center Light Support.')
)
return redirect(reverse('hosting:virtual_machines'))
return render(request, self.template_name, context)
@ -1130,3 +1143,15 @@ class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin,
bill.total_price += vm['price']
context['vms'] = vms
return context
def forbidden_view(request, exception=None, reason=''):
"""
Handle 403 error
"""
logger.error(str(exception) if exception else None)
logger.error('Reason = {reason}'.format(reason=reason))
err_msg = _('There was an error processing your request. Please try '
'again.')
messages.add_message(request, messages.ERROR, err_msg)
return HttpResponseRedirect(request.get_full_path())