Merge branch 'master' into task/3530/upgrade_to_django_1.11
This commit is contained in:
commit
4069199252
18 changed files with 164 additions and 109 deletions
|
@ -2,6 +2,12 @@ Next:
|
||||||
* #3911: [dcl] Integrate resend activation link into dcl landing payment page
|
* #3911: [dcl] Integrate resend activation link into dcl landing payment page
|
||||||
* #3972: [hosting] Add ungleich company info to invoice footer
|
* #3972: [hosting] Add ungleich company info to invoice footer
|
||||||
* #3974: [hosting] Improve invoice number: Show 404 for invoice resources that do not belong to the user
|
* #3974: [hosting] Improve invoice number: Show 404 for invoice resources that do not belong to the user
|
||||||
|
* [ungleich] Add video cover to the header on ungleich.ch landing page and add corresponding cms plugin
|
||||||
|
* #3774: [hosting] Update Stripe subscription on vm delete
|
||||||
|
* [ungleich] Update text on landing page
|
||||||
|
* #3601: [dcl, hosting] Change minimum required RAM from 2GB to 1GB
|
||||||
|
* #3973: [dcl] Update datacenterlight and glasfaser contact address to Linthal and company name to "ungleich glarus ag"
|
||||||
|
* #3993: [dg] Fix new user membership payment by setting cardholder_name field for UserBillingAddressForm
|
||||||
1.2.13: 2017-12-09
|
1.2.13: 2017-12-09
|
||||||
* [cms] Introduce UngleichHeaderBackgroundImageAndTextSliderPlugin that allows to have scrolling images and texts
|
* [cms] Introduce UngleichHeaderBackgroundImageAndTextSliderPlugin that allows to have scrolling images and texts
|
||||||
* [cms] Remove <p> tag for ungleich cms customer item template
|
* [cms] Remove <p> tag for ungleich cms customer item template
|
||||||
|
|
|
@ -56,11 +56,11 @@ msgstr "Standort: Schweiz"
|
||||||
msgid "Please enter a value in range 1 - 48."
|
msgid "Please enter a value in range 1 - 48."
|
||||||
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
|
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
|
||||||
|
|
||||||
msgid "Please enter a value in range 2 - 200."
|
msgid "Please enter a value in range 1 - 200."
|
||||||
msgstr "Bitte gib einen Wert von 2 bis 200 ein."
|
msgstr "Bitte gib einen Wert von 1 bis 200 ein."
|
||||||
|
|
||||||
msgid "Please enter a value in range 10 - 2000."
|
msgid "Please enter a value in range 10 - 2000."
|
||||||
msgstr "Bitte gib einen Wert von 10 bis 200 ein."
|
msgstr "Bitte gib einen Wert von 10 bis 2000 ein."
|
||||||
|
|
||||||
msgid "GB Storage (SSD)"
|
msgid "GB Storage (SSD)"
|
||||||
msgstr "GB Storage (SSD)"
|
msgstr "GB Storage (SSD)"
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
'ram': {
|
'ram': {
|
||||||
'id': 'ramValue',
|
'id': 'ramValue',
|
||||||
'value': 2,
|
'value': 2,
|
||||||
'min': 2,
|
'min': 1,
|
||||||
'max': 200,
|
'max': 200,
|
||||||
'interval': 1
|
'interval': 1
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="description input">
|
<div class="description input">
|
||||||
<i class="fa fa-minus-circle left" data-minus="ram" aria-hidden="true"></i>
|
<i class="fa fa-minus-circle left" data-minus="ram" aria-hidden="true"></i>
|
||||||
<input id="ramValue" class="input-price select-number" type="number" min="2" max="200" name="ram"
|
<input id="ramValue" class="input-price select-number" type="number" min="1" max="200" name="ram"
|
||||||
data-error="{% trans 'Please enter a value in range 2 - 200.' %}" required>
|
data-error="{% trans 'Please enter a value in range 1 - 200.' %}" required>
|
||||||
<span> GB RAM</span>
|
<span> GB RAM</span>
|
||||||
<i class="fa fa-plus-circle right" data-plus="ram" aria-hidden="true"></i>
|
<i class="fa fa-plus-circle right" data-plus="ram" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -160,11 +160,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="contact-details">
|
<div class="contact-details">
|
||||||
<div class="subtitle">
|
<div class="subtitle">
|
||||||
<h3>ungleich GmbH</h3>
|
<h3>ungleich glarus ag</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>info@datacenterlight.ch</p>
|
<p>info@datacenterlight.ch</p>
|
||||||
<p>In der Au 7, Schwanden 8762</p>
|
<p>Bahnhofstrasse 1, 8783 Linthal</p>
|
||||||
<p>{% trans "Switzerland " %}</p>
|
<p>{% trans "Switzerland " %}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -209,7 +209,7 @@ class IndexView(CreateView):
|
||||||
raise ValidationError(_('Invalid number of cores'))
|
raise ValidationError(_('Invalid number of cores'))
|
||||||
|
|
||||||
def validate_memory(self, value):
|
def validate_memory(self, value):
|
||||||
if (value > 200) or (value < 2):
|
if (value > 200) or (value < 1):
|
||||||
raise ValidationError(_('Invalid RAM size'))
|
raise ValidationError(_('Invalid RAM size'))
|
||||||
|
|
||||||
def validate_storage(self, value):
|
def validate_storage(self, value):
|
||||||
|
|
|
@ -376,6 +376,10 @@ class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
charge = charge_response.get('response_object')
|
charge = charge_response.get('response_object')
|
||||||
|
if 'source' in charge:
|
||||||
|
cardholder_name = charge['source']['name']
|
||||||
|
else:
|
||||||
|
cardholder_name = customer.user.name
|
||||||
|
|
||||||
# Create Billing Address
|
# Create Billing Address
|
||||||
billing_address = form.save()
|
billing_address = form.save()
|
||||||
|
@ -383,7 +387,8 @@ class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
|
||||||
# Create Billing Address for User if he does not have one
|
# Create Billing Address for User if he does not have one
|
||||||
if not customer.user.billing_addresses.count():
|
if not customer.user.billing_addresses.count():
|
||||||
data.update({
|
data.update({
|
||||||
'user': customer.user.id
|
'user': customer.user.id,
|
||||||
|
'cardholder_name': cardholder_name
|
||||||
})
|
})
|
||||||
billing_address_user_form = UserBillingAddressForm(data)
|
billing_address_user_form = UserBillingAddressForm(data)
|
||||||
billing_address_user_form.is_valid()
|
billing_address_user_form.is_valid()
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2017-10-26 03:21+0530\n"
|
"POT-Creation-Date: 2017-12-21 00:23+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -128,11 +128,11 @@ msgstr "MwSt. inklusive"
|
||||||
msgid "Please enter a value in range 1 - 48."
|
msgid "Please enter a value in range 1 - 48."
|
||||||
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
|
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
|
||||||
|
|
||||||
msgid "Please enter a value in range 2 - 200."
|
msgid "Please enter a value in range 1 - 200."
|
||||||
msgstr "Bitte gib einen Wert von 2 bis 200 ein."
|
msgstr "Bitte gib einen Wert von 1 bis 200 ein."
|
||||||
|
|
||||||
msgid "Please enter a value in range 10 - 2000."
|
msgid "Please enter a value in range 10 - 2000."
|
||||||
msgstr "Bitte gib einen Wert von 10 bis 200 ein."
|
msgstr "Bitte gib einen Wert von 10 bis 2000 ein."
|
||||||
|
|
||||||
msgid "GB Storage (SSD)"
|
msgid "GB Storage (SSD)"
|
||||||
msgstr "GB Storage (SSD)"
|
msgstr "GB Storage (SSD)"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
'ram': {
|
'ram': {
|
||||||
'id': 'ramValue',
|
'id': 'ramValue',
|
||||||
'value': 2,
|
'value': 2,
|
||||||
'min': 2,
|
'min': 1,
|
||||||
'max': 200,
|
'max': 200,
|
||||||
'interval': 1
|
'interval': 1
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="description input">
|
<div class="description input">
|
||||||
<i class="fa fa-minus left" data-minus="ram" aria-hidden="true"></i>
|
<i class="fa fa-minus left" data-minus="ram" aria-hidden="true"></i>
|
||||||
<input id="ramValue" class="input-price select-number" type="number" min="2" max="200" name="ram"
|
<input id="ramValue" class="input-price select-number" type="number" min="1" max="200" name="ram"
|
||||||
data-error="{% trans 'Please enter a value in range 2 - 200.' %}" required>
|
data-error="{% trans 'Please enter a value in range 1 - 200.' %}" required>
|
||||||
<span> GB RAM</span>
|
<span> GB RAM</span>
|
||||||
<i class="fa fa-plus right" data-plus="ram" aria-hidden="true"></i>
|
<i class="fa fa-plus right" data-plus="ram" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -41,6 +41,7 @@ from utils.forms import (
|
||||||
from utils.hosting_utils import get_vm_price
|
from utils.hosting_utils import get_vm_price
|
||||||
from utils.mailer import BaseEmail
|
from utils.mailer import BaseEmail
|
||||||
from utils.stripe_utils import StripeUtils
|
from utils.stripe_utils import StripeUtils
|
||||||
|
from utils.tasks import send_plain_email_task
|
||||||
from utils.views import (
|
from utils.views import (
|
||||||
PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin,
|
PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin,
|
||||||
ResendActivationLinkViewMixin
|
ResendActivationLinkViewMixin
|
||||||
|
@ -945,7 +946,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
||||||
raise ValidationError(_('Invalid number of cores'))
|
raise ValidationError(_('Invalid number of cores'))
|
||||||
|
|
||||||
def validate_memory(self, value):
|
def validate_memory(self, value):
|
||||||
if (value > 200) or (value < 2):
|
if (value > 200) or (value < 1):
|
||||||
raise ValidationError(_('Invalid RAM size'))
|
raise ValidationError(_('Invalid RAM size'))
|
||||||
|
|
||||||
def validate_storage(self, value):
|
def validate_storage(self, value):
|
||||||
|
@ -1036,7 +1037,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print(error)
|
logger.error(str(error))
|
||||||
raise Http404()
|
raise Http404()
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
|
@ -1079,49 +1080,88 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
response = {'status': False}
|
response = {'status': False}
|
||||||
|
admin_email_body = {}
|
||||||
owner = self.request.user
|
owner = self.request.user
|
||||||
vm = self.get_object()
|
vm = self.get_object()
|
||||||
|
|
||||||
opennebula_vm_id = self.kwargs.get('pk')
|
|
||||||
|
|
||||||
manager = OpenNebulaManager(
|
manager = OpenNebulaManager(
|
||||||
email=owner.email,
|
email=owner.email,
|
||||||
password=owner.password
|
password=owner.password
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
|
vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
|
||||||
vm_name = vm_data.get('name')
|
vm_name = vm_data.get('name')
|
||||||
except WrongIdError:
|
except WrongIdError as wrong_id_err:
|
||||||
|
logger.error(str(wrong_id_err))
|
||||||
return redirect(reverse('hosting:virtual_machines'))
|
return redirect(reverse('hosting:virtual_machines'))
|
||||||
|
|
||||||
|
# Cancel Stripe subscription
|
||||||
|
stripe_utils = StripeUtils()
|
||||||
|
try:
|
||||||
|
hosting_order = HostingOrder.objects.get(
|
||||||
|
vm_id=vm.id
|
||||||
|
)
|
||||||
|
result = stripe_utils.unsubscribe_customer(
|
||||||
|
subscription_id=hosting_order.subscription_id
|
||||||
|
)
|
||||||
|
stripe_subscription_obj = result.get('response_object')
|
||||||
|
# Check if the subscription was canceled
|
||||||
|
if (stripe_subscription_obj is None or
|
||||||
|
stripe_subscription_obj.status != 'canceled'):
|
||||||
|
error_msg = result.get('error')
|
||||||
|
logger.error(
|
||||||
|
'Error canceling subscription for {user} and vm id '
|
||||||
|
'{vm_id}'.format(user=owner.email, vm_id=vm.id)
|
||||||
|
)
|
||||||
|
logger.error(error_msg)
|
||||||
|
admin_email_body['stripe_error_msg'] = error_msg
|
||||||
|
except HostingOrder.DoesNotExist:
|
||||||
|
error_msg = (
|
||||||
|
"HostingOrder corresponding to vm_id={vm_id} does"
|
||||||
|
"not exist. Hence, can not find subscription to "
|
||||||
|
"cancel ".format(vm_id=vm.id)
|
||||||
|
)
|
||||||
|
logger.error(error_msg)
|
||||||
|
admin_email_body['stripe_error_msg'] = error_msg
|
||||||
|
|
||||||
terminated = manager.delete_vm(vm.id)
|
terminated = manager.delete_vm(vm.id)
|
||||||
|
|
||||||
if not terminated:
|
if not terminated:
|
||||||
response['text'] = ugettext(
|
logger.debug(
|
||||||
'Error terminating VM') + opennebula_vm_id
|
"manager.delete_vm returned False. Hence, error making "
|
||||||
|
"xml-rpc call to delete vm failed."
|
||||||
|
)
|
||||||
|
response['text'] = ugettext('Error terminating VM') + vm.id
|
||||||
else:
|
else:
|
||||||
for t in range(15):
|
for t in range(15):
|
||||||
try:
|
try:
|
||||||
manager.get_vm(opennebula_vm_id)
|
manager.get_vm(vm.id)
|
||||||
except WrongIdError:
|
except WrongIdError:
|
||||||
response['status'] = True
|
response['status'] = True
|
||||||
response['text'] = ugettext('Terminated')
|
response['text'] = ugettext('Terminated')
|
||||||
vm_detail_obj = VMDetail.objects.filter(
|
vm_detail_obj = VMDetail.objects.filter(
|
||||||
vm_id=opennebula_vm_id).first()
|
vm_id=vm.id
|
||||||
|
).first()
|
||||||
vm_detail_obj.terminated_at = datetime.utcnow()
|
vm_detail_obj.terminated_at = datetime.utcnow()
|
||||||
vm_detail_obj.save()
|
vm_detail_obj.save()
|
||||||
break
|
except BaseException as base_exception:
|
||||||
except BaseException:
|
logger.error(
|
||||||
|
"manager.get_vm({vm_id}) returned exception: "
|
||||||
|
"{details}.".format(
|
||||||
|
details=str(base_exception), vm_id=vm.id
|
||||||
|
)
|
||||||
|
)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
sleep(2)
|
sleep(2)
|
||||||
context = {
|
context = {
|
||||||
'vm_name': vm_name,
|
'vm_name': vm_name,
|
||||||
'base_url': "{0}://{1}".format(self.request.scheme,
|
'base_url': "{0}://{1}".format(
|
||||||
self.request.get_host()),
|
self.request.scheme, self.request.get_host()
|
||||||
|
),
|
||||||
'page_header': _('Virtual Machine %(vm_name)s Cancelled') % {
|
'page_header': _('Virtual Machine %(vm_name)s Cancelled') % {
|
||||||
'vm_name': vm_name}
|
'vm_name': vm_name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
email_data = {
|
email_data = {
|
||||||
'subject': context['page_header'],
|
'subject': context['page_header'],
|
||||||
|
@ -1133,6 +1173,18 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
||||||
}
|
}
|
||||||
email = BaseEmail(**email_data)
|
email = BaseEmail(**email_data)
|
||||||
email.send()
|
email.send()
|
||||||
|
admin_email_body.update(response)
|
||||||
|
email_to_admin_data = {
|
||||||
|
'subject': "Deleted VM and Subscription for VM {vm_id} and "
|
||||||
|
"user: {user}".format(
|
||||||
|
vm_id=vm.id, user=owner.email
|
||||||
|
),
|
||||||
|
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
|
||||||
|
'to': ['info@ungleich.ch'],
|
||||||
|
'body': "\n".join(
|
||||||
|
["%s=%s" % (k, v) for (k, v) in admin_email_body.items()]),
|
||||||
|
}
|
||||||
|
send_plain_email_task.delay(email_to_admin_data)
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
json.dumps(response),
|
json.dumps(response),
|
||||||
content_type="application/json"
|
content_type="application/json"
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2017-12-22 01:00+0530\n"
|
"POT-Creation-Date: 2017-12-23 05:18+0530\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -71,14 +71,14 @@ msgstr "Die Chronik von ungleich"
|
||||||
msgid "The first incarnation of ungleich"
|
msgid "The first incarnation of ungleich"
|
||||||
msgstr "Die erste Inkarnation von ungleich"
|
msgstr "Die erste Inkarnation von ungleich"
|
||||||
|
|
||||||
msgid "in Germany"
|
msgid "in Germany."
|
||||||
msgstr "in Deutschland"
|
msgstr "in Deutschland."
|
||||||
|
|
||||||
msgid "ungleich founded"
|
msgid "ungleich founded"
|
||||||
msgstr "ungleich gegründet"
|
msgstr "ungleich gegründet"
|
||||||
|
|
||||||
msgid "in Switzerland"
|
msgid "in Switzerland."
|
||||||
msgstr "in der Schweiz"
|
msgstr "in der Schweiz."
|
||||||
|
|
||||||
msgid "ungleich present at various conferences"
|
msgid "ungleich present at various conferences"
|
||||||
msgstr "ungleich präsent an mehreren Konferenzen"
|
msgstr "ungleich präsent an mehreren Konferenzen"
|
||||||
|
@ -107,7 +107,7 @@ msgstr "ungleich bietet einen PC-Grundkurs für Flüchtlinge an."
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"ungleich starts computer learning club for locals, \"Digitale Building "
|
"ungleich starts computer learning club for locals, \"Digitale Building "
|
||||||
"ungleich.\""
|
"ungleich\"."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"ungleich gründet den Verein Digitale Bildung ungleich für Ortsansässige."
|
"ungleich gründet den Verein Digitale Bildung ungleich für Ortsansässige."
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ msgid ""
|
||||||
"startup in canton Zürich."
|
"startup in canton Zürich."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"ungleich verkauft das Projekt <a href=\"https://www.alplora.ch/de/"
|
"ungleich verkauft das Projekt <a href=\"https://www.alplora.ch/de/"
|
||||||
"\">AlpLora</a> an ein IoT-Startup aus dem Kanton Zürich"
|
"\">AlpLora</a> an ein IoT-Startup aus dem Kanton Zürich."
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"ungleich showcases the most affordable Swiss VM hosting, Data Center Light."
|
"ungleich showcases the most affordable Swiss VM hosting, Data Center Light."
|
||||||
|
@ -157,8 +157,37 @@ msgstr "Copyright © ungleich GmbH"
|
||||||
msgid "ungleich Home"
|
msgid "ungleich Home"
|
||||||
msgstr "ungleich Home"
|
msgstr "ungleich Home"
|
||||||
|
|
||||||
msgid "We Design, Configure & Maintain<br>Your Linux Infrastructure "
|
msgid "Hosting"
|
||||||
msgstr "Wir designen, erstellen und warten<br>Ihre Linux-Infrastruktur"
|
msgstr "Hosting"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Ruby on Rails. Java hosting, Django hosting, we make it everything run "
|
||||||
|
"smooth and safe."
|
||||||
|
msgstr ""
|
||||||
|
"Ruby on Rails. Java hosting, Django hosting, wir garantieren einen "
|
||||||
|
"reibungslosen Ablauf."
|
||||||
|
|
||||||
|
msgid "Configuration as a Service"
|
||||||
|
msgstr "Konfiguration als Service"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that "
|
||||||
|
"needs to configured, we provide comprehensive solutions. Amazon, rackspace "
|
||||||
|
"or bare metal servers, we configure for you."
|
||||||
|
msgstr ""
|
||||||
|
"Ruby on Rails, Django, Java, Webserver, Mailserver, jegliche Infrastruktur "
|
||||||
|
"welche eine Konfiguration braucht, wir offerieren umfassende Lösungen, "
|
||||||
|
"Amazon, Rackspace oder Bare Metal Servers, wir konfigurieren alles."
|
||||||
|
|
||||||
|
msgid "Linux System Engineering"
|
||||||
|
msgstr "Linux System Engineering"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Let your developers develop! We take care of your system administration. "
|
||||||
|
"Gentoo, Archlinux, Debian, Ubuntu, and many more."
|
||||||
|
msgstr ""
|
||||||
|
"Lassen sie ihre Entwickler entwickeln! Wir kümmern uns um ihre "
|
||||||
|
"Systemadministration. Gentoo, Archlinux, Debian, Ubuntu und viele mehr."
|
||||||
|
|
||||||
msgid "Our Products"
|
msgid "Our Products"
|
||||||
msgstr "Unsere Produkte"
|
msgstr "Unsere Produkte"
|
||||||
|
@ -216,38 +245,6 @@ msgstr ""
|
||||||
"Unser erstklassiges Konfigurationsmanagement ist erfrischend einfach und "
|
"Unser erstklassiges Konfigurationsmanagement ist erfrischend einfach und "
|
||||||
"zuverlässig."
|
"zuverlässig."
|
||||||
|
|
||||||
msgid "Hosting"
|
|
||||||
msgstr "Hosting"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Ruby on Rails. Java hosting, Django hosting, we make it everything run "
|
|
||||||
"smooth and safe."
|
|
||||||
msgstr ""
|
|
||||||
"Ruby on Rails. Java hosting, Django hosting, wir garantieren einen "
|
|
||||||
"reibungslosen Ablauf"
|
|
||||||
|
|
||||||
msgid "Configuration as a Service"
|
|
||||||
msgstr "Konfiguration als Service"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that "
|
|
||||||
"needs to configured, we provide comprehensive solutions. Amazon, rackspace "
|
|
||||||
"or bare metal servers, we configure for you."
|
|
||||||
msgstr ""
|
|
||||||
"Ruby on Rails, Django, Java, Webserver, Mailserver, jegliche Infrastruktur "
|
|
||||||
"welche eine Konfiguration braucht, wir offerieren umfassende Lösungen, "
|
|
||||||
"Amazon, Rackspace oder Bare Metal Servers, wir konfigurieren alles."
|
|
||||||
|
|
||||||
msgid "Linux System Engineering"
|
|
||||||
msgstr "Linux System Engineering"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Let your developers develop! We take care of your system administration. "
|
|
||||||
"Gentoo, Archlinux, Debian, Ubuntu, and many more."
|
|
||||||
msgstr ""
|
|
||||||
"Lassen sie ihre Entwickler entwickeln! Wir kümmern uns um ihre "
|
|
||||||
"Systemadministration. Gentoo, Archlinux, Debian, Ubuntu und viele mehr."
|
|
||||||
|
|
||||||
msgid "Why ungleich?*"
|
msgid "Why ungleich?*"
|
||||||
msgstr "Warum ungleich?"
|
msgstr "Warum ungleich?"
|
||||||
|
|
||||||
|
@ -363,6 +360,9 @@ msgid "If you have any question, just send us an email."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wenn Sie irgendwelche Fragen haben, schicken Sie uns einfach eine E-Mail."
|
"Wenn Sie irgendwelche Fragen haben, schicken Sie uns einfach eine E-Mail."
|
||||||
|
|
||||||
|
#~ msgid "We Design, Configure & Maintain<br>Your Linux Infrastructure "
|
||||||
|
#~ msgstr "Wir designen, erstellen und warten<br>Ihre Linux-Infrastruktur"
|
||||||
|
|
||||||
#~ msgid "Hosting Products "
|
#~ msgid "Hosting Products "
|
||||||
#~ msgstr "Hosting Produkte"
|
#~ msgstr "Hosting Produkte"
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Migration(migrations.Migration):
|
||||||
blank=True, help_text='Text for the button, if a link is provided.', max_length=50, null=True)),
|
blank=True, help_text='Text for the button, if a link is provided.', max_length=50, null=True)),
|
||||||
('heading', models.CharField(
|
('heading', models.CharField(
|
||||||
blank=True, help_text='An optional title for this slide.', max_length=100, null=True)),
|
blank=True, help_text='An optional title for this slide.', max_length=100, null=True)),
|
||||||
('video', filer.fields.file.FilerFileField(blank=True, help_text='Leavig this blank will make the image as the background.',
|
('video', filer.fields.file.FilerFileField(blank=True, help_text='Leaving this blank will make the image as the background.',
|
||||||
null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ungleich_header_item_video', to='filer.File')),
|
null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ungleich_header_item_video', to='filer.File')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
|
|
@ -372,7 +372,7 @@ section h3.section-subheading {
|
||||||
|
|
||||||
@media(min-width:768px) {
|
@media(min-width:768px) {
|
||||||
section {
|
section {
|
||||||
padding: 125px 0;
|
padding: 80px 0;
|
||||||
}
|
}
|
||||||
section h2.section-heading {
|
section h2.section-heading {
|
||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
|
|
|
@ -220,11 +220,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="contact-details">
|
<div class="contact-details">
|
||||||
<div class="subtitle">
|
<div class="subtitle">
|
||||||
<h3>ungleich GmbH</h3>
|
<h3>ungleich glarus ag</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>glasfaser@ungleich.ch</p>
|
<p>glasfaser@ungleich.ch</p>
|
||||||
<p>In der Au 7, Schwanden 8762</p>
|
<p>Bahnhofstrasse 1, 8783 Linthal</p>
|
||||||
<p>Switzerland</p>
|
<p>Switzerland</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-body">
|
<div class="timeline-body">
|
||||||
<p>{% trans "The first incarnation of ungleich" %}</p>
|
<p>{% trans "The first incarnation of ungleich" %}</p>
|
||||||
<p>{% trans "in Germany" %}</p>
|
<p>{% trans "in Germany." %}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-body">
|
<div class="timeline-body">
|
||||||
<p>{% trans "ungleich founded" %} </p>
|
<p>{% trans "ungleich founded" %} </p>
|
||||||
<p>{% trans "in Switzerland" %}</p>
|
<p>{% trans "in Switzerland." %}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
<h4>2014</h4>
|
<h4>2014</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-body">
|
<div class="timeline-body">
|
||||||
<p>{% trans "ungleich present at various conferences" %}: <br><a href="http://www.linuxtag.org/2014/en/program/talk-details/?eventid=1238">Linuxtag</a>, <a href="https://www.usenix.org/conference/ucms14/summit-program/presentation/schottelius">UCMS</a>, Linux Erfa, <a href="https://www.ethz.ch/en.html">ETH Zurich</a><br>
|
<p>{% trans "ungleich present at various conferences" %}: <br><a href="http://www.linuxtag.org/2014/en/program/talk-details/?eventid=1238">Linuxtag</a>, <a href="https://www.usenix.org/conference/ucms14/summit-program/presentation/schottelius">UCMS</a>, Linux Erfa, <a href="https://www.ethz.ch/en.html">ETH Zurich</a>.<br>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
<p>{% trans "and introduces affordable 24X7 support." %}</p>
|
<p>{% trans "and introduces affordable 24X7 support." %}</p>
|
||||||
<p>
|
<p>
|
||||||
{% trans "ungleich launches" %}
|
{% trans "ungleich launches" %}
|
||||||
<a href="https://digitalglarus.ch">{% trans "Digital Glarus project" %}</a>
|
<a href="https://digitalglarus.ch">{% trans "Digital Glarus project" %}</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -93,19 +93,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="timeline-inverted">
|
|
||||||
<div class="timeline-image">
|
|
||||||
<img class="img-circle img-responsive" src="{% static 'ungleich_page/img/about/2017a.jpg' %}">
|
|
||||||
</div>
|
|
||||||
<div class="timeline-panel wow slideInRight">
|
|
||||||
<div class="timeline-heading">
|
|
||||||
<h4>2017</h4>
|
|
||||||
</div>
|
|
||||||
<div class="timeline-body">
|
|
||||||
<p>{% trans 'ungleich starts computer learning club for locals, "Digitale Building ungleich."' %}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li class="timeline-inverted">
|
<li class="timeline-inverted">
|
||||||
<div class="timeline-image">
|
<div class="timeline-image">
|
||||||
<img class="img-circle img-responsive" src="{% static 'ungleich_page/img/about/2017b.jpg' %}">
|
<img class="img-circle img-responsive" src="{% static 'ungleich_page/img/about/2017b.jpg' %}">
|
||||||
|
@ -115,6 +102,7 @@
|
||||||
<h4>2017</h4>
|
<h4>2017</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-body">
|
<div class="timeline-body">
|
||||||
|
<p>{% trans 'ungleich starts computer learning club for locals, "Digitale Building ungleich".' %}</p>
|
||||||
<p>{% blocktrans %}ungleich sells <a href="https://www.alplora.ch/de/">Alplora</a> to an IoT startup in canton Zürich.{% endblocktrans %}</p>
|
<p>{% blocktrans %}ungleich sells <a href="https://www.alplora.ch/de/">Alplora</a> to an IoT startup in canton Zürich.{% endblocktrans %}</p>
|
||||||
<p>{% trans "ungleich showcases the most affordable Swiss VM hosting, Data Center Light." %}</p>
|
<p>{% trans "ungleich showcases the most affordable Swiss VM hosting, Data Center Light." %}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,11 +18,8 @@
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="intro-cap">
|
<div class="intro-cap">{% trans "Hosting" %}</div>
|
||||||
{% trans "We Design, Configure & Maintain<br>Your Linux Infrastructure " %}
|
<p class="intro_lead">{% trans "Ruby on Rails. Java hosting, Django hosting, we make it everything run smooth and safe." %}</p>
|
||||||
</div>
|
|
||||||
<p class="intro_lead">Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that needs to configured, we provide comprehensive solutions. Amazon, rackspace or bare metal servers, we configure for you.</p>
|
|
||||||
<a class="btn btn-trans" href="">Learn More</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
|
@ -33,11 +30,9 @@
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="intro-cap">
|
<div class="intro-cap">{% trans "Configuration as a Service" %}</div>
|
||||||
{% trans "We Design, Configure & Maintain<br>Your Linux Infrastructure " %}
|
<p class="intro_lead">{% trans "Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that needs to configured, we provide comprehensive solutions. Amazon, rackspace or bare metal servers, we configure for you." %}</p>
|
||||||
</div>
|
<!-- <a class="btn btn-trans" href="">Learn More</a> -->
|
||||||
<p class="intro_lead">Ruby on Rails, Django, Nothing else.</p>
|
|
||||||
<a class="btn btn-trans" href="">Learn More</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
|
@ -47,10 +42,8 @@
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="intro-cap">
|
<div class="intro-cap">{% trans "Linux System Engineering" %}</div>
|
||||||
{% trans "We Design, Configure & Maintain<br>Your Linux Infrastructure " %}
|
<p class="intro_lead">{% trans "Let your developers develop! We take care of your system administration. Gentoo, Archlinux, Debian, Ubuntu, and many more." %}</p>
|
||||||
</div>
|
|
||||||
<a class="btn btn-trans" href="">Learn More</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -232,6 +232,17 @@ class StripeUtils(object):
|
||||||
)
|
)
|
||||||
return subscription_result
|
return subscription_result
|
||||||
|
|
||||||
|
@handleStripeError
|
||||||
|
def unsubscribe_customer(self, subscription_id):
|
||||||
|
"""
|
||||||
|
Cancels a given subscription
|
||||||
|
|
||||||
|
:param subscription_id: The Stripe subscription id string
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
sub = stripe.Subscription.retrieve(subscription_id)
|
||||||
|
return sub.delete()
|
||||||
|
|
||||||
@handleStripeError
|
@handleStripeError
|
||||||
def make_payment(self, customer, amount, token):
|
def make_payment(self, customer, amount, token):
|
||||||
charge = self.stripe.Charge.create(
|
charge = self.stripe.Charge.create(
|
||||||
|
|
Loading…
Add table
Reference in a new issue