merged master

This commit is contained in:
Arvind Tiwari 2017-10-03 18:54:47 +05:30
commit 6802e2fdbc
26 changed files with 294 additions and 395 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-28 18:36+0530\n"
"POT-Creation-Date: 2017-10-03 18:54+0530\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"
@ -308,8 +308,8 @@ msgstr "Alle Benachrichtigungen"
msgid "%(page_header_text)s"
msgstr ""
msgid "Invoice Date"
msgstr "Rechnung Datum"
msgid "Date"
msgstr "Datum"
msgid "Status"
msgstr ""
@ -332,6 +332,9 @@ msgstr "Bezahlmethode"
msgid "ending in"
msgstr "endend in"
msgid "Credit Card"
msgstr "Kreditkarte"
msgid "Order summary"
msgstr "Bestellungsübersicht"
@ -339,7 +342,7 @@ msgid "Product"
msgstr "Produkt"
msgid "Period"
msgstr ""
msgstr "Periode"
msgid "Cores"
msgstr "Prozessorkerne"
@ -385,9 +388,6 @@ 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"
@ -412,9 +412,6 @@ msgstr "inkl. Mehrwertsteuer"
msgid "Billing Address"
msgstr "Rechnungsadresse"
msgid "Credit Card"
msgstr "Kreditkarte"
msgid ""
"\n"
" Please fill in your credit card information "
@ -604,8 +601,10 @@ msgstr "Um eine neue VM zu erzeugen, klicke \"Neue VM erzeugen\""
#, python-format
msgid ""
"To access your VM, add your SSH key <a href=\"%(create_ssh_url)s\">here</a>"
"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 "login"
msgstr "anmelden"
@ -661,6 +660,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."
@ -685,65 +694,29 @@ msgid ""
"contact Data Center Light Support."
msgstr "Kontaktiere den Data Center Light Support."
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"
#, fuzzy, python-format
#| msgid "Virtual Machine Cancellation"
#, python-format
msgid "Virtual Machine %(vm_name)s Cancelled"
msgstr "VM Kündigung"
msgstr "Virtuelle Maschine %(vm_name)s Kündigung"
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 "My VM page"
#~ msgstr "Meine VM page"
#~ msgid ""
#~ "\n"
#~ "You're receiving this email because you requested a password reset for "
#~ "your user account at %(site_name)s.<br/>\n"
#~ "Please go to the following page and choose a new password: %(base_url)s"
#~ "%(password_reset_url)s<br/>\n"
#~ "If you didn't request a new password, ignore this e-mail.<br/>\n"
#~ "Thank you!\n"
#~ msgstr ""
#~ "\n"
#~ "Du erhälst diese E-Mail da Du Dein Passwort für Deinen Account bei "
#~ "%(site_name)s zurücksetzen möchtest.<br/>\n"
#~ "Bitte folge diesem Link und wähle ein neues Passwort: %(base_url)s"
#~ "%(password_reset_url)s Solltest Du kein neues Passwort angefordert haben, "
#~ "dann ignoriere diese E-Mail.<br/>\n"
#~ "Dankeschön!\n"
#~ msgid ""
#~ "You're receiving this email because you requested a password reset for "
#~ "your user account at %(site_name)s.\n"
#~ "Please go to the following page and choose a new password: %(base_url)s"
#~ "%(password_reset_url)s\n"
#~ "If you didn't request a new password, ignore this e-mail.\n"
#~ "Thank you!\n"
#~ msgstr ""
#~ "Du erhälst diese E-Mail da Du Dein Passwort für Deinen Account bei "
#~ "%(site_name)s zurücksetzen möchtest.\n"
#~ "Bitte folge diesem Link und wähle ein neues Passwort: %(base_url)s"
#~ "%(password_reset_url)s Solltest Du kein neues Passwort angefordert haben, "
#~ "dann ignoriere diese E-Mail.\n"
#~ "Dankeschön!\n"
#~ msgid ""
#~ "You're receiving this mail because your virtual machine [%(vm_name)s] has "
#~ "been cancelled.\n"
#~ "You can see your order status by clicking here\n"
#~ "%(base_url)s%(vm_order_url)s\n"
#~ "If you want to order a new virtual machine, you can do it by clicking "
#~ "this link.\n"
#~ "%(base_url)s%(my_virtual_machines_url)s\n"
#~ msgstr ""
#~ "Du erhälst diese E-Mail, da Deine virtuelle Maschine [%(vm_name)s] "
#~ "gekündigt wurde.\n"
#~ "Um Deinen Auftragsstatus zu sehen, klicke hier.\n"
#~ "%(base_url)s%(vm_order_url)s\n"
#~ "Falls Du eine neue virtuelle Maschine bestellen möchtest, kannst Du dies "
#~ "tun, indem Du diesen Link klickst.\n"
#~ "%(base_url)s%(my_virtual_machines_url)s\n"
#~ msgid "Invoice Date"
#~ msgstr "Rechnung Datum"
#~ msgid "VM %(VM_ID)s terminated successfully"
#~ msgstr "VM %(VM_ID)s erfolgreich beendet"

View file

@ -88,19 +88,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

@ -656,7 +656,6 @@ a.unlink:hover {
.card-element {
margin-bottom: 10px;
padding: 0;
}
.card-element label{

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
@ -271,7 +270,8 @@ class SignupValidatedView(SignupValidateView):
user = CustomUser.objects.filter(
validation_slug=self.kwargs['validate_slug']).first()
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"),
@ -653,10 +653,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(
@ -704,7 +701,13 @@ 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']
)
except VMDetail.DoesNotExist:
try:
manager = OpenNebulaManager(
@ -767,7 +770,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
@ -785,8 +787,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)
@ -805,12 +806,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,
@ -821,8 +834,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',
@ -1025,6 +1037,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 = {
@ -1034,7 +1047,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)
@ -1144,3 +1161,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())