diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index 80d88c04..08781bf1 100644 --- a/datacenterlight/locale/de/LC_MESSAGES/django.po +++ b/datacenterlight/locale/de/LC_MESSAGES/django.po @@ -344,8 +344,8 @@ msgstr "Rechnungsadresse" msgid "Payment Method:" msgstr "Bezahlmethode" -msgid "ending" -msgstr "endend" +msgid "ending in" +msgstr "endend in" msgid "Order summary" msgstr "Bestellungsübersicht" diff --git a/datacenterlight/templates/datacenterlight/order_detail.html b/datacenterlight/templates/datacenterlight/order_detail.html index b55953bf..085b0c37 100644 --- a/datacenterlight/templates/datacenterlight/order_detail.html +++ b/datacenterlight/templates/datacenterlight/order_detail.html @@ -50,7 +50,7 @@
{% trans "Payment Method:"%}
- {{cc_brand}} {% trans "ending" %} **** {{cc_last4}}
+ {{cc_brand}} {% trans "ending in" %} **** {{cc_last4}}
{{request.session.user.email}}
diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po index f905d905..9ba7f22b 100644 --- a/hosting/locale/de/LC_MESSAGES/django.po +++ b/hosting/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-09-02 03:08+0530\n" +"POT-Creation-Date: 2017-09-05 00:59+0530\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -356,6 +356,32 @@ msgstr "Deine Kreditkartennummer" msgid "Reset your password" msgstr "Passwort zurücksetzen" +msgid "UPDATE" +msgstr "" + +msgid "Last" +msgstr "" + +msgid "Type" +msgstr "Kartentyp" + +msgid "REMOVE CARD" +msgstr "KARTE ENTFERNEN" + +msgid "EDIT CARD" +msgstr "BEARBEITEN" + +msgid "No Credit Cards Added" +msgstr "Es wurde keine Kreditkarte hinzugefügt" + +msgid "" +"We are using Stripe for payment and do " +"not store your information in our database." +msgstr "" +"Wir nutzen Stripe für die Bezahlung und " +"speichern keine Informationen in unserer Datenbank." + msgid "Add your public SSH key" msgstr "Füge deinen öffentlichen SSH-Key hinzu" @@ -513,6 +539,12 @@ msgid "" "contact Data Center Light Support." msgstr "Kontaktiere den Data Center Light Support." +#~ msgid "Add a new Card." +#~ msgstr "Neue Kreditkarte hinzufügen." + +#~ msgid "You are not making any payment here." +#~ msgstr "Es wird noch keine Bezahlung vorgenommen" + #~ msgid "Your SSH Keys" #~ msgstr "Deine SSH Keys" diff --git a/hosting/static/hosting/css/commons.css b/hosting/static/hosting/css/commons.css index 699f417c..8c8a9470 100644 --- a/hosting/static/hosting/css/commons.css +++ b/hosting/static/hosting/css/commons.css @@ -12,6 +12,11 @@ max-width: 768px; } +.dashboard-container.wide { + padding-top: 90px; + max-width: 980px; +} + .content-dashboard{ min-height: calc(100vh - 70px); width: 80%; @@ -241,6 +246,113 @@ transform: translate(-50%,-50%); } +.settings-container { + padding: 8px; +} + +.settings-container h4 { + margin-bottom: 15px; + color: #333; + font-size: 14px; +} + +.settings-container .card-expiry-element, +.settings-container .card-cvc-element { + padding: 0 15px; +} +.settings-container .card-cvc-element .my-input, +.settings-container .card-cvc-element label { + padding-left: 0; +} + +.settings-container .stripe-payment-btn { + float: none; + position: static; +} + +.settings-container h3 { + font-weight: bold; +} + +.settings-container hr { + margin-top: 15px; +} + +.settings-container .credit-card-details { + padding-bottom: 15px; + border-bottom: 1px solid #eee; +} + +.settings-container .credit-card-details h5 { + font-weight: bold; + font-size: 16px; +} + +.credit-card-form { + max-width: 360px; +} + +.btn-wide { + min-width: 100px; +} + +.caps-link { + font-weight: 600; + color: #8da4c0; + fill: #8da4c0; + padding: 8px 0; + display: block; +} +.caps-link:hover, +.caps-link:focus, +.caps-link:active { + color: #627388; + fill: #627388; + text-decoration: none; +} + +.settings-container .credit-card-details-opt { + padding-top: 15px; +} + +.caps-link .svg-img { + margin-right: 5px; + height: 13px; + position: relative; + top: 1px; + vertical-align: baseline; +} + +.settings-container .caps-link { + font-size: 13px; + letter-spacing: 1.1px; +} + +.settings-container .btn-vm-contact { + font-weight: 600; + font-size: 13px; + /* padding: 4px 15px; */ +} + .btn-wide { min-width: 100px; +} + +.no-cards { + text-align: center; + color: #999; + padding: 15px; + background: rgba(0,0,0,0.02); + display: flex; + flex-direction: column; + height: 230px; + justify-content: center; +} + +.no-cards h4 { + font-size: 24px; +} + +.no-cards a { + color: #7ca3d0; } \ No newline at end of file diff --git a/hosting/static/hosting/css/landing-page.css b/hosting/static/hosting/css/landing-page.css index b69f1b8f..4d87b341 100644 --- a/hosting/static/hosting/css/landing-page.css +++ b/hosting/static/hosting/css/landing-page.css @@ -608,6 +608,7 @@ a.unlink:hover { border: 1px solid #a1a1a1; border-radius: 3px; padding: 5px; + margin-bottom: 15px; } .card-warning-error { border: 1px solid #EB4D5C; @@ -765,12 +766,12 @@ a.unlink:hover { @media (min-width: 768px) { .dcl-billing { - padding-right: 50px; + padding-right: 65px; border-right: 1px solid #eee; } .dcl-creditcard { - padding-left: 50px; + padding-left: 65px; } .tbl-tot { diff --git a/hosting/static/hosting/css/virtual-machine.css b/hosting/static/hosting/css/virtual-machine.css index 806d40c6..b4916da0 100644 --- a/hosting/static/hosting/css/virtual-machine.css +++ b/hosting/static/hosting/css/virtual-machine.css @@ -446,6 +446,11 @@ width: 34px; vertical-align: middle; } +.dashboard-title-thin .un-icon.wide { + height: 38px; + width: 38px; + margin-top: -6px; +} .dashboard-subtitle { font-weight: 300; @@ -533,6 +538,11 @@ width: 22px; margin-top: -3px; } + .dashboard-title-thin .un-icon.wide { + height: 25px; + width: 25px; + margin-top: -5px; + } .dashboard-subtitle p { width: 200px; } diff --git a/hosting/static/hosting/img/delete.svg b/hosting/static/hosting/img/delete.svg new file mode 100644 index 00000000..31991c4a --- /dev/null +++ b/hosting/static/hosting/img/delete.svg @@ -0,0 +1,7 @@ + + + + + Svg Vector Icons : http://www.onlinewebfonts.com/icon + + \ No newline at end of file diff --git a/hosting/static/hosting/js/initial.js b/hosting/static/hosting/js/initial.js index 4408a299..b7d96601 100644 --- a/hosting/static/hosting/js/initial.js +++ b/hosting/static/hosting/js/initial.js @@ -73,7 +73,6 @@ $( document ).ready(function() { * Replace all SVG images with inline SVG */ $('.svg-img').each(function() { - console.log('asa') var $img = $(this); var imgID = $img.attr('id'); var imgClass = $img.attr('class'); diff --git a/hosting/templates/hosting/base_short.html b/hosting/templates/hosting/base_short.html index 5030d9ab..f02f4e0c 100644 --- a/hosting/templates/hosting/base_short.html +++ b/hosting/templates/hosting/base_short.html @@ -25,6 +25,8 @@ + {% block css_extra %} + {% endblock css_extra %} diff --git a/hosting/templates/hosting/dashboard.html b/hosting/templates/hosting/dashboard.html index 4d41874e..d12f75ee 100644 --- a/hosting/templates/hosting/dashboard.html +++ b/hosting/templates/hosting/dashboard.html @@ -32,7 +32,7 @@ - +

