diff --git a/matrixhosting/forms.py b/matrixhosting/forms.py index 6552690..6f60f3c 100644 --- a/matrixhosting/forms.py +++ b/matrixhosting/forms.py @@ -15,16 +15,32 @@ class DomainNameField(forms.CharField): def __init__(self, *args, **kwargs): super(DomainNameField, self).__init__(*args, **kwargs) -class InitialRequestForm(forms.Form): +class MainModelForm(ModelForm): + def __init__(self, *args, **kwargs): + super(MainModelForm, self).__init__(*args, **kwargs) + for visible in self.visible_fields(): + visible.field.widget.attrs['class'] = 'form-control' + +class MainForm(forms.Form): + def __init__(self, *args, **kwargs): + super(MainForm, self).__init__(*args, **kwargs) + for visible in self.visible_fields(): + if (isinstance(visible.field.widget, forms.TextInput)): + visible.field.widget.attrs['class'] = 'form-control' + elif (isinstance(visible.field.widget, forms.CheckboxInput)): + visible.field.widget.attrs['class'] = 'custom-control-input' + + +class InitialRequestForm(MainForm): cores = forms.IntegerField(label='CPU', min_value=1, max_value=48, initial=1) memory = forms.IntegerField(label='RAM', min_value=2, max_value=200, initial=2) storage = forms.IntegerField(label='Storage', min_value=100, max_value=10000, initial=100) pricing_name = forms.CharField(required=True) class RequestHostedVMForm(InitialRequestForm): - matrix_domain = DomainNameField(required=True) - homeserver_domain = DomainNameField(required=True) - webclient_domain = DomainNameField(required=True) + matrix_domain = DomainNameField(required=True, widget=forms.TextInput(attrs={'placeholder': 'Matrix Domain *'})) + homeserver_domain = DomainNameField(required=True, widget=forms.TextInput(attrs={'placeholder': 'Homeserver Domain *'})) + webclient_domain = DomainNameField(required=True, widget=forms.TextInput(attrs={'placeholder': 'Webclient Domain *'})) is_open_registration = forms.BooleanField(required=False, initial=False) def clean(self): @@ -41,7 +57,7 @@ class RequestHostedVMForm(InitialRequestForm): return self.cleaned_data -class BillingAddressForm(ModelForm): +class BillingAddressForm(MainModelForm): class Meta: model = BillingAddress fields = ['full_name', 'street', diff --git a/matrixhosting/static/matrixhosting/css/theme.css b/matrixhosting/static/matrixhosting/css/theme.css index a7049fa..d642d70 100644 --- a/matrixhosting/static/matrixhosting/css/theme.css +++ b/matrixhosting/static/matrixhosting/css/theme.css @@ -535,6 +535,9 @@ body, html { .bg-dark-5 { background-color: #435161 !important; } + .bg-warning-2 { + background-color: #ffe8a3; + } hr { border-top: 1px solid rgba(16, 85, 96, 0.1); @@ -3521,4 +3524,14 @@ body, html { } .logo img { width: 200px; + } + + .errorlist { + padding-left: 0; + list-style: none; + background-color: #e41d25; + color: #fff; + } + #card-errors { + color: #e41d25; } \ No newline at end of file diff --git a/matrixhosting/static/matrixhosting/images/encryption.jpeg b/matrixhosting/static/matrixhosting/images/encryption.jpeg new file mode 100644 index 0000000..1f3f29e Binary files /dev/null and b/matrixhosting/static/matrixhosting/images/encryption.jpeg differ diff --git a/matrixhosting/static/matrixhosting/images/logo.png b/matrixhosting/static/matrixhosting/images/logo.png index 122283f..e5dc7d8 100644 Binary files a/matrixhosting/static/matrixhosting/images/logo.png and b/matrixhosting/static/matrixhosting/images/logo.png differ diff --git a/matrixhosting/static/matrixhosting/images/matrix-bridge-irc.jpg b/matrixhosting/static/matrixhosting/images/matrix-bridge-irc.jpg new file mode 100644 index 0000000..818a820 Binary files /dev/null and b/matrixhosting/static/matrixhosting/images/matrix-bridge-irc.jpg differ diff --git a/matrixhosting/static/matrixhosting/images/matrix.jpg b/matrixhosting/static/matrixhosting/images/matrix.jpg index 1f472e8..cb238ba 100644 Binary files a/matrixhosting/static/matrixhosting/images/matrix.jpg and b/matrixhosting/static/matrixhosting/images/matrix.jpg differ diff --git a/matrixhosting/static/matrixhosting/images/renewable-energy.jpeg b/matrixhosting/static/matrixhosting/images/renewable-energy.jpeg new file mode 100644 index 0000000..c117d27 Binary files /dev/null and b/matrixhosting/static/matrixhosting/images/renewable-energy.jpeg differ diff --git a/matrixhosting/static/matrixhosting/js/payment.js b/matrixhosting/static/matrixhosting/js/payment.js index d009b78..f52aa25 100644 --- a/matrixhosting/static/matrixhosting/js/payment.js +++ b/matrixhosting/static/matrixhosting/js/payment.js @@ -1,59 +1,18 @@ -var cardBrandToPfClass = { - 'visa': 'pf-visa', - 'mastercard': 'pf-mastercard', - 'amex': 'pf-american-express', - 'discover': 'pf-discover', - 'diners': 'pf-diners', - 'jcb': 'pf-jcb', - 'unknown': 'pf-credit-card' -}; function setBrandIcon(brand) { var brandIconElement = document.getElementById('brand-icon'); - var pfClass = 'pf-credit-card'; - if (brand in cardBrandToPfClass) { - pfClass = cardBrandToPfClass[brand]; - } + var pfClass = 'fa-cc-' + brand; for (var i = brandIconElement.classList.length - 1; i >= 0; i--) { brandIconElement.classList.remove(brandIconElement.classList[i]); } - brandIconElement.classList.add('pf'); + brandIconElement.classList.add('fab'); brandIconElement.classList.add(pfClass); } - $(document).ready(function () { - $.ajaxSetup({ - beforeSend: function (xhr, settings) { - function getCookie(name) { - var cookieValue = null; - if (document.cookie && document.cookie != '') { - var cookies = document.cookie.split(';'); - for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); - // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) == (name + '=')) { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; - } - } - } - return cookieValue; - } - - if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) { - // Only send the token to relative URLs i.e. locally. - xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); - } - } - }); - - var hasCreditcard = window.hasCreditcard || false; if (!hasCreditcard && window.stripeKey) { var stripe = Stripe(window.stripeKey); - if (window.pm_id) { - - } else { + if (window.pm_id == undefined) { var element_style = { fonts: [{ family: 'lato-light', @@ -120,9 +79,9 @@ $(document).ready(function () { } function submitBillingForm(pmId) { - var billing_form = $('#billing-form'); - billing_form.append(''); - billing_form.submit(); + var order_form = $('#order_form'); + order_form.append(''); + order_form.submit(); } var $form_new = $('#payment-form-new'); @@ -133,7 +92,6 @@ $(document).ready(function () { e.preventDefault(); function stripePMHandler(paymentMethod) { // Insert the token ID into the form so it gets submitted to the server - console.log(paymentMethod); $('#id_payment_method').val(paymentMethod.id); submitBillingForm(paymentMethod.id); } diff --git a/matrixhosting/templates/account/base.html b/matrixhosting/templates/account/base.html new file mode 100644 index 0000000..9ee0385 --- /dev/null +++ b/matrixhosting/templates/account/base.html @@ -0,0 +1,97 @@ +{% load static i18n %} {% get_current_language as LANGUAGE_CODE %} + + + + + + + + +{% block head_title %}{% endblock %} + + + + + + + + + + + + + + {% block body %} + +
+
+
+ + +
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+

{% trans "Welcome!" %}

+

{% trans "We are glad to see you!" %}

+

{% trans "Grow your community with less effort.!" %}

+
+
+
+
+
+ +
+
+
+
+ {% block content %} + {% endblock %} + {% if messages %} +
+ Messages: +
    + {% for message in messages %} +
  • {{message}}
  • + {% endfor %} +
+
+ {% endif %} +
+
+
+
+
+
+
+ + + + +{% block js_extra %} {% endblock js_extra %} + + +{% endblock %} +{% block extra_body %} +{% endblock %} + + \ No newline at end of file diff --git a/matrixhosting/templates/account/email_confirm.html b/matrixhosting/templates/account/email_confirm.html new file mode 100644 index 0000000..ac0891b --- /dev/null +++ b/matrixhosting/templates/account/email_confirm.html @@ -0,0 +1,31 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account %} + +{% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %} + + +{% block content %} +

{% trans "Confirm E-mail Address" %}

+ +{% if confirmation %} + +{% user_display confirmation.email_address.user as user_display %} + +

{% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}

+ +
+{% csrf_token %} + +
+ +{% else %} + +{% url 'account_email' as email_url %} + +

{% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request.{% endblocktrans %}

+ +{% endif %} + +{% endblock %} diff --git a/matrixhosting/templates/account/login.html b/matrixhosting/templates/account/login.html new file mode 100644 index 0000000..d8d92f7 --- /dev/null +++ b/matrixhosting/templates/account/login.html @@ -0,0 +1,43 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account socialaccount %} + +{% block head_title %}{% trans "Sign In" %}{% endblock %} + +{% block content %} +

Log In

+
+ {% csrf_token %} + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} +
+ + + {{ form.login.errors }} +
+
+ + + {{ form.password.errors }} + {% if redirect_field_value %} + + {% endif %} +
+
+
+
+ + +
+
+ +
+ +
+

{% trans "Don't have an account?" %}{% trans "Sign Up" %}

+ +{% endblock %} diff --git a/matrixhosting/templates/account/logout.html b/matrixhosting/templates/account/logout.html new file mode 100644 index 0000000..8363f84 --- /dev/null +++ b/matrixhosting/templates/account/logout.html @@ -0,0 +1,18 @@ +{% extends "account/base.html" %} + +{% load i18n %} + +{% block head_title %}{% trans "Sign Out" %}{% endblock %} + +{% block content %} +

{% trans "Sign Out" %}

+

{% trans 'Are you sure you want to sign out?' %}

+
+ {% csrf_token %} + {% if redirect_field_value %} + + {% endif %} + +
+{% endblock %} + diff --git a/matrixhosting/templates/account/password_reset.html b/matrixhosting/templates/account/password_reset.html new file mode 100644 index 0000000..033f84e --- /dev/null +++ b/matrixhosting/templates/account/password_reset.html @@ -0,0 +1,29 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account %} + +{% block head_title %}{% trans "Password Reset" %}{% endblock %} + +{% block content %} + {% if user.is_authenticated %} + {% include "account/snippets/already_logged_in.html" %} + {% endif %} +

{% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}

+
+ {% csrf_token %} + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} + {% csrf_token %} +
+ + + {{ form.email.errors }} +
+ +

{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}

+
+{% endblock %} diff --git a/matrixhosting/templates/account/password_reset_from_key.html b/matrixhosting/templates/account/password_reset_from_key.html new file mode 100644 index 0000000..16f27e9 --- /dev/null +++ b/matrixhosting/templates/account/password_reset_from_key.html @@ -0,0 +1,23 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% block head_title %}{% trans "Change Password" %}{% endblock %} + +{% block content %} +

{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}

+ + {% if token_fail %} + {% url 'account_reset_password' as passwd_reset_url %} +

{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktrans %}

+ {% else %} + {% if form %} +
+ {% csrf_token %} + {{ form.as_p }} + +
+ {% else %} +

{% trans 'Your password is now changed.' %}

+ {% endif %} + {% endif %} +{% endblock %} diff --git a/matrixhosting/templates/account/signup.html b/matrixhosting/templates/account/signup.html new file mode 100644 index 0000000..dab2230 --- /dev/null +++ b/matrixhosting/templates/account/signup.html @@ -0,0 +1,43 @@ +{% extends "account/base.html" %} + +{% load i18n %} +{% load account socialaccount %} + +{% block head_title %}{% trans "Sign In" %}{% endblock %} + +{% block content %} +

Log In

+
+ {% csrf_token %} + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} +
+ + + {{ form.username.errors }} +
+
+ + + {{ form.email.errors }} +
+
+ + + {{ form.password1.errors }} +
+
+ + + {{ form.password2.errors }} + {% if redirect_field_value %} + + {% endif %} +
+ +
+

{% trans "Already have an account?" %}{% trans "Login" %}

+{% endblock %} diff --git a/matrixhosting/templates/matrixhosting/base.html b/matrixhosting/templates/matrixhosting/base.html index 46b636a..fa4adcf 100644 --- a/matrixhosting/templates/matrixhosting/base.html +++ b/matrixhosting/templates/matrixhosting/base.html @@ -54,7 +54,6 @@ > - {% block js_extra %} {% endblock js_extra %} diff --git a/matrixhosting/templates/matrixhosting/includes/_calculator_form.html b/matrixhosting/templates/matrixhosting/includes/_calculator_form.html index eb8cd06..7f34a7b 100644 --- a/matrixhosting/templates/matrixhosting/includes/_calculator_form.html +++ b/matrixhosting/templates/matrixhosting/includes/_calculator_form.html @@ -27,15 +27,6 @@ -
- {% for message in messages %} - {% if 'cores' in message.tags %} - - {% endif %} - {% endfor %} -
@@ -47,15 +38,6 @@
-
- {% for message in messages %} - {% if 'memory' in message.tags %} - - {% endif %} - {% endfor %} -
@@ -67,15 +49,6 @@
-
- {% for message in messages %} - {% if 'memory' in message.tags %} - - {% endif %} - {% endfor %} -

{% if matrix_vm_pricing.discount_amount %} diff --git a/matrixhosting/templates/matrixhosting/includes/_card.html b/matrixhosting/templates/matrixhosting/includes/_card.html index ec30a7d..d0dbd79 100644 --- a/matrixhosting/templates/matrixhosting/includes/_card.html +++ b/matrixhosting/templates/matrixhosting/includes/_card.html @@ -1,43 +1,42 @@ {% load i18n %} -
- - -
-
-
- -
-
-
-
- -
+ + + +
+
+
+ +
-
- -
+
+
+ +
+
+
+ +
+
+
+
+
-
-
- - -
+
-
-
-
- {% for message in messages %} - {% if 'failed_payment' in message.tags or 'make_charge_error' in message.tags or 'error' in message.tags %} -
    -
  • {{ message|safe }}

  • -
- {% endif %} - {% endfor %} -
-
- -
-
-

-
- \ No newline at end of file +
+
+ {% for message in messages %} + {% if 'failed_payment' in message.tags or 'make_charge_error' in message.tags or 'error' in message.tags %} +
    +
  • {{ message|safe }}

  • +
+ {% endif %} + {% endfor %} +
+
+ +
+
+

+
+ diff --git a/matrixhosting/templates/matrixhosting/includes/_navbar.html b/matrixhosting/templates/matrixhosting/includes/_navbar.html index 5e904b6..9c11b8b 100644 --- a/matrixhosting/templates/matrixhosting/includes/_navbar.html +++ b/matrixhosting/templates/matrixhosting/includes/_navbar.html @@ -20,8 +20,14 @@ diff --git a/matrixhosting/templates/matrixhosting/index.html b/matrixhosting/templates/matrixhosting/index.html index 5778c2e..8087a3d 100644 --- a/matrixhosting/templates/matrixhosting/index.html +++ b/matrixhosting/templates/matrixhosting/index.html @@ -21,7 +21,7 @@ ============================================= -->
-
@@ -41,7 +41,7 @@
- + @@ -86,10 +86,65 @@
+
+
+
+
+
banner +
+
+
+
+

Growing with ease

+

Organise and grow your community without ethical compromises. You can start with any size you want and scale as you grow.

+
    +
  • Start from 40 CHF/Month
  • +
  • No hidden Cost
  • +
  • No limit number of users
  • +
  • No Fossil fules
  • +
+ How Pricing Works
+
+
+
+
+
+
+
+
+
+

Talk to everybody via bridge while staying on Matrix

+

You can engage in other chat networks such as Slack, Telegram, Whatsapp, IRC, Mattermost, Rocketchat, Discord and more by Matterbridge.

+

The bridging allows you to stay on your own Matrix and receiving and sending messages to a bigger community.

