hosting form view modified
This commit is contained in:
parent
c2b5c62014
commit
87327d028a
8 changed files with 324 additions and 204 deletions
|
@ -26,9 +26,9 @@
|
||||||
<div class="help-block with-errors">
|
<div class="help-block with-errors">
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
{% if 'cores' in message.tags %}
|
{% if 'cores' in message.tags %}
|
||||||
<ul class="list-unstyled"><li>
|
<ul class="list-unstyled">
|
||||||
{{ message|safe }}
|
<li>{{ message|safe }}</li>
|
||||||
</li></ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
/*Pricing page*/
|
/* Create VM calculator */
|
||||||
|
|
||||||
.price-calc-section {
|
.price-calc-section {
|
||||||
padding: 80px 40px !important;
|
padding: 80px 40px !important;
|
||||||
background: -webkit-linear-gradient(top, #f0f4f7, #fff) no-repeat;
|
}
|
||||||
background: linear-gradient(to bottom, #f0f4f7, #fff) no-repeat;
|
|
||||||
display: flex;
|
@media (max-width: 768px) {
|
||||||
/*font-family: 'Lato', sans-serif;*/
|
.price-calc-section {
|
||||||
/* font-weight: normal; */
|
margin-top: 40px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .text {
|
.price-calc-section .text {
|
||||||
|
@ -42,12 +43,12 @@
|
||||||
width: 50%;
|
width: 50%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
|
box-shadow: 1px 3px 6px 2px rgba(0, 0, 0, 0.2);
|
||||||
padding-bottom: 40px;
|
padding-bottom: 30px;
|
||||||
border-radius: 7px;
|
/* border-radius: 7px; */
|
||||||
text-align: center;
|
text-align: center;
|
||||||
/* margin-right: auto; */
|
/* margin-right: auto; */
|
||||||
max-width: 400px;
|
max-width: 320px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description {
|
.price-calc-section .card .description {
|
||||||
padding: 12px;
|
padding: 7px 8px 2px;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around !important;
|
justify-content: space-around !important;
|
||||||
|
@ -95,24 +96,29 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description span {
|
.price-calc-section .card .description span {
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
margin-left: 4px;
|
margin-left: 5px;
|
||||||
margin-left: 0px;
|
/* margin-left: 0px; */
|
||||||
/* justify-self: start; */
|
/* justify-self: start; */
|
||||||
width: 30%;
|
width: 29%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
line-height: 16px;
|
||||||
|
/* font-weight: normal; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description .select-number{
|
.price-calc-section .card .description .select-number{
|
||||||
font-size: 20px;
|
font-size: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 85px;
|
width: 85px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description i {
|
.price-calc-section .card .description i {
|
||||||
color: #29427A;
|
color: #29427a;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
padding: 5px 6px 3px;
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description .left {
|
.price-calc-section .card .description .left {
|
||||||
|
@ -124,7 +130,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .descriptions {
|
.price-calc-section .card .descriptions {
|
||||||
padding: 10px 30px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .description p {
|
.price-calc-section .card .description p {
|
||||||
|
@ -132,9 +138,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .btn {
|
.price-calc-section .card .btn {
|
||||||
margin-top: 20px;
|
margin-top: 15px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
width: 200px;
|
width: 150px;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,11 +148,13 @@
|
||||||
outline: none;
|
outline: none;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: #d0d0d0;
|
border-color: #d0d0d0;
|
||||||
height: 40px;
|
height: 32px;
|
||||||
width: 200px;
|
width: 150px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-calc-section .card .check-ip {
|
.price-calc-section .card .check-ip {
|
||||||
|
@ -173,7 +181,7 @@
|
||||||
width: 200px;
|
width: 200px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 5px 10px;
|
padding: 4px 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #d0d0d0;
|
border: 1px solid #d0d0d0;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
@ -184,3 +192,42 @@
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
margin: 0 8px;
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.help-block.with-errors {
|
||||||
|
text-align: center;
|
||||||
|
margin: 0 0;
|
||||||
|
padding: 0 0 5px;
|
||||||
|
}
|
||||||
|
.help-block.with-errors ul {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group:after {
|
||||||
|
content: ' ';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 18%;
|
||||||
|
z-index: 20;
|
||||||
|
height: 1px;
|
||||||
|
width: 65%;
|
||||||
|
background: rgba(128, 128, 128, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: #29427A;
|
||||||
|
border-color: #29427A;
|
||||||
|
color: #fff;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(min-width: 768px) {
|
||||||
|
.create-vm-container {
|
||||||
|
padding-top: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,72 +1,75 @@
|
||||||
(function($){
|
(function($){
|
||||||
"use strict"; // Start of use strict
|
"use strict"; // Start of use strict
|
||||||
|
|
||||||
|
var cardPricing = {
|
||||||
$(window).load(function(){
|
'cpu': {
|
||||||
|
'id': 'coreValue',
|
||||||
|
'value': 1,
|
||||||
});
|
'min': 1,
|
||||||
|
'max': 48,
|
||||||
$(document).ready(function(){
|
'interval': 1
|
||||||
_initOs();
|
},
|
||||||
|
'ram': {
|
||||||
});
|
'id': 'ramValue',
|
||||||
|
'value': 2,
|
||||||
$(window).resize(function(){
|
'min': 2,
|
||||||
|
'max': 200,
|
||||||
|
'interval': 1
|
||||||
});
|
},
|
||||||
|
'storage': {
|
||||||
|
'id': 'storageValue',
|
||||||
|
'value': 10,
|
||||||
function _initOs(){
|
'min': 10,
|
||||||
|
'max': 2000,
|
||||||
|
'interval': 10
|
||||||
$('.os-circle').click(function(event){
|
|
||||||
$('.os-circle').removeClass('active');
|
|
||||||
$(this).addClass('active');
|
|
||||||
|
|
||||||
var idTemplate = $(this).data('id');
|
|
||||||
$('input[name=vm_template_id]').val(idTemplate);
|
|
||||||
});
|
|
||||||
$('.config-box').click(function(event){
|
|
||||||
$('.config-box').removeClass('active');
|
|
||||||
$(this).addClass('active');
|
|
||||||
var idConfig = $(this).data('id');
|
|
||||||
var price = $(this).data('price');
|
|
||||||
$('input[name=configuration]').val(idConfig);
|
|
||||||
$('.container-button').fadeIn();
|
|
||||||
$('#priceValue').text(price);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.owl-carousel').owlCarousel({
|
|
||||||
items:4,
|
|
||||||
nav: true,
|
|
||||||
margin:30,
|
|
||||||
responsiveClass:true,
|
|
||||||
navText: ['<i class="fa fa-angle-left"></i>', '<i class="fa fa-angle-right"></i>'],
|
|
||||||
responsive:{
|
|
||||||
0:{
|
|
||||||
items:1,
|
|
||||||
nav:true
|
|
||||||
},
|
|
||||||
600:{
|
|
||||||
items:2,
|
|
||||||
nav:true
|
|
||||||
},
|
|
||||||
768:{
|
|
||||||
items:3,
|
|
||||||
nav:true
|
|
||||||
},
|
|
||||||
990:{
|
|
||||||
items:4,
|
|
||||||
nav:true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
function _initPricing() {
|
||||||
|
_fetchPricing();
|
||||||
|
|
||||||
|
$('.fa-minus.left').click(function(event) {
|
||||||
|
var data = $(this).data('minus');
|
||||||
|
|
||||||
|
if (cardPricing[data].value > cardPricing[data].min) {
|
||||||
|
cardPricing[data].value = Number(cardPricing[data].value) - cardPricing[data].interval;
|
||||||
|
}
|
||||||
|
_fetchPricing();
|
||||||
|
});
|
||||||
|
$('.fa-plus.right').click(function(event) {
|
||||||
|
var data = $(this).data('plus');
|
||||||
|
if (cardPricing[data].value < cardPricing[data].max) {
|
||||||
|
cardPricing[data].value = Number(cardPricing[data].value) + cardPricing[data].interval;
|
||||||
|
}
|
||||||
|
_fetchPricing();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.input-price').change(function() {
|
||||||
|
var data = $(this).attr("name");
|
||||||
|
cardPricing[data].value = $('input[name=' + data + ']').val();
|
||||||
|
_fetchPricing();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _fetchPricing() {
|
||||||
|
Object.keys(cardPricing).map(function(element) {
|
||||||
|
//$('#'+cardPricing[element].id).val(cardPricing[element].value);
|
||||||
|
$('input[name=' + element + ']').val(cardPricing[element].value);
|
||||||
|
});
|
||||||
|
_calcPricing();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _calcPricing() {
|
||||||
|
var total = (cardPricing['cpu'].value * 5) + (2 * cardPricing['ram'].value) + (0.6 * cardPricing['storage'].value);
|
||||||
|
total = parseFloat(total.toFixed(2));
|
||||||
|
|
||||||
|
$("#total").text(total);
|
||||||
|
$('input[name=total]').val(total);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
_initPricing();
|
||||||
|
});
|
||||||
|
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|
||||||
|
|
73
hosting/static/hosting/js/createvm_old.js
Normal file
73
hosting/static/hosting/js/createvm_old.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
(function($){
|
||||||
|
"use strict"; // Start of use strict
|
||||||
|
|
||||||
|
|
||||||
|
$(window).load(function(){
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
_initOs();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$(window).resize(function(){
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function _initOs(){
|
||||||
|
|
||||||
|
|
||||||
|
$('.os-circle').click(function(event){
|
||||||
|
$('.os-circle').removeClass('active');
|
||||||
|
$(this).addClass('active');
|
||||||
|
|
||||||
|
var idTemplate = $(this).data('id');
|
||||||
|
$('input[name=vm_template_id]').val(idTemplate);
|
||||||
|
});
|
||||||
|
$('.config-box').click(function(event){
|
||||||
|
$('.config-box').removeClass('active');
|
||||||
|
$(this).addClass('active');
|
||||||
|
var idConfig = $(this).data('id');
|
||||||
|
var price = $(this).data('price');
|
||||||
|
$('input[name=configuration]').val(idConfig);
|
||||||
|
$('.container-button').fadeIn();
|
||||||
|
$('#priceValue').text(price);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.owl-carousel').owlCarousel({
|
||||||
|
items:4,
|
||||||
|
nav: true,
|
||||||
|
margin:30,
|
||||||
|
responsiveClass:true,
|
||||||
|
navText: ['<i class="fa fa-angle-left"></i>', '<i class="fa fa-angle-right"></i>'],
|
||||||
|
responsive:{
|
||||||
|
0:{
|
||||||
|
items:1,
|
||||||
|
nav:true
|
||||||
|
},
|
||||||
|
600:{
|
||||||
|
items:2,
|
||||||
|
nav:true
|
||||||
|
},
|
||||||
|
768:{
|
||||||
|
items:3,
|
||||||
|
nav:true
|
||||||
|
},
|
||||||
|
990:{
|
||||||
|
items:4,
|
||||||
|
nav:true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
|
|
@ -74,8 +74,8 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- jQuery -->
|
<!-- jQuery -->
|
||||||
<script src="{% static 'hosting/js/jquery.js' %}"></script>
|
<script src="{% static 'hosting/js/jquery.js' %}"></script>
|
||||||
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.validation/1.13.1/jquery.validate.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.16.0/jquery.validate.min.js"></script>
|
||||||
<script src="{% static 'hosting/js/vendor/owl.carousel.min.js'%}"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.9/validator.min.js"></script>
|
||||||
<!-- Copy Clipboard -->
|
<!-- Copy Clipboard -->
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.10/clipboard.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.10/clipboard.min.js"></script>
|
||||||
|
|
||||||
|
@ -106,8 +106,6 @@
|
||||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
|
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
|
||||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.js"></script>
|
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,27 +1,20 @@
|
||||||
{% load staticfiles i18n%}
|
{% load staticfiles i18n%}
|
||||||
<form id="order_form" method="POST" action="" data-toggle="validator" role="form">
|
<form id="order_form" method="POST" action="" data-toggle="validator" role="form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="title">
|
|
||||||
<h3>{% trans "VM hosting" %} </h3>
|
|
||||||
</div>
|
|
||||||
<div class="price">
|
<div class="price">
|
||||||
<span id="total">15</span>
|
<span id="total">15</span>
|
||||||
<span>CHF/{% trans "month" %}</span>
|
<span>CHF/30 {% trans "days" %}</span>
|
||||||
<div class="price-text">
|
<div class="price-text">
|
||||||
<p>{% trans "VAT included" %}</p>
|
<p>{% trans "VAT included" %}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="descriptions">
|
<div class="descriptions">
|
||||||
<div class="description form-group">
|
|
||||||
<p>{% trans "Hosted in Switzerland" %}</p>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="description input">
|
<div class="description input">
|
||||||
<i class="fa fa-minus-circle left" data-minus="cpu" aria-hidden="true"></i>
|
<i class="fa fa-minus left" data-minus="cpu" aria-hidden="true"></i>
|
||||||
<input class="input-price select-number" type="number" min="1" max="48" id="coreValue" name="cpu"
|
<input class="input-price select-number" type="number" min="1" max="48" id="coreValue" name="cpu" data-error="{% trans 'Please enter a value in range 1 - 48.' %}" required>
|
||||||
data-error="{% trans 'Please enter a value in range 1 - 48.' %}" required>
|
|
||||||
<span> Core</span>
|
<span> Core</span>
|
||||||
<i class="fa fa-plus-circle right" data-plus="cpu" aria-hidden="true"></i>
|
<i class="fa fa-plus right" data-plus="cpu" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="help-block with-errors">
|
<div class="help-block with-errors">
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
|
@ -35,11 +28,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="description input">
|
<div class="description input">
|
||||||
<i class="fa fa-minus-circle left" data-minus="ram" aria-hidden="true"></i>
|
<i class="fa fa-minus left" data-minus="ram" aria-hidden="true"></i>
|
||||||
<input id="ramValue" class="input-price select-number" type="number" min="2" max="200" name="ram"
|
<input id="ramValue" class="input-price select-number" type="number" min="2" max="200" name="ram"
|
||||||
data-error="{% trans 'Please enter a value in range 2 - 200.' %}" required>
|
data-error="{% trans 'Please enter a value in range 2 - 200.' %}" required>
|
||||||
<span> GB RAM</span>
|
<span> GB RAM</span>
|
||||||
<i class="fa fa-plus-circle right" data-plus="ram" aria-hidden="true"></i>
|
<i class="fa fa-plus right" data-plus="ram" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="help-block with-errors">
|
<div class="help-block with-errors">
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
|
@ -53,11 +46,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="description input">
|
<div class="description input">
|
||||||
<i class="fa fa-minus-circle left" data-minus="storage" aria-hidden="true"></i>
|
<i class="fa fa-minus left" data-minus="storage" aria-hidden="true"></i>
|
||||||
<input id="storageValue" class="input-price select-number" type="number" min="10" max="2000" step="10"
|
<input id="storageValue" class="input-price select-number" type="number" min="10" max="2000" step="10"
|
||||||
name="storage" data-error="{% trans 'Please enter a value in range 10 - 2000.' %}" required>
|
name="storage" data-error="{% trans 'Please enter a value in range 10 - 2000.' %}" required>
|
||||||
<span>{% trans "GB Storage (SSD)" %}</span>
|
<span>{% trans "GB Storage (SSD)" %}</span>
|
||||||
<i class="fa fa-plus-circle right" data-plus="storage" aria-hidden="true"></i>
|
<i class="fa fa-plus right" data-plus="storage" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="help-block with-errors">
|
<div class="help-block with-errors">
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
|
@ -69,55 +62,26 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="description select-configuration input form-group justify-center">
|
<div class="form-group">
|
||||||
<label for="config">OS</label>
|
<div class="description select-configuration input justify-center">
|
||||||
<select name="config" id="">
|
<label for="config">OS</label>
|
||||||
{% for template in templates %}
|
<select name="config" id="">
|
||||||
<option value="{{template.opennebula_vm_template_id}}">{{template.name}}</option>
|
{% for template in templates %}
|
||||||
|
<option value="{{template.opennebula_vm_template_id}}">{{template.name}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="help-block with-errors">
|
||||||
|
{% for message in messages %}
|
||||||
|
{% if 'cores' in message.tags %}
|
||||||
|
<ul class="list-unstyled"><li>
|
||||||
|
{{ message|safe }}
|
||||||
|
</li></ul>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="total">
|
<input type="hidden" name="total">
|
||||||
<!--<div class="description check-ip">
|
|
||||||
<input type="checkbox" name="ipv6"> Ipv6 Only<br>
|
|
||||||
</div>-->
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="description input justify-center">
|
|
||||||
<label for="name" class="control-label">{% trans "Name"%}</label>
|
|
||||||
<input type="text" name="name" class="form-control" placeholder="{% trans 'Your Name'%}"
|
|
||||||
data-minlength="3" data-error="{% trans 'Please enter your name.' %}" required>
|
|
||||||
</div>
|
|
||||||
<div class="help-block with-errors">
|
|
||||||
{% for message in messages %}
|
|
||||||
{% if 'name' in message.tags %}
|
|
||||||
<ul class="list-unstyled">
|
|
||||||
<li>
|
|
||||||
{{ message|safe }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="description input justify-center">
|
|
||||||
<label for="email" class="control-label">{% trans "Email"%}</label>
|
|
||||||
<input name="email" type="email" pattern="^[^@\s]+@([^@\s]+\.)+[^@\s]+$" class="form-control"
|
|
||||||
placeholder="{% trans 'Your Email' %}"
|
|
||||||
data-error="{% trans 'Please enter a valid email address.' %}" required>
|
|
||||||
</div>
|
|
||||||
<div class="help-block with-errors">
|
|
||||||
{% for message in messages %}
|
|
||||||
{% if 'email' in message.tags %}
|
|
||||||
<ul class="list-unstyled">
|
|
||||||
<li>
|
|
||||||
{{ message|safe }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="btn btn-primary disabled" value="{% trans 'Continue' %}"></input>
|
<input type="submit" class="btn btn-primary disabled" value="{% trans 'Continue' %}"></input>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,24 +2,23 @@
|
||||||
{% load staticfiles bootstrap3 i18n %}
|
{% load staticfiles bootstrap3 i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="dashboard-container">
|
<div class="dashboard-container create-vm-container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="dashboard-container-head">
|
<div class="dashboard-container-head">
|
||||||
<h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/plusVM.svg' %}" class="un-icon" style="margin-top: -18px;width: 42px;height: 42px;"> {% trans "Create VM" %}</h3>
|
<h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/plusVM.svg' %}" class="un-icon" style="margin-top: -18px;width: 42px;height: 42px;"> {% trans "Create VM" %}</h3>
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
<span>{{ message }}</span>
|
<span>{{ message }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="price-calc-section no-padding">
|
<div class="price-calc-section no-padding">
|
||||||
<div class="landing card">
|
<div class="landing card">
|
||||||
<img class="img-beta" src="{% static 'datacenterlight/img/beta-img.png' %}" alt="">
|
|
||||||
<div class="caption">
|
<div class="caption">
|
||||||
{% include "hosting/calculator_form.html" %}
|
{% include "hosting/calculator_form.html" %}
|
||||||
</div>
|
</div>
|
||||||
|
|
102
hosting/views.py
102
hosting/views.py
|
@ -1,9 +1,11 @@
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.contrib.auth.tokens import default_token_generator
|
from django.contrib.auth.tokens import default_token_generator
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.core.urlresolvers import reverse_lazy, reverse
|
from django.core.urlresolvers import reverse_lazy, reverse
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
|
@ -25,7 +27,7 @@ from stored_messages.settings import stored_messages_settings
|
||||||
from membership.models import CustomUser, StripeCustomer
|
from membership.models import CustomUser, StripeCustomer
|
||||||
from opennebula_api.models import OpenNebulaManager
|
from opennebula_api.models import OpenNebulaManager
|
||||||
from opennebula_api.serializers import VirtualMachineSerializer, \
|
from opennebula_api.serializers import VirtualMachineSerializer, \
|
||||||
VirtualMachineTemplateSerializer
|
VirtualMachineTemplateSerializer, VMTemplateSerializer
|
||||||
from utils.forms import BillingAddressForm, PasswordResetRequestForm, \
|
from utils.forms import BillingAddressForm, PasswordResetRequestForm, \
|
||||||
UserBillingAddressForm
|
UserBillingAddressForm
|
||||||
from utils.mailer import BaseEmail
|
from utils.mailer import BaseEmail
|
||||||
|
@ -36,6 +38,8 @@ from .forms import HostingUserSignupForm, HostingUserLoginForm, \
|
||||||
UserHostingKeyForm, generate_ssh_key_name
|
UserHostingKeyForm, generate_ssh_key_name
|
||||||
from .mixins import ProcessVMSelectionMixin
|
from .mixins import ProcessVMSelectionMixin
|
||||||
from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
|
from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
|
||||||
|
from datacenterlight.models import VMTemplate
|
||||||
|
|
||||||
|
|
||||||
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a backend \
|
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a backend \
|
||||||
connection error. please try again in a few minutes."
|
connection error. please try again in a few minutes."
|
||||||
|
@ -711,7 +715,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
|
||||||
request.get_host()),
|
request.get_host()),
|
||||||
'page_header': _(
|
'page_header': _(
|
||||||
'Your New VM %(vm_name)s at Data Center Light') % {
|
'Your New VM %(vm_name)s at Data Center Light') % {
|
||||||
'vm_name': vm.get('name')}
|
'vm_name': vm.get('name')}
|
||||||
}
|
}
|
||||||
email_data = {
|
email_data = {
|
||||||
'subject': context.get('page_header'),
|
'subject': context.get('page_header'),
|
||||||
|
@ -827,48 +831,80 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
||||||
template_name = "hosting/create_virtual_machine.html"
|
template_name = "hosting/create_virtual_machine.html"
|
||||||
login_url = reverse_lazy('hosting:login')
|
login_url = reverse_lazy('hosting:login')
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def validate_cores(self, value):
|
||||||
|
if (value > 48) or (value < 1):
|
||||||
|
raise ValidationError(_('Invalid number of cores'))
|
||||||
|
|
||||||
|
def validate_memory(self, value):
|
||||||
|
if (value > 200) or (value < 2):
|
||||||
|
raise ValidationError(_('Invalid RAM size'))
|
||||||
|
|
||||||
|
def validate_storage(self, value):
|
||||||
|
if (value > 2000) or (value < 10):
|
||||||
|
raise ValidationError(_('Invalid storage size'))
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
if not UserHostingKey.objects.filter(user=self.request.user).exists():
|
if not UserHostingKey.objects.filter(user=self.request.user).exists():
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
_(
|
_(
|
||||||
'In order to create a VM, you need to create/upload your SSH KEY first.')
|
'In order to create a VM, you need to'
|
||||||
|
'create/upload your SSH KEY first.'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
|
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
|
||||||
|
context = {'templates': VMTemplate.objects.all()}
|
||||||
try:
|
|
||||||
manager = OpenNebulaManager()
|
|
||||||
templates = manager.get_templates()
|
|
||||||
configuration_options = HostingPlan.get_serialized_configs()
|
|
||||||
|
|
||||||
context = {
|
|
||||||
'templates': VirtualMachineTemplateSerializer(templates,
|
|
||||||
many=True).data,
|
|
||||||
'configuration_options': configuration_options,
|
|
||||||
}
|
|
||||||
except:
|
|
||||||
messages.error(
|
|
||||||
request,
|
|
||||||
'We could not load the VM templates due to a backend connection \
|
|
||||||
error. Please try again in a few minutes'
|
|
||||||
)
|
|
||||||
context = {
|
|
||||||
'error': 'connection'
|
|
||||||
}
|
|
||||||
|
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
manager = OpenNebulaManager()
|
cores = request.POST.get('cpu')
|
||||||
template_id = request.POST.get('vm_template_id')
|
cores_field = forms.IntegerField(validators=[self.validate_cores])
|
||||||
template = manager.get_template(template_id)
|
memory = request.POST.get('ram')
|
||||||
configuration_id = int(request.POST.get('configuration'))
|
memory_field = forms.IntegerField(validators=[self.validate_memory])
|
||||||
configuration = HostingPlan.objects.get(id=configuration_id)
|
storage = request.POST.get('storage')
|
||||||
request.session['template'] = VirtualMachineTemplateSerializer(
|
storage_field = forms.IntegerField(validators=[self.validate_storage])
|
||||||
template).data
|
price = request.POST.get('total')
|
||||||
|
template_id = int(request.POST.get('config'))
|
||||||
|
template = VMTemplate.objects.filter(
|
||||||
|
opennebula_vm_template_id=template_id).first()
|
||||||
|
template_data = VMTemplateSerializer(template).data
|
||||||
|
|
||||||
request.session['specs'] = configuration.serialize()
|
try:
|
||||||
|
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')
|
||||||
|
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')
|
||||||
|
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')
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse('datacenterlight:index') + "#order_form")
|
||||||
|
|
||||||
|
specs = {
|
||||||
|
'cpu': cores,
|
||||||
|
'memory': memory,
|
||||||
|
'disk_size': storage,
|
||||||
|
'price': price
|
||||||
|
}
|
||||||
|
|
||||||
|
request.session['specs'] = specs
|
||||||
|
request.session['template'] = template_data
|
||||||
return redirect(reverse('hosting:payment'))
|
return redirect(reverse('hosting:payment'))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue