Merge branch 'master' into feature/task3637

This commit is contained in:
Siarhei Puhach 2017-08-04 11:05:37 +03:00 committed by GitHub
commit 657e97fc6d
28 changed files with 1154 additions and 614 deletions

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-24 18:51+0300\n"
"POT-Creation-Date: 2017-08-03 03:10+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,23 +18,18 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/datacenterlight/beta_access.html:13
msgid "Enter name"
msgstr "Name"
#: templates/datacenterlight/beta_access.html:17
msgid "Enter email"
msgstr "E-Mail-Adresse"
#: templates/datacenterlight/beta_access.html:21
msgid "Request Beta Access"
msgstr "Beantrage Beta-Zugang"
#: templates/datacenterlight/beta_success.html:10
msgid "Request Sent"
msgstr "Anfrage verschickt"
#: templates/datacenterlight/beta_success.html:13
msgid ""
"Thank you for your subscription! You will receive a confirmation mail from "
"our team"
@ -42,91 +37,64 @@ msgstr ""
"Vielen dank für Ihre Anmeldung. Sie erhalten in kürze eine Bestätigungsmail "
"von unserem Team"
#: templates/datacenterlight/calculator_form.html:5
#: templates/datacenterlight/pricing.html:22
msgid "VM hosting"
msgstr ""
#: templates/datacenterlight/calculator_form.html:9
msgid "month"
msgstr "Monat"
#: templates/datacenterlight/calculator_form.html:11
#: templates/datacenterlight/pricing.html:28
msgid "VAT included"
msgstr "MwSt. inklusive"
#: templates/datacenterlight/calculator_form.html:16
#: templates/datacenterlight/pricing.html:33
msgid "Hosted in Switzerland"
msgstr "Standort: Schweiz"
#: templates/datacenterlight/calculator_form.html:21
msgid "Please enter a value in range 1 - 48."
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
#: templates/datacenterlight/calculator_form.html:30
msgid "Please enter a value in range 2 - 200."
msgstr "Bitte gib einen Wert von 2 bis 200 ein."
#: templates/datacenterlight/calculator_form.html:39
msgid "Please enter a value in range 10 - 2000."
msgstr "Bitte gib einen Wert von 10 bis 200 ein."
#: templates/datacenterlight/calculator_form.html:40
#: templates/datacenterlight/pricing.html:50
msgid "GB Storage (SSD)"
msgstr "GB Storage (SSD)"
#: templates/datacenterlight/calculator_form.html:59
msgid "Name"
msgstr ""
#: templates/datacenterlight/calculator_form.html:60
msgid "Your Name"
msgstr "Dein Name"
#: templates/datacenterlight/calculator_form.html:60
msgid "Please enter your name."
msgstr "Bitte gib Deinen Namen ein."
#: templates/datacenterlight/calculator_form.html:74
msgid "Email"
msgstr "E-Mail-Adresse"
#: templates/datacenterlight/calculator_form.html:75
msgid "Your Email"
msgstr "Deine E-Mail"
#: templates/datacenterlight/calculator_form.html:75
msgid "Please enter a valid email address."
msgstr "Bitte gib eine gültige E-Mailadresse ein."
#: templates/datacenterlight/calculator_form.html:88
msgid "Continue"
msgstr "Weiter"
#: templates/datacenterlight/emails/request_access_confirmation.html:99
#: templates/datacenterlight/emails/request_access_confirmation.txt:99
msgid "Thank you for your request."
msgstr "Vielen Dank für Ihre Anfrage."
#: templates/datacenterlight/emails/request_access_confirmation.html:104
#: templates/datacenterlight/emails/request_access_confirmation.txt:104
msgid "You are one step away from being our beta tester!"
msgstr ""
"Sie sind nur noch einen Schritt davon entfernt, unser Beta-Tester zu werden!"
#: templates/datacenterlight/emails/request_access_confirmation.html:105
#: templates/datacenterlight/emails/request_access_confirmation.txt:105
msgid ""
"Currently we are running our tests to make sure everything runs perfectly."
msgstr ""
"Momentan testen wir die Beta-Umgebung um sie für Ihren Gebrauch "
"sicherzustellen."
#: templates/datacenterlight/emails/request_access_confirmation.html:106
#: templates/datacenterlight/emails/request_access_confirmation.txt:106
msgid ""
"In the meantime, we would like to ask you a little patience<br/> until our "
"team contacts you with beta access."
@ -134,17 +102,12 @@ msgstr ""
"Wir werden dann sobald als möglich Ihren Beta-Zugang erstellen und Sie "
"daraufhin kontaktieren.Bis dahin bitten wir Sie um etwas Geduld."
#: templates/datacenterlight/emails/request_access_confirmation.html:107
#: templates/datacenterlight/emails/request_access_confirmation.txt:107
msgid "Thank you!"
msgstr "Vielen Dank!"
#: templates/datacenterlight/emails/user_activation.html:99
#: templates/datacenterlight/emails/user_activation.txt:3
msgid "account activation"
msgstr "Accountaktivierung"
#: templates/datacenterlight/emails/user_activation.html:105
#, python-format
msgid ""
"\n"
@ -165,17 +128,12 @@ msgstr ""
" %(base_url)s%(activation_link)s\n"
" "
#: templates/datacenterlight/emails/user_activation.html:123
#: templates/datacenterlight/emails/user_activation.txt:11
msgid "Your"
msgstr "Dein"
#: templates/datacenterlight/emails/user_activation.html:123
#: templates/datacenterlight/emails/user_activation.txt:11
msgid "team"
msgstr "Team"
#: templates/datacenterlight/emails/user_activation.txt:5
#, python-format
msgid ""
"\n"
@ -190,75 +148,50 @@ msgstr ""
"Du kannst deinen %(dcl_text)s Account aktivieren, indem du hier klickst "
"%(base_url)s%(activation_link)s\n"
#: templates/datacenterlight/includes/_footer.html:11
#: templates/datacenterlight/includes/_footer.html:31
#: templates/datacenterlight/includes/_navbar.html:27
#: templates/datacenterlight/includes/_navbar.html:28
#: templates/datacenterlight/index.html:19
#: templates/datacenterlight/index.html:46
msgid "Highlights"
msgstr ""
#: templates/datacenterlight/includes/_footer.html:14
#: templates/datacenterlight/includes/_footer.html:34
#: templates/datacenterlight/includes/_navbar.html:30
#: templates/datacenterlight/index.html:85
msgid "Scale out"
msgstr "Skalierung"
#: templates/datacenterlight/includes/_footer.html:17
#: templates/datacenterlight/includes/_footer.html:37
#: templates/datacenterlight/includes/_navbar.html:31
#: templates/datacenterlight/index.html:111
msgid "Reliable and light"
msgstr "Zuverlässig und leicht"
#: templates/datacenterlight/includes/_footer.html:20
#: templates/datacenterlight/includes/_navbar.html:32
msgid "Order VM"
msgstr "VM bestellen"
#: templates/datacenterlight/includes/_footer.html:23
#: templates/datacenterlight/includes/_footer.html:44
#: templates/datacenterlight/includes/_navbar.html:39
msgid "Contact"
msgstr "Kontakt"
#: templates/datacenterlight/includes/_footer.html:27
msgid "Home"
msgstr "Home"
#: templates/datacenterlight/includes/_footer.html:40
msgid "Pricing"
msgstr "Preise"
#: templates/datacenterlight/includes/_navbar.html:36
#: templates/datacenterlight/whydatacenterlight.html:12
msgid "All Rights Reserved"
msgstr "Alle Rechte vorbehalten"
msgid "Why Data Center Light?"
msgstr "Warum Data Center Light?"
#: templates/datacenterlight/index.html:15
msgid "Finally, an affordable VM hosting in Switzerland!"
msgstr "Endlich: bezahlbares VM Hosting in der Schweiz"
#: templates/datacenterlight/index.html:22
msgid "I want it!"
msgstr "Das will ich haben!"
#: templates/datacenterlight/index.html:52
msgid ""
"Reuses existing factory halls instead of building a new expensive building."
msgstr ""
"Verwendet ehemalige Fabrikhallen anstatt ein neues, teures Gebäude zu "
"errichten."
#: templates/datacenterlight/index.html:57
msgid "Only wants you to pay for what you actually need."
msgstr ""
"Möchte, dass du nur bezahlst, was du auch wirklich brauchst: Wähle deine "
"Ressourcen individuell aus!"
#: templates/datacenterlight/index.html:61
msgid ""
"Is creative, using a modern and alternative design for a data center in "
"order to make it more sustainable and affordable at the same time."
@ -267,7 +200,6 @@ msgstr ""
"macht um Nachhaltigkeit zu fördern und somit erschwingliche Preise bieten zu "
"können."
#: templates/datacenterlight/index.html:65
msgid ""
"Cuts down the costs for you by using FOSS (Free Open Source Software) "
"exclusively, wherefore we can save money from paying licenses."
@ -276,7 +208,6 @@ msgstr ""
"mit FOSS (Free Open Source Software) arbeitet und wir daher auf "
"Lizenzgebühren verzichten können."
#: templates/datacenterlight/index.html:88
msgid ""
"We don't use special hardware. We use commodity hardware: we buy computers "
"that you buy. Just many more and put them in a cozy home for computers "
@ -286,7 +217,6 @@ msgstr ""
"erschwingliche Systeme. Bei grösserer Auslastung werden mehr "
"Standardkomponenten hinzugekauft und skalieren so das Datencenter."
#: templates/datacenterlight/index.html:114
msgid ""
"Our VMs are located in Switzerland, with reliable power supply and fast "
"internet connection. Our VM costs less thanks to our featherlight "
@ -296,86 +226,65 @@ msgstr ""
"Energieversorgung, sowie schneller Internetverbindung ausgestattet. Unser "
"Angebot ist aufgrund unserer leichten Infrastruktur überaus kostengünstig."
#: templates/datacenterlight/index.html:132
#: templates/datacenterlight/pricing.html:86
msgid "Simple and affordable: Try our virtual machine with featherlight price."
msgstr ""
"Einfach und bezahlbar: Teste nun unsere virtuellen Maschinen mit "
"federleichten Preisen."
#: templates/datacenterlight/index.html:133
msgid "Affordable VM hosting based in Switzerland"
msgstr "Bezahlbares VM Hosting in der Schweiz"
#: templates/datacenterlight/index.html:166
msgid "Switzerland "
msgstr "Schweiz"
#: templates/datacenterlight/index.html:183
msgid "Questions?"
msgstr "Fragen?"
#: templates/datacenterlight/index.html:183
msgid "Contact us!"
msgstr "Kontaktiere uns!"
#: templates/datacenterlight/order_detail.html:24
msgid "Confirm Order"
msgstr "Bestellung Bestätigen"
#: templates/datacenterlight/order_detail.html:30
msgid "Date"
msgstr "Datum"
#: templates/datacenterlight/order_detail.html:36
msgid "Billed To:"
msgstr "Rechnungsadresse"
#: templates/datacenterlight/order_detail.html:47
msgid "Payment Method:"
msgstr "Bezahlmethode"
#: templates/datacenterlight/order_detail.html:48
msgid "ending"
msgstr "endend in"
#: templates/datacenterlight/order_detail.html:58
msgid "Order summary"
msgstr "Bestellungsübersicht"
#: templates/datacenterlight/order_detail.html:62
msgid "Cores"
msgstr "Prozessorkerne"
#: templates/datacenterlight/order_detail.html:64
msgid "Memory"
msgstr "Arbeitsspeicher"
#: templates/datacenterlight/order_detail.html:66
msgid "Disk space"
msgstr "Festplattenkapazität"
#: templates/datacenterlight/order_detail.html:68
msgid "Configuration"
msgstr "Konfiguration"
#: templates/datacenterlight/order_detail.html:70
msgid "Total"
msgstr ""
#: templates/datacenterlight/order_detail.html:77
msgid "Place order"
msgstr "Bestellen"
#: templates/datacenterlight/pricing.html:9
msgid "We are cutting down the costs significantly!"
msgstr "Wir sorgen dafür, dass die Kosten für Dich signifikant abnehmen"
#: templates/datacenterlight/pricing.html:79
msgid "Order Now!"
msgstr "Bestelle jetzt!"
#: templates/datacenterlight/pricing.html:89
msgid ""
"Our VMs are hosted in Glarus, Switzerland, and our website is currently "
"running in BETA mode. If you want more information that you did not find on "
@ -391,25 +300,20 @@ msgstr ""
"uns unter support@datacenterlight.ch. Unser Team wird sich umgehend um dein "
"Anliegen kümmern!"
#: templates/datacenterlight/success.html:8
msgid "Thank you for order! Our team will contact you via email"
msgstr ""
"Vielen Dank für die Bestellung. Unser Team setzt sich sobald wie möglich mit "
"Ihnen via E-Mail in Verbindung."
#: templates/datacenterlight/success.html:10
msgid "as soon as possible!"
msgstr ""
#: templates/datacenterlight/whydatacenterlight.html:26
msgid "Tech Stack"
msgstr "Tech Stack"
#: templates/datacenterlight/whydatacenterlight.html:29
msgid "We are seriously open source."
msgstr "Wir sind vollends opensource."
#: templates/datacenterlight/whydatacenterlight.html:30
msgid ""
" Our full software stack is open source We don't use anything that isn't "
"open source. <br>Yes, we are that cool. "
@ -417,43 +321,33 @@ msgstr ""
"Unser gesamter Softwaresstack ist Open-Source Wir verwenden nichts, das "
"nicht Open-Source ist.<br/>Yep, so cool sind wir."
#: templates/datacenterlight/whydatacenterlight.html:37
msgid "Our services run on"
msgstr "Unsere Dienste läuft auf"
#: templates/datacenterlight/whydatacenterlight.html:41
msgid "Our monitoring"
msgstr "Unser Monitoring"
#: templates/datacenterlight/whydatacenterlight.html:45
msgid "Our storage layer"
msgstr "Unser Storage-Layer"
#: templates/datacenterlight/whydatacenterlight.html:49
msgid "Our web frontend"
msgstr "Unser Web-Frontend"
#: templates/datacenterlight/whydatacenterlight.html:53
msgid "Our cloud"
msgstr "Unsere Cloud"
#: templates/datacenterlight/whydatacenterlight.html:57
msgid "Our configuration management system"
msgstr "Unser Konfigurationsmanagementsystem"
#: templates/datacenterlight/whydatacenterlight.html:61
msgid "Our awesome juice"
msgstr "Unser Treibstoff"
#: templates/datacenterlight/whydatacenterlight.html:65
msgid "Our NAT64 gateway"
msgstr "Unser NAT64 Gateway"
#: templates/datacenterlight/whydatacenterlight.html:90
msgid "We believe in giving back to the FOSS community."
msgstr "Wir unterstützen die FOSS Community."
#: templates/datacenterlight/whydatacenterlight.html:91
msgid ""
"Data Center Light is the child of free and open source software (FOSS) "
"movement. <br>We grew up with it, live by it, and believe in it.<br> The "
@ -465,22 +359,18 @@ msgstr ""
"<br/> Je weiter wir mit unserem Data Center Light vorankommen, desto mehr "
"können wir etwas an die FOSS Community zurückgeben."
#: templates/datacenterlight/whydatacenterlight.html:104
msgid "We bring the future to you."
msgstr "Wir bringen die Zukunft zu dir."
#: templates/datacenterlight/whydatacenterlight.html:107
msgid ""
" Data Center Light uses the most modern technologies out there.<br>\n"
" Your VM needs only IPv6. Data Center Light "
"provides<br> transparent two-way IPv6/IPv4 translation.\n"
" "
"Data Center Light uses the most modern technologies out there.<br>Your VM "
"needs only IPv6. Data Center Light provides<br> transparent two-way IPv6/"
"IPv4 translation."
msgstr ""
"Data Center Light verwendet die zur Zeit modernsten Technologien.<br/>Deine "
"VM läuft mit IPv6. Data Center Light bietet eine transparente IPv6/IPv4-"
"Zweiweglösung."
#: templates/datacenterlight/whydatacenterlight.html:122
msgid ""
" No more spinning metal plates! Data Center Light uses only SSDs. We keep "
"things faster and lighter. "
@ -488,19 +378,24 @@ msgstr ""
"Keine drehenden Metallplatten mehr! Data Center Light verwendet "
"ausschliesslich SSDs. Wir halten die Dinge schnell, leicht und effizient."
#: templates/datacenterlight/whydatacenterlight.html:138
msgid "Starting from only 15CHF per month. Try now."
msgstr "Unser Angebot beginnt bei 15 CHF pro Monat. Probier's jetzt aus!"
#: templates/datacenterlight/whydatacenterlight.html:139
msgid "Actions speak louder than words. Let's do it, try our VM now."
msgstr "Tagen sagen mehr als Worte Teste jetzt unsere VM!"
#: views.py:235
msgid "Invalid number of cores"
msgstr "Ungültige Anzahle CPU-Kerne"
msgid "Invalid RAM size"
msgstr "Ungültige RAM-Grösse"
msgid "Invalid storage size"
msgstr "Ungültige Speicher-Grösse"
msgid "is not a proper name"
msgstr "ist kein gültiger Name"
#: views.py:242
msgid "is not a proper email"
msgstr "ist keine gültige E-Mailadresse"