+ Learn more about Matterbridge
+
+
+
banner +
+
+
+
+
+
+
+
+
+
banner +
+
+
+
+

Secure Matrix chat for your action

+

It's a secure chat that does not depend on a single point of failure and does not give away your data to the malicious third parties.

+

is End-to-End Encrypted (E2EE) by default. As your communication is encrypted with multiple keys, the thrid parties can not decrypt your message, including the hosting company and the law enforcement. Your communication and community data stays private and secure.

+
+
+
+
-
+

As simple as 1-2-3

Lorem Ipsum is simply dummy text of the printing and typesetting industry.

@@ -128,43 +183,46 @@
-
-
+
+
-

Why MatrixHosting?

-

Lisque persius interesset his et, in quot quidam persequeris vim, ad mea essent possim iriure. Mutat tacimates id sit. Ridens mediocritatem ius an, eu nec magna imperdiet.

-

Request a matrix instance

-

Lisque persius interesset his et, in quot quidam persequeris vim, ad mea essent possim iriure. Mutat tacimates id sit. Ridens mediocritatem ius an, eu nec magna imperdiet.

-

Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et.

+

Fully Sustainable

+

MatrixHosting is a clean chat for the environment. + You can build and grow your community with as little carbon footprint as possible. The Matrix instance we run are hosted in Data Center Light, a Swiss datacenter built with sustainability to its core.

+

100% Renewable Energy

+

Not every data center has an in-house hydropower plant, but we do. Data Center Light runs with 99.9%* hydropower. Few meters away from where our servers are running, the hydropower plant is generating electricity in the basement. We assure you that our electricity is made of 100% renewable energy. + + *0.1 % of electricity comes from solar power.

+
+ -
-
-
-
-
-
-

How does it works?

-
-
-
+
+ +
+
+

Try it now for free

+

Want to try it before committing to a plan? You can create a free account and see how you like it. You can chat, join different rooms and invite others. You will join our actual work chat where all our team and the bigger community of Matrix users are working and chatting day and night. +

+ A free test ride on ungleich Matrix
+
+
@@ -294,7 +353,7 @@
-
See more FAQ
+
See more FAQ
diff --git a/matrixhosting/templates/matrixhosting/order_confirmation.html b/matrixhosting/templates/matrixhosting/order_confirmation.html new file mode 100644 index 0000000..3a15284 --- /dev/null +++ b/matrixhosting/templates/matrixhosting/order_confirmation.html @@ -0,0 +1,256 @@ +{% extends "matrixhosting/base.html" %} + +{% load static i18n %} + +{% block title %} Request Details {% endblock %} + +{% block content %} +
+ +
+
+
+
+
{%trans "Details" %}
+
+
+
+
+
+
{%trans "Confirm" %}
+
+
+
+
+
+
{%trans "Success" %}
+
+
+
+
+
+
+
+
+ {% if messages %} +
+ {% for message in messages %} + {{ message }} + {% endfor %} +
+ {% endif %} + {% if not error %} +
+
+
+
{% trans "Billed To" %}
+

+ {% with request.session.billing_address_data as billing_address %} + {{billing_address.full_name}}
+ {{billing_address.street}}, {{billing_address.postal_code}}
+ {{billing_address.city}}, {{billing_address.country}} + {% if billing_address.vat_number %} +
{% trans "VAT Number" %} {{billing_address.vat_number}} + {% if pricing.vat_country != "ch" and pricing.vat_validation_status != "not_needed" %} + {% if pricing.vat_validation_status == "verified" %} + + {% else %} + + {% endif %} + {% endif %} + {% endif %} + {% endwith %} +

+
+
+
+
+
+
{% trans "Billed To" %}
+

+ {% with request.session.billing_address_data as billing_address %} + {{billing_address.full_name}}
+ {{billing_address.street}}, {{billing_address.postal_code}}
+ {{billing_address.city}}, {{billing_address.country}} + {% if billing_address.vat_number %} +
{% trans "VAT Number" %} {{billing_address.vat_number}} + {% if pricing.vat_country != "ch" and pricing.vat_validation_status != "not_needed" %} + {% if pricing.vat_validation_status == "verified" %} + + {% else %} + + {% endif %} + {% endif %} + {% endif %} + {% endwith %} +

+
+
+
+

{{ balance }} CHF

+ {% trans "Available Balance"%} +
+
+
+
+
{% trans "Order summary" %}
+

+ {% trans "Product" %}:  + Matrix Chat Hosting +

+
+
+

+ {% trans "Cores" %}: + {{order.cores}} +

+

+ {% trans "Memory" %}: + {{order.memory}} GB +

+

+ {% trans "Disk space" %}: + {{order.storage}} GB +

+
+
+
+
+
+

+ {% trans "Price Before VAT" %} + {{pricing.subtotal|floatformat:2}} CHF +

+
+
+
+
+
+
+
+

+
+
+

{% trans "Pre VAT" %}

+
+
+

{% trans "With VAT for" %} {{pricing.vat_country}} ({{pricing.vat_percent}}%)

+
+
+
+
+

Subtotal

+
+
+

{{pricing.subtotal|floatformat:2}} CHF

+
+
+

{{pricing.price_with_vat|floatformat:2}} CHF

+
+
+ {% if pricing.discount.amount > 0 %} +
+
+

{{pricing.discount.name}}

+
+
+

-{{pricing.discount.amount|floatformat:2}} CHF

+
+
+

-{{pricing.discount.amount_with_vat|floatformat:2}} CHF

+
+
+ {% endif %} +
+
+
+
+
+
+
+