{% trans "My Settings" %}

diff --git a/hosting/templates/hosting/payment.html b/hosting/templates/hosting/payment.html index b9a04e43..9b1c9e45 100644 --- a/hosting/templates/hosting/payment.html +++ b/hosting/templates/hosting/payment.html @@ -1,9 +1,12 @@ {% extends "hosting/base_short.html" %} {% load staticfiles bootstrap3 i18n %} +{% block css_extra %} + +{% endblock css_extra %} + {% block content %} -
diff --git a/hosting/templates/hosting/settings.html b/hosting/templates/hosting/settings.html new file mode 100644 index 00000000..0bafe8e5 --- /dev/null +++ b/hosting/templates/hosting/settings.html @@ -0,0 +1,149 @@ +{% extends "hosting/base_short.html" %} +{% load staticfiles bootstrap3 i18n %} + +{% block css_extra %} + +{% endblock css_extra %} + +{% block content %} +
+
+

{% trans "My Settings" %}

+
+ +
+
+
+

{%trans "Billing Address"%}

+
+
+ {% for field in form %} + {% csrf_token %} + {% bootstrap_field field show_label=False type='fields' bound_css_class='' %} + {% endfor %} +
+ +
+
+
+
+

{%trans "Credit Card"%}

+
+
+ {% if credit_card_data.last4 %} + + {% else %} +
+

