Merge master into task/3934/move_hosting_order_out_of_celery_task
and resolve some conflicts
This commit is contained in:
commit
2cd73b313a
45 changed files with 1148 additions and 674 deletions
18
Changelog
18
Changelog
|
@ -1,3 +1,21 @@
|
||||||
|
Next:
|
||||||
|
* bugfix: Fix flake8 error that was ignored in release 1.9.1
|
||||||
|
1.9.1: 2018-06-24
|
||||||
|
* #4799: [dcl] Show selected vm templates only in calculator (PR #638)
|
||||||
|
* #4847: [comic] Add google analytics code for comic.ungleich.ch (PR #639)
|
||||||
|
* feature: add vm_type option to vm_template and dcl calculator to distinguish between public and ipv6only templates (PR #635)
|
||||||
|
1.9: 2018-05-16
|
||||||
|
* #4559: [cms] enable discount on cms calculator
|
||||||
|
1.8: 2018-05-01
|
||||||
|
* #4527: [hosting] cms calculator on non-cms pages for the hosting app
|
||||||
|
* bgfix: [dcl] navbar dropdown target fix
|
||||||
|
* bgfix: [hosting] login/signup pages footer link fix
|
||||||
|
1.7.2: 2018-04-30
|
||||||
|
* bgfix: [cms] add favicon extension to ungleich cms pages
|
||||||
|
* #4474: [cms] reduce heading slider side padding
|
||||||
|
1.7.1: 2018-04-21
|
||||||
|
* #4481: [blog] fix de blog pages 500 error
|
||||||
|
* #4370: [comic] new url /comic to show only comic blogs
|
||||||
1.7: 2018-04-20
|
1.7: 2018-04-20
|
||||||
* bgfix: [all] Make /blog available on all domains
|
* bgfix: [all] Make /blog available on all domains
|
||||||
* #4367: [dcl] email logo resolution fix
|
* #4367: [dcl] email logo resolution fix
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.contrib import admin
|
||||||
from cms.admin.placeholderadmin import PlaceholderAdminMixin
|
from cms.admin.placeholderadmin import PlaceholderAdminMixin
|
||||||
from cms.extensions import PageExtensionAdmin
|
from cms.extensions import PageExtensionAdmin
|
||||||
from .cms_models import CMSIntegration, CMSFaviconExtension
|
from .cms_models import CMSIntegration, CMSFaviconExtension
|
||||||
from .models import VMPricing
|
from .models import VMPricing, VMTemplate
|
||||||
|
|
||||||
|
|
||||||
class CMSIntegrationAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
|
class CMSIntegrationAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
|
||||||
|
@ -16,3 +16,4 @@ class CMSFaviconExtensionAdmin(PageExtensionAdmin):
|
||||||
admin.site.register(CMSIntegration, CMSIntegrationAdmin)
|
admin.site.register(CMSIntegration, CMSIntegrationAdmin)
|
||||||
admin.site.register(CMSFaviconExtension, CMSFaviconExtensionAdmin)
|
admin.site.register(CMSFaviconExtension, CMSFaviconExtensionAdmin)
|
||||||
admin.site.register(VMPricing)
|
admin.site.register(VMPricing)
|
||||||
|
admin.site.register(VMTemplate)
|
||||||
|
|
|
@ -2,6 +2,9 @@ from cms.extensions import PageExtension
|
||||||
from cms.extensions.extension_pool import extension_pool
|
from cms.extensions.extension_pool import extension_pool
|
||||||
from cms.models.fields import PlaceholderField
|
from cms.models.fields import PlaceholderField
|
||||||
from cms.models.pluginmodel import CMSPlugin
|
from cms.models.pluginmodel import CMSPlugin
|
||||||
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -9,7 +12,7 @@ from djangocms_text_ckeditor.fields import HTMLField
|
||||||
from filer.fields.file import FilerFileField
|
from filer.fields.file import FilerFileField
|
||||||
from filer.fields.image import FilerImageField
|
from filer.fields.image import FilerImageField
|
||||||
|
|
||||||
from datacenterlight.models import VMPricing
|
from datacenterlight.models import VMPricing, VMTemplate
|
||||||
|
|
||||||
|
|
||||||
class CMSIntegration(models.Model):
|
class CMSIntegration(models.Model):
|
||||||
|
@ -26,6 +29,10 @@ class CMSIntegration(models.Model):
|
||||||
navbar_placeholder = PlaceholderField(
|
navbar_placeholder = PlaceholderField(
|
||||||
'datacenterlight_navbar', related_name='dcl-navbar-placeholder+'
|
'datacenterlight_navbar', related_name='dcl-navbar-placeholder+'
|
||||||
)
|
)
|
||||||
|
calculator_placeholder = PlaceholderField(
|
||||||
|
'datacenterlight_calculator',
|
||||||
|
related_name='dcl-calculator-placeholder+'
|
||||||
|
)
|
||||||
domain = models.ForeignKey(Site, null=True, blank=True)
|
domain = models.ForeignKey(Site, null=True, blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -288,10 +295,58 @@ class DCLSectionPromoPluginModel(CMSPlugin):
|
||||||
return extra_classes
|
return extra_classes
|
||||||
|
|
||||||
|
|
||||||
class DCLCustomPricingModel(CMSPlugin):
|
class MultipleChoiceArrayField(ArrayField):
|
||||||
|
"""
|
||||||
|
A field that allows us to store an array of choices.
|
||||||
|
Uses Django's Postgres ArrayField
|
||||||
|
and a MultipleChoiceField for its formfield.
|
||||||
|
"""
|
||||||
|
VMTemplateChoices = []
|
||||||
|
if settings.OPENNEBULA_DOMAIN != 'test_domain':
|
||||||
|
VMTemplateChoices = list(
|
||||||
|
(
|
||||||
|
str(obj.opennebula_vm_template_id),
|
||||||
|
(obj.name + ' - ' + VMTemplate.IPV6.title()
|
||||||
|
if obj.vm_type == VMTemplate.IPV6 else obj.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for obj in VMTemplate.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
def formfield(self, **kwargs):
|
||||||
|
defaults = {
|
||||||
|
'form_class': forms.MultipleChoiceField,
|
||||||
|
'choices': self.VMTemplateChoices,
|
||||||
|
}
|
||||||
|
defaults.update(kwargs)
|
||||||
|
# Skip our parent's formfield implementation completely as we don't
|
||||||
|
# care for it.
|
||||||
|
# pylint:disable=bad-super-call
|
||||||
|
return super(ArrayField, self).formfield(**defaults)
|
||||||
|
|
||||||
|
|
||||||
|
class DCLCalculatorPluginModel(CMSPlugin):
|
||||||
pricing = models.ForeignKey(
|
pricing = models.ForeignKey(
|
||||||
VMPricing,
|
VMPricing,
|
||||||
related_name="dcl_custom_pricing_vm_pricing",
|
related_name="dcl_custom_pricing_vm_pricing",
|
||||||
help_text='Choose a pricing that will be associated with this '
|
help_text='Choose a pricing that will be associated with this '
|
||||||
'Calculator'
|
'Calculator'
|
||||||
)
|
)
|
||||||
|
vm_type = models.CharField(
|
||||||
|
max_length=50, choices=VMTemplate.VM_TYPE_CHOICES,
|
||||||
|
default=VMTemplate.PUBLIC
|
||||||
|
)
|
||||||
|
vm_templates_to_show = MultipleChoiceArrayField(
|
||||||
|
base_field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
max_length=256,
|
||||||
|
),
|
||||||
|
default=list,
|
||||||
|
blank=True,
|
||||||
|
help_text="Recommended: If you wish to show all templates of the "
|
||||||
|
"corresponding VM Type (public/ipv6only), please do not "
|
||||||
|
"select any of the items in the above field. "
|
||||||
|
"This will allow any new template(s) added "
|
||||||
|
"in the backend to be automatically listed in this "
|
||||||
|
"calculator instance."
|
||||||
|
)
|
||||||
|
|
|
@ -6,9 +6,9 @@ from .cms_models import (
|
||||||
DCLFooterPluginModel, DCLLinkPluginModel, DCLNavbarDropdownPluginModel,
|
DCLFooterPluginModel, DCLLinkPluginModel, DCLNavbarDropdownPluginModel,
|
||||||
DCLSectionIconPluginModel, DCLSectionImagePluginModel,
|
DCLSectionIconPluginModel, DCLSectionImagePluginModel,
|
||||||
DCLSectionPluginModel, DCLNavbarPluginModel,
|
DCLSectionPluginModel, DCLNavbarPluginModel,
|
||||||
DCLSectionPromoPluginModel, DCLCustomPricingModel
|
DCLSectionPromoPluginModel, DCLCalculatorPluginModel
|
||||||
)
|
)
|
||||||
from .models import VMTemplate, VMPricing
|
from .models import VMTemplate
|
||||||
|
|
||||||
|
|
||||||
@plugin_pool.register_plugin
|
@plugin_pool.register_plugin
|
||||||
|
@ -21,7 +21,7 @@ class DCLSectionPlugin(CMSPluginBase):
|
||||||
allow_children = True
|
allow_children = True
|
||||||
child_classes = [
|
child_classes = [
|
||||||
'DCLSectionIconPlugin', 'DCLSectionImagePlugin',
|
'DCLSectionIconPlugin', 'DCLSectionImagePlugin',
|
||||||
'DCLSectionPromoPlugin', 'UngleichHTMLPlugin'
|
'DCLSectionPromoPlugin', 'UngleichHTMLPlugin', 'DCLCalculatorPlugin'
|
||||||
]
|
]
|
||||||
|
|
||||||
def render(self, context, instance, placeholder):
|
def render(self, context, instance, placeholder):
|
||||||
|
@ -30,14 +30,17 @@ class DCLSectionPlugin(CMSPluginBase):
|
||||||
)
|
)
|
||||||
context['children_to_side'] = []
|
context['children_to_side'] = []
|
||||||
context['children_to_content'] = []
|
context['children_to_content'] = []
|
||||||
|
context['children_calculator'] = []
|
||||||
if instance.child_plugin_instances is not None:
|
if instance.child_plugin_instances is not None:
|
||||||
right_children = [
|
right_children = [
|
||||||
'DCLSectionImagePluginModel',
|
'DCLSectionImagePluginModel',
|
||||||
'DCLSectionIconPluginModel'
|
'DCLSectionIconPluginModel',
|
||||||
]
|
]
|
||||||
for child in instance.child_plugin_instances:
|
for child in instance.child_plugin_instances:
|
||||||
if child.__class__.__name__ in right_children:
|
if child.__class__.__name__ in right_children:
|
||||||
context['children_to_side'].append(child)
|
context['children_to_side'].append(child)
|
||||||
|
elif child.plugin_type == 'DCLCalculatorPlugin':
|
||||||
|
context['children_calculator'].append(child)
|
||||||
else:
|
else:
|
||||||
context['children_to_content'].append(child)
|
context['children_to_content'].append(child)
|
||||||
return context
|
return context
|
||||||
|
@ -75,52 +78,28 @@ class DCLSectionPromoPlugin(CMSPluginBase):
|
||||||
@plugin_pool.register_plugin
|
@plugin_pool.register_plugin
|
||||||
class DCLCalculatorPlugin(CMSPluginBase):
|
class DCLCalculatorPlugin(CMSPluginBase):
|
||||||
module = "Datacenterlight"
|
module = "Datacenterlight"
|
||||||
name = "DCL Calculator Section Plugin"
|
name = "DCL Calculator Plugin"
|
||||||
model = DCLSectionPluginModel
|
model = DCLCalculatorPluginModel
|
||||||
render_template = "datacenterlight/cms/calculator.html"
|
render_template = "datacenterlight/cms/calculator.html"
|
||||||
cache = False
|
cache = False
|
||||||
allow_children = True
|
require_parent = True
|
||||||
child_classes = [
|
|
||||||
'DCLSectionPromoPlugin', 'UngleichHTMLPlugin', 'DCLCustomPricingPlugin'
|
|
||||||
]
|
|
||||||
|
|
||||||
def render(self, context, instance, placeholder):
|
def render(self, context, instance, placeholder):
|
||||||
context = super(DCLCalculatorPlugin, self).render(
|
context = super(DCLCalculatorPlugin, self).render(
|
||||||
context, instance, placeholder
|
context, instance, placeholder
|
||||||
)
|
)
|
||||||
context['templates'] = VMTemplate.objects.all()
|
ids = instance.vm_templates_to_show
|
||||||
context['children_to_content'] = []
|
if ids:
|
||||||
pricing_plugin_model = None
|
context['templates'] = VMTemplate.objects.filter(
|
||||||
if instance.child_plugin_instances is not None:
|
vm_type=instance.vm_type
|
||||||
context['children_to_content'].extend(
|
).filter(opennebula_vm_template_id__in=ids)
|
||||||
instance.child_plugin_instances
|
|
||||||
)
|
|
||||||
for child in instance.child_plugin_instances:
|
|
||||||
if child.__class__.__name__ == 'DCLCustomPricingModel':
|
|
||||||
# The second clause is just to make sure we pick up the
|
|
||||||
# most recent CustomPricing, if more than one is present
|
|
||||||
if (pricing_plugin_model is None or child.pricing_id >
|
|
||||||
pricing_plugin_model.model.pricing_id):
|
|
||||||
pricing_plugin_model = child
|
|
||||||
|
|
||||||
if pricing_plugin_model:
|
|
||||||
context['vm_pricing'] = VMPricing.get_vm_pricing_by_name(
|
|
||||||
name=pricing_plugin_model.pricing.name
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
context['vm_pricing'] = VMPricing.get_default_pricing()
|
context['templates'] = VMTemplate.objects.filter(
|
||||||
|
vm_type=instance.vm_type
|
||||||
|
)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@plugin_pool.register_plugin
|
|
||||||
class DCLCustomPricingPlugin(CMSPluginBase):
|
|
||||||
module = "Datacenterlight"
|
|
||||||
name = "DCL Custom Pricing Plugin"
|
|
||||||
model = DCLCustomPricingModel
|
|
||||||
render_plugin = False
|
|
||||||
|
|
||||||
|
|
||||||
@plugin_pool.register_plugin
|
@plugin_pool.register_plugin
|
||||||
class DCLBannerListPlugin(CMSPluginBase):
|
class DCLBannerListPlugin(CMSPluginBase):
|
||||||
module = "Datacenterlight"
|
module = "Datacenterlight"
|
||||||
|
|
|
@ -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: 2018-04-17 19:26+0000\n"
|
"POT-Creation-Date: 2018-05-12 21:43+0530\n"
|
||||||
"PO-Revision-Date: 2018-03-30 23:22+0000\n"
|
"PO-Revision-Date: 2018-03-30 23:22+0000\n"
|
||||||
"Last-Translator: b'Anonymous User <coder.purple+25@gmail.com>'\n"
|
"Last-Translator: b'Anonymous User <coder.purple+25@gmail.com>'\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -19,6 +19,9 @@ msgstr ""
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Translated-Using: django-rosetta 0.8.1\n"
|
"X-Translated-Using: django-rosetta 0.8.1\n"
|
||||||
|
|
||||||
|
msgid "CMS Favicon"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your New VM %(vm_name)s at Data Center Light"
|
msgid "Your New VM %(vm_name)s at Data Center Light"
|
||||||
msgstr "Deine neue VM %(vm_name)s bei Data Center Light"
|
msgstr "Deine neue VM %(vm_name)s bei Data Center Light"
|
||||||
|
@ -140,6 +143,9 @@ msgstr "Monat"
|
||||||
msgid "VAT included"
|
msgid "VAT included"
|
||||||
msgstr "MwSt. inklusive"
|
msgstr "MwSt. inklusive"
|
||||||
|
|
||||||
|
msgid "You save"
|
||||||
|
msgstr "Du sparst"
|
||||||
|
|
||||||
msgid "Hosted in Switzerland"
|
msgid "Hosted in Switzerland"
|
||||||
msgstr "Standort: Schweiz"
|
msgstr "Standort: Schweiz"
|
||||||
|
|
||||||
|
@ -314,6 +320,12 @@ msgstr "exkl. Mehrwertsteuer"
|
||||||
msgid "Month"
|
msgid "Month"
|
||||||
msgstr "Monat"
|
msgstr "Monat"
|
||||||
|
|
||||||
|
msgid "Discount"
|
||||||
|
msgstr "Rabatt"
|
||||||
|
|
||||||
|
msgid "Will be applied at checkout"
|
||||||
|
msgstr "wird an der Kasse angewendet"
|
||||||
|
|
||||||
msgid "Credit Card"
|
msgid "Credit Card"
|
||||||
msgstr "Kreditkarte"
|
msgstr "Kreditkarte"
|
||||||
|
|
||||||
|
@ -386,9 +398,10 @@ msgstr "Zwischensumme"
|
||||||
msgid "VAT"
|
msgid "VAT"
|
||||||
msgstr "Mehrwertsteuer"
|
msgstr "Mehrwertsteuer"
|
||||||
|
|
||||||
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"By clicking \"Place order\" this plan will charge your credit card account "
|
"By clicking \"Place order\" this plan will charge your credit card account "
|
||||||
"with the fee of %(vm_total_price)s CHF/month"
|
"with %(vm_total_price)s CHF/month"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
|
"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit "
|
||||||
"%(vm_total_price)s CHF pro Monat belastet"
|
"%(vm_total_price)s CHF pro Monat belastet"
|
||||||
|
|
|
@ -10,16 +10,28 @@ class Command(BaseCommand):
|
||||||
help = '''Fetches the VM templates from OpenNebula and populates the dcl
|
help = '''Fetches the VM templates from OpenNebula and populates the dcl
|
||||||
VMTemplate model'''
|
VMTemplate model'''
|
||||||
|
|
||||||
|
def get_templates(self, manager, prefix):
|
||||||
|
templates = manager.get_templates('%s-' % prefix)
|
||||||
|
dcl_vm_templates = []
|
||||||
|
for template in templates:
|
||||||
|
template_name = template.name.lstrip('%s-' % prefix)
|
||||||
|
template_id = template.id
|
||||||
|
dcl_vm_template = VMTemplate.create(
|
||||||
|
template_name, template_id, prefix
|
||||||
|
)
|
||||||
|
dcl_vm_templates.append(dcl_vm_template)
|
||||||
|
return dcl_vm_templates
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
try:
|
try:
|
||||||
manager = OpenNebulaManager()
|
manager = OpenNebulaManager()
|
||||||
templates = manager.get_templates()
|
|
||||||
dcl_vm_templates = []
|
dcl_vm_templates = []
|
||||||
for template in templates:
|
dcl_vm_templates.extend(
|
||||||
template_name = template.name.lstrip('public-')
|
self.get_templates(manager, VMTemplate.PUBLIC)
|
||||||
template_id = template.id
|
)
|
||||||
dcl_vm_template = VMTemplate.create(template_name, template_id)
|
dcl_vm_templates.extend(
|
||||||
dcl_vm_templates.append(dcl_vm_template)
|
self.get_templates(manager, VMTemplate.IPV6)
|
||||||
|
)
|
||||||
|
|
||||||
old_vm_templates = VMTemplate.objects.all()
|
old_vm_templates = VMTemplate.objects.all()
|
||||||
old_vm_templates.delete()
|
old_vm_templates.delete()
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2018-04-25 09:20
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import cms.models.fields
|
||||||
|
from django.db import migrations
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('datacenterlight', '0020_merge'),
|
||||||
|
('cms', '0014_auto_20160404_1908'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='cmsintegration',
|
||||||
|
name='calculator_placeholder',
|
||||||
|
field=cms.models.fields.PlaceholderField(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='dcl-calculator-placeholder+', slotname='datacenterlight_calculator', to='cms.Placeholder'),
|
||||||
|
),
|
||||||
|
migrations.RenameModel(
|
||||||
|
old_name='DCLCustomPricingModel',
|
||||||
|
new_name='DCLCalculatorPluginModel',
|
||||||
|
),
|
||||||
|
]
|
26
datacenterlight/migrations/0022_auto_20180506_1950.py
Normal file
26
datacenterlight/migrations/0022_auto_20180506_1950.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2018-05-07 02:19
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('datacenterlight', '0021_cmsintegration_calculator_placeholder'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vmpricing',
|
||||||
|
name='discount_amount',
|
||||||
|
field=models.DecimalField(
|
||||||
|
decimal_places=2, default=0, max_digits=6),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vmpricing',
|
||||||
|
name='discount_name',
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True),
|
||||||
|
),
|
||||||
|
]
|
25
datacenterlight/migrations/0023_auto_20180524_0349.py
Normal file
25
datacenterlight/migrations/0023_auto_20180524_0349.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2018-05-23 22:19
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('datacenterlight', '0022_auto_20180506_1950'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='dclcalculatorpluginmodel',
|
||||||
|
name='vm_type',
|
||||||
|
field=models.CharField(choices=[('public', 'Public'), ('ipv6only', 'Ipv6Only')], default='public', max_length=50),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vmtemplate',
|
||||||
|
name='vm_type',
|
||||||
|
field=models.CharField(choices=[('public', 'Public'), ('ipv6only', 'Ipv6Only')], default='public', max_length=50),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2018-06-24 08:23
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import datacenterlight.cms_models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('datacenterlight', '0023_auto_20180524_0349'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='dclcalculatorpluginmodel',
|
||||||
|
name='vm_templates_to_show',
|
||||||
|
field=datacenterlight.cms_models.MultipleChoiceArrayField(base_field=models.CharField(blank=True, max_length=256), blank=True, default=list, help_text='Recommended: If you wish to show all templates of the corresponding VM Type (public/ipv6only), please do not select any of the items in the above field. This will allow any new template(s) added in the backend to be automatically listed in this calculator instance.', size=None),
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,13 +6,29 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class VMTemplate(models.Model):
|
class VMTemplate(models.Model):
|
||||||
|
PUBLIC = 'public'
|
||||||
|
IPV6 = 'ipv6only'
|
||||||
|
VM_TYPE_CHOICES = (
|
||||||
|
(PUBLIC, PUBLIC.title()),
|
||||||
|
(IPV6, IPV6.title()),
|
||||||
|
)
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
opennebula_vm_template_id = models.IntegerField()
|
opennebula_vm_template_id = models.IntegerField()
|
||||||
|
vm_type = models.CharField(
|
||||||
|
max_length=50, choices=VM_TYPE_CHOICES, default=PUBLIC
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s - %s - %s' % (
|
||||||
|
self.opennebula_vm_template_id, self.vm_type, self.name
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, name, opennebula_vm_template_id):
|
def create(cls, name, opennebula_vm_template_id, vm_type):
|
||||||
vm_template = cls(
|
vm_template = cls(
|
||||||
name=name, opennebula_vm_template_id=opennebula_vm_template_id)
|
name=name, opennebula_vm_template_id=opennebula_vm_template_id,
|
||||||
|
vm_type=vm_type
|
||||||
|
)
|
||||||
return vm_template
|
return vm_template
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,16 +50,29 @@ class VMPricing(models.Model):
|
||||||
hdd_unit_price = models.DecimalField(
|
hdd_unit_price = models.DecimalField(
|
||||||
max_digits=7, decimal_places=6, default=0
|
max_digits=7, decimal_places=6, default=0
|
||||||
)
|
)
|
||||||
|
discount_name = models.CharField(max_length=255, null=True, blank=True)
|
||||||
|
discount_amount = models.DecimalField(
|
||||||
|
max_digits=6, decimal_places=2, default=0
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name + ' => ' + ' - '.join([
|
display_str = self.name + ' => ' + ' - '.join([
|
||||||
'{}/Core'.format(self.cores_unit_price.normalize()),
|
'{}/Core'.format(self.cores_unit_price.normalize()),
|
||||||
'{}/GB RAM'.format(self.ram_unit_price.normalize()),
|
'{}/GB RAM'.format(self.ram_unit_price.normalize()),
|
||||||
'{}/GB SSD'.format(self.ssd_unit_price.normalize()),
|
'{}/GB SSD'.format(self.ssd_unit_price.normalize()),
|
||||||
'{}/GB HDD'.format(self.hdd_unit_price.normalize()),
|
'{}/GB HDD'.format(self.hdd_unit_price.normalize()),
|
||||||
'{}% VAT'.format(self.vat_percentage.normalize())
|
'{}% VAT'.format(self.vat_percentage.normalize())
|
||||||
if not self.vat_inclusive else 'VAT-Incl', ]
|
if not self.vat_inclusive else 'VAT-Incl',
|
||||||
)
|
])
|
||||||
|
if self.discount_amount:
|
||||||
|
display_str = ' - '.join([
|
||||||
|
display_str,
|
||||||
|
'{} {}'.format(
|
||||||
|
self.discount_amount,
|
||||||
|
self.discount_name if self.discount_name else 'Discount'
|
||||||
|
)
|
||||||
|
])
|
||||||
|
return display_str
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_vm_pricing_by_name(cls, name):
|
def get_vm_pricing_by_name(cls, name):
|
||||||
|
|
|
@ -150,3 +150,12 @@ footer .dcl-link-separator::before {
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background: #777;
|
background: #777;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb-0 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thin-hr {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
|
@ -55,7 +55,7 @@
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_slider > .carousel .item .container {
|
.header_slider > .carousel .item .container-fluid {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 50px 20px 60px;
|
padding: 50px 20px 60px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -104,9 +104,9 @@
|
||||||
.header_slider .carousel-control .fa {
|
.header_slider .carousel-control .fa {
|
||||||
font-size: 4em;
|
font-size: 4em;
|
||||||
}
|
}
|
||||||
.header_slider > .carousel .item .container {
|
.header_slider > .carousel .item .container-fluid {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 75px 50px;
|
padding: 75px;
|
||||||
}
|
}
|
||||||
.header_slider .btn-trans {
|
.header_slider .btn-trans {
|
||||||
padding: 8px 15px;
|
padding: 8px 15px;
|
||||||
|
@ -120,11 +120,6 @@
|
||||||
.header_slider .intro-cap {
|
.header_slider .intro-cap {
|
||||||
font-size: 3.25em;
|
font-size: 3.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_slider > .carousel .item .container {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_slider .intro_lead {
|
.header_slider .intro_lead {
|
||||||
|
|
|
@ -482,6 +482,7 @@
|
||||||
margin: 100px auto 40px;
|
margin: 100px auto 40px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
padding: 30px 30px 20px;
|
padding: 30px 30px 20px;
|
||||||
|
color: #595959;
|
||||||
}
|
}
|
||||||
|
|
||||||
.order-detail-container .dashboard-title-thin {
|
.order-detail-container .dashboard-title-thin {
|
||||||
|
@ -503,10 +504,6 @@
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.order-detail-container .order-details strong {
|
|
||||||
color: #595959;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-detail-container h4 {
|
.order-detail-container h4 {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -515,13 +512,28 @@
|
||||||
|
|
||||||
.order-detail-container p {
|
.order-detail-container p {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
color: #595959;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.order-detail-container hr {
|
.order-detail-container hr {
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.order-detail-container .thin-hr {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-detail-container .subtotal-price {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-detail-container .subtotal-price .text-primary {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-detail-container .total-price {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.order-detail-container {
|
.order-detail-container {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
|
|
@ -776,7 +776,7 @@ textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1), 0 0 6px rgba(0, 0, 0, 0.15);
|
||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -929,7 +929,7 @@ textarea {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media(max-width:991px) {
|
@media(max-width:767px) {
|
||||||
.section-sm-center .split-text,
|
.section-sm-center .split-text,
|
||||||
.section-sm-center .space {
|
.section-sm-center .space {
|
||||||
text-align: center !important;
|
text-align: center !important;
|
||||||
|
|
|
@ -175,14 +175,18 @@
|
||||||
window.coresUnitPrice = 5;
|
window.coresUnitPrice = 5;
|
||||||
}
|
}
|
||||||
if(typeof window.ramUnitPrice === 'undefined'){
|
if(typeof window.ramUnitPrice === 'undefined'){
|
||||||
window.coresUnitPrice = 2;
|
window.ramUnitPrice = 2;
|
||||||
}
|
}
|
||||||
if(typeof window.ssdUnitPrice === 'undefined'){
|
if(typeof window.ssdUnitPrice === 'undefined'){
|
||||||
window.ssdUnitPrice = 0.6;
|
window.ssdUnitPrice = 0.6;
|
||||||
}
|
}
|
||||||
|
if(typeof window.discountAmount === 'undefined'){
|
||||||
|
window.discountAmount = 0;
|
||||||
|
}
|
||||||
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
|
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
|
||||||
(cardPricing['ram'].value * window.ramUnitPrice) +
|
(cardPricing['ram'].value * window.ramUnitPrice) +
|
||||||
(cardPricing['storage'].value * window.ssdUnitPrice);
|
(cardPricing['storage'].value * window.ssdUnitPrice) -
|
||||||
|
window.discountAmount;
|
||||||
total = parseFloat(total.toFixed(2));
|
total = parseFloat(total.toFixed(2));
|
||||||
$("#total").text(total);
|
$("#total").text(total);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endplaceholder %}
|
{% endplaceholder %}
|
||||||
|
|
||||||
|
{% url 'datacenterlight:index' as calculator_form_url %}
|
||||||
{% placeholder 'Datacenterlight Content' %}
|
{% placeholder 'Datacenterlight Content' %}
|
||||||
|
|
||||||
{% placeholder 'datacenterlight_footer'%}
|
{% placeholder 'datacenterlight_footer'%}
|
||||||
|
|
|
@ -1,16 +1,5 @@
|
||||||
<div class="split-section {{ instance.get_extra_classes }}" id="{{ instance.html_id }}">
|
<div class="price-calc-section">
|
||||||
<div class="container">
|
<div class="card">
|
||||||
<div class="row">
|
{% include "datacenterlight/includes/_calculator_form.html" with vm_pricing=instance.pricing %}
|
||||||
<div class="col-sm-6 {% if instance.text_direction == 'right' %}col-sm-push-6{% endif %} split-text">
|
|
||||||
{% include "datacenterlight/cms/includes/_section_split_content.html" %}
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6 {% if instance.text_direction == 'right' %}col-sm-pull-6{% endif %}">
|
|
||||||
<div class="price-calc-section">
|
|
||||||
<div class="card">
|
|
||||||
{% include "datacenterlight/includes/_calculator_form.html" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,7 +1,7 @@
|
||||||
{% load cms_tags %}
|
{% load cms_tags %}
|
||||||
|
|
||||||
<div class="dropdown highlights-dropdown">
|
<div class="dropdown highlights-dropdown">
|
||||||
<a class="dropdown-toggle url-init dcl-link" href="{{ instance.url|default:'#' }}" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ instance.text }} <span class="caret"></span></a>
|
<a class="dropdown-toggle url-init dcl-link" href="{{ instance.target|default:'#' }}" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ instance.text }} <span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
{% for plugin in instance.child_plugin_instances %}
|
{% for plugin in instance.child_plugin_instances %}
|
||||||
{% render_plugin plugin %}
|
{% render_plugin plugin %}
|
||||||
|
|
|
@ -2,17 +2,24 @@
|
||||||
|
|
||||||
<section class="split-section {{ instance.get_extra_classes }}" id="{{ instance.html_id }}">
|
<section class="split-section {{ instance.get_extra_classes }}" id="{{ instance.html_id }}">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% if children_to_side|length %}
|
{% if children_to_side|length or children_calculator|length %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 {% if instance.text_direction == 'right' %}col-sm-push-6{% endif %} split-text">
|
<div class="col-sm-6 {% if instance.text_direction == 'right' %}col-sm-push-6{% endif %} split-text">
|
||||||
{% include "datacenterlight/cms/includes/_section_split_content.html" %}
|
{% include "datacenterlight/cms/includes/_section_split_content.html" %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 {% if instance.text_direction == 'right' %}col-sm-pull-6{% endif %} split-figure">
|
<div class="col-sm-6 {% if instance.text_direction == 'right' %}col-sm-pull-6{% endif %} split-figure">
|
||||||
<div class="section-figure">
|
{% if children_calculator|length %}
|
||||||
{% for plugin in children_to_side %}
|
{% for plugin in children_calculator %}
|
||||||
{% render_plugin plugin %}
|
{% render_plugin plugin %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
{% endif %}
|
||||||
|
{% if children_to_side %}
|
||||||
|
<div class="section-figure">
|
||||||
|
{% for plugin in children_to_side %}
|
||||||
|
{% render_plugin plugin %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -8,22 +8,26 @@
|
||||||
window.ramUnitPrice = {{vm_pricing.ram_unit_price|default:0}};
|
window.ramUnitPrice = {{vm_pricing.ram_unit_price|default:0}};
|
||||||
window.ssdUnitPrice = {{vm_pricing.ssd_unit_price|default:0}};
|
window.ssdUnitPrice = {{vm_pricing.ssd_unit_price|default:0}};
|
||||||
window.hddUnitPrice = {{vm_pricing.hdd_unit_price|default:0}};
|
window.hddUnitPrice = {{vm_pricing.hdd_unit_price|default:0}};
|
||||||
|
window.discountAmount = {{vm_pricing.discount_amount|default:0}};
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<form id="order_form" method="POST" action="{% url 'datacenterlight:index' %}" data-toggle="validator" role="form">
|
<form id="order_form" method="POST" action="{{calculator_form_url}}" data-toggle="validator" role="form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<h3>{% trans "VM hosting" %} </h3>
|
<h3>{% trans "VM hosting" %} </h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="price">
|
<div class="price">
|
||||||
<span id="total">15</span>
|
<span id="total"></span>
|
||||||
<span>CHF/{% trans "month" %}</span>
|
<span>CHF/{% trans "month" %}</span>
|
||||||
{% if vm_pricing.vat_inclusive %}
|
|
||||||
<div class="price-text">
|
<div class="price-text">
|
||||||
<p>{% trans "VAT included" %}</p>
|
<p>
|
||||||
|
{% if vm_pricing.vat_inclusive %}{% trans "VAT included" %} <br>{% endif %}
|
||||||
|
{% if vm_pricing.discount_amount %}
|
||||||
|
{% trans "You save" %} {{ vm_pricing.discount_amount }} CHF
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptions">
|
<div class="descriptions">
|
||||||
<div class="description form-group">
|
<div class="description form-group">
|
||||||
|
|
|
@ -78,7 +78,24 @@
|
||||||
<hr>
|
<hr>
|
||||||
<p>{% trans "Configuration"%} <strong class="pull-right">{{request.session.template.name}}</strong></p>
|
<p>{% trans "Configuration"%} <strong class="pull-right">{{request.session.template.name}}</strong></p>
|
||||||
<hr>
|
<hr>
|
||||||
<p class="last-p"><strong>{%trans "Total" %}</strong> <small>({% if vm_pricing.vat_inclusive %}{%trans "including VAT" %}{% else %}{%trans "excluding VAT" %}{% endif %})</small> <strong class="pull-right">{{request.session.specs.price|intcomma}} CHF/{% trans "Month" %}</strong></p>
|
<p>
|
||||||
|
<strong>{%trans "Total" %}</strong>
|
||||||
|
<small>
|
||||||
|
({% if vm_pricing.vat_inclusive %}{%trans "including VAT" %}{% else %}{%trans "excluding VAT" %}{% endif %})
|
||||||
|
</small>
|
||||||
|
<strong class="pull-right">{{request.session.specs.price|intcomma}} CHF/{% trans "Month" %}</strong>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
{% if vm_pricing.discount_amount %}
|
||||||
|
<p class="mb-0">
|
||||||
|
{%trans "Discount" as discount_name %}
|
||||||
|
<strong>{{ vm_pricing.discount_name|default:discount_name }}</strong>
|
||||||
|
<strong class="pull-right text-primary">- {{ vm_pricing.discount_amount }} CHF/{% trans "Month" %}</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
({% trans "Will be applied at checkout" %})
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -55,40 +55,61 @@
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<p>
|
<p>
|
||||||
<span>{% trans "Cores" %}: </span>
|
<span>{% trans "Cores" %}: </span>
|
||||||
<span class="pull-right">{{vm.cpu|floatformat}}</span>
|
<strong class="pull-right">{{vm.cpu|floatformat}}</strong>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span>{% trans "Memory" %}: </span>
|
<span>{% trans "Memory" %}: </span>
|
||||||
<span class="pull-right">{{vm.memory|intcomma}} GB</span>
|
<strong class="pull-right">{{vm.memory|intcomma}} GB</strong>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span>{% trans "Disk space" %}: </span>
|
<span>{% trans "Disk space" %}: </span>
|
||||||
<span class="pull-right">{{vm.disk_size|intcomma}} GB</span>
|
<strong class="pull-right">{{vm.disk_size|intcomma}} GB</strong>
|
||||||
</p>
|
</p>
|
||||||
{% if vm.vat > 0 %}
|
</div>
|
||||||
<p>
|
<div class="col-sm-12">
|
||||||
<strong>{% trans "Subtotal" %}: </strong>
|
<hr class="thin-hr">
|
||||||
<span class="pull-right">{{vm.price|floatformat:2|intcomma}} CHF</span>
|
</div>
|
||||||
</p>
|
{% if vm.vat > 0 or vm.discount.amount > 0 %}
|
||||||
<p>
|
<div class="col-sm-6">
|
||||||
<span>{% trans "VAT" %} ({{ vm.vat_percent|floatformat:2|intcomma }}%): </span>
|
<div class="subtotal-price">
|
||||||
<span class="pull-right">{{vm.vat|floatformat:2|intcomma}} CHF</span>
|
{% if vm.vat > 0 %}
|
||||||
</p>
|
<p>
|
||||||
{% endif %}
|
<strong class="text-lg">{% trans "Subtotal" %} </strong>
|
||||||
<p>
|
<strong class="pull-right">{{vm.price|floatformat:2|intcomma}} CHF</strong>
|
||||||
<strong>{% trans "Total" %}</strong>
|
</p>
|
||||||
<span class="pull-right">{{vm.total_price|floatformat:2|intcomma}} CHF</span>
|
<p>
|
||||||
|
<small>{% trans "VAT" %} ({{ vm.vat_percent|floatformat:2|intcomma }}%) </small>
|
||||||
|
<strong class="pull-right">{{vm.vat|floatformat:2|intcomma}} CHF</strong>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if vm.discount.amount > 0 %}
|
||||||
|
<p class="text-primary">
|
||||||
|
{%trans "Discount" as discount_name %}
|
||||||
|
<strong>{{ vm.discount.name|default:discount_name }} </strong>
|
||||||
|
<strong class="pull-right">- {{ vm.discount.amount }} CHF</strong>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<hr class="thin-hr">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<p class="total-price">
|
||||||
|
<strong>{% trans "Total" %} </strong>
|
||||||
|
<strong class="pull-right">{{vm.total_price|floatformat:2|intcomma}} CHF</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr class="thin-hr">
|
||||||
</div>
|
</div>
|
||||||
<form id="virtual_machine_create_form" action="" method="POST">
|
<form id="virtual_machine_create_form" action="" method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<div class="dcl-place-order-text">{% blocktrans with vm_total_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with the fee of {{vm_total_price}} CHF/month{% endblocktrans %}.</div>
|
<div class="dcl-place-order-text">{% blocktrans with vm_total_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{vm_total_price}} CHF/month{% endblocktrans %}.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 order-confirm-btn text-right">
|
<div class="col-sm-4 order-confirm-btn text-right">
|
||||||
<button class="btn choice-btn" id="btn-create-vm" data-toggle="modal" data-target="#createvm-modal">
|
<button class="btn choice-btn" id="btn-create-vm" data-toggle="modal" data-target="#createvm-modal">
|
||||||
|
|
|
@ -156,7 +156,7 @@ class IndexView(CreateView):
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(referer_url + "#order_form")
|
return HttpResponseRedirect(referer_url + "#order_form")
|
||||||
|
|
||||||
price, vat, vat_percent = get_vm_price_with_vat(
|
price, vat, vat_percent, discount = get_vm_price_with_vat(
|
||||||
cpu=cores,
|
cpu=cores,
|
||||||
memory=memory,
|
memory=memory,
|
||||||
ssd_size=storage,
|
ssd_size=storage,
|
||||||
|
@ -169,7 +169,8 @@ class IndexView(CreateView):
|
||||||
'price': price,
|
'price': price,
|
||||||
'vat': vat,
|
'vat': vat,
|
||||||
'vat_percent': vat_percent,
|
'vat_percent': vat_percent,
|
||||||
'total_price': price + vat,
|
'discount': discount,
|
||||||
|
'total_price': price + vat - discount['amount'],
|
||||||
'pricing_name': vm_pricing_name
|
'pricing_name': vm_pricing_name
|
||||||
}
|
}
|
||||||
request.session['specs'] = specs
|
request.session['specs'] = specs
|
||||||
|
@ -385,7 +386,7 @@ class OrderConfirmationView(DetailView):
|
||||||
'billing_address_data': (
|
'billing_address_data': (
|
||||||
request.session.get('billing_address_data')
|
request.session.get('billing_address_data')
|
||||||
),
|
),
|
||||||
'cms_integration': get_cms_integration('default')
|
'cms_integration': get_cms_integration('default'),
|
||||||
}
|
}
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect, Http404
|
||||||
from django.core.urlresolvers import reverse_lazy, reverse
|
from django.core.urlresolvers import reverse_lazy, reverse
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.generic import TemplateView, UpdateView
|
from django.views.generic import TemplateView, UpdateView
|
||||||
|
@ -834,8 +834,9 @@ class ContactView(FormView):
|
||||||
|
|
||||||
def blog(request):
|
def blog(request):
|
||||||
tags = ["digitalglarus"]
|
tags = ["digitalglarus"]
|
||||||
posts = Post.objects.filter(tags__name__in=tags, publish=True).translated(get_language())
|
posts = (Post.objects
|
||||||
# posts = Post.objects.filter_by_language(get_language()).filter(tags__name__in=tags, publish=True)
|
.filter(tags__name__in=tags, publish=True)
|
||||||
|
.translated(get_language()))
|
||||||
context = {
|
context = {
|
||||||
'post_list': posts,
|
'post_list': posts,
|
||||||
}
|
}
|
||||||
|
@ -843,9 +844,9 @@ def blog(request):
|
||||||
|
|
||||||
|
|
||||||
def blog_detail(request, slug):
|
def blog_detail(request, slug):
|
||||||
# post = Post.objects.filter_by_language(get_language()).filter(slug=slug).first()
|
|
||||||
|
|
||||||
post = Post.objects.translated(get_language(), slug=slug).first()
|
post = Post.objects.translated(get_language(), slug=slug).first()
|
||||||
|
if post is None:
|
||||||
|
raise Http404()
|
||||||
context = {
|
context = {
|
||||||
'post': post,
|
'post': post,
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,6 +267,10 @@ LANGUAGES = (
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
LOCALE_PATHS = [
|
||||||
|
os.path.join(PROJECT_DIR, 'digitalglarus/locale'),
|
||||||
|
]
|
||||||
|
|
||||||
CMS_PLACEHOLDER_CONF = {
|
CMS_PLACEHOLDER_CONF = {
|
||||||
'logo_image': {
|
'logo_image': {
|
||||||
'name': 'Logo Image',
|
'name': 'Logo Image',
|
||||||
|
@ -352,6 +356,18 @@ CMS_PLACEHOLDER_CONF = {
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
'datacenterlight_calculator': {
|
||||||
|
'name': _('Datacenterlight Calculator'),
|
||||||
|
'plugins': ['DCLCalculatorPlugin'],
|
||||||
|
'default_plugins': [
|
||||||
|
{
|
||||||
|
'plugin_type': 'DCLCalculatorPlugin',
|
||||||
|
'values': {
|
||||||
|
'pricing_id': 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
CMS_PERMISSION = True
|
CMS_PERMISSION = True
|
||||||
|
@ -614,6 +630,7 @@ GOOGLE_ANALYTICS_PROPERTY_IDS = {
|
||||||
'ipv6onlyhosting.ch': 'UA-62285904-10',
|
'ipv6onlyhosting.ch': 'UA-62285904-10',
|
||||||
'ipv6onlyhosting.net': 'UA-62285904-10',
|
'ipv6onlyhosting.net': 'UA-62285904-10',
|
||||||
'ipv6onlyhosting.com': 'UA-62285904-10',
|
'ipv6onlyhosting.com': 'UA-62285904-10',
|
||||||
|
'comic.ungleich.ch': 'UA-62285904-13',
|
||||||
'127.0.0.1:8000': 'localhost',
|
'127.0.0.1:8000': 'localhost',
|
||||||
'dynamicweb-development.ungleich.ch': 'development',
|
'dynamicweb-development.ungleich.ch': 'development',
|
||||||
'dynamicweb-staging.ungleich.ch': 'staging'
|
'dynamicweb-staging.ungleich.ch': 'staging'
|
||||||
|
|
|
@ -11,6 +11,7 @@ from hosting.views import (
|
||||||
RailsHostingView, DjangoHostingView, NodeJSHostingView
|
RailsHostingView, DjangoHostingView, NodeJSHostingView
|
||||||
)
|
)
|
||||||
from membership import urls as membership_urls
|
from membership import urls as membership_urls
|
||||||
|
from ungleich import views as ungleich_views
|
||||||
from ungleich_page.views import LandingView
|
from ungleich_page.views import LandingView
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
from django.core.urlresolvers import reverse_lazy
|
from django.core.urlresolvers import reverse_lazy
|
||||||
|
@ -54,7 +55,11 @@ urlpatterns += i18n_patterns(
|
||||||
url(r'^blog/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>\w[-\w]*)/$',
|
url(r'^blog/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>\w[-\w]*)/$',
|
||||||
RedirectView.as_view(pattern_name='ungleich:post-detail')),
|
RedirectView.as_view(pattern_name='ungleich:post-detail')),
|
||||||
url(r'^blog/$',
|
url(r'^blog/$',
|
||||||
RedirectView.as_view(url=reverse_lazy('ungleich:post-list')), name='blog_list_view'),
|
RedirectView.as_view(url=reverse_lazy('ungleich:post-list')),
|
||||||
|
name='blog_list_view'),
|
||||||
|
url(r'^comic/$',
|
||||||
|
ungleich_views.PostListViewUngleich.as_view(category='comic'),
|
||||||
|
name='comic_post_list_view'),
|
||||||
url(r'^cms/', include('cms.urls')),
|
url(r'^cms/', include('cms.urls')),
|
||||||
url(r'^blog/', include('djangocms_blog.urls', namespace='djangocms_blog')),
|
url(r'^blog/', include('djangocms_blog.urls', namespace='djangocms_blog')),
|
||||||
url(r'^$', RedirectView.as_view(url='/cms') if REDIRECT_TO_CMS
|
url(r'^$', RedirectView.as_view(url='/cms') if REDIRECT_TO_CMS
|
||||||
|
|
|
@ -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-21 00:23+0000\n"
|
"POT-Creation-Date: 2018-05-12 03:53+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"
|
||||||
|
@ -365,15 +365,24 @@ msgstr "Arbeitsspeicher"
|
||||||
msgid "Disk space"
|
msgid "Disk space"
|
||||||
msgstr "Festplattenkapazität"
|
msgstr "Festplattenkapazität"
|
||||||
|
|
||||||
|
msgid "Subtotal"
|
||||||
|
msgstr "Zwischensumme"
|
||||||
|
|
||||||
|
msgid "VAT"
|
||||||
|
msgstr "Mehrwertsteuer"
|
||||||
|
|
||||||
|
msgid "Discount"
|
||||||
|
msgstr "Rabatt"
|
||||||
|
|
||||||
msgid "Total"
|
msgid "Total"
|
||||||
msgstr "Gesamt"
|
msgstr "Gesamt"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"By clicking \"Place order\" this plan will charge your credit card account "
|
"By clicking \"Place order\" this plan will charge your credit card account "
|
||||||
"with the fee of %(vm_price)sCHF/month"
|
"with %(vm_price)s CHF/month"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(vm_price)sCHF "
|
"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(vm_price)s CHF "
|
||||||
"pro Monat belastet"
|
"pro Monat belastet"
|
||||||
|
|
||||||
msgid "Place order"
|
msgid "Place order"
|
||||||
|
@ -421,6 +430,12 @@ msgstr "Konfiguration"
|
||||||
msgid "including VAT"
|
msgid "including VAT"
|
||||||
msgstr "inkl. Mehrwertsteuer"
|
msgstr "inkl. Mehrwertsteuer"
|
||||||
|
|
||||||
|
msgid "excluding VAT"
|
||||||
|
msgstr "exkl. Mehrwertsteuer"
|
||||||
|
|
||||||
|
msgid "Will be applied at checkout"
|
||||||
|
msgstr "wird an der Kasse angewendet"
|
||||||
|
|
||||||
msgid "Billing Address"
|
msgid "Billing Address"
|
||||||
msgstr "Rechnungsadresse"
|
msgstr "Rechnungsadresse"
|
||||||
|
|
||||||
|
@ -699,6 +714,10 @@ msgstr "Ungültige RAM-Grösse"
|
||||||
msgid "Invalid storage size"
|
msgid "Invalid storage size"
|
||||||
msgstr "Ungültige Speicher-Grösse"
|
msgstr "Ungültige Speicher-Grösse"
|
||||||
|
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Incorrect pricing name. Please contact support{support_email}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"We could not find the requested VM. Please "
|
"We could not find the requested VM. Please "
|
||||||
"contact Data Center Light Support."
|
"contact Data Center Light Support."
|
||||||
|
|
|
@ -362,3 +362,12 @@
|
||||||
.locale_date.done{
|
.locale_date.done{
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb-0 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thin-hr {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
|
@ -449,230 +449,6 @@ a.unlink:hover {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** DCL payment page **********/
|
|
||||||
.dcl-order-container {
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-header {
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding-top: 15px;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-content {
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding-top: 15px;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tbl-content {
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-total {
|
|
||||||
border-bottom: 4px solid #eee;
|
|
||||||
padding-top: 15px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-total span {
|
|
||||||
font-size: 13px;
|
|
||||||
color: #999;
|
|
||||||
font-weight: 400;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-place-order-text{
|
|
||||||
color: #808080;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-total .tbl-total {
|
|
||||||
text-align: center;
|
|
||||||
color: #000;
|
|
||||||
padding-left: 44px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tbl-total .dcl-price-month {
|
|
||||||
font-size: 16px;
|
|
||||||
text-transform: capitalize;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tbl-no-padding {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-billing-sec {
|
|
||||||
margin-top: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-sec {
|
|
||||||
padding: 0 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-warning-content {
|
|
||||||
font-weight: 300;
|
|
||||||
border: 1px solid #a1a1a1;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 5px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
.card-warning-error {
|
|
||||||
border: 1px solid #EB4D5C;
|
|
||||||
color: #EB4D5C;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-warning-addtional-margin {
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stripe-payment-btn {
|
|
||||||
outline: none;
|
|
||||||
width: auto;
|
|
||||||
float: right;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 300;
|
|
||||||
position: absolute;
|
|
||||||
padding-left: 30px;
|
|
||||||
padding-right: 30px;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-cvc-element label {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-element {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-element label{
|
|
||||||
width:100%;
|
|
||||||
margin-bottom:0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-input {
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-cvc-element .my-input {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#card-errors {
|
|
||||||
clear: both;
|
|
||||||
padding: 0 0 10px;
|
|
||||||
color: #eb4d5c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.credit-card-goup{
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
.dcl-order-table-total span {
|
|
||||||
padding-left: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-sec {
|
|
||||||
padding: 10px 20px 30px 20px;
|
|
||||||
border-bottom: 4px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tbl-header {
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tbl-content {
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-header {
|
|
||||||
border-bottom: 0px solid #eee;
|
|
||||||
padding: 10px 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-content {
|
|
||||||
border-bottom: 0px solid #eee;
|
|
||||||
padding: 10px 0;
|
|
||||||
text-align: right;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-total {
|
|
||||||
font-size: 18px;
|
|
||||||
color: #000;
|
|
||||||
padding: 10px 0;
|
|
||||||
border-bottom: 0px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-order-table-total .tbl-total {
|
|
||||||
padding: 0px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-billing-sec {
|
|
||||||
margin-top: 30px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-expiry-element {
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-cvc-element {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#billing-form .form-control {
|
|
||||||
box-shadow: none !important;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
.dcl-order-container {
|
|
||||||
width: 990px;
|
|
||||||
padding-right: 15px;
|
|
||||||
padding-left: 15px;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.dcl-billing {
|
|
||||||
padding-right: 65px;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dcl-creditcard {
|
|
||||||
padding-left: 65px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tbl-tot {
|
|
||||||
padding-left: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-dashboard {
|
|
||||||
/*width: auto !important;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1040px) and (min-width: 768px) {
|
@media only screen and (max-width: 1040px) and (min-width: 768px) {
|
||||||
.content-dashboard {
|
.content-dashboard {
|
||||||
width: 96% !important;
|
width: 96% !important;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
margin: 100px auto 40px;
|
margin: 100px auto 40px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
color: #595959;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(min-width: 768px) {
|
@media(min-width: 768px) {
|
||||||
|
@ -48,10 +49,6 @@
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.order-detail-container .order-details strong {
|
|
||||||
color: #595959;
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-detail-container h4 {
|
.order-detail-container h4 {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -60,13 +57,28 @@
|
||||||
|
|
||||||
.order-detail-container p {
|
.order-detail-container p {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
color: #595959;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.order-detail-container hr {
|
.order-detail-container hr {
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.order-detail-container .thin-hr {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-detail-container .subtotal-price {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-detail-container .subtotal-price .text-primary {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-detail-container .total-price {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.order-confirm-btn {
|
.order-confirm-btn {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -97,3 +109,7 @@
|
||||||
#virtual_machine_create_form {
|
#virtual_machine_create_form {
|
||||||
padding: 15px 0;
|
padding: 15px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dcl-place-order-text {
|
||||||
|
color: #808080;
|
||||||
|
}
|
|
@ -1,19 +1,35 @@
|
||||||
|
.payment-container {
|
||||||
.payment-container {padding-top:70px; padding-bottom: 11%;}
|
padding-top: 70px;
|
||||||
.creditcard-box .panel-title {display: inline;font-weight: bold; font-size:17px;}
|
padding-bottom: 11%;
|
||||||
.creditcard-box .checkbox.pull-right { margin: 0; }
|
|
||||||
.creditcard-box .pl-ziro { padding-left: 0px; }
|
|
||||||
.creditcard-box .form-control.error {
|
|
||||||
border-color: red;
|
|
||||||
outline: 0;
|
|
||||||
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(255,0,0,0.6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.creditcard-box .panel-title {
|
||||||
|
display: inline;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.creditcard-box .checkbox.pull-right {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.creditcard-box .pl-ziro {
|
||||||
|
padding-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.creditcard-box .form-control.error {
|
||||||
|
border-color: red;
|
||||||
|
outline: 0;
|
||||||
|
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
.creditcard-box label.error {
|
.creditcard-box label.error {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: red;
|
color: red;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.creditcard-box .payment-errors {
|
.creditcard-box .payment-errors {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: red;
|
color: red;
|
||||||
|
@ -21,96 +37,221 @@
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* landing page payment new style */
|
.dcl-order-sec {
|
||||||
.last-p {
|
padding: 0 30px;
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.dcl-payment-section {
|
|
||||||
max-width: 391px;
|
|
||||||
margin: 0 auto 30px;
|
|
||||||
padding: 0 10px 30px;
|
|
||||||
border-bottom: 1px solid #edebeb;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.dcl-payment-section hr{
|
|
||||||
margin-top: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
.dcl-payment-section .top-hr {
|
|
||||||
margin-left: -10px;
|
|
||||||
}
|
|
||||||
.dcl-payment-section h3 {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.dcl-payment-section p {
|
|
||||||
/*padding: 0 5px;*/
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
.dcl-payment-section .card-warning-content {
|
|
||||||
padding: 8px 10px;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
.dcl-payment-order strong{
|
|
||||||
font-size: 17px;
|
|
||||||
}
|
|
||||||
.dcl-payment-order p {
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
.dcl-payment-section .form-group {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.dcl-payment-section .form-control {
|
|
||||||
box-shadow: none;
|
|
||||||
padding: 6px 12px;
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
.dcl-payment-user {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dcl-payment-user h4 {
|
.dcl-billing-sec {
|
||||||
font-weight: 600;
|
margin-top: 50px;
|
||||||
font-size: 17px;
|
}
|
||||||
|
|
||||||
|
.dcl-order-container {
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-header {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
padding: 15px 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-content {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
padding: 15px 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-total {
|
||||||
|
border-bottom: 4px solid #eee;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-total span {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #999;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-total .tbl-total {
|
||||||
|
text-align: right;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tbl-no-padding {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-warning-content {
|
||||||
|
font-weight: 300;
|
||||||
|
border: 1px solid #a1a1a1;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-warning-error {
|
||||||
|
border: 1px solid #EB4D5C;
|
||||||
|
color: #EB4D5C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-warning-addtional-margin {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stripe-payment-btn {
|
||||||
|
outline: none;
|
||||||
|
width: auto;
|
||||||
|
float: right;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
position: absolute;
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-cvc-element label {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-element {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-element label {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-input {
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-cvc-element .my-input {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#card-errors {
|
||||||
|
clear: both;
|
||||||
|
padding: 0 0 10px;
|
||||||
|
color: #eb4d5c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credit-card-goup {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.dcl-order-sec {
|
||||||
|
padding: 10px 5px 30px;
|
||||||
|
border-bottom: 4px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-billing-sec {
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-billing {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tbl-header {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-right: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-total .tbl-total {
|
||||||
|
margin-left: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-total .tbl-tot {
|
||||||
|
margin-right: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tbl-content {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-left: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-header {
|
||||||
|
border-bottom: 0px solid #eee;
|
||||||
|
padding: 10px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-content {
|
||||||
|
border-bottom: 0px solid #eee;
|
||||||
|
padding: 10px 0;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dcl-order-table-total {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #000;
|
||||||
|
padding: 10px 0;
|
||||||
|
border-bottom: 0px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-expiry-element {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-cvc-element {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#billing-form .form-control {
|
||||||
|
box-shadow: none !important;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.dcl-payment-grid {
|
.dcl-billing {
|
||||||
display: flex;
|
padding-right: 65px;
|
||||||
align-items: stretch;
|
border-right: 1px solid #eee;
|
||||||
flex-wrap: wrap;
|
}
|
||||||
}
|
|
||||||
.dcl-payment-box {
|
.dcl-creditcard {
|
||||||
width: 50%;
|
padding-left: 65px;
|
||||||
position: relative;
|
}
|
||||||
padding: 0 30px;
|
|
||||||
}
|
.dcl-order-table-total .tbl-total,
|
||||||
.dcl-payment-box:nth-child(2) {
|
.dcl-order-table-total .tbl-tot {
|
||||||
order: 1;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
.dcl-payment-box:nth-child(4) {
|
|
||||||
order: 2;
|
.tbl-header-center,
|
||||||
}
|
.tbl-content-center {
|
||||||
.dcl-payment-section {
|
text-align: center;
|
||||||
padding: 15px 10px;
|
}
|
||||||
margin-bottom: 0;
|
|
||||||
border-bottom-width: 5px;
|
.tbl-header-right,
|
||||||
}
|
.tbl-content-right {
|
||||||
.dcl-payment-box:nth-child(2n) .dcl-payment-section {
|
text-align: right;
|
||||||
border-bottom: none;
|
}
|
||||||
}
|
}
|
||||||
.dcl-payment-box:nth-child(1):after,
|
|
||||||
.dcl-payment-box:nth-child(2):after {
|
@media (min-width: 1200px) {
|
||||||
content: ' ';
|
.dcl-order-container {
|
||||||
display: block;
|
width: 990px;
|
||||||
background: #eee;
|
padding-right: 15px;
|
||||||
width: 1px;
|
padding-left: 15px;
|
||||||
position: absolute;
|
margin-right: auto;
|
||||||
right: 0;
|
margin-left: auto;
|
||||||
z-index: 2;
|
}
|
||||||
top: 20px;
|
|
||||||
bottom: 20px;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
/* Create VM calculator */
|
/* Create VM calculator */
|
||||||
|
|
||||||
.price-calc-section {
|
.price-calc-section {
|
||||||
padding: 80px 40px !important;
|
padding: 20px 0 !important;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
@ -40,19 +42,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card {
|
.price-calc-section .card {
|
||||||
width: 50%;
|
border-radius: 7px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 1px 3px 6px 2px rgba(0, 0, 0, 0.2);
|
box-shadow: 1px 3px 6px 2px rgba(0, 0, 0, 0.2);
|
||||||
padding-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 320px;
|
max-width: 4000px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.price-calc-section .card {
|
.price-calc-section .card {
|
||||||
margin-left: 0;
|
/* margin-left: 0; */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +87,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description {
|
.price-calc-section .card .description {
|
||||||
padding: 7px 8px 2px;
|
padding: 12px;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around !important;
|
justify-content: space-around !important;
|
||||||
|
@ -93,7 +95,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description span {
|
.price-calc-section .card .description span {
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
/* margin-left: 0px; */
|
/* margin-left: 0px; */
|
||||||
/* justify-self: start; */
|
/* justify-self: start; */
|
||||||
|
@ -104,17 +106,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description .select-number{
|
.price-calc-section .card .description .select-number{
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 85px;
|
width: 85px;
|
||||||
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description i {
|
.price-calc-section .card .description i {
|
||||||
color: #29427a;
|
color: #29427a;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
border: 1px solid #ccc;
|
/* border: 1px solid #ccc; */
|
||||||
padding: 5px 6px 3px;
|
/* padding: 5px 6px 3px; */
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +196,7 @@
|
||||||
.price-calc-section .help-block.with-errors {
|
.price-calc-section .help-block.with-errors {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0 0;
|
margin: 0 0;
|
||||||
padding: 0 0 5px;
|
padding: 0 0;
|
||||||
}
|
}
|
||||||
.price-calc-section .help-block.with-errors ul {
|
.price-calc-section .help-block.with-errors ul {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
@ -209,10 +212,10 @@
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 18%;
|
left: 0;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
width: 65%;
|
width: 100%;
|
||||||
background: rgba(128, 128, 128, 0.2);
|
background: rgba(128, 128, 128, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,4 +153,87 @@ $( document ).ready(function() {
|
||||||
$('.navbar-fixed-top.topnav').css('padding-right', topnavPadding-scrollbarWidth);
|
$('.navbar-fixed-top.topnav').css('padding-right', topnavPadding-scrollbarWidth);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* ---------------------------------------------
|
||||||
|
Scripts initialization
|
||||||
|
--------------------------------------------- */
|
||||||
|
var cardPricing = {
|
||||||
|
'cpu': {
|
||||||
|
'id': 'coreValue',
|
||||||
|
'value': 1,
|
||||||
|
'min': 1,
|
||||||
|
'max': 48,
|
||||||
|
'interval': 1
|
||||||
|
},
|
||||||
|
'ram': {
|
||||||
|
'id': 'ramValue',
|
||||||
|
'value': 2,
|
||||||
|
'min': 1,
|
||||||
|
'max': 200,
|
||||||
|
'interval': 1
|
||||||
|
},
|
||||||
|
'storage': {
|
||||||
|
'id': 'storageValue',
|
||||||
|
'value': 10,
|
||||||
|
'min': 10,
|
||||||
|
'max': 2000,
|
||||||
|
'interval': 10
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function _initPricing() {
|
||||||
|
_fetchPricing();
|
||||||
|
|
||||||
|
$('.fa-minus-circle.left').click(function(event) {
|
||||||
|
var data = $(this).data('minus');
|
||||||
|
|
||||||
|
if (cardPricing[data].value > cardPricing[data].min) {
|
||||||
|
cardPricing[data].value = Number(cardPricing[data].value) - cardPricing[data].interval;
|
||||||
|
}
|
||||||
|
_fetchPricing();
|
||||||
|
});
|
||||||
|
$('.fa-plus-circle.right').click(function(event) {
|
||||||
|
var data = $(this).data('plus');
|
||||||
|
if (cardPricing[data].value < cardPricing[data].max) {
|
||||||
|
cardPricing[data].value = Number(cardPricing[data].value) + cardPricing[data].interval;
|
||||||
|
}
|
||||||
|
_fetchPricing();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.input-price').change(function() {
|
||||||
|
var data = $(this).attr("name");
|
||||||
|
cardPricing[data].value = $('input[name=' + data + ']').val();
|
||||||
|
_fetchPricing();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _fetchPricing() {
|
||||||
|
Object.keys(cardPricing).map(function(element) {
|
||||||
|
$('input[name=' + element + ']').val(cardPricing[element].value);
|
||||||
|
});
|
||||||
|
_calcPricing();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _calcPricing() {
|
||||||
|
if(typeof window.coresUnitPrice === 'undefined'){
|
||||||
|
window.coresUnitPrice = 5;
|
||||||
|
}
|
||||||
|
if(typeof window.ramUnitPrice === 'undefined'){
|
||||||
|
window.ramUnitPrice = 2;
|
||||||
|
}
|
||||||
|
if(typeof window.ssdUnitPrice === 'undefined'){
|
||||||
|
window.ssdUnitPrice = 0.6;
|
||||||
|
}
|
||||||
|
if(typeof window.discountAmount === 'undefined'){
|
||||||
|
window.discountAmount = 0;
|
||||||
|
}
|
||||||
|
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
|
||||||
|
(cardPricing['ram'].value * window.ramUnitPrice) +
|
||||||
|
(cardPricing['storage'].value * window.ssdUnitPrice) -
|
||||||
|
window.discountAmount;
|
||||||
|
total = parseFloat(total.toFixed(2));
|
||||||
|
$("#total").text(total);
|
||||||
|
}
|
||||||
|
|
||||||
|
_initPricing();
|
||||||
});
|
});
|
|
@ -1,5 +1,5 @@
|
||||||
{% load staticfiles bootstrap3%}
|
{% load staticfiles i18n cms_tags sekizai_tags %}
|
||||||
{% load i18n %}
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
|
@ -29,6 +29,9 @@
|
||||||
{% block css_extra %}
|
{% block css_extra %}
|
||||||
{% endblock css_extra %}
|
{% endblock css_extra %}
|
||||||
|
|
||||||
|
{% render_block "css" postprocessor "compressor.contrib.sekizai.compress" %}
|
||||||
|
{% render_block "js" postprocessor "compressor.contrib.sekizai.compress" %}
|
||||||
|
|
||||||
<!-- Custom Fonts -->
|
<!-- Custom Fonts -->
|
||||||
<link href='//fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
|
<link href='//fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
|
||||||
<link href="{% static 'datacenterlight/font-awesome/css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
|
<link href="{% static 'datacenterlight/font-awesome/css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
|
||||||
|
@ -48,7 +51,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
{% cms_toolbar %}
|
||||||
|
|
||||||
{% block navbar %}
|
{% block navbar %}
|
||||||
{% include "hosting/includes/_navbar_user.html" %}
|
{% include "hosting/includes/_navbar_user.html" %}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
{% extends "hosting/base_short.html" %}
|
{% extends "hosting/base_short.html" %}
|
||||||
{% load staticfiles bootstrap3 i18n %}
|
{% load staticfiles bootstrap3 i18n cms_tags %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
<div class="dashboard-container create-vm-container">
|
<div class="dashboard-container create-vm-container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-5">
|
<div class="col-sm-5">
|
||||||
|
@ -17,14 +19,8 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6 hosting-calculator">
|
||||||
<div class="price-calc-section no-padding">
|
{% render_placeholder cms_integration.calculator_placeholder %}
|
||||||
<div class="landing card">
|
|
||||||
<div class="caption">
|
|
||||||
{% include "hosting/calculator_form.html" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -114,37 +114,58 @@
|
||||||
<p>
|
<p>
|
||||||
<span>{% trans "Cores" %}: </span>
|
<span>{% trans "Cores" %}: </span>
|
||||||
{% if vm.cores %}
|
{% if vm.cores %}
|
||||||
<span class="pull-right">{{vm.cores|floatformat}}</span>
|
<strong class="pull-right">{{vm.cores|floatformat}}</strong>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="pull-right">{{vm.cpu|floatformat}}</span>
|
<strong class="pull-right">{{vm.cpu|floatformat}}</strong>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span>{% trans "Memory" %}: </span>
|
<span>{% trans "Memory" %}: </span>
|
||||||
<span class="pull-right">{{vm.memory}} GB</span>
|
<strong class="pull-right">{{vm.memory}} GB</strong>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span>{% trans "Disk space" %}: </span>
|
<span>{% trans "Disk space" %}: </span>
|
||||||
<span class="pull-right">{{vm.disk_size}} GB</span>
|
<strong class="pull-right">{{vm.disk_size}} GB</strong>
|
||||||
</p>
|
</p>
|
||||||
{% if vm.vat > 0 %}
|
</div>
|
||||||
<p>
|
<div class="col-sm-12">
|
||||||
<strong>{% trans "Subtotal" %}: </strong>
|
<hr class="thin-hr">
|
||||||
<span class="pull-right">{{vm.price|floatformat:2|intcomma}} CHF</span>
|
</div>
|
||||||
</p>
|
{% if vm.vat > 0 or vm.discount.amount > 0 %}
|
||||||
<p>
|
<div class="col-sm-6">
|
||||||
<span>{% trans "VAT" %} ({{ vm.vat_percent|floatformat:2|intcomma }}%): </span>
|
<div class="subtotal-price">
|
||||||
<span class="pull-right">{{vm.vat|floatformat:2|intcomma}} CHF</span>
|
{% if vm.vat > 0 %}
|
||||||
</p>
|
<p>
|
||||||
{% endif %}
|
<strong>{% trans "Subtotal" %} </strong>
|
||||||
<p>
|
<strong class="pull-right">{{vm.price|floatformat:2|intcomma}} CHF</strong>
|
||||||
<strong>{% trans "Total" %}</strong>
|
</p>
|
||||||
<span class="pull-right">{% if vm.total_price %}{{vm.total_price|floatformat:2|intcomma}}{% else %}{{vm.price|floatformat:2|intcomma}}{% endif %} CHF</span>
|
<p>
|
||||||
|
<small>{% trans "VAT" %} ({{ vm.vat_percent|floatformat:2|intcomma }}%) </small>
|
||||||
|
<strong class="pull-right">{{vm.vat|floatformat:2|intcomma}} CHF</strong>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if vm.discount.amount > 0 %}
|
||||||
|
<p class="text-primary">
|
||||||
|
{%trans "Discount" as discount_name %}
|
||||||
|
<strong>{{ vm.discount.name|default:discount_name }} </strong>
|
||||||
|
<strong class="pull-right">- {{ vm.discount.amount }} CHF</strong>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<hr class="thin-hr">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<p class="total-price">
|
||||||
|
<strong>{% trans "Total" %} </strong>
|
||||||
|
<strong class="pull-right">{% if vm.total_price %}{{vm.total_price|floatformat:2|intcomma}}{% else %}{{vm.price|floatformat:2|intcomma}}{% endif %} CHF</strong>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr class="thin-hr">
|
||||||
</div>
|
</div>
|
||||||
{% if not order %}
|
{% if not order %}
|
||||||
{% block submit_btn %}
|
{% block submit_btn %}
|
||||||
|
@ -152,7 +173,7 @@
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-8">
|
<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|intcomma }}CHF/month{% endblocktrans %}.</div>
|
<div class="dcl-place-order-text">{% blocktrans with vm_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with {{ vm_price }} CHF/month{% endblocktrans %}.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 order-confirm-btn text-right">
|
<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">
|
<button class="btn choice-btn" id="btn-create-vm" data-href="{% url 'hosting:order-confirmation' %}" data-toggle="modal" data-target="#createvm-modal">
|
||||||
|
|
|
@ -9,159 +9,208 @@
|
||||||
<!-- Credit card form -->
|
<!-- Credit card form -->
|
||||||
<div class="dcl-order-container">
|
<div class="dcl-order-container">
|
||||||
<div class="payment-container">
|
<div class="payment-container">
|
||||||
<div class="row">
|
<div class="dcl-order-sec">
|
||||||
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-order-sec">
|
<h3><strong>{%trans "Your Order" %}</strong></h3>
|
||||||
<h3><strong>{%trans "Your Order" %}</strong></h3>
|
<div class="row">
|
||||||
<div class="col-xs-6 col-sm-12 col-md-12 col-lg-12 dcl-order-table-header">
|
<div class="col-xs-6 col-sm-12">
|
||||||
<div class="col-xs-12 col-sm-2 col-md-1 col-lg-1 tbl-header">
|
<div class="dcl-order-table-header">
|
||||||
{%trans "Cores" %}
|
<div class="row">
|
||||||
</div>
|
<div class="col-sm-2">
|
||||||
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4 tbl-header">
|
<div class="tbl-header">
|
||||||
{%trans "Memory" %}
|
{%trans "Cores" %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3 tbl-header">
|
</div>
|
||||||
{%trans "Disk space" %}
|
<div class="col-sm-4">
|
||||||
</div>
|
<div class="tbl-header tbl-header-center">
|
||||||
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 tbl-header">
|
{%trans "Memory" %}
|
||||||
{%trans "Configuration" %}
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<div class="tbl-header tbl-header-center">
|
||||||
|
{%trans "Disk space" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<div class="tbl-header tbl-header-right">
|
||||||
|
{%trans "Configuration" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6 col-sm-12 col-md-12 col-lg-12 dcl-order-table-content">
|
<div class="col-xs-6 col-sm-12">
|
||||||
<div class="col-xs-12 col-sm-2 col-md-1 col-lg-1 tbl-content">
|
<div class="dcl-order-table-content">
|
||||||
{{request.session.specs.cpu|floatformat}}
|
<div class="row">
|
||||||
</div>
|
<div class="col-sm-2">
|
||||||
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4 tbl-content">
|
<div class="tbl-content">
|
||||||
{{request.session.specs.memory|floatformat}} GB
|
{{request.session.specs.cpu|floatformat}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-3 tbl-content">
|
</div>
|
||||||
{{request.session.specs.disk_size|floatformat|intcomma}} GB
|
<div class="col-sm-4">
|
||||||
</div>
|
<div class="tbl-content tbl-content-center">
|
||||||
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 tbl-content">
|
{{request.session.specs.memory|floatformat}} GB
|
||||||
{{request.session.template.name}}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-sm-3">
|
||||||
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-order-table-total">
|
<div class="tbl-content tbl-content-center">
|
||||||
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 tbl-tot tbl-no-padding">
|
{{request.session.specs.disk_size|floatformat|intcomma}} GB
|
||||||
{%trans "Total" %} <span>{%trans "including VAT" %}</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 tbl-no-padding">
|
<div class="col-sm-3">
|
||||||
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4"></div>
|
<div class="tbl-content tbl-content-right">
|
||||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 tbl-total">{{request.session.specs.price|intcomma}}
|
{{request.session.template.name}}
|
||||||
CHF<span class="dcl-price-month">/{% trans "Month" %}</span>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="dcl-order-table-total">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 dcl-billing-sec">
|
<div class="col-xs-6">
|
||||||
<div class="col-xs-12 col-sm-5 col-md-6 billing dcl-billing">
|
<div class="tbl-tot">
|
||||||
<h3><b>{%trans "Billing Address"%}</b></h3>
|
{%trans "Total" %}
|
||||||
<hr>
|
<span>{% if vm_pricing.vat_inclusive %}{%trans "including VAT" %}{% else %}{%trans "excluding VAT" %}{% endif %}</span>
|
||||||
<form role="form" id="billing-form" method="post" action="" novalidate>
|
</div>
|
||||||
{% for field in form %}
|
</div>
|
||||||
{% csrf_token %}
|
<div class="col-xs-6">
|
||||||
{% bootstrap_field field show_label=False type='fields'%}
|
<div class="tbl-total">
|
||||||
{% endfor %}
|
{{request.session.specs.price|intcomma}} CHF/{% trans "Month" %}
|
||||||
</form>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-7 col-md-6 creditcard-box dcl-creditcard">
|
{% if vm_pricing.discount_amount %}
|
||||||
<h3><b>{%trans "Credit Card"%}</b></h3>
|
<hr class="thin-hr">
|
||||||
<hr>
|
<div class="row">
|
||||||
<div>
|
<div class="col-xs-6">
|
||||||
<p>
|
<div class="tbl-tot">
|
||||||
{% blocktrans %}Please fill in your credit card information below. We are using <a href="https://stripe.com" target="_blank">Stripe</a> for payment and do not store your information in our database.{% endblocktrans %}
|
{%trans "Discount" as discount_name %}
|
||||||
</p>
|
{{ vm_pricing.discount_name|default:discount_name }} <br>
|
||||||
|
<span>({% trans "Will be applied at checkout" %})</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 text-right">
|
||||||
|
<div class="tbl-total">
|
||||||
|
<div class="text-primary">- {{ vm_pricing.discount_amount }} CHF/{% trans "Month" %}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dcl-billing-sec">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-5 col-md-6">
|
||||||
|
<div class="billing dcl-billing">
|
||||||
|
<h3><b>{%trans "Billing Address"%}</b></h3>
|
||||||
|
<hr>
|
||||||
|
<form role="form" id="billing-form" method="post" action="" novalidate>
|
||||||
|
{% for field in form %}
|
||||||
|
{% csrf_token %}
|
||||||
|
{% bootstrap_field field show_label=False type='fields'%}
|
||||||
|
{% endfor %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-7 col-md-6">
|
||||||
|
<div class="creditcard-box dcl-creditcard">
|
||||||
|
<h3><b>{%trans "Credit Card"%}</b></h3>
|
||||||
|
<hr>
|
||||||
<div>
|
<div>
|
||||||
{% if credit_card_data.last4 %}
|
<p>
|
||||||
<form role="form" id="payment-form-with-creditcard" novalidate>
|
{% blocktrans %}Please fill in your credit card information below. We are using <a href="https://stripe.com" target="_blank">Stripe</a> for payment and do not store your information in our database.{% endblocktrans %}
|
||||||
<h5 class="billing-head">Credit Card</h5>
|
</p>
|
||||||
<h5 class="membership-lead">Last 4: *****{{credit_card_data.last4}}</h5>
|
<div>
|
||||||
<h5 class="membership-lead">Type: {{credit_card_data.cc_brand}}</h5>
|
{% if credit_card_data.last4 %}
|
||||||
<input type="hidden" name="credit_card_needed" value="false"/>
|
<form role="form" id="payment-form-with-creditcard" novalidate>
|
||||||
</form>
|
<h5 class="billing-head">Credit Card</h5>
|
||||||
{% if not messages and not form.non_field_errors %}
|
<h5 class="membership-lead">Last 4: *****{{credit_card_data.last4}}</h5>
|
||||||
<p class="card-warning-content card-warning-addtional-margin">
|
<h5 class="membership-lead">Type: {{credit_card_data.cc_brand}}</h5>
|
||||||
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}
|
<input type="hidden" name="credit_card_needed" value="false"/>
|
||||||
</p>
|
</form>
|
||||||
{% endif %}
|
{% if not messages and not form.non_field_errors %}
|
||||||
<div id='payment_error'>
|
<p class="card-warning-content card-warning-addtional-margin">
|
||||||
{% for message in messages %}
|
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}
|
||||||
{% if 'failed_payment' or 'make_charge_error' in message.tags %}
|
|
||||||
<ul class="list-unstyled">
|
|
||||||
<li>
|
|
||||||
<p class="card-warning-content card-warning-error">{{ message|safe }}</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% for error in form.non_field_errors %}
|
|
||||||
<p class="card-warning-content card-warning-error">
|
|
||||||
{{ error|escape }}
|
|
||||||
</p>
|
</p>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
</div>
|
<div id='payment_error'>
|
||||||
<div class="text-right">
|
{% for message in messages %}
|
||||||
<button id="payment_button_with_creditcard" class="btn btn-vm-contact" type="submit">{%trans "SUBMIT" %}</button>
|
{% if 'failed_payment' or 'make_charge_error' in message.tags %}
|
||||||
</div>
|
<ul class="list-unstyled">
|
||||||
{% else %}
|
<li>
|
||||||
<form action="" id="payment-form-new" method="POST">
|
<p class="card-warning-content card-warning-error">{{ message|safe }}</p>
|
||||||
<input type="hidden" name="token"/>
|
</li>
|
||||||
<div class="group">
|
</ul>
|
||||||
<div class="credit-card-goup">
|
{% endif %}
|
||||||
<div class="card-element card-number-element">
|
{% endfor %}
|
||||||
<label>{%trans "Card Number" %}</label>
|
{% for error in form.non_field_errors %}
|
||||||
<div id="card-number-element" class="field my-input"></div>
|
<p class="card-warning-content card-warning-error">
|
||||||
</div>
|
{{ error|escape }}
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-5 card-element card-expiry-element">
|
|
||||||
<label>{%trans "Expiry Date" %}</label>
|
|
||||||
<div id="card-expiry-element" class="field my-input"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-3 col-xs-offset-4 card-element card-cvc-element">
|
|
||||||
<label>{%trans "CVC" %}</label>
|
|
||||||
<div id="card-cvc-element" class="field my-input"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-element brand">
|
|
||||||
<label>{%trans "Card Type" %}</label>
|
|
||||||
<i class="pf pf-credit-card" id="brand-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="card-errors"></div>
|
|
||||||
{% if not messages and not form.non_field_errors %}
|
|
||||||
<p class="card-warning-content">
|
|
||||||
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}
|
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
<div id='payment_error'>
|
</div>
|
||||||
{% for message in messages %}
|
<div class="text-right">
|
||||||
{% if 'failed_payment' or 'make_charge_error' in message.tags %}
|
<button id="payment_button_with_creditcard" class="btn btn-vm-contact" type="submit">{%trans "SUBMIT" %}</button>
|
||||||
<ul class="list-unstyled">
|
</div>
|
||||||
<li>
|
{% else %}
|
||||||
<p class="card-warning-content card-warning-error">{{ message|safe }}</p>
|
<form action="" id="payment-form-new" method="POST">
|
||||||
</li>
|
<input type="hidden" name="token"/>
|
||||||
</ul>
|
<div class="group">
|
||||||
{% endif %}
|
<div class="credit-card-goup">
|
||||||
{% endfor %}
|
<div class="card-element card-number-element">
|
||||||
|
<label>{%trans "Card Number" %}</label>
|
||||||
{% for error in form.non_field_errors %}
|
<div id="card-number-element" class="field my-input"></div>
|
||||||
<p class="card-warning-content card-warning-error">
|
</div>
|
||||||
{{ error|escape }}
|
<div class="row">
|
||||||
|
<div class="col-xs-5 card-element card-expiry-element">
|
||||||
|
<label>{%trans "Expiry Date" %}</label>
|
||||||
|
<div id="card-expiry-element" class="field my-input"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-3 col-xs-offset-4 card-element card-cvc-element">
|
||||||
|
<label>{%trans "CVC" %}</label>
|
||||||
|
<div id="card-cvc-element" class="field my-input"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-element brand">
|
||||||
|
<label>{%trans "Card Type" %}</label>
|
||||||
|
<i class="pf pf-credit-card" id="brand-icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="card-errors"></div>
|
||||||
|
{% if not messages and not form.non_field_errors %}
|
||||||
|
<p class="card-warning-content">
|
||||||
|
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}
|
||||||
</p>
|
</p>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
</div>
|
<div id='payment_error'>
|
||||||
<div class="text-right">
|
{% for message in messages %}
|
||||||
<button class="btn btn-vm-contact btn-wide" type="submit">{%trans "SUBMIT" %}</button>
|
{% if 'failed_payment' or 'make_charge_error' in message.tags %}
|
||||||
</div>
|
<ul class="list-unstyled">
|
||||||
</div>
|
<li>
|
||||||
|
<p class="card-warning-content card-warning-error">{{ message|safe }}</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<div style="display:none;">
|
{% for error in form.non_field_errors %}
|
||||||
<p class="payment-errors"></p>
|
<p class="card-warning-content card-warning-error">
|
||||||
</div>
|
{{ error|escape }}
|
||||||
</form>
|
</p>
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="text-right">
|
||||||
|
<button class="btn btn-vm-contact btn-wide" type="submit">{%trans "SUBMIT" %}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display:none;">
|
||||||
|
<p class="payment-errors"></p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,8 +31,8 @@ from stored_messages.api import mark_read
|
||||||
from stored_messages.models import Message
|
from stored_messages.models import Message
|
||||||
from stored_messages.settings import stored_messages_settings
|
from stored_messages.settings import stored_messages_settings
|
||||||
|
|
||||||
from datacenterlight.models import VMTemplate
|
from datacenterlight.models import VMTemplate, VMPricing
|
||||||
from datacenterlight.utils import create_vm
|
from datacenterlight.utils import create_vm, get_cms_integration
|
||||||
from membership.models import CustomUser, StripeCustomer
|
from membership.models import CustomUser, StripeCustomer
|
||||||
from opennebula_api.models import OpenNebulaManager
|
from opennebula_api.models import OpenNebulaManager
|
||||||
from opennebula_api.serializers import (
|
from opennebula_api.serializers import (
|
||||||
|
@ -43,7 +43,7 @@ from utils.forms import (
|
||||||
BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm,
|
BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm,
|
||||||
ResendActivationEmailForm
|
ResendActivationEmailForm
|
||||||
)
|
)
|
||||||
from utils.hosting_utils import get_vm_price, get_vm_price_with_vat
|
from utils.hosting_utils import get_vm_price_with_vat
|
||||||
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.tasks import send_plain_email_task
|
||||||
|
@ -652,7 +652,10 @@ class PaymentVMView(LoginRequiredMixin, FormView):
|
||||||
})
|
})
|
||||||
|
|
||||||
context.update({
|
context.update({
|
||||||
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
|
'stripe_key': settings.STRIPE_API_PUBLIC_KEY,
|
||||||
|
'vm_pricing': VMPricing.get_vm_pricing_by_name(
|
||||||
|
self.request.session.get('specs', {}).get('pricing_name')
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
@ -750,7 +753,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
||||||
context['vm'] = vm_detail.__dict__
|
context['vm'] = vm_detail.__dict__
|
||||||
context['vm']['name'] = '{}-{}'.format(
|
context['vm']['name'] = '{}-{}'.format(
|
||||||
context['vm']['configuration'], context['vm']['vm_id'])
|
context['vm']['configuration'], context['vm']['vm_id'])
|
||||||
price, vat, vat_percent = get_vm_price_with_vat(
|
price, vat, vat_percent, discount = get_vm_price_with_vat(
|
||||||
cpu=context['vm']['cores'],
|
cpu=context['vm']['cores'],
|
||||||
ssd_size=context['vm']['disk_size'],
|
ssd_size=context['vm']['disk_size'],
|
||||||
memory=context['vm']['memory'],
|
memory=context['vm']['memory'],
|
||||||
|
@ -759,8 +762,9 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
||||||
)
|
)
|
||||||
context['vm']['vat'] = vat
|
context['vm']['vat'] = vat
|
||||||
context['vm']['price'] = price
|
context['vm']['price'] = price
|
||||||
|
context['vm']['discount'] = discount
|
||||||
context['vm']['vat_percent'] = vat_percent
|
context['vm']['vat_percent'] = vat_percent
|
||||||
context['vm']['total_price'] = price + vat
|
context['vm']['total_price'] = price + vat - discount['amount']
|
||||||
context['subscription_end_date'] = vm_detail.end_date()
|
context['subscription_end_date'] = vm_detail.end_date()
|
||||||
except VMDetail.DoesNotExist:
|
except VMDetail.DoesNotExist:
|
||||||
try:
|
try:
|
||||||
|
@ -769,7 +773,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
||||||
)
|
)
|
||||||
vm = manager.get_vm(obj.vm_id)
|
vm = manager.get_vm(obj.vm_id)
|
||||||
context['vm'] = VirtualMachineSerializer(vm).data
|
context['vm'] = VirtualMachineSerializer(vm).data
|
||||||
price, vat, vat_percent = get_vm_price_with_vat(
|
price, vat, vat_percent, discount = get_vm_price_with_vat(
|
||||||
cpu=context['vm']['cores'],
|
cpu=context['vm']['cores'],
|
||||||
ssd_size=context['vm']['disk_size'],
|
ssd_size=context['vm']['disk_size'],
|
||||||
memory=context['vm']['memory'],
|
memory=context['vm']['memory'],
|
||||||
|
@ -778,8 +782,10 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
||||||
)
|
)
|
||||||
context['vm']['vat'] = vat
|
context['vm']['vat'] = vat
|
||||||
context['vm']['price'] = price
|
context['vm']['price'] = price
|
||||||
|
context['vm']['discount'] = discount
|
||||||
context['vm']['vat_percent'] = vat_percent
|
context['vm']['vat_percent'] = vat_percent
|
||||||
context['vm']['total_price'] = price + vat
|
context['vm']['total_price'] = price + \
|
||||||
|
vat - discount['amount']
|
||||||
except WrongIdError:
|
except WrongIdError:
|
||||||
messages.error(
|
messages.error(
|
||||||
self.request,
|
self.request,
|
||||||
|
@ -855,7 +861,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView):
|
||||||
cpu = specs.get('cpu')
|
cpu = specs.get('cpu')
|
||||||
memory = specs.get('memory')
|
memory = specs.get('memory')
|
||||||
disk_size = specs.get('disk_size')
|
disk_size = specs.get('disk_size')
|
||||||
amount_to_be_charged = specs.get('price')
|
amount_to_be_charged = specs.get('total_price')
|
||||||
plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu,
|
plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu,
|
||||||
memory=memory,
|
memory=memory,
|
||||||
disk_size=disk_size)
|
disk_size=disk_size)
|
||||||
|
@ -1000,7 +1006,10 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
||||||
|
|
||||||
@method_decorator(decorators)
|
@method_decorator(decorators)
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
context = {'templates': VMTemplate.objects.all()}
|
context = {
|
||||||
|
'templates': VMTemplate.objects.all(),
|
||||||
|
'cms_integration': get_cms_integration('default'),
|
||||||
|
}
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
@method_decorator(decorators)
|
@method_decorator(decorators)
|
||||||
|
@ -1012,18 +1021,34 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
||||||
storage = request.POST.get('storage')
|
storage = request.POST.get('storage')
|
||||||
storage_field = forms.IntegerField(validators=[self.validate_storage])
|
storage_field = forms.IntegerField(validators=[self.validate_storage])
|
||||||
template_id = int(request.POST.get('config'))
|
template_id = int(request.POST.get('config'))
|
||||||
|
pricing_name = request.POST.get('pricing_name')
|
||||||
|
vm_pricing = VMPricing.get_vm_pricing_by_name(pricing_name)
|
||||||
template = VMTemplate.objects.filter(
|
template = VMTemplate.objects.filter(
|
||||||
opennebula_vm_template_id=template_id).first()
|
opennebula_vm_template_id=template_id).first()
|
||||||
template_data = VMTemplateSerializer(template).data
|
template_data = VMTemplateSerializer(template).data
|
||||||
|
|
||||||
|
if vm_pricing is None:
|
||||||
|
vm_pricing_name_msg = _(
|
||||||
|
"Incorrect pricing name. Please contact support"
|
||||||
|
"{support_email}".format(
|
||||||
|
support_email=settings.DCL_SUPPORT_FROM_ADDRESS
|
||||||
|
)
|
||||||
|
)
|
||||||
|
messages.add_message(
|
||||||
|
self.request, messages.ERROR, vm_pricing_name_msg,
|
||||||
|
extra_tags='pricing'
|
||||||
|
)
|
||||||
|
return redirect(CreateVirtualMachinesView.as_view())
|
||||||
|
else:
|
||||||
|
vm_pricing_name = vm_pricing.name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cores = cores_field.clean(cores)
|
cores = cores_field.clean(cores)
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
msg = '{} : {}.'.format(cores, str(err))
|
msg = '{} : {}.'.format(cores, str(err))
|
||||||
messages.add_message(self.request, messages.ERROR, msg,
|
messages.add_message(self.request, messages.ERROR, msg,
|
||||||
extra_tags='cores')
|
extra_tags='cores')
|
||||||
return HttpResponseRedirect(
|
return redirect(CreateVirtualMachinesView.as_view())
|
||||||
reverse('datacenterlight:index') + "#order_form")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
memory = memory_field.clean(memory)
|
memory = memory_field.clean(memory)
|
||||||
|
@ -1031,8 +1056,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
||||||
msg = '{} : {}.'.format(memory, str(err))
|
msg = '{} : {}.'.format(memory, str(err))
|
||||||
messages.add_message(self.request, messages.ERROR, msg,
|
messages.add_message(self.request, messages.ERROR, msg,
|
||||||
extra_tags='memory')
|
extra_tags='memory')
|
||||||
return HttpResponseRedirect(
|
return redirect(CreateVirtualMachinesView.as_view())
|
||||||
reverse('datacenterlight:index') + "#order_form")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
storage = storage_field.clean(storage)
|
storage = storage_field.clean(storage)
|
||||||
|
@ -1040,15 +1064,25 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
||||||
msg = '{} : {}.'.format(storage, str(err))
|
msg = '{} : {}.'.format(storage, str(err))
|
||||||
messages.add_message(self.request, messages.ERROR, msg,
|
messages.add_message(self.request, messages.ERROR, msg,
|
||||||
extra_tags='storage')
|
extra_tags='storage')
|
||||||
return HttpResponseRedirect(
|
return redirect(CreateVirtualMachinesView.as_view())
|
||||||
reverse('datacenterlight:index') + "#order_form")
|
|
||||||
price = get_vm_price(cpu=cores, memory=memory,
|
price, vat, vat_percent, discount = get_vm_price_with_vat(
|
||||||
disk_size=storage)
|
cpu=cores,
|
||||||
|
memory=memory,
|
||||||
|
ssd_size=storage,
|
||||||
|
pricing_name=vm_pricing_name
|
||||||
|
)
|
||||||
|
|
||||||
specs = {
|
specs = {
|
||||||
'cpu': cores,
|
'cpu': cores,
|
||||||
'memory': memory,
|
'memory': memory,
|
||||||
'disk_size': storage,
|
'disk_size': storage,
|
||||||
'price': price
|
'discount': discount,
|
||||||
|
'price': price,
|
||||||
|
'vat': vat,
|
||||||
|
'vat_percent': vat_percent,
|
||||||
|
'total_price': price + vat - discount['amount'],
|
||||||
|
'pricing_name': vm_pricing_name
|
||||||
}
|
}
|
||||||
|
|
||||||
request.session['specs'] = specs
|
request.session['specs'] = specs
|
||||||
|
@ -1232,7 +1266,10 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
||||||
["%s=%s" % (k, v) for (k, v) in admin_email_body.items()]),
|
["%s=%s" % (k, v) for (k, v) in admin_email_body.items()]),
|
||||||
}
|
}
|
||||||
send_plain_email_task.delay(email_to_admin_data)
|
send_plain_email_task.delay(email_to_admin_data)
|
||||||
return JsonResponse(response)
|
return HttpResponse(
|
||||||
|
json.dumps(response),
|
||||||
|
content_type="application/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin,
|
class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin,
|
||||||
|
|
|
@ -61,7 +61,7 @@ class OpenNebulaManager():
|
||||||
domain=settings.OPENNEBULA_DOMAIN,
|
domain=settings.OPENNEBULA_DOMAIN,
|
||||||
port=settings.OPENNEBULA_PORT,
|
port=settings.OPENNEBULA_PORT,
|
||||||
endpoint=settings.OPENNEBULA_ENDPOINT
|
endpoint=settings.OPENNEBULA_ENDPOINT
|
||||||
))
|
))
|
||||||
|
|
||||||
def _get_opennebula_client(self, username, password):
|
def _get_opennebula_client(self, username, password):
|
||||||
return oca.Client("{0}:{1}".format(
|
return oca.Client("{0}:{1}".format(
|
||||||
|
@ -73,7 +73,7 @@ class OpenNebulaManager():
|
||||||
domain=settings.OPENNEBULA_DOMAIN,
|
domain=settings.OPENNEBULA_DOMAIN,
|
||||||
port=settings.OPENNEBULA_PORT,
|
port=settings.OPENNEBULA_PORT,
|
||||||
endpoint=settings.OPENNEBULA_ENDPOINT
|
endpoint=settings.OPENNEBULA_ENDPOINT
|
||||||
))
|
))
|
||||||
|
|
||||||
def _get_user(self, user):
|
def _get_user(self, user):
|
||||||
"""Get the corresponding opennebula user for a CustomUser object
|
"""Get the corresponding opennebula user for a CustomUser object
|
||||||
|
@ -362,12 +362,12 @@ class OpenNebulaManager():
|
||||||
except:
|
except:
|
||||||
raise ConnectionRefusedError
|
raise ConnectionRefusedError
|
||||||
|
|
||||||
def get_templates(self):
|
def get_templates(self, prefix='public-'):
|
||||||
try:
|
try:
|
||||||
public_templates = [
|
public_templates = [
|
||||||
template
|
template
|
||||||
for template in self._get_template_pool()
|
for template in self._get_template_pool()
|
||||||
if template.name.startswith('public-')
|
if template.name.startswith(prefix)
|
||||||
]
|
]
|
||||||
return public_templates
|
return public_templates
|
||||||
except ConnectionRefusedError:
|
except ConnectionRefusedError:
|
||||||
|
@ -439,7 +439,7 @@ class OpenNebulaManager():
|
||||||
|
|
||||||
def delete_template(self, template_id):
|
def delete_template(self, template_id):
|
||||||
self.oneadmin_client.call(oca.VmTemplate.METHODS[
|
self.oneadmin_client.call(oca.VmTemplate.METHODS[
|
||||||
'delete'], template_id, False)
|
'delete'], template_id, False)
|
||||||
|
|
||||||
def change_user_password(self, passwd_hash):
|
def change_user_password(self, passwd_hash):
|
||||||
self.oneadmin_client.call(
|
self.oneadmin_client.call(
|
||||||
|
|
|
@ -7,6 +7,7 @@ from djangocms_blog.models import Post
|
||||||
from djangocms_blog.views import PostListView
|
from djangocms_blog.views import PostListView
|
||||||
from djangocms_blog.settings import get_setting
|
from djangocms_blog.settings import get_setting
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from djangocms_blog.models import BlogCategory
|
||||||
|
|
||||||
|
|
||||||
def blog(request):
|
def blog(request):
|
||||||
|
@ -20,6 +21,7 @@ def blog(request):
|
||||||
|
|
||||||
|
|
||||||
class PostListViewUngleich(PostListView):
|
class PostListViewUngleich(PostListView):
|
||||||
|
category = None
|
||||||
model = Post
|
model = Post
|
||||||
context_object_name = 'post_list'
|
context_object_name = 'post_list'
|
||||||
base_template_name = 'post_list_ungleich.html'
|
base_template_name = 'post_list_ungleich.html'
|
||||||
|
@ -38,7 +40,26 @@ class PostListViewUngleich(PostListView):
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
language = get_language()
|
language = get_language()
|
||||||
queryset = self.model.objects.filter(publish=True).translated(language)
|
if self.category:
|
||||||
|
blog_category = (
|
||||||
|
BlogCategory
|
||||||
|
._default_manager
|
||||||
|
.language(language)
|
||||||
|
.filter(
|
||||||
|
translations__language_code=language,
|
||||||
|
translations__slug=self.category
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
queryset = (self.model
|
||||||
|
.objects
|
||||||
|
.filter(categories=blog_category, publish=True)
|
||||||
|
.translated(language))
|
||||||
|
else:
|
||||||
|
queryset = (self.model
|
||||||
|
.objects
|
||||||
|
.filter(publish=True)
|
||||||
|
.translated(language))
|
||||||
setattr(self.request, get_setting('CURRENT_NAMESPACE'), self.config)
|
setattr(self.request, get_setting('CURRENT_NAMESPACE'), self.config)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header_slider > .carousel .item .container {
|
.header_slider > .carousel .item .container-fluid {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 50px 20px 60px;
|
padding: 50px 20px 60px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
.header_slider .carousel-control .fa {
|
.header_slider .carousel-control .fa {
|
||||||
font-size: 4em;
|
font-size: 4em;
|
||||||
}
|
}
|
||||||
.header_slider > .carousel .item .container {
|
.header_slider > .carousel .item .container-fluid {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 75px 50px;
|
padding: 75px 50px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="container">
|
<div class="container-fluid">
|
||||||
{% if instance.heading %}
|
{% if instance.heading %}
|
||||||
<div class="intro-cap">{{ instance.heading }}</div>
|
<div class="intro-cap">{{ instance.heading }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -33,7 +33,11 @@
|
||||||
{% include "google_analytics.html" %}
|
{% include "google_analytics.html" %}
|
||||||
<!-- End Google Analytics -->
|
<!-- End Google Analytics -->
|
||||||
|
|
||||||
<link rel="shortcut icon" href="{% static 'ungleich_page/img/favicon.ico' %}" type="image/x-icon">
|
{% if request.current_page.cmsfaviconextension %}
|
||||||
|
<link rel="shortcut icon" href="{% static request.current_page.cmsfaviconextension.favicon.url %}" type="image/x-icon">
|
||||||
|
{% else %}
|
||||||
|
<link rel="shortcut icon" href="{% static 'ungleich_page/img/favicon.ico' %}" type="image/x-icon">
|
||||||
|
{% endif %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id="page-top" class="index">
|
<body id="page-top" class="index">
|
||||||
|
|
|
@ -107,10 +107,12 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0,
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
price = ((decimal.Decimal(cpu) * pricing.cores_unit_price) +
|
price = (
|
||||||
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
(decimal.Decimal(cpu) * pricing.cores_unit_price) +
|
||||||
(decimal.Decimal(ssd_size) * pricing.ssd_unit_price) +
|
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
||||||
(decimal.Decimal(hdd_size) * pricing.hdd_unit_price))
|
(decimal.Decimal(ssd_size) * pricing.ssd_unit_price) +
|
||||||
|
(decimal.Decimal(hdd_size) * pricing.hdd_unit_price)
|
||||||
|
)
|
||||||
if pricing.vat_inclusive:
|
if pricing.vat_inclusive:
|
||||||
vat = decimal.Decimal(0)
|
vat = decimal.Decimal(0)
|
||||||
vat_percent = decimal.Decimal(0)
|
vat_percent = decimal.Decimal(0)
|
||||||
|
@ -121,4 +123,8 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0,
|
||||||
cents = decimal.Decimal('.01')
|
cents = decimal.Decimal('.01')
|
||||||
price = price.quantize(cents, decimal.ROUND_HALF_UP)
|
price = price.quantize(cents, decimal.ROUND_HALF_UP)
|
||||||
vat = vat.quantize(cents, decimal.ROUND_HALF_UP)
|
vat = vat.quantize(cents, decimal.ROUND_HALF_UP)
|
||||||
return float(price), float(vat), float(vat_percent)
|
discount = {
|
||||||
|
'name': pricing.discount_name,
|
||||||
|
'amount': float(pricing.discount_amount),
|
||||||
|
}
|
||||||
|
return float(price), float(vat), float(vat_percent), discount
|
||||||
|
|
Loading…
Reference in a new issue