Total

+
+
+

{{pricing.subtotal_after_discount|floatformat:2}} CHF

+
+
+

{{pricing.price_after_discount_with_vat|floatformat:2}} CHF

+
+
+
+
+
+
+
+ {% trans "Your Price in Total" %} + {{pricing.total_price|floatformat:2}} CHF +
+
+
+
+
+
+ {% csrf_token %} +
+
+
{% blocktrans with vm_total_price=vm.total_price|floatformat:2 %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ vm_total_price }} CHF/month{% endblocktrans %}.
+
+
+ +
+
+
+ {% endif %} +
+
+
+
+ + +{% endblock %} + +{% block js_extra %} +{% if stripe_key %} + {% get_current_language as LANGUAGE_CODE %} + + {%endif%} + + + + + + +{% endblock js_extra %} \ No newline at end of file diff --git a/matrixhosting/templates/matrixhosting/order_detail.html b/matrixhosting/templates/matrixhosting/order_detail.html deleted file mode 100644 index aef9d28..0000000 --- a/matrixhosting/templates/matrixhosting/order_detail.html +++ /dev/null @@ -1,266 +0,0 @@ -{% load static i18n %} - - - - - - - - - - Matrix Hosting - {% block title %} made in Switzerland{% endblock %} - - - - - - - - - - - - - - - - - - -
- {% if messages %} -
- {% for message in messages %} - {{ message }} - {% endfor %} -
- {% endif %} - {% if not error %} -
-

- {% blocktrans with page_header_text=page_header_text|default:"Order" %}{{page_header_text}}{% endblocktrans %} -

-
-
-
-
-
-

{% trans "Billed to" %}:

-

- {% with request.session.billing_address_data as billing_address %} - {{billing_address.full_name}}
- {{billing_address.street}}, {{billing_address.postal_code}}
- {{billing_address.city}}, {{billing_address.country}} - {% if billing_address.vat_number %} -
{% trans "VAT Number" %} {{billing_address.vat_number}} - {% if pricing.vat_country != "ch" and pricing.vat_validation_status != "not_needed" %} - {% if pricing.vat_validation_status == "verified" %} - - {% else %} - - {% endif %} - {% endif %} - {% endif %} - {% endwith %} -

-
-
-
-
-

{% trans "Payment method" %}:

-

- {{card.brand|default:_('Credit Card')}} {% trans "ending in" %} ****{{card.last4}}
- {% trans "Expiry" %} {{card.exp_year}}/{{card.exp_month}}
- {{request.user.email}} -

-
-
-
-

{% trans "Order summary" %}

- -

- {% trans "Product" %}:  - Matrix Chat Hosting -

-
-
-

- {% trans "Cores" %}: - {{order.cores}} -

-

- {% trans "Memory" %}: - {{order.memory}} GB -

-

- {% trans "Disk space" %}: - {{order.storage}} GB -

-
-
-
-
-
-

- {% trans "Price Before VAT" %} - {{pricing.subtotal|floatformat:2}} CHF -

-
-
-
-
-
-
-
-

-
-
-

{% trans "Pre VAT" %}

-
-
-

{% trans "With VAT for" %} {{pricing.vat_country}} ({{pricing.vat_percent}}%)

-
-
-
-
-

Subtotal

-
-
-

{{pricing.subtotal|floatformat:2}} CHF

-
-
-

{{pricing.price_with_vat|floatformat:2}} CHF

-
-
- {% if pricing.discount.amount > 0 %} -
-
-

{{pricing.discount.name}}

-
-
-

-{{pricing.discount.amount|floatformat:2}} CHF

-
-
-

-{{pricing.discount.amount_with_vat|floatformat:2}} CHF

-
-
- {% endif %} -
-
-
-
-
-
-
-

Total

-
-
-

{{pricing.subtotal_after_discount|floatformat:2}} CHF

-
-
-

{{pricing.price_after_discount_with_vat|floatformat:2}} CHF

-
-
-
-
-
-
-
- {% trans "Your Price in Total" %} - {{pricing.total_price|floatformat:2}} CHF -
-
-
-
-
-
- {% csrf_token %} -
-
-
{% blocktrans with vm_total_price=vm.total_price|floatformat:2 %}By clicking "Place order" you agree to our Terms of Service and this plan will charge your credit card account with {{ vm_total_price }} CHF/month{% endblocktrans %}.
-
-
- -
-
-
- {% endif %} -
- - - - - - - - - - - - - - - - - - diff --git a/matrixhosting/templates/matrixhosting/order_details.html b/matrixhosting/templates/matrixhosting/order_details.html new file mode 100644 index 0000000..6d147c7 --- /dev/null +++ b/matrixhosting/templates/matrixhosting/order_details.html @@ -0,0 +1,270 @@ +{% extends "matrixhosting/base.html" %} + +{% load static i18n %} + +{% block title %} Request Details {% endblock %} + +{% block content %} +
+ +
+
+
+
+
{%trans "Details" %}
+
+
+
+
+
+
{%trans "Confirm" %}
+
+
+
+
+
+
{%trans "Success" %}
+
+
+
+
+
+
+
+
+ {% csrf_token %} +
+
+

{% trans "Order Details"%}

