diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py index 39902025..9b4c2f75 100644 --- a/dynamicweb/settings/base.py +++ b/dynamicweb/settings/base.py @@ -30,6 +30,7 @@ dotenv.read_dotenv("{0}/.env".format(PROJECT_DIR)) SITE_ID = 1 APP_ROOT_ENDPOINT = "/" +APPEND_SLASH=True LOGIN_URL = None LOGOUT_URL = None diff --git a/hosting/mixins.py b/hosting/mixins.py new file mode 100644 index 00000000..7104e157 --- /dev/null +++ b/hosting/mixins.py @@ -0,0 +1,20 @@ +from django.shortcuts import redirect +from django.core.urlresolvers import reverse + + +class ProcessVMSelectionMixin(object): + + def post(self, request, *args, **kwargs): + vm_specs = { + 'cores': request.POST.get('cores'), + 'memory': request.POST.get('memory'), + 'disk_size': request.POST.get('disk_space'), + 'hosting_company': request.POST.get('hosting_company'), + 'hosting_company_name': request.POST.get('hosting_company_name'), + 'final_price': request.POST.get('final_price') + } + request.session['vm_specs'] = vm_specs + if not request.user.is_authenticated(): + request.session['vm_specs'] = vm_specs + return redirect(reverse('hosting:login')) + return redirect(reverse('hosting:payment')) diff --git a/hosting/static/hosting/css/landing-page.css b/hosting/static/hosting/css/landing-page.css index 24be9dec..6698c5ec 100644 --- a/hosting/static/hosting/css/landing-page.css +++ b/hosting/static/hosting/css/landing-page.css @@ -31,8 +31,7 @@ h6 { } .intro-header { - height: 85%; - padding-top: 10%; /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ + padding-top: 50px; /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ padding-bottom: 50px; text-align: center; color: #f8f8f8; @@ -48,8 +47,7 @@ h6 { background-size: cover; } .intro-header-2 { - height: 85%; - padding-top: 100px; /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ + padding-top: 50px; /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ padding-bottom: 50px; text-align: center; color: #f8f8f8; diff --git a/hosting/static/hosting/css/payment.css b/hosting/static/hosting/css/payment.css new file mode 100644 index 00000000..9b16f8b3 --- /dev/null +++ b/hosting/static/hosting/css/payment.css @@ -0,0 +1,33 @@ +.creditcard-box {padding-top:17%; padding-bottom: 11%;} +.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 { + font-weight: bold; + color: red; + padding: 2px 8px; + margin-top: 2px; +} +.creditcard-box .payment-errors { + font-weight: bold; + color: red; + padding: 2px 8px; + margin-top: 2px; +} + +.summary-box { + + padding-top:17%; + padding-bottom: 11%; +} + +.summary-box .content { + + padding-top: 15px; + +} \ No newline at end of file diff --git a/hosting/static/hosting/js/payment.js b/hosting/static/hosting/js/payment.js new file mode 100644 index 00000000..2e187201 --- /dev/null +++ b/hosting/static/hosting/js/payment.js @@ -0,0 +1,110 @@ +$( document ).ready(function() { + + var $form = $('#payment-form'); + $form.submit(payWithStripe); + + /* If you're using Stripe for payments */ + function payWithStripe(e) { + e.preventDefault(); + + /* Visual feedback */ + $form.find('[type=submit]').html('Validating '); + + var PublishableKey = 'pk_test_6pRNASCoBOKtIshFeQd4XMUh'; // Replace with your API publishable key + Stripe.setPublishableKey(PublishableKey); + Stripe.card.createToken($form, function stripeResponseHandler(status, response) { + console.log + if (response.error) { + /* Visual feedback */ + $form.find('[type=submit]').html('Try again'); + /* Show Stripe errors on the form */ + $form.find('.payment-errors').text(response.error.message); + $form.find('.payment-errors').closest('.row').show(); + } else { + /* Visual feedback */ + $form.find('[type=submit]').html('Processing '); + /* Hide Stripe errors on the form */ + $form.find('.payment-errors').closest('.row').hide(); + $form.find('.payment-errors').text(""); + // response contains id and card, which contains additional card details + var token = response.id; + console.log(token); + // AJAX + $.post('/account/stripe_card_token', { + token: token + }) + // Assign handlers immediately after making the request, + .done(function(data, textStatus, jqXHR) { + $form.find('[type=submit]').html('Payment successful ').prop('disabled', true); + }) + .fail(function(jqXHR, textStatus, errorThrown) { + $form.find('[type=submit]').html('There was a problem').removeClass('success').addClass('error'); + /* Show Stripe errors on the form */ + $form.find('.payment-errors').text('Try refreshing the page and trying again.'); + $form.find('.payment-errors').closest('.row').show(); + }); + } + }); + } + + /* Form validation */ + $.validator.addMethod("month", function(value, element) { + return this.optional(element) || /^(01|02|03|04|05|06|07|08|09|10|11|12)$/.test(value); + }, "Please specify a valid 2-digit month."); + + $.validator.addMethod("year", function(value, element) { + return this.optional(element) || /^[0-9]{2}$/.test(value); + }, "Please specify a valid 2-digit year."); + + validator = $form.validate({ + rules: { + cardNumber: { + required: true, + creditcard: true, + digits: true + }, + expMonth: { + required: true, + month: true + }, + expYear: { + required: true, + year: true + }, + cvCode: { + required: true, + digits: true + } + }, + highlight: function(element) { + $(element).closest('.form-control').removeClass('success').addClass('error'); + }, + unhighlight: function(element) { + $(element).closest('.form-control').removeClass('error').addClass('success'); + }, + errorPlacement: function(error, element) { + $(element).closest('.form-group').append(error); + } + }); + + paymentFormReady = function() { + if ($form.find('[name=cardNumber]').hasClass("success") && + $form.find('[name=expMonth]').hasClass("success") && + $form.find('[name=expYear]').hasClass("success") && + $form.find('[name=cvCode]').val().length > 1) { + return true; + } else { + return false; + } + } + + $form.find('[type=submit]').prop('disabled', true); + var readyInterval = setInterval(function() { + if (paymentFormReady()) { + $form.find('[type=submit]').prop('disabled', false); + clearInterval(readyInterval); + } + }, 250); + +}); + diff --git a/hosting/static/hosting/js/pricing.js b/hosting/static/hosting/js/pricing.js index 64e80638..7ff24518 100644 --- a/hosting/static/hosting/js/pricing.js +++ b/hosting/static/hosting/js/pricing.js @@ -8,7 +8,7 @@ $( document ).ready(function() { function calculate_price(vm_type){ var ID_SELECTOR = "#"; - var CURRENCY = "$"; + var CURRENCY = "CHF"; var final_price_selector = ID_SELECTOR.concat(vm_type.concat('-final-price')); var core_selector = ID_SELECTOR.concat(vm_type.concat('-cores')); var memory_selector = ID_SELECTOR.concat(vm_type.concat('-memory')); diff --git a/hosting/templates/hosting/base_short.html b/hosting/templates/hosting/base_short.html new file mode 100644 index 00000000..7aa1e702 --- /dev/null +++ b/hosting/templates/hosting/base_short.html @@ -0,0 +1,135 @@ +{% load staticfiles bootstrap3%} + + + +
+ + + + + + + +