{% trans "No Credit Cards Added" %}

+

{% blocktrans %}We are using Stripe for payment and do not store your information in our database.{% endblocktrans %}

+
+ + {% comment %} +

{% trans "Add a new Card." %}

+

+ {% 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 %} +

+
+ +
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+ + +
+
+ +
+ {% if not messages and not form.non_field_errors %} +

+ {% blocktrans %}You are not making any payment here.{% endblocktrans %} +

+ {% endif %} +
+ {% for message in messages %} + {% if 'failed_payment' or 'make_charge_error' in message.tags %} +
  • +

    {{ message|safe }}

    +
+ {% endif %} + {% endfor %} + + {% for error in form.non_field_errors %} +

+ {{ error|escape }} +

+ {% endfor %} +
+
+
+ +
+
+
+ +
+

+
+
+ {% endcomment %} + {% endif %} +
+
+
+
+
+ + {% comment %} + + {% if stripe_key %} + {% get_current_language as LANGUAGE_CODE %} + + {%endif%} + + {% if credit_card_data.last4 and credit_card_data.cc_brand %} + + {%endif%} + {% endcomment %} +{%endblock%} diff --git a/hosting/urls.py b/hosting/urls.py index e6b6fee3..455aa97f 100644 --- a/hosting/urls.py +++ b/hosting/urls.py @@ -1,6 +1,5 @@ from django.conf.urls import url from django.contrib.auth import views as auth_views - from .views import ( DjangoHostingView, RailsHostingView, PaymentVMView, NodeJSHostingView, LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView, @@ -9,7 +8,8 @@ from .views import ( MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView, CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, - SSHKeyChoiceView, DashboardView) + SSHKeyChoiceView, DashboardView, SettingsView) + urlpatterns = [ url(r'index/?$', IndexView.as_view(), name='index'), @@ -19,6 +19,7 @@ urlpatterns = [ url(r'rails/?$', RailsHostingView.as_view(), name='railshosting'), url(r'pricing/?$', HostingPricingView.as_view(), name='pricing'), url(r'payment/?$', PaymentVMView.as_view(), name='payment'), + url(r'settings/?$', SettingsView.as_view(), name='settings'), url(r'orders/?$', OrdersHostingListView.as_view(), name='orders'), url(r'orders/(?P\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'), url(r'bills/?$', HostingBillListView.as_view(), name='bills'), diff --git a/hosting/views.py b/hosting/views.py index 08f0862e..47b18d2a 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -487,6 +487,57 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView): return self.form_invalid(form) +class SettingsView(LoginRequiredMixin, FormView): + template_name = "hosting/settings.html" + login_url = reverse_lazy('hosting:login') + form_class = BillingAddressForm + + def get_form(self, form_class): + """ + Check if the user already saved contact details. If so, then show + the form populated with those details, to let user change them. + """ + return form_class( + instance=self.request.user.billing_addresses.first(), + **self.get_form_kwargs()) + + def get_context_data(self, **kwargs): + context = super(SettingsView, self).get_context_data(**kwargs) + # Get user + user = self.request.user + # Get user last order + last_hosting_order = HostingOrder.objects.filter( + customer__user=user).last() + # If user has already an hosting order, get the credit card data from + # it + if last_hosting_order: + credit_card_data = last_hosting_order.get_cc_data() + context.update({ + 'credit_card_data': credit_card_data if credit_card_data else None, + }) + context.update({ + 'stripe_key': settings.STRIPE_API_PUBLIC_KEY + }) + + return context + + def post(self, request, *args, **kwargs): + form = self.get_form() + if form.is_valid(): + billing_address_data = form.cleaned_data + billing_address_data.update({ + 'user': self.request.user.id + }) + billing_address_user_form = UserBillingAddressForm( + instance=self.request.user.billing_addresses.first(), + data=billing_address_data) + billing_address_user_form.save() + return self.render_to_response(self.get_context_data()) + else: + billing_address_data = form.cleaned_data + return self.form_invalid(form) + + class PaymentVMView(LoginRequiredMixin, FormView): template_name = 'hosting/payment.html' login_url = reverse_lazy('hosting:login') diff --git a/utils/forms.py b/utils/forms.py index c521e3ba..c3f3b6db 100644 --- a/utils/forms.py +++ b/utils/forms.py @@ -41,7 +41,8 @@ class LoginFormMixin(forms.Form): password = self.cleaned_data.get('password') is_auth = authenticate(email=email, password=password) if not is_auth: - raise forms.ValidationError("Your username and/or password were incorrect.") + raise forms.ValidationError( + "Your username and/or password were incorrect.") return self.cleaned_data def clean_email(self): @@ -101,7 +102,8 @@ class BillingAddressForm(forms.ModelForm): class Meta: model = BillingAddress - fields = ['cardholder_name', 'street_address', 'city', 'postal_code', 'country'] + fields = ['cardholder_name', 'street_address', + 'city', 'postal_code', 'country'] labels = { 'cardholder_name': _('Cardholder Name'), 'street_address': _('Street Address'), @@ -117,8 +119,10 @@ class UserBillingAddressForm(forms.ModelForm): class Meta: model = UserBillingAddress - fields = ['street_address', 'city', 'postal_code', 'country', 'user'] + fields = ['cardholder_name', 'street_address', + 'city', 'postal_code', 'country', 'user'] labels = { + 'cardholder_name': _('Cardholder Name'), 'street_address': _('Street Building'), 'city': _('City'), 'postal_code': _('Postal Code'), @@ -146,8 +150,10 @@ class ContactUsForm(forms.ModelForm): } def send_email(self, email_to='info@digitalglarus.ch'): - text_content = render_to_string('emails/contact.txt', {'data': self.cleaned_data}) - html_content = render_to_string('emails/contact.html', {'data': self.cleaned_data}) + text_content = render_to_string( + 'emails/contact.txt', {'data': self.cleaned_data}) + html_content = render_to_string( + 'emails/contact.html', {'data': self.cleaned_data}) email = EmailMultiAlternatives('Subject', text_content) email.attach_alternative(html_content, "text/html") email.to = [email_to]