+
+ {% if details_form.non_field_errors %} +
+ {{ details_form.non_field_errors }} +
+ {% endif %} +
+
+
+ {{details_form.matrix_domain}} + {{ details_form.matrix_domain.errors }} +
+
+ {{details_form.homeserver_domain}} + {{ details_form.homeserver_domain.errors }} +
+
+ {{details_form.webclient_domain}} + {{ details_form.webclient_domain.errors }} +
+
+ {{details_form.is_open_registration}} + + {{ details_form.is_open_registration.errors }} +
+ {{details_form.pricing_name.as_hidden}} +
+
+
+
+
+ +
+ Core + +
+
+
+
+
+
+ +
+ {% trans "RAM" %} + +
+
+
+
+
+
+ +
+ {% trans "GB" %} + +
+
+
+
+
+
+
+
+
+

{%trans "Billing Address"%}

+
+ {% for message in messages %} + {% if 'vat_error' in message.tags %} +
  • + {{ message|safe }} +
+ {% endif %} + {% endfor %} + {% if billing_address_form.non_field_errors %} +
+ {{ billing_address_form.non_field_errors }} +
+ {% endif %} +
+
+
+ + {{billing_address_form.full_name}} + {{ billing_address_form.full_name.errors }} +
+
+
+
+ + {{billing_address_form.street}} + {{ billing_address_form.full_name.errors }} +
+
+
+
+ + {{billing_address_form.city}} + {{ billing_address_form.city.errors }} +
+
+
+
+ + {{billing_address_form.country}} + {{ billing_address_form.country.errors }} +
+
+
+
+ + {{billing_address_form.postal_code}} + {{ billing_address_form.postal_code.errors }} +
+
+
+
+ + {{billing_address_form.vat_number}} + {{ billing_address_form.vat_number.errors }} +
+
+ {% for field in billing_address_form %} + {% if field.html_name in 'active,owner' %} + {{ field.as_hidden }} + {% endif %} + {% endfor %} +
+
+
+
+
+
+
+
+

{% trans "Payment Details"%}

+
+
+
+
+
+

{{ balance }} CHF

+ {% trans "Available Balance"%} +
+
+
+
+
+
+

{% trans "Total To Pay"%}

+ + ({% if matrix_vm_pricing.vat_inclusive %}{%trans "including VAT" %}{% else %}{%trans "excluding VAT" %}{% endif %}) + + {% if matrix_vm_pricing.discount_amount %} +
Discount {{matrix_vm_pricing.discount_amount}}CHF
+ {% endif %} +
+
+
{{request.session.pricing.total|floatformat}}CHF
+
+
+
+ {% with cards_len=cards|length %} +

+ {% if cards_len > 0 %} + {% blocktrans %}Please select one of the cards that you used before or fill in your credit card information below.{% endblocktrans %} + {% else %} + {% blocktrans %}Please fill in your credit card information below.{% endblocktrans %} + {% endif %} +

+
+ {% for card in cards %} +
+
+ + +
+
+ {% endfor %} + {% if cards_len > 0 %} +
+ + +
+
+
+ {% include "matrixhosting/includes/_card.html" %} +
+
+ {% else%} + {% include "matrixhosting/includes/_card.html" %} + {% endif %} +
+ {% endwith %} +
+
+
+
+
+ +{% endblock %} + +{% block js_extra %} +{% if stripe_key %} + {% get_current_language as LANGUAGE_CODE %} + + {%endif%} + + + + + + +{% endblock js_extra %} \ No newline at end of file diff --git a/matrixhosting/templates/matrixhosting/payment.html b/matrixhosting/templates/matrixhosting/payment.html deleted file mode 100644 index 347b460..0000000 --- a/matrixhosting/templates/matrixhosting/payment.html +++ /dev/null @@ -1,166 +0,0 @@ -{% load static i18n %} - - - - - - - - - - - Matrix Hosting - {% block title %} made in Switzerland{% endblock %} - - - - - - - - - - - - - - - - - -
-
-
-
-
-

{%trans "Your Order" %}

-
-
-

{% trans "Cores"%} {{request.session.order.cores|floatformat}}

-
-

{% trans "Memory"%} {{request.session.order.memory|floatformat}} GB

-
-

{% trans "Disk space"%} {{request.session.order.storage|floatformat}} GB

-
-

- {%trans "Total" %}   - - ({% if matrix_vm_pricing.vat_inclusive %}{%trans "including VAT" %}{% else %}{%trans "excluding VAT" %}{% endif %}) - - {{request.session.order.subtotal|floatformat}} CHF / {% trans "Month" %} -

-
- {% if matrix_vm_pricing.discount_amount %} -

- {{ request.session.order.discount.name }}   - - {{ request.session.order.discount.amount }} CHF / {% trans "Month" %} -

- {% endif %} -
-
-
-
-

{%trans "Billing Address"%}

-
- {% for message in messages %} - {% if 'vat_error' in message.tags %} -
  • - {{ message|safe }} -
- {% endif %} - {% endfor %} -
- {% csrf_token %} - {% for field in billing_address_form %} - {% if field.html_name in 'active,owner' %} - {{ field.as_hidden }} - {%else %} - {{field}} - {% endif %} - {% endfor %} -
-
-
-
-
-
-
- {% with cards_len=cards|length %} -

{%trans "Credit Card"%}

-
-

- {% if cards_len > 0 %} - {% blocktrans %}Please select one of the cards that you used before or fill in your credit card information below. We are using Stripe for payment and do not store your information in our database.{% endblocktrans %} - {% else %} - {% blocktrans %}Please fill in your credit card information below. We are using Stripe for payment and do not store your information in our database.{% endblocktrans %} - {% endif %} -

-
- {% for card in cards %} -
-
-
{% trans "Credit Card" %}
-
{% trans "Last" %} 4: ***** {{card.last4}}
-
{% trans "Type" %}: {{card.brand}}
-
{% trans "Expiry" %}: {{card.month}}/{{card.year}}
-
- -
- {% endfor %} - {% if cards_len > 0 %} -
-
-
-