View file

@ -786,6 +786,7 @@ tech-sub-sec h2 {
}
.percent-text {
font-family: 'Lato', sans-serif;
font-size: 50px;
color: #999;
}
@ -794,17 +795,20 @@ tech-sub-sec h2 {
font-size: 40px;
line-height: 55px;
}
.space-middle {
padding: 45px 0;
.space-middle{
padding: 45px 0;
display: inline-block;
}
.padding-vertical {
padding: 35px 0;
.ssdimg {
vertical-align: middle;
display: inline-block;
}
.padding-vertical{
padding: 30px 9px;
}
.percent-text img {
margin-left: 20px;
/* margin-left: 20px; */
}
.space-block {
@ -1085,24 +1089,24 @@ tech-sub-sec h2 {
}
@media(max-width:767px) {
.percent-text {
font-size: 50px;
}
#tech_stack h3 {
font-size: 30px;
line-height: 40px;
width: 100%;
}
.navbar-nav .open .dropdown-menu {
text-align: left;
font-size: 12px;
}
.visible-mobile {
display: block;
}
.visible-desktop {
display: none !important;
}
.percent-text {
/* font-size: 50px; */
}
#tech_stack h3 {
font-size: 30px;
line-height: 40px;
width: 100%;
}
.navbar-nav .open .dropdown-menu {
text-align: left;
font-size: 12px;
}
.visible-mobile {
display:block;
}
.visible-desktop {
display:none !important;
}
.navbar-default .navbar-nav>.open>a,
.navbar-default .navbar-nav>.open>a:focus,
.navbar-default .navbar-nav>.open>a:hover {
@ -1158,11 +1162,12 @@ tech-sub-sec h2 {
@media(max-width:768px) {
.percent-text {
font-size: 43px;
/* font-size: 43px; */
}
.tech-sub-sec h2 {
font-size: 30px;
line-height: 40px;
.tech-sub-sec h2 {
/* font-size: 30px; */
/* line-height: 40px; */
/* font-weight: 500; */
}
.single-heading h2 {
font-size: 50px;
@ -1348,7 +1353,9 @@ tech-sub-sec h2 {
padding: 30px;
}
.percent-text {
text-align: center;
font-family: 'Lato';
font-size: 31px;
/* text-align: center; */
}
.pricing-section .card {
width: 90%;
@ -1472,3 +1479,33 @@ a#forgotpassword {
.error-message-box {
margin-top: 20px;
}
.flex-row-rev {
margin-top: 25px;
}
@media (min-width: 768px) {
.flex-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex-row .percent-text {
flex-shrink : 0;
padding: 0 15px;
}
.flex-row .percent-text,
.flex-row .desc-text {
max-width: 600px;
}
.flex-row-rev .percent-text {
order: 2;
}
.flex-row-rev {
margin-bottom: 25px;
}
}
.w380 {
max-width: 380px !important;
}

View file

@ -2,19 +2,18 @@
{% load i18n %}
<div class="modal fade bs-example-modal-sm" style="color:black;" id="successModal" tabindex="-1" role="dialog">
<div class="vertical-alignment-helper">
<div class="modal-dialog vertical-align-center">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{% trans "Request Sent" %}</h4>
</div>
<div class="modal-body">
<p>{% trans "Thank you for your subscription! You will receive a confirmation mail from our team" %}</p>
</div>
</div><!-- /.modal-content -->
</div>
</div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="modal-icon"><i class="fa fa-check" aria-hidden="true"></i></div>
<h4 class="modal-title">{% trans "Request Sent" %}</h4>
<p class="modal-text">{% trans "Thank you for your subscription! You will receive a confirmation mail from our team" %}</p>
</div>
</div><!-- /.modal-content -->
</div>
</div><!-- /.modal -->
<script>
// Show modal
@ -22,7 +21,7 @@
// close the modal after 3 seconds
setTimeout(function() {
$('#successModal').modal('hide');
}, 5000);
}, 5000);
</script>
<style>
.vertical-alignment-helper {

View file

@ -46,7 +46,7 @@
{% endif %}
</ul>
<p class="copyright text-muted small">Copyright &copy; ungleich GmbH {% now "Y" %}. All Rights Reserved</p>
<p class="copyright text-muted small">Copyright &copy; ungleich GmbH {% now "Y" %}. {% trans "All Rights Reserved" %}</p>
</div>
</div>
</div>

View file

@ -64,7 +64,7 @@
<img class="img-responsive btm-space-tayga" src="{% static 'datacenterlight/img/tayga.png' %}" alt="Tayga">
<span class="logo-caption">{% trans "Our NAT64 gateway" %}</span>
</div>
</div>
</div>
</div>
@ -98,30 +98,23 @@
<hr class="thick-divider"/><!-- Divider -->
<div class="space">
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 tech-sub-sec">
<h2>{% trans "We bring the future to you." %}</h2>
</div>
<div class="col-xs-12 col-sm-7 col-md-8 col-lg-8 text-left tech-sub-sec landscape-xs-6">
<p class="lead new-lead">{% blocktrans %} Data Center Light uses the most modern technologies out there.<br>
Your VM needs only IPv6. Data Center Light provides<br> transparent two-way IPv6/IPv4 translation.
{% endblocktrans %}</p>
</div>
<div class="col-xs-12 col-sm-5 col-md-4 col-lg-4 percent-text text-right landscape-xs-6">
100% <strong>IPv6</strong>
</div>
<div class="tech-sub-sec">
<h2>{% trans "We bring the future to you." %}</h2>
</div>
<div class="flex-row flex-row-rev">
<div class="percent-text">
100% <strong>IPv6</strong>
</div>
<div class="col-lg-12 space-block"></div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div class="col-xs-12 col-sm-7 col-md-8 col-lg-8 percent-text landscape-xs-8">
<span class="pull-left space-middle"> 100% <strong>SSD</strong></span> <span class="pull-left ssdimg"><img class="img-responsive" src="{% static 'datacenterlight/img/ssd.jpg' %}" alt="SSD"></span>
</div>
<div class="col-xs-12 col-sm-5 col-md-4 col-lg-4 text-right tech-sub-sec padding-vertical landscape-xs-4">
<div>
<p class="lead new-lead">{% blocktrans %} No more spinning metal plates! Data Center Light uses only SSDs. We keep things faster and lighter. {% endblocktrans %}</p>
</div>
</div>
<div class="desc-text padding-vertical">
<p class="lead new-lead">{% blocktrans %}Data Center Light uses the most modern technologies out there.<br>Your VM needs only IPv6. Data Center Light provides<br> transparent two-way IPv6/IPv4 translation.{% endblocktrans %}</p>
</div>
</div>
<div class="flex-row">
<div class="percent-text">
<span class="space-middle"> 100% <strong>SSD</strong></span> <span class="ssdimg"><img class="img-responsive" src="{% static 'datacenterlight/img/ssd.jpg' %}" alt="SSD"></span>
</div>
<div class="desc-text padding-vertical w380">
<p class="lead new-lead">{% blocktrans %} No more spinning metal plates! Data Center Light uses only SSDs. We keep things faster and lighter. {% endblocktrans %}</p>
</div>
</div>
</div>
@ -154,6 +147,6 @@
</div>
</div>
<!-- End Why Data Center Light? -->
{% endblock %}

View file

@ -19,7 +19,6 @@ from hosting.models import HostingOrder, HostingBill
from utils.stripe_utils import StripeUtils
from datetime import datetime
from membership.models import CustomUser, StripeCustomer
from opennebula_api.models import OpenNebulaManager
from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer
@ -34,6 +33,7 @@ class SuccessView(TemplateView):
def get(self, request, *args, **kwargs):
if 'specs' not in request.session or 'user' not in request.session:
return HttpResponseRedirect(reverse('datacenterlight:index'))
elif 'token' not in request.session:
return HttpResponseRedirect(reverse('datacenterlight:payment'))
elif 'order_confirmation' not in request.session:
@ -79,7 +79,8 @@ class PricingView(TemplateView):
manager = OpenNebulaManager()
template = manager.get_template(template_id)
request.session['template'] = VirtualMachineTemplateSerializer(template).data
request.session['template'] = VirtualMachineTemplateSerializer(
template).data
if not request.user.is_authenticated():
request.session['next'] = reverse('hosting:payment')
@ -131,7 +132,8 @@ class BetaAccessView(FormView):
email = BaseEmail(**email_data)
email.send()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
messages.add_message(
self.request, messages.SUCCESS, self.success_message)
return render(self.request, 'datacenterlight/beta_success.html', {})
@ -183,7 +185,8 @@ class BetaProgramView(CreateView):
email = BaseEmail(**email_data)
email.send()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
messages.add_message(
self.request, messages.SUCCESS, self.success_message)
return HttpResponseRedirect(self.get_success_url())
@ -196,15 +199,15 @@ class IndexView(CreateView):
def validate_cores(self, value):
if (value > 48) or (value < 1):
raise ValidationError(_('Not a proper cores number'))
raise ValidationError(_('Invalid number of cores'))
def validate_memory(self, value):
if (value > 200) or (value < 2):
raise ValidationError(_('Not a proper ram number'))
raise ValidationError(_('Invalid RAM size'))
def validate_storage(self, value):
if (value > 2000) or (value < 10):
raise ValidationError(_('Not a proper storage number'))
raise ValidationError(_('Invalid storage size'))
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
def get(self, request, *args, **kwargs):
@ -227,7 +230,8 @@ class IndexView(CreateView):
storage_field = forms.IntegerField(validators=[self.validate_storage])
price = request.POST.get('total')
template_id = int(request.POST.get('config'))
template = VMTemplate.objects.filter(opennebula_vm_template_id=template_id).first()
template = VMTemplate.objects.filter(
opennebula_vm_template_id=template_id).first()
template_data = VMTemplateSerializer(template).data
name = request.POST.get('name')
@ -239,35 +243,40 @@ class IndexView(CreateView):
cores = cores_field.clean(cores)
except ValidationError as err:
msg = '{} : {}.'.format(cores, str(err))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='cores')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='cores')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
memory = memory_field.clean(memory)
except ValidationError as err:
msg = '{} : {}.'.format(memory, str(err))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='memory')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='memory')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
storage = storage_field.clean(storage)
except ValidationError as err:
msg = '{} : {}.'.format(storage, str(err))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='storage')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='storage')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
name = name_field.clean(name)
except ValidationError as err:
msg = '{} {}.'.format(name, _('is not a proper name'))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='name')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='name')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
try:
email = email_field.clean(email)
except ValidationError as err:
msg = '{} {}.'.format(email, _('is not a proper email'))
messages.add_message(self.request, messages.ERROR, msg, extra_tags='email')
messages.add_message(
self.request, messages.ERROR, msg, extra_tags='email')
return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
specs = {
@ -332,7 +341,8 @@ class IndexView(CreateView):
email = BaseEmail(**email_data)
email.send()
messages.add_message(self.request, messages.SUCCESS, self.success_message)
messages.add_message(
self.request, messages.SUCCESS, self.success_message)
return super(IndexView, self).form_valid(form)
@ -401,6 +411,7 @@ class PaymentOrderView(FormView):
# Create Billing Address
billing_address = form.save()
request.session['billing_address_data'] = billing_address_data
request.session['billing_address'] = billing_address.id
request.session['token'] = token
@ -425,11 +436,13 @@ class OrderConfirmationView(DetailView):
stripe_customer_id = request.session.get('customer')
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
stripe_utils = StripeUtils()
card_details = stripe_utils.get_card_details(customer.stripe_id, request.session.get('token'))
card_details = stripe_utils.get_card_details(
customer.stripe_id, request.session.get('token'))
if not card_details.get('response_object') and not card_details.get('paid'):
msg = card_details.get('error')
messages.add_message(self.request, messages.ERROR, msg, extra_tags='failed_payment')
return HttpResponseRedirect(reverse('datacenterlight:payment'))
context = {
'site_url': reverse('datacenterlight:index'),
'cc_last4': card_details.get('response_object').get('last4'),
@ -445,7 +458,8 @@ class OrderConfirmationView(DetailView):
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
billing_address_data = request.session.get('billing_address_data')
billing_address_id = request.session.get('billing_address')
billing_address = BillingAddress.objects.filter(id=billing_address_id).first()
billing_address = BillingAddress.objects.filter(
id=billing_address_id).first()
vm_template_id = template.get('id', 1)
final_price = specs.get('price')

View file

@ -195,7 +195,7 @@ CMS_TEMPLATES = (
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'app'
'NAME': 'app',
}
}

View file

@ -1,4 +1,4 @@
from .base import * # flake8: noqa
from .base import * # flake8: noqa
# List of people that get admin messages
ADMINS = ((x, x + "@ungleich.ch") for x in ["web-team"])

View file

@ -1,3 +1,5 @@
import datetime
from django import forms
from membership.models import CustomUser
from django.contrib.auth import authenticate
@ -7,6 +9,10 @@ from django.utils.translation import ugettext_lazy as _
from .models import UserHostingKey
def generate_ssh_key_name():
return 'dcl-generated-key-' + datetime.datetime.now().strftime('%m%d%y%H%M')
class HostingUserLoginForm(forms.Form):
email = forms.CharField(widget=forms.EmailInput())
@ -20,9 +26,11 @@ class HostingUserLoginForm(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."))
elif is_auth.validated == 0:
raise forms.ValidationError(_("Your account is not activated yet."))
raise forms.ValidationError(
_("Your account is not activated yet."))
return self.cleaned_data
def clean_email(self):
@ -58,15 +66,19 @@ class HostingUserSignupForm(forms.ModelForm):
class UserHostingKeyForm(forms.ModelForm):
private_key = forms.CharField(widget=forms.HiddenInput(), required=False)
public_key = forms.CharField(widget=forms.Textarea(), required=False,
help_text=_('Paste here your public key'))
public_key = forms.CharField(widget=forms.Textarea(
attrs={'class': 'form_public_key', 'placeholder': _('Paste here your public key')}),
required=False,
)
user = forms.models.ModelChoiceField(queryset=CustomUser.objects.all(),
required=False, widget=forms.HiddenInput())
name = forms.CharField(required=True)
name = forms.CharField(required=False, widget=forms.TextInput(
attrs={'class': 'form_key_name', 'placeholder': _('Give a name to your key')}))
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(UserHostingKeyForm, self).__init__(*args, **kwargs)
self.fields['name'].label = _('Key name')
def clean_name(self):
return self.data.get('name')
@ -76,7 +88,8 @@ class UserHostingKeyForm(forms.ModelForm):
def clean(self):
cleaned_data = self.cleaned_data
if not self.cleaned_data.get('name', ''):
self.cleaned_data['name'] = generate_ssh_key_name()
if not cleaned_data.get('public_key'):
private_key, public_key = UserHostingKey.generate_keys()
cleaned_data.update({

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-17 00:53+0530\n"
"POT-Creation-Date: 2017-08-03 03:31+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,359 +18,274 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: forms.py:25
msgid "Your username and/or password were incorrect."
msgstr "Dein Benutzername und/oder Dein Passwort ist falsch."
msgid "Your account is not activated yet."
msgstr "Dein Account wurde noch nicht aktiviert."
#: forms.py:62
msgid "Paste here your public key"
msgstr "Fügen Sie Ihren public key ein"
msgstr "Füge deinen Public Key ein"
msgid "Give a name to your key"
msgstr "Gebe deinem SSH-Key einen Name"
msgid "Key name"
msgstr "Key-Name"
#: templates/hosting/base_short.html:71
msgid "My Virtual Machines"
msgstr "Meine virtuellen Maschinen"
#: templates/hosting/base_short.html:76 templates/hosting/orders.html.py:12
msgid "My Orders"
msgstr "Meine Bestellungen"
#: templates/hosting/base_short.html:85
msgid "Keys"
msgstr "Schlüssel"
#: templates/hosting/base_short.html:90
msgid "Notifications "
msgstr "Benachrichtigungen"
#: templates/hosting/base_short.html:93
msgid "Logout"
msgstr "Abmelden"
#: templates/hosting/base_short.html:98
msgid "How it works"
msgstr "So funktioniert es"
msgid "All Rights Reserved"
msgstr "Alle Rechte vorbehalten"
#: templates/hosting/base_short.html:101
msgid "Your infrastructure"
msgstr "deine Infrastruktur"
#: templates/hosting/base_short.html:104
msgid "Our inftrastructure"
msgstr "Unsere Infrastruktur"
#: templates/hosting/base_short.html:107
msgid "Pricing"
msgstr "Preise"
#: templates/hosting/base_short.html:110
msgid "Contact"
msgstr "Kontakt"
#: templates/hosting/base_short.html:113
#: templates/hosting/confirm_reset_password.html:38
#: templates/hosting/login.html:17 templates/hosting/login.html.py:26
#: templates/hosting/reset_password.html:32 templates/hosting/signup.html:30
msgid "Login"
msgstr "Anmelden"
#: templates/hosting/bill_detail.html:11
msgid "Invoice"
msgstr "Rechnung"
#: templates/hosting/bill_detail.html:11 templates/hosting/order_detail.html:23
msgid "Order #"
msgstr "Bestellung #"
#: templates/hosting/bill_detail.html:25
msgid "ungleich GmbH"
msgstr ""
#: templates/hosting/bill_detail.html:26
msgid "buchhaltung@ungleich.ch"
msgstr ""
#: templates/hosting/bill_detail.html:27
msgid "Hauptstrasse 14"
msgstr ""
#: templates/hosting/bill_detail.html:28
msgid "CH-8775 Luchsingen"
msgstr ""
#: templates/hosting/bill_detail.html:29
msgid "Mwst-Nummer: CHE-109.549.333 MWST"
msgstr ""
#: templates/hosting/bill_detail.html:60
msgid "Total:"
msgstr ""
#: templates/hosting/bill_detail.html:68
#, python-format
msgid "Alles Preise in CHF mit 8%% Mehrwertsteuer."
msgstr "All prices in CHF including 8%% VAT"
#: templates/hosting/bill_detail.html:69
msgid "Betrag zahlbar innerhalb von 30 Tagen ab Rechnungseingang."
msgstr ""
#: templates/hosting/bill_detail.html:70
msgid "Kontoverbindung:"
msgstr ""
#: templates/hosting/bill_detail.html:73
msgid "IBAN:"
msgstr ""
#: templates/hosting/bill_detail.html:76
msgid "BIC:"
msgstr ""
#: templates/hosting/bill_detail.html:81
msgid "CH02 0900 0000 6071 8848 8"
msgstr ""
#: templates/hosting/bill_detail.html:84
msgid "POFICHBEXXX"
msgstr ""
#: templates/hosting/bills.html:12
msgid "Customers"
msgstr "Kunden"
#: templates/hosting/bills.html:16 templates/hosting/user_keys.html.py:25
msgid "Name"
msgstr ""
#: templates/hosting/bills.html:17
msgid "Email"
msgstr ""
#: templates/hosting/bills.html:28
msgid "View Bill"
msgstr "Rechnung anzeigen"
#: templates/hosting/bills.html:41 templates/hosting/orders.html.py:82
#: templates/hosting/virtual_machines.html:70
msgid "previous"
msgstr "vorherige"
#: templates/hosting/bills.html:47 templates/hosting/orders.html.py:88
#: templates/hosting/virtual_machines.html:76
msgid "next"
msgstr "nächste"
#: templates/hosting/confirm_reset_password.html:10
#: templates/hosting/login.html:12 templates/hosting/reset_password.html:10
#: templates/hosting/signup.html:9 templates/hosting/signup_validate.html:9
msgid "SSH Key"
msgstr "SSH Key"
msgid "Choose a key option in order to access your VM"
msgstr "Wähle eine Option um Zugriff auf deine VM zu erhalten"
msgid "Generating a new key pair"
msgstr "Neuen SSH-Key erstellen"
msgid "I want to generate a new key pair"
msgstr "Ich möchte einen neuen SSH-Key erstellen"
msgid "Generate"
msgstr "Generieren"
msgid "Using existing key"
msgstr "Nutzung eines existierenden SSH-Keys"
msgid "I want to use my existing public key"
msgstr "Ich möchte einen existierenden SSH-Key nutzen"
msgid "Upload"
msgstr "Hochladen"
msgid "Your VM hosted in Switzerland"
msgstr "deine VM in der Schweiz"
#: templates/hosting/confirm_reset_password.html:14
msgid "Set your new password"
msgstr "Setze dein neues Passwort"
#: templates/hosting/confirm_reset_password.html:29
#: templates/hosting/reset_password.html:23
msgid "Reset"
msgstr "Zurücksetzen"
#: templates/hosting/confirm_reset_password.html:35
#: templates/hosting/reset_password.html:29 templates/hosting/signup.html:27
msgid "Already have an account ?"
msgstr "Hast Du bereits ein Benutzerkonto?"
#: templates/hosting/create_virtual_machine.html:20
msgid "Login"
msgstr "Anmelden"
msgid "New Virtual Machine"
msgstr "Neue virtuelle Maschine"
#: templates/hosting/create_virtual_machine.html:28
msgid "Step 1. Select VM Template:"
msgstr "Wähle eine Vorlage"
#: templates/hosting/create_virtual_machine.html:42
msgid "Step2. Select VM Configuration"
msgstr "Wähle eine Konfiguration"
#: templates/hosting/create_virtual_machine.html:59
msgid "Price "
msgstr "Preis"
#: templates/hosting/create_virtual_machine.html:59
msgid "CHF/Month"
msgstr "CHF/Monat"
#: templates/hosting/create_virtual_machine.html:61
msgid "Start VM"
msgstr "VM jetzt starten"
#: templates/hosting/emails/password_reset_email.html:2
#: templates/hosting/emails/password_reset_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
#: templates/hosting/emails/password_reset_email.html:4
#: templates/hosting/emails/password_reset_email.txt:4
msgid "Please go to the following page and choose a new password:"
msgstr ""
#: templates/hosting/emails/password_reset_email.html:9
#: templates/hosting/emails/password_reset_email.txt:9
msgid "Thanks for using our site!"
msgstr ""
#: templates/hosting/emails/password_reset_email.html:11
#: templates/hosting/emails/password_reset_email.txt:11
#, python-format
msgid "The %(site_name)s team"
msgstr ""
#: templates/hosting/login.html:34
msgid "Don't have an account yet ? "
msgstr "Besitzt du kein Benutzerkonto?"
#: templates/hosting/login.html:37 templates/hosting/signup.html.py:13
#: templates/hosting/signup.html:21 views.py:219
msgid "Sign up"
msgstr "Registrieren"
#: templates/hosting/login.html:39
msgid "Forgot your password ? "
msgstr "Passwort vergessen?"
#: templates/hosting/notifications.html:9
msgid "Notifications"
msgstr "Benachrichtigungen"
#: templates/hosting/notifications.html:16
msgid "Unread"
msgstr "Ungelesen"
#: templates/hosting/notifications.html:26
msgid "All"
msgstr "Alle"
#: templates/hosting/notifications.html:38
msgid "Unread notifications"
msgstr "Ungelesene Benachrichtigungen"
#: templates/hosting/notifications.html:48
msgid "Mark as read"
msgstr "Als gelesen markieren"
#: templates/hosting/notifications.html:59
msgid "All notifications"
msgstr "Alle Benachrichtigungen"
#: templates/hosting/order_detail.html:23
msgid "Confirm Order"
msgstr "Bestellung Bestätigen"
#: templates/hosting/order_detail.html:29
msgid "Billed To:"
msgstr "Rechnungsadresse"
#: templates/hosting/order_detail.html:37 templates/hosting/orders.html:17
msgid "Date"
msgstr "Datum"
#: templates/hosting/order_detail.html:39
msgid "Status:"
msgstr ""
#: templates/hosting/order_detail.html:51
msgid "Billed To:"
msgstr "Rechnungsadresse"
msgid "Payment Method:"
msgstr "Bezahlmethode"
#: templates/hosting/order_detail.html:62
msgid "Order summary"
msgstr "Bestellungsübersicht"
#: templates/hosting/order_detail.html:65 templates/hosting/payment.html:13
#: templates/hosting/virtual_machine_detail.html:76
msgid "Cores"
msgstr "Prozessorkerne"
#: templates/hosting/order_detail.html:67 templates/hosting/payment.html:16
#: templates/hosting/virtual_machine_detail.html:82
msgid "Memory"
msgstr "Arbeitsspeicher"
#: templates/hosting/order_detail.html:69 templates/hosting/payment.html:19
msgid "Disk space"
msgstr "Festplattenkapazität"
#: templates/hosting/order_detail.html:71 templates/hosting/payment.html:41
msgid "Total"
msgstr "Gesamt"
#: templates/hosting/order_detail.html:77
msgid "Finish Configuration"
msgstr "Konfiguration beenden"
#: templates/hosting/orders.html:18
msgid "Amount"
msgstr "Betrag"
#: templates/hosting/orders.html:19 templates/hosting/user_keys.html.py:27
#: templates/hosting/virtual_machine_detail.html:30
#: templates/hosting/virtual_machines.html:31
msgid "Status"
msgstr ""
#: templates/hosting/orders.html:30
msgid "Approved"
msgstr "Akzeptiert"
#: templates/hosting/orders.html:32
msgid "Declined"
msgstr "Abgelehnt"
#: templates/hosting/orders.html:37 templates/hosting/virtual_machines.html:58
msgid "View Detail"
msgstr "Details anzeigen"
#: templates/hosting/orders.html:40
msgid "Cancel Order"
msgstr "Bestellung stornieren"
#: templates/hosting/orders.html:55
msgid "Do You want to delete your order?"
#, fuzzy
#| msgid "Do You want to delete your order?"
msgid "Do you want to delete your order?"
msgstr "Willst du deine Bestellung löschen?"
#: templates/hosting/orders.html:63 templates/hosting/user_keys.html.py:63
msgid "Close"
msgstr "Schliessen"
#: templates/hosting/orders.html:65 templates/hosting/user_keys.html.py:65
msgid "Delete"
msgstr "Löschen"
#: templates/hosting/payment.html:10
msgid "Your Order"
msgstr "Deine Bestellung"
#: templates/hosting/payment.html:22
#: templates/hosting/virtual_machine_detail.html:98
msgid "Configuration"
msgstr "Konfiguration"
#: templates/hosting/payment.html:41
msgid "including VAT"
msgstr "inkl. Mehrwertsteuer"
#: templates/hosting/payment.html:55
msgid "Billing Address"
msgstr "Rechnungsadresse"
#: templates/hosting/payment.html:66
msgid "Credit Card"
msgstr "Kreditkarte"
#: templates/hosting/payment.html:71
msgid ""
"\n"
" Please fill in your credit card information "
@ -385,7 +300,6 @@ msgstr ""
"\"https://stripe.com\" target=\"_blank\">Stripe</a> für die Bezahlung und "
"speichern keine Informationen in unserer Datenbank."
#: templates/hosting/payment.html:90
msgid ""
"\n"
" You are not making any payment yet. "
@ -399,27 +313,21 @@ msgstr ""
"Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
"weitergeleitet."
#: templates/hosting/payment.html:101 templates/hosting/payment.html.py:143
msgid "Submit"
msgstr "Absenden"
#: templates/hosting/payment.html:113
msgid "Card Number"
msgstr "Kreditkartennummer"
#: templates/hosting/payment.html:117
msgid "Expiry Date"
msgstr "Ablaufdatum"
#: templates/hosting/payment.html:122
msgid "CVC"
msgstr ""
#: templates/hosting/payment.html:126
msgid "Card Type"
msgstr "Kartentyp"
#: templates/hosting/payment.html:135
msgid ""
"\n"
" You are not making any payment "
@ -433,125 +341,115 @@ msgstr ""
"Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
"weitergeleitet."
#: templates/hosting/payment.html:178
msgid "Processing"
msgstr "Weiter"
#: templates/hosting/payment.html:179
msgid "Enter your credit card number"
msgstr "Deine Kreditkartennummer"
#: templates/hosting/reset_password.html:15
msgid "Reset your password"
msgstr "Passwort zurücksetzen"
#: templates/hosting/user_key.html:11 templates/hosting/user_keys.html.py:9
msgid "Access Key"
msgstr "Zugriffsschlüssel"
msgid "Add your public SSH key"
msgstr "Füge deinen öffentlichen SSH-Key hinzu"
#: templates/hosting/user_key.html:24
msgid "Upload your own key. "
msgstr "Lade deinen Key hoch"
msgid "Use your created key to access to the VM"
msgstr "Benutze deinen erstellten SSH-Key um auf deine VM zugreifen zu können"
#: templates/hosting/user_key.html:28
msgid "Or generate a new key pair."
msgstr "Oder erstelle dein neues Keypaar"
msgid "Add SSH Key"
msgstr "Hinzufügen"
#: templates/hosting/user_key.html:30
msgid "Generate Key Pair"
msgstr "Schlüsselpaar generieren"
msgid "Or you can generate a new key pair"
msgstr "Erstelle dein neues Keypaar"
#: templates/hosting/user_key.html:40
msgid "Warning!"
msgstr "Achtung!"
#: templates/hosting/user_key.html:40
msgid "You can download your SSH private key once. Don't lost your key"
#, fuzzy
#| msgid "You can download your SSH private key once. Don't lost your key"
msgid "You can download your SSH private key once. Don't loose your key"
msgstr ""
"Du kannst deinen privaten SSH Schlüssel nur einmal herunterladen. Beware ihn "
"sicher auf."
#: templates/hosting/user_keys.html:18
msgid "Add Key"
msgstr "Schlüssel hinzufügen"
msgid "Your SSH Keys"
msgstr "Deine SSH Keys"
#: templates/hosting/user_keys.html:26
msgid "Created at"
msgstr "Erstellt am"
msgid ""
"To generate a new key pair or to upload your existing key, click 'Add Key'"
msgstr ""
"Um einen neuen SSH-Key zu erstellen oder um einen vorhandenen SSH-Key "
"hinzuzufügen, klicke auf 'Hinzufügen'"
#: templates/hosting/user_keys.html:43
msgid "Delete Key"
msgstr "Löschen"
#: templates/hosting/user_keys.html:56
msgid "Public Key"
msgstr ""
msgid "Private Key"
msgstr ""
msgid "Do You want to delete this key?"
msgstr "Möchtest Du den Schlüssel löschen?"
#: templates/hosting/virtual_machine_detail.html:19
msgid "Close"
msgstr "Schliessen"
msgid "Show"
msgstr "Anzeigen"
msgid "Public ssh key"
msgstr ""
msgid "Download"
msgstr ""
msgid "Settings"
msgstr "Einstellungen"
#: templates/hosting/virtual_machine_detail.html:25
msgid "Billing"
msgstr "Abrechnungen"
#: templates/hosting/virtual_machine_detail.html:60
msgid "Ip not assigned yet"
msgstr "Ip nicht zugewiesen"
#: templates/hosting/virtual_machine_detail.html:89
msgid "Disk"
msgstr "Festplatte"
#: templates/hosting/virtual_machine_detail.html:108
msgid "Current pricing"
msgstr "Aktueller Preis"
#: templates/hosting/virtual_machine_detail.html:117
msgid "Current status"
msgstr "Aktueller Status"
#: templates/hosting/virtual_machine_detail.html:142
msgid "Terminate Virtual Machine"
msgstr "Virtuelle Maschine beenden"
#: templates/hosting/virtual_machine_detail.html:163
msgid "Terminate your Virtual Machine"
msgstr "Ihre virtuelle Maschine beenden"
#: templates/hosting/virtual_machine_detail.html:166
msgid "Are you sure do you want to cancel your Virtual Machine "
msgstr "Sind Sie sicher, dass Sie ihre virtuelle Maschine beenden wollen "
#: templates/hosting/virtual_machine_detail.html:169
msgid "Cancel"
msgstr "Beenden"
#: templates/hosting/virtual_machines.html:9
msgid "Virtual Machines"
msgstr "Virtuelle Maschinen"
#: templates/hosting/virtual_machines.html:22
msgid "Create VM"
msgstr "Neue VM"
#: templates/hosting/virtual_machines.html:28
msgid "ID"
msgstr ""
#: templates/hosting/virtual_machines.html:29
msgid "Ipv4"
msgstr "IPv4"
#: templates/hosting/virtual_machines.html:30
msgid "Ipv6"
msgstr "IPv6"
#: views.py:207 views.py:229
msgid "login"
msgstr "einloggen"
#: views.py:212
msgid ""
"Thank you for signing up. We have sent an email to you. Please follow the "
"instructions in it to activate your account. Once activated, you can login "
@ -561,32 +459,135 @@ msgstr ""
"den Anweisungen um deinen Account zu aktivieren. Danach kannst du dich über "
"diesen"
#: views.py:214 views.py:240
msgid "Go back to"
msgstr "Zurück"
#: views.py:230
msgid "Account activation"
msgstr "Accountaktivierung"
#: views.py:233
msgid "Your account has been activated."
msgstr "Dein Account wurde aktiviert."
#: views.py:234
msgid "You can now"
msgstr "Du kannst dich nun"
#: views.py:239
msgid "Sorry. Your request is invalid."
msgstr "Entschuldigung, deine Anfrage ist ungültig."
#: views.py:757
msgid ""
"We could not find the requested VM. Please "
"contact Data Center Light Support."
msgstr ""
#~ msgid "Cancel"
#~ msgstr "Beenden"
#~ msgid "Add SSH key"
#~ msgstr "Hinzufügen"
#~ msgid "Keys"
#~ msgstr "Schlüssel"
#, fuzzy
#~| msgid "Contact"
#~ msgid "Content"
#~ msgstr "Kontakt"
#, fuzzy
#~| msgid "Contact"
#~ msgid "DG.Contact"
#~ msgstr "Kontakt"
#, fuzzy
#~| msgid "Home"
#~ msgid "DG.Home"
#~ msgstr "Home"
#, fuzzy
#~| msgid "Amount"
#~ msgid "Country"
#~ msgstr "Betrag"
#~ msgid "Log in"
#~ msgstr "Anmelden"
#, fuzzy
#~| msgid "Configuration"
#~ msgid "Donation #"
#~ msgstr "Konfiguration"
#, fuzzy
#~| msgid "Billing Address"
#~ msgid "Billing Address:"
#~ msgstr "Rechnungsadresse"
#, fuzzy
#~| msgid "Date"
#~ msgid "Date:"
#~ msgstr "Datum"
#, fuzzy
#~| msgid "Configuration"
#~ msgid "Donation"
#~ msgstr "Konfiguration"
#, fuzzy
#~| msgid "View Detail"
#~ msgid "View Donations"
#~ msgstr "Details anzeigen"
#~ msgid "You haven been logged out"
#~ msgstr "Sie wurden abgmeldet"
#, fuzzy
#~| msgid "Log in"
#~ msgid "Log in "
#~ msgstr "Anmelden"
#, fuzzy
#~| msgid "View Detail"
#~ msgid "DG.Detail"
#~ msgstr "Details anzeigen"
#, fuzzy
#~| msgid "Cancel"
#~ msgid "France"
#~ msgstr "Beenden"
#, fuzzy
#~| msgid "Enter your credit card number"
#~ msgid "Enter your name or company name"
#~ msgstr "Deine Kreditkartennummer"
#, fuzzy
#~| msgid "Card Number"
#~ msgid "Cardholder Name"
#~ msgstr "Kreditkartennummer"
#~ msgid "How it works"
#~ msgstr "So funktioniert es"
#~ msgid "Your infrastructure"
#~ msgstr "deine Infrastruktur"
#~ msgid "Our inftrastructure"
#~ msgstr "Unsere Infrastruktur"
#~ msgid "Pricing"
#~ msgstr "Preise"
#~ msgid "Access Key"
#~ msgstr "Zugriffsschlüssel"
#~ msgid "Upload your own key. "
#~ msgstr "Lade deinen Key hoch"
#~ msgid "Generate Key Pair"
#~ msgstr "Schlüsselpaar generieren"
#~ msgid "Created at"
#~ msgstr "Erstellt am"
#~ msgid "Billing Amount"
#~ msgstr "Rechnungsbetrag"
@ -610,25 +611,6 @@ msgstr ""
#~ msgid "EXPIRATION DATE"
#~ msgstr "Ablaufdatum"
#~ msgid "Home"
#~ msgstr "Home"
#~ msgid "Log in"
#~ msgstr "Anmelden"
#~ msgid "You haven been logged out"
#~ msgstr "Sie wurden abgmeldet"
#~ msgid "Upload Key"
#~ msgstr "Schlüssel hochladen"
#~ msgid ""
#~ "Use your created key to access to the machine. If you lost it, contact us."
#~ msgstr ""
#~ "Verwende deinen privaten SSH Schlüssel, um dich mit deinen Maschinen zu "
#~ "verbinden. Solltest du deinen privaten Schlüssel verloren haben, dann "
#~ "kontaktiere uns."
#~ msgid "Copy to Clipboard"
#~ msgstr "Kopieren"
@ -638,6 +620,3 @@ msgstr ""
#~ msgstr ""
#~ "Dein privater SSH Schlüssel wurde bereits generiert und heruntergeladen. "
#~ "Falls du ihn verloren hast, kontaktiere uns."
#~ msgid "Generate my key"
#~ msgstr "Generiere meinen Schlüssel"

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2017-07-06 09:06
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hosting', '0040_hostingplan'),
]
operations = [
migrations.AddField(
model_name='userhostingkey',
name='private_key',
field=models.FileField(blank=True, upload_to='private_keys'),
),
]

View file

@ -101,6 +101,7 @@ class HostingOrder(AssignPermissionsMixin, models.Model):
class UserHostingKey(models.Model):
user = models.ForeignKey(CustomUser)
public_key = models.TextField()
private_key = models.FileField(upload_to='private_keys', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=100)

View file

@ -1,22 +1,23 @@
.dashboard-container {
padding-top:70px; padding-bottom: 70px;
width: 90%;
margin: 0 auto;
max-width: 768px;
padding-top:70px;
padding-bottom: 70px;
width: 90%;
margin: 0 auto;
max-width: 768px;
}
.content-dashboard{
min-height: 100vh;
width: 80%;
margin: 0 auto;
max-width: 1120px;
min-height: 100vh;
width: 80%;
margin: 0 auto;
max-width: 1120px;
}
.container-table{
margin-top: 35px;
overflow-y: hidden;
margin-top: 35px;
overflow-y: hidden;
}
.container-table table{
overflow-y: auto;
overflow-y: auto;
}
.borderless td {
border: none !important;
@ -36,25 +37,150 @@
}
.space-above {
margin-top: 4%;
margin-top: 4%;
}
.space-above-big {
margin-top: 20%;
margin-top: 20%;
}
.table>tbody>tr>td{
vertical-align: middle;
vertical-align: middle;
}
.fa-separate{
margin-right: 15px;
margin-right: 15px;
}
@media (max-width: 540px) {
select {
width: 280px;
width: 280px;
}
.content-dashboard {
width: 90%;
}
width: 90%;
}
}
.btn:focus, .btn:active:focus {
outline: 0;
}
/***********Styles for Model********************/
.modal-content {
border-radius: 0px;
font-family: Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 100%;
float: left;
border-radius: 0;
font-weight: 300;
}
.modal-header {
min-height: 30px;
}
.modal-header .close {
font-size: 75px;
font-weight: 300;
margin-top: 0;
position: absolute;
top: 0;
right: 11px;
z-index: 10;
line-height: 60px;
}
.modal-header .close span {
display: block;
}
.modal-header .close:focus {
outline: 0;
}
.modal-header {
border-bottom: 0px solid #e5e5e5;
padding: 0px 15px;
width: 100%;
}
.modal-body {
text-align: center;
width: 100%;
float: left;
padding: 0px 40px 15px 30px;
}
.modal-body .modal-icon i {
font-size: 80px;
font-weight: 100;
color: #999;
}
.modal-title {
margin: 0;
line-height: 1.42857143;
font-size: 25px;
padding: 0;
font-family: 'Lato', sans-serif;
}
.modal-text {
padding-top: 15px;
font-size: 16px;
}
.modal-footer {
border-top: 0px solid #e5e5e5;
width: 100%;
float: left;
text-align: center;
padding: 15px 15px;
}
.modal-footer button[type="submit"] {
min-width: 80px;
}
@media (min-width: 1300px) {
.modal-dialog {/* top: 30%; */width: 35%;}
}
@media (max-width: 1299px) {
.modal-dialog {
/* top: 20%; */
width: 43%;
}
}
@media (max-width: 900px) {
.modal-dialog {
/* top: 20%; */
width: 50%;
}
}
@media (max-width: 767px) {
.modal-dialog {
/* top: 30%; */
width: 95%;
margin: 0 auto !important;
}
}
/* ========= */
@media(min-width: 320px) {
.modal:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -4px;
}
}
@media (min-width: 768px) {
.modal-dialog {
/* width: 520px; */
margin: 15px auto;
}
}
.modal {
text-align: center;
}
.modal-dialog {
display: inline-block;
text-align: left;
vertical-align: middle;
}

View file

@ -225,7 +225,7 @@ h6 {
}
.auth-bg {
background: url(../img/auth-bg.jpg);
background: url(../img/auth-bg-sm.jpg);
position: fixed;
left: 0;
top: 0;
@ -538,6 +538,10 @@ a.unlink:hover {
padding: 5px;
}
.card-warning-addtional-margin {
margin-top: 15px;
}
.stripe-payment-btn {
outline: none;
width: auto;
@ -718,4 +722,4 @@ a.unlink:hover {
.footer-light a:hover, .footer-light a:focus, .footer-light a:active {
color: #ddd;
}
}

View file

@ -0,0 +1,325 @@
/* ssh_keys_choice */
.h1-thin {
font-family: Lato, sans-serif;
font-weight: 300;
font-size: 32px;
}
.dashboard-container .page-header {
border: 0;
margin-top: 0;
}
.dashboard-choice-container .page-header p {
font-size: 16px;
font-family: Lato, sans-serif;
font-weight: 300;
}
.dashboard-choice-container h2 {
font-family: Lato, sans-serif;
font-weight: 400;
font-size: 22px;
margin-top: 0;
}
.choice-container {
border: 1px solid #C9C6C6;
padding: 25px;
border-radius: 1px;
}
.choice-container p{
font-size: 18px;
font-family: Lato, sans-serif;
font-weight: 300;
}
.choice-container-top {
border-bottom: 1px solid #C9C6C6;
padding-bottom: 25px;
margin-bottom: 25px;
}
.choice-container .choice-btn {
margin-top: 25px;
}
.choice-btn {
min-width: 110px;
background-color: #3C5480;
color: #fff;
border: 2px solid #3C5480;
padding: 4px 10px;
transition: 0.3s all ease-out;
}
.choice-btn:focus,
.choice-btn:hover,
.choice-btn:active {
color: #3C5480;
background-color: #fff;
}
.choice-btn-faded {
background-color: #8396C4;
border: 2px solid #8396C4;
}
@media (max-width: 767px) {
.h1-thin {
font-size: 27px;
}
.dashboard-choice-container h2 {
font-size: 20px;
}
.choice-container p {
font-size: 16px;
}
.choice-btn{
margin-top: 15px;
}
}
@media (max-width: 420px) {
.ssh-keys-table {table-layout: fixed;}
}
.ssh-keys-table thead tr th,
.ssh-keys-table tbody tr td{
color: #717274;
text-align: center;
border-bottom: 1px solid #cbcbcb;
vertical-align: middle;
}
.ssh-keys-table tbody tr{
border-bottom: 1px solid #cbcbcb;
}
.ssh-keys-table thead tr th:first-of-type,
.ssh-keys-table tbody tr td:first-of-type{
text-align: left;
}
.ssh-keys-table thead tr th:last-of-type,
.ssh-keys-table tbody tr td:last-of-type{
width: 20%;
}
.ssh-key-header {
color: #717274;
font-size: 16px;
font-weight: 300;
text-align: justify;
}
.ssh-header-container{
padding-top: 15px;
}
@media (min-width: 768px) {
.ssh-header-container {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.ssh-header-container p{
margin-bottom: 0;
}
}
.ssh-header-container p{
padding: 0;
color: #717274;
font-size: 16px;
font-weight: 300;
font-family: 'Lato';
}
.borderless tbody:before {
display: none !important;
}
.btn-custom-download{
background-color: #337ab7;
margin-top: auto;
margin-bottom: auto;
/* font-weight: 700; */
vertical-align: middle;
margin-right: 25px;
}
.btn-custom-delete{
width: 100px;
background-color: #f1f0f0;
}
.btn-custom-delete a, .btn-custom-download a{
text-decoration: none;
}
.modal-body p{
width: 100%;
word-wrap: break-word;
text-align: left;
}
@media screen and (max-width: 768px) {
.ssh-header-container{
flex-direction: column-reverse;
align-items: flex-start;
}
.btn-custom-delete{
width: auto;
}
.dashboard-container {
width: 100% !important;
}
.row {
/* margin-right: 0; */
/* margin-left: 0; */
}
.col-md-12, .col-sm-12{
padding-left: 5px;
padding-right: 5px;
}
}
@media (max-width: 360px){
.content-dashboard {
/* width: 100% !important; */
}
.container {
padding-right: 5px;
padding-left: 5px;
}
}
.dashboard-choice-container {
max-width: 834px !important;
}
.form_public_key{
resize: none;
}
@media (min-width: 768px) {
.form_key_name{
width:60%;
min-width: 215px;
}
}
.form_public_key,
.form_key_name{
position: relative;
border:none;
border-bottom: 1px solid grey;
box-shadow: none;
border-radius: 0;
font-family: 'Lato-Light', sans-serif;
font-size: 20px;
padding-left: 0;
}
.form_key_name::-webkit-input-placeholder{
font-size: 20px;
font-weight:100;
font-family: 'Lato-Light', sans-serif;
}
.form_key_name::-moz-input-placeholder{
font-size: 20px;
font-weight:200;
font-family: 'Lato-Light', sans-serif;
}
.form_key_name:-moz-input-placeholder{
font-family: 'Lato-Light', sans-serif;
font-size: 20px;
font-weight:200;
}
.form_key_name:-ms-input-placeholder {
font-size: 20px;
font-family: 'Lato-Light', sans-serif;
font-weight:200;
}
.form_public_key::-webkit-input-placeholder{
position: relative;
top: 110px;
font-size: 20px;
font-weight: 200;
font-family: 'Lato-Light', sans-serif;
}
.form_public_key::-moz-input-placeholder{
position: relative;
top: 110px;
font-size: 20px;
font-family: 'Lato-Light', sans-serif;
font-weight:200;
}
.form_public_key:-moz-input-placeholder{
position: relative;
top: 110px;
font-size: 20px;
font-weight:200;
font-family: 'Lato-Light', sans-serif;
}
.form_public_key:-ms-input-placeholder {
position: relative;
top: 110px;
font-size: 20px;
font-weight:200;
font-family: 'Lato-Light', sans-serif;
}
.underform-contaner{
margin-bottom: 20px;
}
@media (min-width: 767px) {
.underform-contaner {
display: flex;
vertical-align: middle;
align-items: center;
justify-content: space-between;
flex-direction: row;
}
}
@media (max-width: 767px) {
.underform-contaner .btn-container {
text-align: right;
}
}
.underform-contaner h4{
font-family: 'Lato-Light', sans-serif;
}
.underform-contaner button{
/* font-family: Lato; */
/* font-weight: 600; */
min-width: 120px;
height: 35px;
margin-top: 0;
}
.underform-contaner .btn-default{
background-color: #ccc;
color: #fff;
}
.control-label{
font-family: 'Lato-Light', sans-serif;
font-size: 20px;
font-weight:200;
}
.form-ssh h3{
margin-bottom: 40px;
}
.custom_form_button{
border-radius: 0;
}
.form_key_name:focus,
.form_public_key:focus,
.has-error .form_key_name,
.has-error .form_key_name:focus,
.has-error .form_public_key,
.has-error .form_public_key:focus,
.has-success .form_key_name,
.has-success .form_key_name:focus,
.has-success .form_public_key,
.has-success .form_public_key:focus {
box-shadow: none;
}
.wide440 {
max-width: 440px;
margin: auto;
}
.mob-only {
display: none;
}
@media (max-width: 767px) {
.mob-only {
display: initial;
}
.pc-only {
display: none;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

View file

@ -18,6 +18,7 @@
<!-- Custom CSS -->
<link href="{% static 'hosting/css/landing-page.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/user_keys.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/payment.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/order.css' %}" rel="stylesheet">
<link href="{% static 'hosting/css/orders.css' %}" rel="stylesheet">
@ -27,7 +28,7 @@
<!-- Custom Fonts -->
<link href='//fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link href="//fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=Lato:300,400,500,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="{% static 'hosting/css/owl.carousel.min.css' %}">
<link rel="stylesheet" href="{% static 'hosting/css/owl.theme.default.min.css' %}">
@ -84,7 +85,7 @@
<ul id="g-account-menu" class="dropdown-menu" role="menu">
<li>
<a href="{% url 'hosting:ssh_keys' %}">
<i class="fa fa-key"></i> {% trans "Keys"%}
<i class="fa fa-key"></i> {% trans "SSH Keys" %}
</a>
</li>
<li>
@ -114,7 +115,7 @@
{% if request.user.is_authenticated %}
<footer class="footer-vm">
<div class="container">
<p class="copyright text-muted small">Copyright &copy; ungleich GmbH {% now "Y" %}. All Rights Reserved</p>
<p class="copyright text-muted small">Copyright &copy; ungleich GmbH {% now "Y" %}. {% trans "All Rights Reserved" %}</p>
</div>
</footer>
{% else %}

View file

@ -0,0 +1,66 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% block content %}
<div>
<div class="container virtual-machine-container dashboard-container dashboard-choice-container">
<div class="wide440">
<div class="page-header">
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% trans "SSH Key"%}</h1>
<p>{% trans "Choose a key option in order to access your VM" %}.</p>
</div>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
<div class="choice-container">
<div class="choice-container-top">
<h2>{% trans "Generating a new key pair" %}</h2>
<p>{% trans "I want to generate a new key pair" %}.</p>
<form class="text-right" action="" method="post">
{% csrf_token %}
<button type="submit" class="btn choice-btn choice-btn-faded">
{% trans "Generate" %}
</button>
</form>
</div>
<div>
<h2>{% trans "Using existing key" %}</h2>
<p>{% trans "I want to use my existing public key"%}.</p>
<form class="text-right" action="{% url 'hosting:create_ssh_key' %}">
<button type="submit" class="btn choice-btn">
{% trans "Upload" %}
</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% if next_url %}
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}
<script type="text/javascript">
window.onload = function () {
{% for user_key in keys %}
var locale_date = moment.utc(document.getElementById("ssh-created_at-{{user_key.id}}").textContent,'YYYY-MM-DD HH:mm').toDate();
locale_date = moment(locale_date).format("YYYY-MM-DD h:mm:ss a");
document.getElementById('ssh-created_at-{{user_key.id}}').innerHTML = locale_date;
{% endfor %}
};
</script>
{%endblock%}

View file

@ -26,8 +26,8 @@
<a href="#contact">Contact</a>
</li>
</ul>
<p class="copyright text-muted small">Copyright &copy; ungleich GmbH {% now "Y" %}. All Rights Reserved</p>
<p class="copyright text-muted small">Copyright &copy; ungleich GmbH {% now "Y" %}. {% trans "All Rights Reserved" %}</p>
</div>
</div>
</div>
</footer>
</footer>

View file

@ -20,7 +20,7 @@
<div class="row">
<div class="col-xs-12 col-md-8 col-md-offset-2">
<div class="invoice-title">
<h2>{% trans "Confirm Order"%}</h2><h3 class="pull-right">{% trans "Order #"%} {{order.id}}</h3>
<h2>{{page_header_text}}</h2><h3 class="pull-right">{% trans "Order #"%} {{order.id}}</h3>
</div>
<hr>
<div class="row">

View file

@ -52,16 +52,13 @@
</button>
</div>
<div class="modal-body">
<h4 class="modal-title" id="ModalLabel">{% trans "Do You want to delete your order?"%}</h4>
<div class="modal-icon"><i class="fa fa-trash" aria-hidden="true"></i></div>
<h4 class="modal-title" id="ModalLabel">{% trans "Do you want to delete your order?"%}</h4>
<form method="post"
action="{% url 'hosting:delete_order' order.id %}">
{% csrf_token %}
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">
{% trans "Close"%}
</button>
<button type="submit" class="btn btn-primary">{% trans "Delete"%}
</button>
</div>
@ -71,7 +68,6 @@
</div>
</div>
{% endfor %}
</tbody>
</table>

View file

@ -86,7 +86,7 @@
</form>
<div class="row">
<div class="col-xs-12">
<p>
<p class="card-warning-content card-warning-addtional-margin">
{% blocktrans %}
You are not making any payment yet. After submitting your card
information, you will be taken to the Confirm Order Page.

View file

@ -1,60 +1,61 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% block content %}
{% block content %}
<div>
<div class="virtual-machine-container dashboard-container ">
<div class="virtual-machine-container dashboard-container">
<div class="row">
<div class="container-table col-md-9 col-md-offset-2">
<div class="col-sm-12">
<form method="POST" action="" novalidate class="form-ssh">
{% csrf_token %}
<h3><i class="fa fa-key fa-separate" aria-hidden="true"></i>{% trans "Access Key"%} </h3>
{% if messages %}
<div class="col-md-9 col-md-offset-2">
<form method="POST" action="" novalidate class="form-ssh">
{% csrf_token %}
<div class="page-header">
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% trans "Add your public SSH key" %}</h1>
</div>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
{% buttons %}
<button type="submit" class="btn btn-success">
{% trans "Upload your own key. "%}
{% endif %}
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
{% buttons %}
<div class="underform-contaner">
<h4>{% trans "Use your created key to access to the VM" %}.</h4>
<div class="btn-container">
<button type="submit" name="add_ssh" class="btn choice-btn choice-btn-faded">
{% trans "Add SSH Key" %}
</button>
<br />
<br />
{% trans "Or generate a new key pair."%} <br />
<br />
<button class="btn btn-success">{% trans "Generate Key Pair"%} </a>
</div>
</div>
<div class="underform-contaner">
<h4>{% trans "Or you can generate a new key pair"%}.</h4>
<div class="btn-container">
<button type="submit" name="generate" class="btn choice-btn">
{% trans "Generate" %}
</button>
</div>
</div>
{% endbuttons %}
</form>
{% endbuttons %}
</form>
<h5> Use your created key to access to the machine. If you lost it, contact us. </h5>
{% if private_key %}
<div class="alert alert-warning">
<strong>{% trans "Warning!"%}</strong>{% trans "You can download your SSH private key once. Don't lost your key"%}
</div>
<div class="form-group">
<textarea class="form-control" rows="6" id="ssh_key" type="hidden" style="display:none">{{private_key}}</textarea>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
{% if private_key %}
<div class="alert alert-warning">
<strong>{% trans "Warning!"%}</strong>{% trans "You can download your SSH private key once. Don't loose your key" %}
</div>
<div class="form-group">
<textarea class="form-control" rows="6" id="ssh_key" type="hidden" style="display:none">{{private_key}}</textarea>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% if private_key %}
<!-- Force to download ssh key on page load -->
<script type="text/javascript">
<script type="text/javascript">
var key = window.document.getElementById('ssh_key');
@ -75,7 +76,7 @@
{%endif%}
{% if next_url %}
<script type="text/javascript">
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}

