Merged upstream master into task/3731/cdist_ssh_key_handler

This commit is contained in:
PCoder 2017-09-09 13:44:41 +05:30
commit f9abdfe1bc
23 changed files with 556 additions and 130 deletions

View file

@ -1,3 +1,14 @@
1.2.2: 2017-09-08
* #3704: [hosting] Added my settings page
* #3771: [datacenterlight] Fixed the inconsistency in navbar style in billing page and onward
* #3769: [datacenterlight] Fixed EN dashboard url redirecting to the wrong page
* #3775: [hosting] Made the dashboard as the default start page for hosting app
* #3779: [hosting] Changed signup validation and activation page navbar transparent
* #3759: [hosting] Made the navbar style consistent to the dcl navbar and changed font weight from 300 to 400 for mobile navbar text
* #3644: [datacenterlight] Added a login button on landing
* #3659: [hosting] Changed hosting navbar design
1.2.1: 2017-09-06
* #3757: [datacenterlight] Added /l route for linkedin
1.2: 2017-09-01 1.2: 2017-09-01
* #3703: [hosting] Added a new dashboard * #3703: [hosting] Added a new dashboard
* #3717: [datacenterlight, hosting] Changed warning color for box * #3717: [datacenterlight, hosting] Changed warning color for box

View file

@ -344,8 +344,8 @@ msgstr "Rechnungsadresse"
msgid "Payment Method:" msgid "Payment Method:"
msgstr "Bezahlmethode" msgstr "Bezahlmethode"
msgid "ending" msgid "ending in"
msgstr "endend" msgstr "endend in"
msgid "Order summary" msgid "Order summary"
msgstr "Bestellungsübersicht" msgstr "Bestellungsübersicht"

View file

@ -122,7 +122,7 @@ button, input, optgroup, select, textarea {
.navbar-default { .navbar-default {
background: #fff; background: #fff;
border: none; /* border: none; */
padding: 5px; padding: 5px;
} }
@ -143,15 +143,19 @@ button, input, optgroup, select, textarea {
.navbar-default .navbar-nav>li>a { .navbar-default .navbar-nav>li>a {
cursor: pointer; cursor: pointer;
/*font-family: 'Lato-Light', sans-serif;*/ font-weight: 400;
font-weight: 300;
} }
.navbar-transparent .navbar-nav>li>a { .navbar-transparent .navbar-nav>li>a {
color: #fff; color: #fff;
cursor: pointer; cursor: pointer;
/*font-family: 'Lato-Light', sans-serif;*/ }
font-weight: 300;
@media (min-width: 768px) {
.navbar-default .navbar-nav>li>a,
.navbar-transparent .navbar-nav>li>a {
font-weight: 300;
}
} }
.navbar-transparent .navbar-nav>li>a:hover { .navbar-transparent .navbar-nav>li>a:hover {
@ -924,7 +928,7 @@ tech-sub-sec h2 {
border: 1px solid #fff; border: 1px solid #fff;
-webkit-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); -webkit-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1);
-moz-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); -moz-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1);
box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); box-shadow: -8px 14px 20px -5px rgba(77, 77, 77, 0.5);
display: none; display: none;
text-align: center; text-align: center;
border-radius: 4px !important; border-radius: 4px !important;
@ -976,8 +980,12 @@ tech-sub-sec h2 {
.dropdown-menu>li>a { .dropdown-menu>li>a {
font-size: 13px; font-size: 13px;
font-weight: 300; }
/*font-family: 'Lato-Light', sans-serif;*/
@media (min-width: 768px) {
.dropdown-menu>li>a {
font-weight: 300;
}
} }
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a,

View file

@ -1,10 +1,12 @@
{% load staticfiles i18n%} {% load custom_tags %} {% get_current_language as LANGUAGE_CODE %} {% load staticfiles i18n%}
{% load custom_tags %}
{% get_current_language as LANGUAGE_CODE %}
<nav class="navbar navbar-default navbar-fixed-top topnav"> <nav class="navbar navbar-default navbar-fixed-top topnav">
<div class="topnav"> <div class="topnav">
<!-- Brand and toggle get grouped for better mobile display --> <!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header"> <div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span> <span class="sr-only">{% trans "Toggle navigation" %}</span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
@ -34,6 +36,15 @@
<a class="on-hover-border" href="{% change_lang 'de' %}">Deutsch&nbsp;&nbsp;<i class="fa fa-globe" aria-hidden="true"></i></a> {% else %} <a class="on-hover-border" href="{% change_lang 'de' %}">Deutsch&nbsp;&nbsp;<i class="fa fa-globe" aria-hidden="true"></i></a> {% else %}
<a class="on-hover-border" href="{% change_lang 'en-us' %}">English&nbsp;&nbsp;<i class="fa fa-globe" aria-hidden="true"></i></a> {% endif %} <a class="on-hover-border" href="{% change_lang 'en-us' %}">English&nbsp;&nbsp;<i class="fa fa-globe" aria-hidden="true"></i></a> {% endif %}
</li> </li>
{% if not request.user.is_authenticated %}
<li>
<a href="{% url 'hosting:login' %}">{% trans "Login" %}&nbsp;&nbsp;<span class="fa fa-sign-in"></span></a>
</li>
{% else %}
<li>
<a href="{% url 'hosting:dashboard' %}">{% trans "Dashboard" %}</a>
</li>
{% endif %}
{% comment %} {% comment %}
<!-- to be used when more than one option for language --> <!-- to be used when more than one option for language -->
<li class="nav-language"> <li class="nav-language">

View file

@ -50,7 +50,7 @@
<div class="col-xs-6"> <div class="col-xs-6">
<address> <address>
<strong>{% trans "Payment Method:"%}</strong><br> <strong>{% trans "Payment Method:"%}</strong><br>
{{cc_brand}} {% trans "ending" %} **** {{cc_last4}}<br> {{cc_brand}} {% trans "ending in" %} **** {{cc_last4}}<br>
{{request.session.user.email}} {{request.session.user.email}}
</address> </address>
</div> </div>

View file

@ -7,9 +7,10 @@ from .views import IndexView, BetaProgramView, LandingProgramView, \
urlpatterns = [ urlpatterns = [
url(r'^$', IndexView.as_view(), name='index'), url(r'^$', IndexView.as_view(), name='index'),
url(r'^t$', IndexView.as_view(), name='index_t'), url(r'^t/$', IndexView.as_view(), name='index_t'),
url(r'^g$', IndexView.as_view(), name='index_g'), url(r'^g/$', IndexView.as_view(), name='index_g'),
url(r'^f$', IndexView.as_view(), name='index_f'), url(r'^f/$', IndexView.as_view(), name='index_f'),
url(r'^l/$', IndexView.as_view(), name='index_l'),
url(r'^whydatacenterlight/?$', WhyDataCenterLightView.as_view(), url(r'^whydatacenterlight/?$', WhyDataCenterLightView.as_view(),
name='whydatacenterlight'), name='whydatacenterlight'),
url(r'^beta-program/?$', BetaProgramView.as_view(), name='beta'), url(r'^beta-program/?$', BetaProgramView.as_view(), name='beta'),

View file

@ -12,42 +12,54 @@ from django.views.generic import RedirectView
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
import debug_toolbar import debug_toolbar
urlpatterns = [url(r'^index.html$', LandingView.as_view()), urlpatterns = [
url(r'^hosting/', include('hosting.urls', namespace="hosting")), url(r'^index.html$', LandingView.as_view()),
url(r'^open_api/', include('opennebula_api.urls', url(r'^open_api/', include('opennebula_api.urls',
namespace='opennebula_api')), namespace='opennebula_api')),
url(r'^railshosting/', RailsHostingView.as_view(), name="rails.hosting"), url(r'^railshosting/', RailsHostingView.as_view(),
url(r'^nodehosting/', NodeJSHostingView.as_view(), name="node.hosting"), name="rails.hosting"),
url(r'^djangohosting/', DjangoHostingView.as_view(), name="django.hosting"), url(r'^nodehosting/', NodeJSHostingView.as_view(),
url(r'^nosystemd/', include('nosystemd.urls', namespace="nosystemd")), name="node.hosting"),
url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')), url(r'^djangohosting/', DjangoHostingView.as_view(),
url(r'^jsi18n/(?P<packages>\S+?)/$', name="django.hosting"),
i18n.javascript_catalog), url(r'^nosystemd/', include('nosystemd.urls', namespace="nosystemd")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')),
url(r'^jsi18n/(?P<packages>\S+?)/$',
i18n.javascript_catalog),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += i18n_patterns(
url(r'^hosting/', include('hosting.urls', namespace="hosting")),
)
# note the django CMS URLs included via i18n_patterns # note the django CMS URLs included via i18n_patterns
urlpatterns += i18n_patterns( urlpatterns += i18n_patterns(
url(r'^$', LandingView.as_view()), url(r'^$', LandingView.as_view()),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^datacenterlight/', include('datacenterlight.urls', namespace="datacenterlight")), url(r'^datacenterlight/',
url(r'^hosting/', RedirectView.as_view( include('datacenterlight.urls', namespace="datacenterlight")),
url=reverse_lazy('hosting:login')), name='redirect_hosting_login'), url(r'^hosting/', RedirectView.as_view(
url(r'^alplora/', include('alplora.urls', namespace="alplora")), url=reverse_lazy('hosting:login')), name='redirect_hosting_login'),
url(r'^membership/', include(membership_urls)), url(r'^alplora/', include('alplora.urls', namespace="alplora")),
url(r'^digitalglarus/', include('digitalglarus.urls', url(r'^membership/', include(membership_urls)),
namespace="digitalglarus")), url(r'^digitalglarus/', include('digitalglarus.urls',
# url(r'^blog/', include('ungleich.urls', namespace='ungleich')), namespace="digitalglarus")),
url(r'^', # url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
include('ungleich_page.urls', namespace='ungleich_page'), url(r'^',
name='ungleich_page'), include('ungleich_page.urls',
url(r'^blog/', include('ungleich.urls', namespace='ungleich')), namespace='ungleich_page'),
url(r'^', include('cms.urls')) name='ungleich_page'),
) url(r'^blog/', include('ungleich.urls',
namespace='ungleich')),
url(r'^', include('cms.urls'))
)
urlpatterns += [ urlpatterns += [
url(r'^media/(?P<path>.*)$', url(r'^media/(?P<path>.*)$',
static_view.serve, { static_view.serve, {
'document_root': settings.MEDIA_ROOT, 'document_root': settings.MEDIA_ROOT,
}), }),
] ]
if settings.DEBUG: if settings.DEBUG:
urlpatterns += [url(r'^__debug__/', include(debug_toolbar.urls))] urlpatterns += [url(r'^__debug__/', include(debug_toolbar.urls))]

View file

@ -25,7 +25,7 @@ msgid "Your account is not activated yet."
msgstr "Dein Account wurde noch nicht aktiviert." msgstr "Dein Account wurde noch nicht aktiviert."
msgid "User does not exist" msgid "User does not exist"
msgstr "" msgstr "Der Benutzer existiert nicht"
msgid "Paste here your public key" msgid "Paste here your public key"
msgstr "Füge deinen Public Key ein" msgstr "Füge deinen Public Key ein"
@ -37,7 +37,7 @@ msgid "Key name"
msgstr "Key-Name" msgstr "Key-Name"
msgid "Please input a proper SSH key" msgid "Please input a proper SSH key"
msgstr "" msgstr "Bitte verwende einen gültigen SSH-Key"
msgid "My Virtual Machines" msgid "My Virtual Machines"
msgstr "Meine virtuellen Maschinen" msgstr "Meine virtuellen Maschinen"
@ -362,6 +362,32 @@ msgstr "Deine Kreditkartennummer"
msgid "Reset your password" msgid "Reset your password"
msgstr "Passwort zurücksetzen" 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 <a href=\"https://stripe.com\">Stripe</a> for payment and do "
"not store your information in our database."
msgstr ""
"Wir nutzen <a href="
"\"https://stripe.com\" target=\"_blank\">Stripe</a> für die Bezahlung und "
"speichern keine Informationen in unserer Datenbank."
msgid "Add your public SSH key" msgid "Add your public SSH key"
msgstr "Füge deinen öffentlichen SSH-Key hinzu" msgstr "Füge deinen öffentlichen SSH-Key hinzu"
@ -519,6 +545,12 @@ msgid ""
"contact Data Center Light Support." "contact Data Center Light Support."
msgstr "Kontaktiere den 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" #~ msgid "Your SSH Keys"
#~ msgstr "Deine SSH Keys" #~ msgstr "Deine SSH Keys"

View file

@ -5,13 +5,18 @@
} }
.dashboard-container { .dashboard-container {
padding-top:70px; padding-top: 80px;
padding-bottom: 70px; padding-bottom: 70px;
width: 90%; width: 90%;
margin: 0 auto; margin: 0 auto;
max-width: 768px; max-width: 768px;
} }
.dashboard-container.wide {
padding-top: 90px;
max-width: 980px;
}
.content-dashboard{ .content-dashboard{
min-height: calc(100vh - 70px); min-height: calc(100vh - 70px);
width: 80%; width: 80%;
@ -241,6 +246,113 @@
transform: translate(-50%,-50%); 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 { .btn-wide {
min-width: 100px; 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;
}

View file

@ -34,7 +34,8 @@ h6 {
.navbar-default { .navbar-default {
background: #fff; background: #fff;
box-shadow: 0 3px 3px -2px hsla(0,0%,78%,.72); /* box-shadow: 0 3px 3px -2px hsla(0,0%,78%,.72); */
padding: 5px;
} }
.navbar-default .navbar-header { .navbar-default .navbar-header {
@ -78,13 +79,20 @@ h6 {
left: 0 !important; left: 0 !important;
min-width: 155px; min-width: 155px;
margin-left: 15px; margin-left: 15px;
padding: 5px !important; padding: 0 5px 8px !important;
} }
@media(min-width: 768px) { @media(min-width: 768px) {
.navbar-right .highlights-dropdown .dropdown-menu { .navbar-default .navbar-nav>li>a,
border: 1px solid #fff; .navbar-right .highlights-dropdown .dropdown-menu > li > a {
font-weight: 300;
} }
.navbar-right .highlights-dropdown .dropdown-menu:before { .navbar-right .highlights-dropdown .dropdown-menu {
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.02);
border-width: 0 0 1px 0;
border-color: #e7e7e7;
box-shadow: -8px 14px 20px -5px rgba(77, 77, 77, 0.5);
}
/* .navbar-right .highlights-dropdown .dropdown-menu:before {
content: ''; content: '';
display: block; display: block;
height: 1px; height: 1px;
@ -93,13 +101,12 @@ h6 {
top: -1px; top: -1px;
left: -1px; left: -1px;
right: -1px; right: -1px;
} } */
} }
.navbar-right .highlights-dropdown .dropdown-menu > li > a{ .navbar-right .highlights-dropdown .dropdown-menu > li > a{
font-size: 13px; font-size: 13px;
font-weight: 300;
font-family: 'Lato', sans-serif; font-family: 'Lato', sans-serif;
padding: 1px 10px !important; padding: 1px 10px 1px 18px !important;
background: transparent; background: transparent;
color: #333; color: #333;
} }
@ -608,6 +615,7 @@ a.unlink:hover {
border: 1px solid #a1a1a1; border: 1px solid #a1a1a1;
border-radius: 3px; border-radius: 3px;
padding: 5px; padding: 5px;
margin-bottom: 15px;
} }
.card-warning-error { .card-warning-error {
border: 1px solid #EB4D5C; border: 1px solid #EB4D5C;
@ -765,12 +773,12 @@ a.unlink:hover {
@media (min-width: 768px) { @media (min-width: 768px) {
.dcl-billing { .dcl-billing {
padding-right: 50px; padding-right: 65px;
border-right: 1px solid #eee; border-right: 1px solid #eee;
} }
.dcl-creditcard { .dcl-creditcard {
padding-left: 50px; padding-left: 65px;
} }
.tbl-tot { .tbl-tot {

View file

@ -446,6 +446,11 @@
width: 34px; width: 34px;
vertical-align: middle; vertical-align: middle;
} }
.dashboard-title-thin .un-icon.wide {
height: 38px;
width: 38px;
margin-top: -6px;
}
.dashboard-subtitle { .dashboard-subtitle {
font-weight: 300; font-weight: 300;
@ -533,6 +538,11 @@
width: 22px; width: 22px;
margin-top: -3px; margin-top: -3px;
} }
.dashboard-title-thin .un-icon.wide {
height: 25px;
width: 25px;
margin-top: -5px;
}
.dashboard-subtitle p { .dashboard-subtitle p {
width: 200px; width: 200px;
} }

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M185,150h630c19.3,0,35-15.7,35-35s-15.7-35-35-35H605c0-38.7-31.3-70-70-70h-70c-38.7,0-70,31.3-70,70H185c-19.3,0-35,15.7-35,35S165.7,150,185,150z"/><path d="M885,220h-69.9c-0.1,0-0.3,0-0.4,0H395.1c0,0-0.1,0-0.1,0H185.3c-0.1,0-0.2,0-0.3,0h-70c-19.3,0-35,15.7-35,35c0,19.3,15.7,35,35,35h39.9l100.5,670.2C258,977.3,272.7,990,290,990h139.9c0,0,0,0,0,0c0,0,0,0,0,0h140c0,0,0,0,0,0c0,0,0,0,0,0H710c17.3,0,32-12.7,34.6-29.8L845.1,290H885c19.3,0,35-15.7,35-35C920,235.7,904.3,220,885,220z M463.3,920l-31.5-630h136.4l-31.5,630H463.3z M225.6,290h136.1l31.5,630h-73.1L225.6,290z M679.9,920h-73.1l31.5-630h136.1L679.9,920z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -73,7 +73,6 @@ $( document ).ready(function() {
* Replace all SVG images with inline SVG * Replace all SVG images with inline SVG
*/ */
$('.svg-img').each(function() { $('.svg-img').each(function() {
console.log('asa')
var $img = $(this); var $img = $(this);
var imgID = $img.attr('id'); var imgID = $img.attr('id');
var imgClass = $img.attr('class'); var imgClass = $img.attr('class');

View file

@ -25,6 +25,8 @@
<link href="{% static 'hosting/css/commons.css' %}" rel="stylesheet"> <link href="{% static 'hosting/css/commons.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/virtual-machine.css' %}" rel="stylesheet"> <link href="{% static 'hosting/css/virtual-machine.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/dashboard.css' %}" rel="stylesheet"> <link href="{% static 'hosting/css/dashboard.css' %}" rel="stylesheet">
{% block css_extra %}
{% endblock css_extra %}
<!-- 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'>
@ -51,61 +53,7 @@
{% block navbar %} {% block navbar %}
{% include "hosting/includes/_navbar_user.html" %}
<!-- Navigation -->
<nav class="navbar navbar-default navbar-fixed-top topnav" role="navigation">
<div class="container topnav">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
{% if request.user.is_authenticated %}
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
{% endif %}
<a class="navbar-brand topnav" href="{% if site_url %}{{site_url}}{% else %}{{ request.session.hosting_url}}{% endif %}"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a>
</div>
{% if request.user.is_authenticated %}
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>
<a href="{% url 'hosting:virtual_machines' %}">
<i class="fa fa-server" aria-hidden="true"></i> {% trans "My Virtual Machines"%}
</a>
</li>
<li>
<a href="{% url 'hosting:orders' %}">
<i class="fa fa-credit-card"></i> {% trans "My Orders"%}
</a>
</li>
<li class="dropdown">
<a class="dropdown-toggle" role="button" data-toggle="dropdown" href="#">
<i class="glyphicon glyphicon-user"></i> {{request.user.name}} <span class="caret"></span></a>
<ul id="g-account-menu" class="dropdown-menu" role="menu">
<li>
<a href="{% url 'hosting:ssh_keys' %}">
<i class="fa fa-key"></i> {% trans "SSH Keys" %}
</a>
</li>
<li>
<a href="{% url 'hosting:notifications' %}">
<i class="fa fa-bell"></i> {% trans "Notifications "%}
</a>
</li>
<li><a href="{% url 'hosting:logout' %}"><i class="glyphicon glyphicon-lock"></i>{% trans "Logout"%} </a></li>
</ul>
</li>
</ul>
</div>
{% endif %}
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
{% endblock navbar %} {% endblock navbar %}

View file

@ -32,7 +32,7 @@
<img class="svg-img" src="{% static 'hosting/img/billing.svg' %}"> <img class="svg-img" src="{% static 'hosting/img/billing.svg' %}">
</div> </div>
</a> </a>
<a href="" class="hosting-dashboard-item"> <a href="{% url 'hosting:settings' %}" class="hosting-dashboard-item">
<h2>{% trans "My Settings" %}</h2> <h2>{% trans "My Settings" %}</h2>
<div class="hosting-dashboard-image"> <div class="hosting-dashboard-image">
<img class="svg-img" src="{% static 'hosting/img/dashboard_settings.svg' %}"> <img class="svg-img" src="{% static 'hosting/img/dashboard_settings.svg' %}">

View file

@ -1,10 +1,10 @@
{% load static i18n %} {% load static i18n %}
<nav class="navbar navbar-default topnav navbar-transparent" role="navigation"> <nav class="navbar navbar-default topnav navbar-transparent" role="navigation">
<div class="container topnav"> <div class="topnav">
<!-- Brand and toggle get grouped for better mobile display --> <!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header"> <div class="navbar-header">
<a id="logoWhite" class="navbar-brand topnav" href="{% if site_url %}{{site_url}}{% else %}{{ request.session.hosting_url}}{% endif %}"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a> <a id="logoWhite" class="navbar-brand topnav" href="{% url 'datacenterlight:index' %}"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a>
</div> </div>
</div> </div>
<!-- /.container --> <!-- /.container -->

View file

@ -0,0 +1,52 @@
{% load staticfiles %}
{% load i18n %}
{% load custom_tags %}
<!-- Navigation -->
<nav class="navbar navbar-default navbar-fixed-top topnav" role="navigation">
<div class="topnav">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
{% if request.user.is_authenticated %}
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">{% trans "Toggle navigation" %}</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
{% endif %}
<a class="navbar-brand topnav" href="{% url 'datacenterlight:index' %}"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a>
</div>
{% if request.user.is_authenticated %}
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>
<a href="{% url 'hosting:dashboard' %}">
<i class="fa fa-fw fa-server" aria-hidden="true"></i>&nbsp;&nbsp;{% trans "Dashboard"%}
</a>
</li>
<li class="dropdown highlights-dropdown">
<a class="dropdown-toggle" role="button" data-toggle="dropdown" href="#">
<i class="fa fa-fw fa-user"></i>&nbsp;&nbsp;{{request.user.name}}&nbsp;<span class="fa fa-fw fa-caret-down"></span>
</a>
<ul id="g-account-menu" class="dropdown-menu" role="menu">
<li><a href="{% url 'hosting:logout' %}">{% trans "Logout"%}</a></li>
</ul>
</li>
<li>
{% get_current_language as LANGUAGE_CODE %}
{% if LANGUAGE_CODE == 'en-us'%}
<a href="{% change_lang 'de' %}"><i class="fa fa-fw fa-globe" aria-hidden="true"></i>&nbsp;&nbsp;Deutsch</a>
{% else %}
<a href="{% change_lang 'en-us' %}"><i class="fa fa-fw fa-globe" aria-hidden="true"></i>&nbsp;&nbsp;English</a>
{% endif %}
</li>
</ul>
</div>
{% endif %}
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>

View file

@ -1,9 +1,12 @@
{% extends "hosting/base_short.html" %} {% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %} {% load staticfiles bootstrap3 i18n %}
{% block css_extra %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
{% endblock css_extra %}
{% block content %} {% block content %}
<!-- Credit card form --> <!-- Credit card form -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
<div class="dcl-order-container"> <div class="dcl-order-container">
<div class="payment-container"> <div class="payment-container">
<div class="row"> <div class="row">

View file

@ -0,0 +1,149 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% block css_extra %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
{% endblock css_extra %}
{% block content %}
<div class="dashboard-container wide">
<div class="dashboard-container-head">
<h1 class="dashboard-title-thin"><img src="{% static 'hosting/img/dashboard_settings.svg' %}" class="un-icon wide"> {% trans "My Settings" %}</h1>
</div>
<!-- Credit card form -->
<div class="settings-container">
<div class="row">
<div class="col-sm-5 col-md-6 billing dcl-billing">
<h3>{%trans "Billing Address"%}</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' bound_css_class='' %}
{% endfor %}
<div class="form-group text-right">
<button type="submit" class="btn btn-vm-contact btn-wide">{% trans "UPDATE" %}</button>
</div>
</form>
</div>
<div class="col-sm-7 col-md-6 creditcard-box dcl-creditcard">
<h3>{%trans "Credit Card"%}</h3>
<hr>
<div>
{% if credit_card_data.last4 %}
<div class="credit-card-details">
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
<h5 class="membership-lead">{% trans "Last" %} 4: *****{{credit_card_data.last4}}</h5>
<h5 class="membership-lead">{% trans "Type" %}: {{credit_card_data.cc_brand}}</h5>
{% comment %}
<div class="credit-card-details-opt">
<div class="row">
<div class="col-xs-6">
<a class="caps-link" href=""><img src="{% static 'hosting/img/delete.svg' %}" class="svg-img">{% trans "REMOVE CARD" %}</a>
</div>
<div class="col-xs-6 text-right">
<a class="btn btn-vm-contact" href="">{% trans "EDIT CARD" %}</a>
</div>
</div>
</div>
{% endcomment %}
</div>
{% else %}
<div class="no-cards">
<h4>{% trans "No Credit Cards Added" %}</h4>
<p>{% blocktrans %}We are using <a href="https://stripe.com">Stripe</a> for payment and do not store your information in our database.{% endblocktrans %}</p>
</div>
{% comment %}
<h4>{% trans "Add a new Card." %}</h4>
<p style="margin-bottom: 15px;">
{% 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 %}
</p>
<form action="" id="payment-form-new" class="credit-card-form" method="POST">
<input type="hidden" name="token"/>
<div class="credit-card-goup">
<div class="card-element card-number-element">
<label>{%trans "Card Number" %}</label>
<div id="card-number-element" class="field my-input"></div>
</div>
<div class="row">
<div class="col-xs-6 col-sm-4 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-6 col-sm-4 col-sm-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 id="card-errors" role="alert"></div>
<div>
{% if not messages and not form.non_field_errors %}
<p class="card-warning-content">
{% blocktrans %}You are not making any payment here.{% endblocktrans %}
</p>
{% endif %}
<div id='payment_error'>
{% for message in messages %}
{% 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>
{% endfor %}
</div>
<div class="row">
<div class="col-xs-6 col-xs-offset-6 text-right">
<button class="btn btn-success stripe-payment-btn" type="submit">{%trans "Submit" %}
</button>
</div>
</div>
</div>
<div style="display:none;">
<p class="payment-errors"></p>
</div>
</form>
{% endcomment %}
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% comment %}
<!-- stripe key data -->
{% if stripe_key %}
{% get_current_language as LANGUAGE_CODE %}
<script type="text/javascript">
window.processing_text = '{%trans "Processing" %}';
window.enter_your_card_text = '{%trans "Enter your credit card number" %}';
(function () {
window.stripeKey = "{{stripe_key}}";
window.current_lan = "{{LANGUAGE_CODE}}";
})();
</script>
{%endif%}
{% if credit_card_data.last4 and credit_card_data.cc_brand %}
<script type="text/javascript">
(function () {
window.hasCreditcard = true;
})();
</script>
{%endif%}
{% endcomment %}
{%endblock%}

View file

@ -1,6 +1,10 @@
{% extends "hosting/base_short.html" %} {% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %} {% load staticfiles bootstrap3 i18n %}
{% block navbar %}
{% include 'hosting/includes/_navbar_transparent.html' %}
{% endblock navbar %}
{% block content %} {% block content %}
<div class="auth-container"> <div class="auth-container">
<div class="auth-bg"></div> <div class="auth-bg"></div>

View file

@ -1,6 +1,5 @@
from django.conf.urls import url from django.conf.urls import url
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from .views import ( from .views import (
DjangoHostingView, RailsHostingView, PaymentVMView, NodeJSHostingView, DjangoHostingView, RailsHostingView, PaymentVMView, NodeJSHostingView,
LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView, LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView,
@ -9,7 +8,9 @@ from .views import (
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView,
HostingPricingView, CreateVirtualMachinesView, HostingBillListView, HostingPricingView, CreateVirtualMachinesView, HostingBillListView,
HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView,
SSHKeyChoiceView, DashboardView) SSHKeyChoiceView, DashboardView, SettingsView)
urlpatterns = [ urlpatterns = [
url(r'index/?$', IndexView.as_view(), name='index'), url(r'index/?$', IndexView.as_view(), name='index'),
@ -19,6 +20,7 @@ urlpatterns = [
url(r'rails/?$', RailsHostingView.as_view(), name='railshosting'), url(r'rails/?$', RailsHostingView.as_view(), name='railshosting'),
url(r'pricing/?$', HostingPricingView.as_view(), name='pricing'), url(r'pricing/?$', HostingPricingView.as_view(), name='pricing'),
url(r'payment/?$', PaymentVMView.as_view(), name='payment'), 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/?$', OrdersHostingListView.as_view(), name='orders'),
url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'), url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'),
url(r'bills/?$', HostingBillListView.as_view(), name='bills'), url(r'bills/?$', HostingBillListView.as_view(), name='bills'),

View file

@ -196,7 +196,7 @@ class IndexView(View):
class LoginView(LoginViewMixin): class LoginView(LoginViewMixin):
template_name = "hosting/login.html" template_name = "hosting/login.html"
form_class = HostingUserLoginForm form_class = HostingUserLoginForm
success_url = reverse_lazy('hosting:virtual_machines') success_url = reverse_lazy('hosting:dashboard')
class SignupView(CreateView): class SignupView(CreateView):
@ -494,6 +494,57 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
return self.form_invalid(form) 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): class PaymentVMView(LoginRequiredMixin, FormView):
template_name = 'hosting/payment.html' template_name = 'hosting/payment.html'
login_url = reverse_lazy('hosting:login') login_url = reverse_lazy('hosting:login')

View file

@ -41,7 +41,8 @@ class LoginFormMixin(forms.Form):
password = self.cleaned_data.get('password') password = self.cleaned_data.get('password')
is_auth = authenticate(email=email, password=password) is_auth = authenticate(email=email, password=password)
if not is_auth: 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 return self.cleaned_data
def clean_email(self): def clean_email(self):
@ -101,7 +102,8 @@ class BillingAddressForm(forms.ModelForm):
class Meta: class Meta:
model = BillingAddress model = BillingAddress
fields = ['cardholder_name', 'street_address', 'city', 'postal_code', 'country'] fields = ['cardholder_name', 'street_address',
'city', 'postal_code', 'country']
labels = { labels = {
'cardholder_name': _('Cardholder Name'), 'cardholder_name': _('Cardholder Name'),
'street_address': _('Street Address'), 'street_address': _('Street Address'),
@ -117,8 +119,10 @@ class UserBillingAddressForm(forms.ModelForm):
class Meta: class Meta:
model = UserBillingAddress model = UserBillingAddress
fields = ['street_address', 'city', 'postal_code', 'country', 'user'] fields = ['cardholder_name', 'street_address',
'city', 'postal_code', 'country', 'user']
labels = { labels = {
'cardholder_name': _('Cardholder Name'),
'street_address': _('Street Building'), 'street_address': _('Street Building'),
'city': _('City'), 'city': _('City'),
'postal_code': _('Postal Code'), 'postal_code': _('Postal Code'),
@ -146,8 +150,10 @@ class ContactUsForm(forms.ModelForm):
} }
def send_email(self, email_to='info@digitalglarus.ch'): def send_email(self, email_to='info@digitalglarus.ch'):
text_content = render_to_string('emails/contact.txt', {'data': self.cleaned_data}) text_content = render_to_string(
html_content = render_to_string('emails/contact.html', {'data': self.cleaned_data}) '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 = EmailMultiAlternatives('Subject', text_content)
email.attach_alternative(html_content, "text/html") email.attach_alternative(html_content, "text/html")
email.to = [email_to] email.to = [email_to]