{% trans "Add a new credit card" %}

-
-
- -
-
-
-
-
-
-

{%trans "New Credit Card" %}

-
- {% include "matrixhosting/includes/_card.html" %} -
-
- {% else%} - {% include "matrixhosting/includes/_card.html" %} - {% endif %} -
- {% endwith %} -
-
-
-
- {% if stripe_key %} - {% get_current_language as LANGUAGE_CODE %} - - {%endif%} - - - - - - - - - - - diff --git a/matrixhosting/urls.py b/matrixhosting/urls.py index 318ef8b..f3015bd 100644 --- a/matrixhosting/urls.py +++ b/matrixhosting/urls.py @@ -8,8 +8,8 @@ app_name = 'matrixhosting' urlpatterns = [ path('pricing//calculate/', PricingView.as_view(), name='pricing_calculator'), - path('payment/', OrderPaymentView.as_view(), name='payment'), - path('order/details/', OrderDetailsView.as_view(), name='order_details'), + path('order/new/', OrderPaymentView.as_view(), name='payment'), + path('order/confirm/', OrderDetailsView.as_view(), name='order_confirmation'), path('dashboard/', Dashboard.as_view(), name='dashboard'), path('', IndexView.as_view(), name='index'), ] diff --git a/matrixhosting/views.py b/matrixhosting/views.py index f485a70..9cb33e1 100644 --- a/matrixhosting/views.py +++ b/matrixhosting/views.py @@ -22,7 +22,7 @@ from uncloud_pay.models import PricingPlan from uncloud_pay.utils import get_order_total_with_vat from uncloud_pay.models import * from uncloud_pay.utils import validate_vat_number -from uncloud_pay.selectors import get_billing_address_for_user +from uncloud_pay.selectors import get_billing_address_for_user, has_enough_balance, get_balance_for_user import uncloud_pay.stripe as uncloud_stripe from .models import VMInstance from .serializers import * @@ -61,13 +61,13 @@ class IndexView(FormView): False ) self.request.session['pricing'] = {'name': form.cleaned_data['pricing_name'], - 'subtotal': subtotal, 'vat': vat, + 'subtotal': subtotal, 'vat': vat, 'total': total, 'vat_percent': vat_percent, 'discount': discount} return HttpResponseRedirect(reverse('matrix:payment')) class OrderPaymentView(FormView): - template_name = 'matrixhosting/payment.html' + template_name = 'matrixhosting/order_details.html' success_url = 'matrix:order_confirmation' form_class = BillingAddressForm @@ -88,12 +88,17 @@ class OrderPaymentView(FormView): ) if old_active else BillingAddressForm( initial={'active': True, 'owner': self.request.user.id} ) + details_form = RequestHostedVMForm( + initial=self.request.session.get('order', {}) + ) customer_id = uncloud_stripe.get_customer_id_for(self.request.user) cards = uncloud_stripe.get_customer_cards(customer_id) context.update({ 'matrix_vm_pricing': PricingPlan.get_by_name(self.request.session.get('pricing', {'name': 'unknown'})['name']), 'billing_address_form': billing_address_form, + 'details_form': details_form, 'cards': cards, + 'balance': get_balance_for_user(self.request.user), 'stripe_key': settings.STRIPE_PUBLIC_KEY }) @@ -107,8 +112,15 @@ class OrderPaymentView(FormView): if 'order' not in request.session: return HttpResponseRedirect(reverse('matrix:index')) return self.render_to_response(self.get_context_data()) - - def form_valid(self, address_form): + + def post(self, request, *args, **kwargs): + details_form = RequestHostedVMForm(request.POST) + billing_address_form = BillingAddressForm(request.POST) + if not details_form.is_valid() or not billing_address_form.is_valid(): + context = self.get_context_data() + context.update({'details_form': details_form, + 'billing_address_form': billing_address_form}) + return self.render_to_response(context) id_payment_method = self.request.POST.get('id_payment_method', None) self.request.session["id_payment_method"] = id_payment_method this_user = { @@ -125,12 +137,11 @@ class OrderPaymentView(FormView): if form.is_valid: billing_address_ins = form.save() self.request.session["billing_address_id"] = billing_address_ins.id - self.request.session['billing_address_data'] = address_form.cleaned_data + self.request.session['billing_address_data'] = billing_address_form.cleaned_data self.request.session['billing_address_data']['owner'] = self.request.user.id self.request.session['user'] = this_user self.request.session['customer'] = customer_id - - vat_number = address_form.cleaned_data.get('vat_number').strip() + vat_number = billing_address_form.cleaned_data.get('vat_number').strip() if vat_number: validate_result = validate_vat_number( stripe_customer_id=customer_id, @@ -146,58 +157,56 @@ class OrderPaymentView(FormView): reverse('matrix:payment') + '#vat_error' ) self.request.session["vat_validation_status"] = validate_result["status"] - - return HttpResponseRedirect(reverse('matrix:order_details')) - + return HttpResponseRedirect(reverse('matrix:order_confirmation')) class OrderDetailsView(DetailView): - template_name = "matrixhosting/order_detail.html" + template_name = "matrixhosting/order_confirmation.html" context_object_name = "order" model = Order - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super().dispatch(*args, **kwargs) + # @method_decorator(login_required) + # def dispatch(self, *args, **kwargs): + # return super().dispatch(*args, **kwargs) @cache_control(no_cache=True, must_revalidate=True, no_store=True) def get(self, request, *args, **kwargs): context = {} - if ('order' not in request.session or 'user' not in request.session): - return HttpResponseRedirect(reverse('matrix:index')) - if 'id_payment_method' in self.request.session: - card = uncloud_stripe.get_card_from_payment(self.request.user, self.request.session['id_payment_method']) - if not card: - return HttpResponseRedirect(reverse('matrix:payment')) - context['card'] = card - elif 'id_payment_method' not in self.request.session or 'vat_validation_status' not in self.request.session: - return HttpResponseRedirect(reverse('matrix:payment')) - specs = request.session.get('order') - pricing = request.session.get('pricing') - billing_address = BillingAddress.objects.get(id=request.session.get('billing_address_id')) - vat_rate = VATRate.get_vat_rate(billing_address) - vat_validation_status = "verified" if billing_address.vat_number_validated_on and billing_address.vat_number_verified else False - subtotal, subtotal_after_discount, price_after_discount_with_vat, vat, vat_percent, discount = get_order_total_with_vat( - specs['cores'], specs['memory'], specs['storage'], request.session['pricing']['name'], - vat_rate=vat_rate * 100, vat_validation_status = vat_validation_status - ) - pricing = { - "subtotal": subtotal, "discount": discount, "vat": vat, "vat_percent": vat_percent, - "vat_country": billing_address.country.lower(), - "subtotal_after_discount": subtotal_after_discount, - "price_after_discount_with_vat": price_after_discount_with_vat + # if ('order' not in request.session or 'user' not in request.session): + # return HttpResponseRedirect(reverse('matrix:index')) + # if 'id_payment_method' in self.request.session: + # card = uncloud_stripe.get_card_from_payment(self.request.user, self.request.session['id_payment_method']) + # if not card: + # return HttpResponseRedirect(reverse('matrix:payment')) + # context['card'] = card + # elif 'id_payment_method' not in self.request.session or 'vat_validation_status' not in self.request.session: + # return HttpResponseRedirect(reverse('matrix:payment')) + # specs = request.session.get('order') + # pricing = request.session.get('pricing') + # billing_address = BillingAddress.objects.get(id=request.session.get('billing_address_id')) + # vat_rate = VATRate.get_vat_rate(billing_address) + # vat_validation_status = "verified" if billing_address.vat_number_validated_on and billing_address.vat_number_verified else False + # subtotal, subtotal_after_discount, price_after_discount_with_vat, vat, vat_percent, discount = get_order_total_with_vat( + # specs['cores'], specs['memory'], specs['storage'], request.session['pricing']['name'], + # vat_rate=vat_rate * 100, vat_validation_status = vat_validation_status + # ) + # pricing = { + # "subtotal": subtotal, "discount": discount, "vat": vat, "vat_percent": vat_percent, + # "vat_country": billing_address.country.lower(), + # "subtotal_after_discount": subtotal_after_discount, + # "price_after_discount_with_vat": price_after_discount_with_vat - } - pricing["price_with_vat"] = round(subtotal * (1 + pricing["vat_percent"] * 0.01), 2) - discount["amount_with_vat"] = round(pricing["price_with_vat"] - pricing["price_after_discount_with_vat"], 2) - pricing["total_price"] = pricing["price_after_discount_with_vat"] - self.request.session['total_price'] = pricing["price_after_discount_with_vat"] - payment_intent_response = uncloud_stripe.get_payment_intent(request.user, pricing["price_after_discount_with_vat"]) - context.update({ - 'payment_intent_secret': payment_intent_response.client_secret, - 'order': specs, - 'pricing': pricing, - 'stripe_key': settings.STRIPE_PUBLIC_KEY, - }) + # } + # pricing["price_with_vat"] = round(subtotal * (1 + pricing["vat_percent"] * 0.01), 2) + # discount["amount_with_vat"] = round(pricing["price_with_vat"] - pricing["price_after_discount_with_vat"], 2) + # pricing["total_price"] = pricing["price_after_discount_with_vat"] + # self.request.session['total_price'] = pricing["price_after_discount_with_vat"] + # payment_intent_response = uncloud_stripe.get_payment_intent(request.user, pricing["price_after_discount_with_vat"]) + # context.update({ + # 'payment_intent_secret': payment_intent_response.client_secret, + # 'order': specs, + # 'pricing': pricing, + # 'stripe_key': settings.STRIPE_PUBLIC_KEY, + # }) return render(request, self.template_name, context) def post(self, request, *args, **kwargs): diff --git a/uncloud/.env-sample b/uncloud/.env similarity index 100% rename from uncloud/.env-sample rename to uncloud/.env diff --git a/uncloud/.gitignore b/uncloud/.gitignore index ca64c17..7da5485 100644 --- a/uncloud/.gitignore +++ b/uncloud/.gitignore @@ -1,3 +1,2 @@ local_settings.py ldap_max_uid_file -.env \ No newline at end of file diff --git a/uncloud/settings.py b/uncloud/settings.py index f909c52..86e0942 100644 --- a/uncloud/settings.py +++ b/uncloud/settings.py @@ -60,9 +60,6 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.sites', - 'allauth', - 'allauth.account', - 'allauth.socialaccount', 'django.contrib.staticfiles', 'django_extensions', 'rest_framework', @@ -77,6 +74,9 @@ INSTALLED_APPS = [ 'uncloud_service', 'opennebula', 'matrixhosting', + 'allauth', + 'allauth.account', + 'allauth.socialaccount', ] MIDDLEWARE = [