View file

@ -1,104 +1,124 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% block content %}
{% block content %}
<div>
<div class="container virtual-machine-container dashboard-container ">
<div class="row">
<div class="col-md-9 col-md-offset-2">
<div class="col-sm-12">
<h3><i class="fa fa-key" aria-hidden="true"></i>{% trans "Access Key"%} </h3>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
{% endif %}
<p class="pull-right">
<a class="btn btn-success" href="{% url 'hosting:create_ssh_key' %}" >{% trans "Add Key"%} </a>
</p>
<h5> Use your created key to access to the machine. If you lost it, contact us. </h5>
<table class="table borderless table-hover">
<br/>
<thead>
<tr>
<th>{% trans "Name"%}</th>
<th>{% trans "Created at"%} </th>
<th>{% trans "Status"%} </th>
<th></th>
</tr>
</thead>
<tbody>
{% for user_key in keys %}
<tr>
<td scope="row">{{user_key.name}}</td>
<td><span id="ssh-created_at-{{user_key.id}}">{{user_key.created_at|date:'Y-m-d H:i' }}</span></td>
<td>
<span class="h3 label label-success"><strong>Active</strong></span>
</td>
<td>
<button type="button" class="btn btn-default" data-toggle="modal"
data-target="#Modal{{ user_key.id }}"><a
href="#">{% trans "Delete Key"%}</a>
</button>
<div class="modal fade" id="Modal{{user_key.id }}" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Confirm"><span
aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4 class="modal-title" id="ModalLabel">{% trans "Do You want to delete this key?"%}</h4>
<form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}">
{% csrf_token %}
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">
{% trans "Close"%}
</button>
<button type="submit" class="btn btn-primary">{% trans "Delete"%}
</button>
</div>
</form>
</div>
</div>
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i>&nbsp;{% trans "Your SSH Keys" %}</h1>
{% if messages %}
<div class="alert alert-warning">
{% for message in messages %}
<span>{{ message }}</span>
{% endfor %}
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<div class="ssh-header-container">
<p>{% trans "To generate a new key pair or to upload your existing key, click 'Add Key'" %}</p>
<a class="btn choice-btn" href="{% url 'hosting:choice_ssh_keys' %}" >
<span class="fa fa-plus"></span>&nbsp;&nbsp;{% trans "Add SSH Key" %}
</a>
</div>
<table class="table borderless table-hover ssh-keys-table">
<br/>
<thead>
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Delete Key" %}</th>
<th>{% trans "Public Key" %}</th>
<th>{% trans "Private Key" %}</th>
</tr>
</thead>
<tbody>
{% for user_key in keys %}
<tr>
<td scope="row">{{user_key.name}}</td>
<td>
<button type="button" class="btn btn-default btn-custom-delete" data-toggle="modal"
data-target="#Modal{{ user_key.id }}" style="color: #717274">
<span class="pc-only">{% trans "Delete" %}</span>
<span class="mob-only"><i class="fa fa-trash"></i></span>
</button>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="modal fade" id="Modal{{user_key.id }}" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Confirm"><span
aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4 class="modal-title" id="ModalLabel">{% trans "Do You want to delete this key?" %}</h4>
<form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}">
{% csrf_token %}
<div class="modal-footer">
<button type="submit" class="btn btn-primary">{% trans "Delete" %}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</td>
<td>
<p type="button" data-toggle="modal" style="margin: 0" data-target="#Modal_public_key{{ user_key.id }}">
<a href="#">{% trans "Show" %}</a>
</p>
<div class="modal fade" id="Modal_public_key{{user_key.id }}" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Confirm"><span
aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4 class="modal-title" id="ModalLabel_Public_Key">{% trans "Public ssh key" %}</h4>
<p style="margin-top: 10px;">{{ user_key.public_key }}</p>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">
{% trans "Close" %}
</button>
</div>
</div>
</div>
</div>
</div>
</td>
</td>
<td>
{% if user_key.private_key %}
<form action="{{ user_key.private_key.url }}">
<button style="color: #717274" type="submit" class="btn btn-default" data-toggle="modal"
>
<span class="pc-only">{% trans "Download" %}</span>
<span class="mob-only"><i class="fa fa-download"></i></span>
</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% if next_url %}
<script type="text/javascript">
<script type="text/javascript">
window.location.href = '{{next_url}}';
</script>
{% endif %}
<script type="text/javascript">
<script type="text/javascript">
window.onload = function () {
{% for user_key in keys %}
// var locale_date = new Date(document.getElementById("ssh-created_at-{{user_key.id}}").textContent).toISOString();
var locale_date = moment.utc(document.getElementById("ssh-created_at-{{user_key.id}}").textContent,'YYYY-MM-DD HH:mm').toDate();
locale_date = moment(locale_date).format("YYYY-MM-DD h:mm:ss a");
document.getElementById('ssh-created_at-{{user_key.id}}').innerHTML = locale_date;

View file

@ -2,7 +2,7 @@
{% load staticfiles bootstrap3 %}
{% load i18n %}
{% block content %}
{% block content %}
<div>
<div class="virtual-machine-container dashboard-container ">
<div class="row">
@ -46,19 +46,19 @@
<button type="link"
data-clipboard-text="{{virtual_machine.ipv4}}" id="copy_vm_id" class="to_copy btn btn-link"
data-toggle="tooltip" data-placement="bottom" title="Copied" data-trigger="click">
Ipv4: {{virtual_machine.ipv4}} <i class="fa fa-files-o" aria-hidden="true"></i>
Ipv4: {{virtual_machine.ipv4}} <i class="fa fa-files-o" aria-hidden="true"></i>
</button>
<button type="link"
data-clipboard-text="{{virtual_machine.ipv6}}" id="copy_vm_id" class="to_copy btn btn-link"
data-toggle="tooltip" data-placement="bottom" title="Copied" data-trigger="click">
Ipv6: {{virtual_machine.ipv6}} <i class="fa fa-files-o" aria-hidden="true"></i>
Ipv6: {{virtual_machine.ipv6}} <i class="fa fa-files-o" aria-hidden="true"></i>
</button>
</div>
{% else %}
<div class="pull-right right-place">
<span class="label label-warning"><strong>{% trans "Ip not assigned yet"%}</strong></span>
<i data-toggle="tooltip" title="Your ip will be assigned soon" class="fa fa-info-circle" aria-hidden="true"></i>
<i data-toggle="tooltip" title="Your ip will be assigned soon" class="fa fa-info-circle" aria-hidden="true"></i>
</div>
{% endif %}
@ -85,12 +85,12 @@
</div>
<div class="col-md-3">
<div class="well text-center box-setting">
<i class="fa fa-hdd-o" aria-hidden="true"></i>
<i class="fa fa-hdd-o" aria-hidden="true"></i>
<span>{% trans "Disk"%}</span>
<span class="label label-success">{{virtual_machine.disk_size|floatformat:2}} GB</span>
</div>
</div>
</div><!--/row-->
</div><!--/row-->
</div><!--/col-12-->
</div><!--/row-->
<div class="row">
@ -106,7 +106,7 @@
<div class="row ">
<div class="col-md-12 inline-headers">
<h3>{% trans "Current pricing"%}</h3>
<span class="h3 pull-right"><strong>{{virtual_machine.price|floatformat}} CHF</strong>/month</span>
<span class="h3 pull-right"><strong>{{virtual_machine.price|floatformat}} CHF</strong>/month</span>
<hr>
</div>
</div>
@ -136,13 +136,13 @@
<div class="pull-right">
<form method="POST"
id="virtual_machine_cancel_form" class="cancel-form" action="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}">
{% csrf_token %}
</form>
{% csrf_token %}
</form>
<button type="text" data-href="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}" data-toggle="modal" data-target="#confirm-cancel" class="btn btn-danger">{% trans "Terminate Virtual Machine"%}</button>
</div>
</div>
<div class="col-md-12">
<br/>
@ -159,14 +159,18 @@
<div class="modal fade" id="confirm-cancel" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
{% trans "Terminate your Virtual Machine"%}
</div>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Confirm"><span
aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{% trans "Are you sure do you want to cancel your Virtual Machine "%} {{virtual_machine.name}} ?
<div class="modal-icon"><i class="fa fa-ban" aria-hidden="true"></i></div>
<h4 class="modal-title" id="ModalLabel">{% trans "Terminate your Virtual Machine"%}</h4>
<p class="modal-text">{% trans "Are you sure do you want to cancel your Virtual Machine "%} {{virtual_machine.name}} ?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Cancel"%}</button>
<a class="btn btn-danger btn-ok">OK</a>
</div>
</div>

View file

@ -7,7 +7,7 @@ from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
VirtualMachineView, OrdersHostingDeleteView, NotificationsView, \
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\
CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, \
SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView
SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, SSHKeyChoiceView
urlpatterns = [
url(r'index/?$', IndexView.as_view(), name='index'),
@ -27,6 +27,8 @@ urlpatterns = [
name='virtual_machines'),
url(r'ssh_keys/?$', SSHKeyListView.as_view(),
name='ssh_keys'),
url(r'ssh_keys_choice/?$', SSHKeyChoiceView.as_view(),
name='choice_ssh_keys'),
url(r'delete_ssh_key/(?P<pk>\d+)/?$', SSHKeyDeleteView.as_view(),
name='delete_ssh_key'),
url(r'create_ssh_key/?$', SSHKeyCreateView.as_view(),

View file

@ -1,3 +1,7 @@
import uuid
from django.core.files.base import ContentFile
from oca.pool import WrongNameError, WrongIdError
from django.shortcuts import render
from django.http import Http404
@ -24,7 +28,7 @@ from utils.forms import BillingAddressForm, PasswordResetRequestForm, UserBillin
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin
from utils.mailer import BaseEmail
from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm, generate_ssh_key_name
from .mixins import ProcessVMSelectionMixin
from opennebula_api.models import OpenNebulaManager
@ -32,7 +36,6 @@ from opennebula_api.serializers import VirtualMachineSerializer, \
VirtualMachineTemplateSerializer
from django.utils.translation import ugettext_lazy as _
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a backend \
connection error. please try again in a few minutes."
@ -193,8 +196,10 @@ class SignupView(CreateView):
name = form.cleaned_data.get('name')
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
this_base_url = "{0}://{1}".format(self.request.scheme, self.request.get_host())
CustomUser.register(name, password, email, app='dcl', base_url=this_base_url)
this_base_url = "{0}://{1}".format(self.request.scheme,
self.request.get_host())
CustomUser.register(name, password, email,
app='dcl', base_url=this_base_url)
return HttpResponseRedirect(reverse_lazy('hosting:signup-validate'))
@ -204,8 +209,10 @@ class SignupValidateView(TemplateView):
def get_context_data(self, **kwargs):
context = super(SignupValidateView, self).get_context_data(**kwargs)
login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) + '</a>'
home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>'
login_url = '<a href="' + \
reverse('hosting:login') + '">' + str(_('login')) + '</a>'
home_url = '<a href="' + \
reverse('datacenterlight:index') + '">Data Center Light</a>'
message = '{signup_success_message} {lurl}</a> \
<br />{go_back} {hurl}.'.format(
signup_success_message=_(
@ -226,15 +233,18 @@ class SignupValidatedView(SignupValidateView):
def get_context_data(self, **kwargs):
context = super(SignupValidateView, self).get_context_data(**kwargs)
validated = CustomUser.validate_url(self.kwargs['validate_slug'])
login_url = '<a href="' + reverse('hosting:login') + '">' + str(_('login')) + '</a>'
login_url = '<a href="' + \
reverse('hosting:login') + '">' + str(_('login')) + '</a>'
section_title = _('Account activation')
if validated:
message = '{account_activation_string} <br /> {login_string} {lurl}.'.format(
account_activation_string=_("Your account has been activated."),
account_activation_string=_(
"Your account has been activated."),
login_string=_("You can now"),
lurl=login_url)
else:
home_url = '<a href="' + reverse('datacenterlight:index') + '">Data Center Light</a>'
home_url = '<a href="' + \
reverse('datacenterlight:index') + '">Data Center Light</a>'
message = '{sorry_message} <br />{go_back_to} {hurl}'.format(
sorry_message=_("Sorry. Your request is invalid."),
go_back_to=_('Go back to'),
@ -364,10 +374,29 @@ class SSHKeyListView(LoginRequiredMixin, ListView):
def render_to_response(self, context, **response_kwargs):
if not self.queryset:
return HttpResponseRedirect(reverse('hosting:create_ssh_key'))
return HttpResponseRedirect(reverse('hosting:choice_ssh_keys'))
return super(SSHKeyListView, self).render_to_response(context, **response_kwargs)
class SSHKeyChoiceView(LoginRequiredMixin, View):
template_name = "hosting/choice_ssh_keys.html"
login_url = reverse_lazy('hosting:login')
def get(self, request, *args, **kwargs):
context = {}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
name = generate_ssh_key_name()
private_key, public_key = UserHostingKey.generate_keys()
content = ContentFile(private_key)
ssh_key = UserHostingKey.objects.create(
user=request.user, public_key=public_key, name=name)
filename = name + '_' + str(uuid.uuid4())[:8] + '_private.pem'
ssh_key.private_key.save(filename, content)
return redirect(reverse_lazy('hosting:ssh_keys'), foo='bar')
class SSHKeyCreateView(LoginRequiredMixin, FormView):
form_class = UserHostingKeyForm
model = UserHostingKey
@ -383,6 +412,11 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
def form_valid(self, form):
form.save()
if 'dcl-generated-key-' in form.instance.name:
content = ContentFile(form.cleaned_data.get('private_key'))
filename = form.cleaned_data.get(
'name') + '_' + str(uuid.uuid4())[:8] + '_private.pem'
form.instance.private_key.save(filename, content)
context = self.get_context_data()
next_url = self.request.session.get(
@ -407,10 +441,11 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
manager = OpenNebulaManager()
# Get user ssh key
public_key = form.cleaned_data.get('public_key', '').decode('utf-8')
public_key = str(form.cleaned_data.get('public_key', ''))
# Add ssh key to user
try:
manager.add_public_key(user=owner, public_key=public_key, merge=True)
manager.add_public_key(
user=owner, public_key=public_key, merge=True)
except ConnectionError:
pass
except WrongNameError:
@ -421,6 +456,9 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
def post(self, request, *args, **kwargs):
print(self.request.POST.dict())
form = self.get_form()
required = 'add_ssh' in self.request.POST
form.fields['name'].required = required
form.fields['public_key'].required = required
if form.is_valid():
return self.form_valid(form)
else:
@ -563,7 +601,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
# Create a Hosting Bill
HostingBill.create(
customer=customer, billing_address=billing_address)
customer=customer, billing_address=billing_address)
# Create Billing Address for User if he does not have one
if not customer.user.billing_addresses.count():
@ -600,7 +638,9 @@ class PaymentVMView(LoginRequiredMixin, FormView):
email = BaseEmail(**email_data)
email.send()
return HttpResponseRedirect(reverse('hosting:orders', kwargs={'pk': order.id}))
return HttpResponseRedirect(
"{url}?{query_params}".format(url=reverse('hosting:orders', kwargs={'pk': order.id}),
query_params='page=payment'))
else:
return self.form_invalid(form)
@ -619,6 +659,10 @@ class OrdersHostingDetailView(PermissionRequiredMixin, LoginRequiredMixin, Detai
owner = self.request.user
manager = OpenNebulaManager(email=owner.email,
password=owner.password)
if self.request.GET.get('page', '') == 'payment':
context['page_header_text'] = _('Confirm Order')
else:
context['page_header_text'] = _('Invoice')
try:
vm = manager.get_vm(obj.vm_id)
context['vm'] = VirtualMachineSerializer(vm).data