diff --git a/datacenterlight/management/commands/fetchvmtemplates.py b/datacenterlight/management/commands/fetchvmtemplates.py new file mode 100644 index 00000000..15b76fc1 --- /dev/null +++ b/datacenterlight/management/commands/fetchvmtemplates.py @@ -0,0 +1,29 @@ +from django.core.management.base import BaseCommand +from opennebula_api.models import OpenNebulaManager +from datacenterlight.models import VMTemplate +import logging + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + help = 'Fetches the VM templates from OpenNebula and populates the dcl VMTemplate model' + + def handle(self, *args, **options): + try: + manager = OpenNebulaManager() + templates = manager.get_templates() + dcl_vm_templates = [] + for template in templates: + template_name = template.name.strip('public-') + template_id = template.id + dcl_vm_template = VMTemplate.create(template_name, template_id) + dcl_vm_templates.append(dcl_vm_template) + + old_vm_templates = VMTemplate.objects.all() + old_vm_templates.delete() + + for dcl_vm_template in dcl_vm_templates: + dcl_vm_template.save() + except Exception as e: + logger.error('Error connecting to OpenNebula. Error Details: {err}'.format(err=str(e))) diff --git a/datacenterlight/models.py b/datacenterlight/models.py index 605a944c..fdfebc96 100644 --- a/datacenterlight/models.py +++ b/datacenterlight/models.py @@ -9,12 +9,13 @@ class BetaAccessVMType(models.Model): def __str__(self): return "ID: %s - SSD %s - RAM %s - CPU %s - Price %s " % \ - (self.id, str(self.ssd), self.ram, self.cpu, self.price) + (self.id, str(self.ssd), self.ram, self.cpu, self.price) class BetaAccess(models.Model): email = models.CharField(max_length=250) name = models.CharField(max_length=250) + # vm = models.ForeignKey(BetaAccessVM) def __str__(self): @@ -48,3 +49,13 @@ class BetaAccessVM(models.Model): amount=vm[VM_AMOUNT], type=vm_type)) return created_vms + + +class VMTemplate(models.Model): + name = models.CharField(max_length=50) + opennebula_vm_template_id = models.IntegerField() + + @classmethod + def create(cls, name, opennebula_vm_template_id): + vm_template = cls(name=name, opennebula_vm_template_id=opennebula_vm_template_id) + return vm_template diff --git a/datacenterlight/static/datacenterlight/css/landing-page.css b/datacenterlight/static/datacenterlight/css/landing-page.css index e02d620a..bfd9e36b 100755 --- a/datacenterlight/static/datacenterlight/css/landing-page.css +++ b/datacenterlight/static/datacenterlight/css/landing-page.css @@ -3,14 +3,12 @@ * Code licensed under the Apache License v2.0. * For details, see http://www.apache.org/licenses/LICENSE-2.0. */ -@font-face { - font-family: 'Lato-Regular'; - src: url('../fonts/Lato/Lato-Regular.ttf'); -} + @font-face { font-family: 'Lato-Light'; src: url('../fonts/Lato/Lato-Light.ttf'); } + body, html { width: 100%; @@ -27,140 +25,179 @@ h6 { font-family: 'Lato-Light', sans-serif; font-weight: 300; } + + /*blue light #5A74AF*/ + + /*blue dark #29427A*/ + .topnav { font-size: 14px; } +.menu-url { + cursor: pointer; +} + .lead { font-size: 18px; font-weight: 400; } -.btn{ + +.btn { box-shadow: 0 1px 4px rgba(0, 0, 0, .6); } + .fa-li.fa-lg { color: #29427A; margin-top: 6px; } -.btn-transparent{ + +.btn-transparent { background: transparent; border: 2px solid #fff; color: #fff; transition: all .2s ease-in; } -.btn-primary{ - background: #465882; - border-color: transparent; + +.btn-primary { + background: #29427A; + border-color: #29427A; color: #fff; width: auto; } -.btn-primary:hover{ + +.btn-primary:hover { background: rgba(41, 66, 122, 0.8); border-color: #29427A; } -.btn-transparent:hover{ + +.btn-transparent:hover { background: #fff; border: 2px solid #fff; color: #000; transition: all .2s ease-in; } + .btn-info { color: #fff; background-color: #5A74AF; border-color: #5A74AF; } + .btn-info:hover { color: #fff; background-color: rgba(90, 116, 175, 0.8); border-color: #5A74AF; } + .btn-info:focus { color: #fff; background-color: rgba(90, 116, 175, 0.8); border-color: #5A74AF; } -.btn-lg{ + +.btn-lg { min-width: 180px; } -#logoWhite{ + +#logoWhite { display: none; } -#logoBlack{ + +#logoBlack { display: block; } -.navbar{ + +.navbar { transition: all .3s ease-in; } -.navbar-default{ + +.navbar-default { background: #fff; border: none; padding: 5px; } -.navbar-transparent{ + +.navbar-transparent { background: transparent; border: none; padding: 20px; } -.navbar-transparent #logoBlack{ + +.navbar-transparent #logoBlack { display: none; } -.navbar-transparent #logoWhite{ + +.navbar-transparent #logoWhite { display: block; width: 220px; } + .navbar-default .navbar-nav>li>a { cursor: pointer; font-family: 'Lato-Light', sans-serif; } + .navbar-transparent .navbar-nav>li>a { color: #fff; cursor: pointer; font-family: 'Lato-Light', sans-serif; } + .navbar-transparent .navbar-nav>li>a:hover { color: #fff; } -.navbar-transparent .navbar-nav>li>a:focus, .navbar-transparent .navbar-nav>li>a:hover { + +.navbar-transparent .navbar-nav>li>a:focus, +.navbar-transparent .navbar-nav>li>a:hover { color: #fff; background-color: transparent; } + .navbar-default .btn-link { box-shadow: none; } + .navbar-brand { padding: 10px 15px; cursor: pointer; } + .navbar-right { margin-right: 10px; } + .navbar-default .btn-link { color: #fff; } + .navbar-default .btn-link:hover { color: #fff !important; } -.nav-language{ + +.nav-language { position: relative; } -.nav-language .select-language{ + +.nav-language .select-language { padding: 15px 10px; color: #777; } -.navbar-transparent .nav-language .select-language{ + +.navbar-transparent .nav-language .select-language { color: #fff; font-family: 'Lato-Light', sans-serif; } -.nav-language .select-language span{ +.nav-language .select-language span { margin-left: 5px; margin-right: 5px; - font-family: 'Lato-Light', sans-serif; - + font-family: 'Lato', sans-serif; } -.nav-language .drop-language{ + +.nav-language .drop-language { position: absolute; top: 45px; left: -8px; @@ -168,30 +205,35 @@ h6 { width: 100px; height: 40px; padding: 9px 10px; - -webkit-box-shadow: -8px 13px 31px -8px rgba(77,77,77,1); - -moz-box-shadow: -8px 13px 31px -8px rgba(77,77,77,1); - box-shadow: -8px 13px 31px -8px rgba(77,77,77,1); + -webkit-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); + -moz-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); + box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); display: none; z-index: 100; /* margin-left: 10px; */ text-align: center; border-radius: 4px; } -.nav-language .drop-language a{ - cursor: pointer; - font-family: 'Lato-Light', sans-serif; + +.nav-language .drop-language a { + cursor: pointer; + font-family: 'Lato', sans-serif; } -.navbar-transparent .nav-language .drop-language{ + +.navbar-transparent .nav-language .drop-language { background: transparent; border: 1px solid #fff; } -.navbar-transparent .nav-language .drop-language a{ + +.navbar-transparent .nav-language .drop-language a { color: #fff; font-family: 'Lato-Light', sans-serif; } -.nav-language:hover .drop-language{ + +.nav-language:hover .drop-language { display: block; } + .intro-header { height: 100vh; text-align: center; @@ -204,7 +246,7 @@ h6 { align-items: center; } -.intro-header::before{ +.intro-header::before { content: ""; position: absolute; top: 0; @@ -213,8 +255,10 @@ h6 { right: 0; background: rgba(38, 59, 107, 0.7); } + .intro-header-1 { - padding-top: 50px; /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ + padding-top: 50px; + /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ padding-bottom: 50px; text-align: center; color: #fff; @@ -222,7 +266,8 @@ h6 { background-size: cover; position: relative; } -.intro-header-1::before{ + +.intro-header-1::before { content: ""; position: absolute; top: 0; @@ -231,8 +276,10 @@ h6 { right: 0; background: rgba(90, 116, 175, 0.36); } + .intro-header-2 { - padding-top: 50px; /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ + padding-top: 50px; + /* If you're making other pages, make sure there is 50px of padding to make sure the navbar doesn't overlap content! */ padding-bottom: 50px; text-align: center; color: #f8f8f8; @@ -240,7 +287,8 @@ h6 { background-size: cover; position: relative; } -.intro-header-2::before{ + +.intro-header-2::before { content: ""; position: absolute; top: 0; @@ -249,19 +297,20 @@ h6 { right: 0; background: rgba(41, 66, 122, 0.59); } + .intro-message { position: relative; - width: 80%; + width: 80%; margin: 0 auto; - } + .intro-signup { position: relative; padding-top: 20%; padding-bottom: 20%; } -.intro-message > h1 { +.intro-message>h1 { margin: 0; font-weight: 400; font-size: 6em; @@ -270,15 +319,14 @@ h6 { .intro-divider { width: 400px; border-top: 1px solid #f8f8f8; - border-bottom: 1px solid rgba(0,0,0,0.2); + border-bottom: 1px solid rgba(0, 0, 0, 0.2); } -.intro-message > h3 { +.intro-message>h3 { font-weight: 300; - } -.intro-pricing{ +.intro-pricing { text-align: center; color: #fff; background: url(../img/pattern.jpg) no-repeat center center; @@ -290,11 +338,13 @@ h6 { align-items: center; position: relative; } -.intro-pricing.success-pricing{ + +.intro-pricing.success-pricing { height: 100vh; max-height: 100vh; } -.intro-pricing::before{ + +.intro-pricing::before { content: ""; position: absolute; top: 0; @@ -303,19 +353,23 @@ h6 { right: 0; background: rgba(90, 116, 175, 0.7); } -.intro-pricing .intro-message .section-heading{ + +.intro-pricing .intro-message .section-heading { font-size: 45px; width: 80%; margin: 0 auto; } + .split-section { padding: 70px 0; } -.split-section .icon-section{ + +.split-section .icon-section { position: relative; min-height: 330px; } -.split-section .icon-section i{ + +.split-section .icon-section i { position: absolute; left: 50%; top: 50%; @@ -323,7 +377,8 @@ h6 { font-size: 216px; color: #5A74AF; } -.split-section .split-text .lead{ + +.split-section .split-text .lead { font-size: 21px; color: #3a3a3a; font-weight: 300 !important; @@ -338,50 +393,58 @@ h6 { position: relative; margin-bottom: 25px; } -.split-section .split-text .split-title h2{ + +.split-section .split-text .split-title h2 { font-size: 50px; line-height: 50px; padding-bottom: 25px; color: #3a3a3a; letter-spacing: 3px; } -.split-section.left{ - background: -webkit-linear-gradient(#f0f4f7, #fff) no-repeat; - background: -o-linear-gradient(#f0f4f7, #fff) no-repeat; - background: linear-gradient(#f0f4f7, #fff) no-repeat; + +.split-section.left { + background: -webkit-linear-gradient(#f0f4f7, #fff) no-repeat; + background: -o-linear-gradient(#f0f4f7, #fff) no-repeat; + background: linear-gradient(#f0f4f7, #fff) no-repeat; } -.split-section.left .split-description{ +.split-section.left .split-description { width: 90%; margin-right: auto; } -.split-section.right .split-description{ + +.split-section.right .split-description { width: 90%; margin-left: auto; } -.split-section.right .split-description.title p{ + +.split-section.right .split-description.title p { font-size: 27px; margin-bottom: 10px; text-align: left; - } + .split-section.right .split-text { text-align: right; } -.split-section.right .split-text ul{ + +.split-section.right .split-text ul { text-align: left; } + .split-section.left .split-text { text-align: left; } -.split-section.right .split-text .split-title h2{ +.split-section.right .split-text .split-title h2 { text-align: right; } -.split-section.left .split-text .split-title h2{ + +.split-section.left .split-text .split-title h2 { text-align: left; } -.split-section.right .split-text .split-title::before{ + +.split-section.right .split-text .split-title::before { content: ""; position: absolute; bottom: 0; @@ -390,7 +453,8 @@ h6 { width: 70px; right: 0; } -.split-section.left .split-text .split-title::before{ + +.split-section.left .split-text .split-title::before { content: ""; position: absolute; bottom: 0; @@ -400,67 +464,79 @@ h6 { left: 0; } -.split-section.what .icon-section{ +.split-section.what .icon-section { position: relative; min-height: 500px; } + .split-section.what .split-text .lead { font-size: 19px; color: #3a3a3a; margin-bottom: 5px; line-height: 29px; } -.split-section.what .fa-li.fa-lg{ + +.split-section.what .fa-li.fa-lg { font-size: 17px; } -.pricing-section{ + +.pricing-section { padding: 80px 0 !important; background: -webkit-linear-gradient(top, #f0f4f7, #fff) no-repeat; background: linear-gradient(to bottom, #f0f4f7, #fff) no-repeat; } -.pricing-section .card{ +.pricing-section .card { width: 350px; margin: 0 auto; background: #fff; - box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); padding-bottom: 40px; border-radius: 7px; position: relative; } -.pricing-section .card .img-beta{ + +.pricing-section .card .img-beta { position: absolute; top: 5px; width: 60px; left: 3px; } -.pricing-section .card .title{ + +.pricing-section .card .title { padding: 15px 40px; } -.pricing-section .card .title h3{ -} -.pricing-section .card .price{ + +.pricing-section .card .title h3 {} + +.pricing-section .card .price { background: #5A74AF; padding: 22px; color: #fff; font-size: 32px; } -.pricing-section .card .description{ + +.pricing-section .card .description { padding: 12px; } -.pricing-section .card .descriptions{ + +.pricing-section .card .descriptions { padding: 10px 30px; } -.pricing-section .card .description p{ + +.pricing-section .card .description p { margin: 0; } -.pricing-section .card .btn{ + +.pricing-section .card .btn { margin-top: 20px; } -.pricing-section .text{ + +.pricing-section .text { text-align: left; } -.pricing-section .text .section-heading{ + +.pricing-section .text .section-heading { /*font-size: 50px;*/ font-size: 48px; line-height: 50px; @@ -469,7 +545,8 @@ h6 { letter-spacing: 1px; position: relative; } -.pricing-section .text .section-heading::before{ + +.pricing-section .text .section-heading::before { content: ""; position: absolute; bottom: 0; @@ -478,7 +555,8 @@ h6 { width: 70px; left: 0; } -.request-section{ + +.request-section { background-image: -ms-linear-gradient(right, #29427A 50%, #4F6699 100%); background-image: -moz-linear-gradient(right, #29427A 50%, #4F6699 100%); background-image: -o-linear-gradient(right, #29427A 50%, #4F6699 100%); @@ -487,14 +565,16 @@ h6 { background-image: linear-gradient(to left, #29427A 50%, #4F6699 100%); padding: 70px 0; } -.request-section .title h2{ + +.request-section .title h2 { font-size: 45px; margin: 0; color: #fff; padding-bottom: 25px; position: relative; } -.request-section .title h2::before{ + +.request-section .title h2::before { content: ""; position: absolute; bottom: 0; @@ -503,23 +583,27 @@ h6 { width: 70px; left: 0; } -.request-section .form-beta{ + +.request-section .form-beta { width: 80%; margin: 0 auto; max-width: 350px; text-align: center; +} +.request-section .form-beta input { + height: 50px; } -.request-section .form-beta input{ - height: 50px; + +.request-section .form-beta input { + height: 50px; } -.request-section .form-beta input{ - height: 50px; -} -.request-section .form-beta .btn-lg{ + +.request-section .form-beta .btn-lg { width: 100%; font-size: 16px; } + .banner { padding: 100px 0; color: #fff; @@ -527,7 +611,8 @@ h6 { background-size: cover; position: relative; } -.full-contact-section{ + +.full-contact-section { background-image: -ms-linear-gradient(right, #29427A 50%, #4F6699 100%); background-image: -moz-linear-gradient(right, #29427A 50%, #4F6699 100%); background-image: -o-linear-gradient(right, #29427A 50%, #4F6699 100%); @@ -542,12 +627,12 @@ h6 { background-attachment: fixed; } -.contact-section .card{ +.contact-section .card { text-align: center; width: 350px; margin: 0 auto; background: #fff; - box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); padding-bottom: 40px; border-radius: 7px; color: #4c4444; @@ -555,23 +640,28 @@ h6 { padding: 45px; margin-top: -115px; } -.contact-section .card .social a{ + +.contact-section .card .social a { color: #29427A; font-size: 45px; } -.contact-section .card .subtitle h3{ + +.contact-section .card .subtitle h3 { font-size: 30px; margin-bottom: 23px; } -.contact-section .card .social a:hover{ + +.contact-section .card .social a:hover { text-decoration: none; } + .contact-section .title { margin-right: auto; width: 80%; max-width: 468px; } -.contact-section .title h2{ + +.contact-section .title h2 { font-size: 65px; margin: 0; color: #fff; @@ -579,7 +669,8 @@ h6 { position: relative; text-align: right; } -.contact-section .title h2::before{ + +.contact-section .title h2::before { content: ""; position: absolute; bottom: 0; @@ -588,19 +679,23 @@ h6 { width: 70px; right: 0; } + + /*Why DCL*/ + .full-whydcl-sec { color: #fff; text-align: center; background-image: -ms-linear-gradient(right, #29427A 50%, #4F6699 100%); - background-image: -moz-linear-gradient(right, #29427A 50%, #4F6699 100%); - background-image: -o-linear-gradient(right, #29427A 50%, #4F6699 100%); - background-image: -webkit-gradient(linear, right top, left top, color-stop(50, #29427A), color-stop(100, #4F6699)); - background-image: -webkit-linear-gradient(right, #29427A 50%, #4F6699 100%); - background-image: linear-gradient(to left, #29427A 50%, #4F6699 100%); + background-image: -moz-linear-gradient(right, #29427A 50%, #4F6699 100%); + background-image: -o-linear-gradient(right, #29427A 50%, #4F6699 100%); + background-image: -webkit-gradient(linear, right top, left top, color-stop(50, #29427A), color-stop(100, #4F6699)); + background-image: -webkit-linear-gradient(right, #29427A 50%, #4F6699 100%); + background-image: linear-gradient(to left, #29427A 50%, #4F6699 100%); } + .whydcl-header { - padding: 150px 0 150px 0; + padding: 150px 0 150px 0; text-align: center; color: #f8f8f8; background: url(../img/pattern.jpg) no-repeat center center; @@ -608,6 +703,7 @@ h6 { position: relative; background-attachment: fixed; } + .whydcl-header::before { content: ""; position: absolute; @@ -615,27 +711,33 @@ h6 { bottom: 0; left: 0; right: 0; - background: rgba(90, 116, 175,0.85); + background: rgba(90, 116, 175, 0.85); /*background: rgba(45,70,122,0.8);*/ } + .single-heading h2 { font-size: 65px; margin: 0; - padding: 0; + padding: 0; } + #tech_stack { background: #fff; } + #tech_stack h3 { font-size: 42px; width: 70%; } + hr.thick-divider { border-top: 3px solid #eee !important; } + .space { padding: 50px 0; } + tech-sub-sec h2 { font-size: 45px; line-height: 60px; @@ -643,21 +745,26 @@ tech-sub-sec h2 { color: #3a3a3a; letter-spacing: 1px; } + .logo-wrap { text-align: center; min-height: 140px; padding: 20px 40px 30px 40px; } -.btm-space{ - padding-bottom: 8px; + +.btm-space { + padding-bottom: 8px; } -.btm-space-tayga{ - padding-bottom: 12px; + +.btm-space-tayga { + padding-bottom: 12px; } + .percent-text { font-size: 50px; color: #999; } + .tech-sub-sec h2 { font-size: 40px; line-height: 55px; @@ -673,75 +780,95 @@ tech-sub-sec h2 { .padding-vertical{ padding: 30px 9px; } + .percent-text img { - margin-left:20px; + margin-left: 20px; } + .space-block { padding: 30px 0; } + .dropdown-menu { border: 1px solid #fff; - -webkit-box-shadow: -8px 13px 31px -8px rgba(77,77,77,1); - -moz-box-shadow: -8px 13px 31px -8px rgba(77,77,77,1); - box-shadow: -8px 13px 31px -8px rgba(77,77,77,1); + -webkit-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); + -moz-box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); + box-shadow: -8px 13px 31px -8px rgba(77, 77, 77, 1); display: none; text-align: center; border-radius: 4px !important; padding: 5px !important; } -.dropdown-menu > li > a:focus, .dropdown-menu > li > a:hover { + +.dropdown-menu>li>a:focus, +.dropdown-menu>li>a:hover { background: transparent; text-decoration: underline !important; } + .logo-wrap .logo-caption { padding-top: 20px; display: inline-block; color: #999 !important; } + .lead-light { color: #999 !important; line-height: 32px !important; } + .logo-wrap-1 { padding-top: 50px; } -.dropdown-menu > li > a { + +.dropdown-menu>li>a { padding: 1px 10px !important; } -.dropdown-menu{ - left: 0 !important; - min-width: 155px; - text-align: left; - margin-left: 15px; + +.dropdown-menu { + left: 0 !important; + min-width: 155px; + text-align: left; + margin-left: 15px; } -.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:focus, .navbar-default .navbar-nav > .open > a:hover { + +.navbar-default .navbar-nav>.open>a, +.navbar-default .navbar-nav>.open>a:focus, +.navbar-default .navbar-nav>.open>a:hover { background: transparent; color: #fff; } -.dropdown-menu > li > a { + +.dropdown-menu>li>a { font-size: 13px; font-weight: 300; font-family: 'Lato-Light', sans-serif; } -.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:focus, .navbar-default .navbar-nav > .active > a:hover { + +.navbar-default .navbar-nav>.active>a, +.navbar-default .navbar-nav>.active>a:focus, +.navbar-default .navbar-nav>.active>a:hover { background: #2D457A; color: #fff; border-radius: 6px; } + /*Pricing page*/ -.price-calc-section{ +.price-calc-section { padding: 80px 40px !important; background: -webkit-linear-gradient(top, #f0f4f7, #fff) no-repeat; background: linear-gradient(to bottom, #f0f4f7, #fff) no-repeat; display: flex; - font-family: 'Lato-Regular', sans-serif; + font-family: 'Lato', sans-serif; } -.price-calc-section .text{ - width: 50%; + +.price-calc-section .text { + width: 50%; } -.price-calc-section .text .section-heading{ + +.price-calc-section .text .section-heading { font-size: 48px; line-height: 48px; padding-bottom: 27px; @@ -750,12 +877,13 @@ tech-sub-sec h2 { position: relative; text-align: right; } -.price-calc-section .text .description{ + +.price-calc-section .text .description { font-size: 20px; text-align: right; } -.price-calc-section .text .section-heading::before{ +.price-calc-section .text .section-heading::before { content: ""; position: absolute; bottom: 0; @@ -764,11 +892,12 @@ tech-sub-sec h2 { width: 70px; right: 0; } -.price-calc-section .card{ + +.price-calc-section .card { width: 50%; margin: 0 auto; background: #fff; - box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); padding-bottom: 40px; border-radius: 7px; text-align: center; @@ -776,34 +905,42 @@ tech-sub-sec h2 { max-width: 400px; position: relative; } + .price-calc-section .landing { width: 100% !important; } -.no-padding{ - padding:0 !important; + +.no-padding { + padding: 0 !important; } -.price-calc-section .card .img-beta{ + +.price-calc-section .card .img-beta { position: absolute; top: 5px; width: 60px; left: 3px; } -.price-calc-section .card .title{ + +.price-calc-section .card .title { padding: 15px 40px; } -.price-calc-section .card .title h3{ - font-family: 'Lato-Regular', sans-serif; + +.price-calc-section .card .title h3 { + font-family: 'Lato', sans-serif; } -.price-calc-section .card .price{ + +.price-calc-section .card .price { background: #5A74AF; padding: 22px; color: #fff; font-size: 32px; } -.price-calc-section .card .price .price-text{ + +.price-calc-section .card .price .price-text { font-size: 14px; } -.price-calc-section .card .description{ + +.price-calc-section .card .description { padding: 12px; position: relative; display: flex; @@ -819,35 +956,43 @@ tech-sub-sec h2 { width: 30%; text-align: left; } + .price-calc-section .card .description .select-number{ - font-size: 20px; - text-align: center; - width: 85px; + font-size: 20px; + text-align: center; + width: 85px; } -.price-calc-section .card .description i{ + +.price-calc-section .card .description i { color: #29427A; cursor: pointer; font-size: 24px; } -.price-calc-section .card .description .left{ - margin-right: 7px; + +.price-calc-section .card .description .left { + margin-right: 7px; } -.price-calc-section .card .description .right{ - margin-left: 7px; + +.price-calc-section .card .description .right { + margin-left: 7px; } -.price-calc-section .card .descriptions{ + +.price-calc-section .card .descriptions { padding: 10px 30px; } -.price-calc-section .card .description p{ + +.price-calc-section .card .description p { margin: 0; } -.price-calc-section .card .btn{ + +.price-calc-section .card .btn { margin-top: 20px; font-size: 20px; width: 200px; border: none; } -.price-calc-section .card .select-configuration select{ + +.price-calc-section .card .select-configuration select { outline: none; background: #fff; border-color: #d0d0d0; @@ -857,24 +1002,30 @@ tech-sub-sec h2 { font-size: 16px; margin-left: 10px; } -.price-calc-section .card .check-ip{ + +.price-calc-section .card .check-ip { font-size: 18px; } -.price-calc-section .card .justify-center{ + +.price-calc-section .card .justify-center { justify-content: center !important; } -.price-calc-section .card .description.input label{ + +.price-calc-section .card .description.input label { font-size: 15px; font-weight: 800; - font-family: 'Lato-Regular'; + font-family: 'Lato'; margin-bottom: 0; width: 40px; } + + /*Changed class****.price-calc-section .card .description.input input*/ -.price-calc-section .card .description input{ - width: 200px; - font-size: 14px; - text-align: left; + +.price-calc-section .card .description input { + width: 200px; + font-size: 14px; + text-align: left; padding: 5px 10px; border-radius: 4px; border: 1px solid #d0d0d0; @@ -882,22 +1033,35 @@ tech-sub-sec h2 { margin-left: 10px; } -.price-calc-section .card .check-ip input[type=checkbox]{ +.price-calc-section .card .check-ip input[type=checkbox] { font-size: 17px; margin: 0 8px; } + .help-block.with-errors { text-align: center; margin: 0; padding: 0; } -.has-error .checkbox, .has-error .checkbox-inline, .has-error .control-label, .has-error .help-block, .has-error .radio, .has-error .radio-inline, .has-error.checkbox label, .has-error.checkbox-inline label, .has-error.radio label, .has-error.radio-inline label{ -color: #eb4d5c; + +.has-error .checkbox, +.has-error .checkbox-inline, +.has-error .control-label, +.has-error .help-block, +.has-error .radio, +.has-error .radio-inline, +.has-error.checkbox label, +.has-error.checkbox-inline label, +.has-error.radio label, +.has-error.radio-inline label { + color: #eb4d5c; } + .form-group { margin: 0; border-bottom: 1px solid rgba(128, 128, 128, 0.3); } + @media(max-width:767px) { .percent-text { /* font-size: 50px; */ @@ -917,43 +1081,45 @@ color: #eb4d5c; .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 { - background: transparent; - color: #777 !important; + .navbar-default .navbar-nav>.open>a, + .navbar-default .navbar-nav>.open>a:focus, + .navbar-default .navbar-nav>.open>a:hover { + background: transparent; + color: #777 !important; + } } -} @media screen and (min-device-width: 480px) and (max-device-width: 767px) { -.logo-wrap { - width: 50%; - padding: 15px 30px !important; - min-height: 179px; -} -.logo-wrap-1 { - width: 50%; - padding: 15px 30px !important; - min-height: 179px; -} -.landscape-xs-6{ - width: 50%; -} -.landscape-xs-8{ - width: 66.66666667%; -} -.landscape-xs-4{ - width: 33.33333333%; + .logo-wrap { + width: 50%; + padding: 15px 30px !important; + min-height: 179px; + } + .logo-wrap-1 { + width: 50%; + padding: 15px 30px !important; + min-height: 179px; + } + .landscape-xs-6 { + width: 50%; + } + .landscape-xs-8 { + width: 66.66666667%; + } + .landscape-xs-4 { + width: 33.33333333%; + } } -} @media(min-width:768px) { - .visible-mobile { - display:none !important; - } - .visible-desktop { - display:block; - } - + .visible-mobile { + display: none !important; + } + .visible-desktop { + display: block; + } } + @media(max-width:990px) { .pricing-section .text { text-align: center; @@ -969,32 +1135,30 @@ color: #eb4d5c; } @media(max-width:768px) { -.percent-text { - /* font-size: 43px; */ -} - .tech-sub-sec h2 { - /* font-size: 30px; */ - /* line-height: 40px; */ - /* font-weight: 500; */ -} -.single-heading h2 { - font-size: 50px; + .percent-text { + /* font-size: 43px; */ + } + .tech-sub-sec h2 { + /* font-size: 30px; */ + /* line-height: 40px; */ + /* font-weight: 500; */ + } + .single-heading h2 { + font-size: 50px; + } + .logo-wrap { + padding: 10px; + } + .navbar-transparent li a { + color: #777 !important; } -.logo-wrap { - padding: 10px; -} -.navbar-transparent li a { - color: #777 !important; -} .intro-message { padding-bottom: 15%; } - - .intro-message > h1 { + .intro-message>h1 { font-size: 3em; } - - ul.intro-social-buttons > li { + ul.intro-social-buttons>li { display: block; margin-bottom: 20px; padding: 0; @@ -1007,11 +1171,9 @@ color: #eb4d5c; .intro-pricing .intro-message { padding-bottom: 0; } - - ul.intro-social-buttons > li:last-child { + ul.intro-social-buttons>li:last-child { margin-bottom: 0; } - .intro-divider { width: 100%; } @@ -1020,17 +1182,17 @@ color: #eb4d5c; border: none; padding: 5px; } - .navbar-transparent #logoBlack{ + .navbar-transparent #logoBlack { display: block; } - .navbar-transparent #logoWhite{ + .navbar-transparent #logoWhite { display: none; } .navbar-transparent .navbar-nav>li>a { font-size: 14px; color: #777; } - .nav-language:hover{ + .nav-language:hover { height: 80px; } .navbar-transparent .nav-language .select-language { @@ -1047,7 +1209,6 @@ color: #eb4d5c; border: 1px solid rgba(119, 119, 119, 0.4); box-shadow: none; } - .navbar-default .nav-language .drop-language { background: #fff; /* border: 1px solid #fff; */ @@ -1062,11 +1223,13 @@ color: #eb4d5c; .navbar-default .nav-language .drop-language a { color: #777; } - .navbar-transparent .navbar-nav>li>a:focus, .navbar-transparent .navbar-nav>li>a:hover { + .navbar-transparent .navbar-nav>li>a:focus, + .navbar-transparent .navbar-nav>li>a:hover { color: #333; background-color: transparent; } - .navbar-default .navbar-nav>li>a:focus, .navbar-default .navbar-nav>li>a:hover { + .navbar-default .navbar-nav>li>a:focus, + .navbar-default .navbar-nav>li>a:hover { color: #333; background-color: transparent; } @@ -1076,17 +1239,17 @@ color: #eb4d5c; .split-section .icon-section { min-height: 160px; } - .split-section.what .icon-section{ + .split-section.what .icon-section { min-height: 160px; } - .split-section .icon-section i{ + .split-section .icon-section i { font-size: 120px; } - .split-section .split-text .split-title h2{ + .split-section .split-text .split-title h2 { font-size: 35px; line-height: 35px; } - .pricing-section .text .section-heading{ + .pricing-section .text .section-heading { font-size: 35px; line-height: 35px; } @@ -1100,7 +1263,7 @@ color: #eb4d5c; text-align: center; margin-bottom: 55px; } - .request-section .title h2::before{ + .request-section .title h2::before { left: 50%; transform: translate(-50%, 0); } @@ -1108,13 +1271,13 @@ color: #eb4d5c; width: 300px; margin: 0 auto; } - .contact-section .title h2{ + .contact-section .title h2 { font-size: 35px; line-height: 40px; text-align: center; margin-top: 35px; } - .contact-section .title h2::before{ + .contact-section .title h2::before { left: 50%; transform: translate(-50%, 0); } @@ -1122,12 +1285,10 @@ color: #eb4d5c; color: #29427A; font-size: 30px; } - .intro-pricing .intro-message .section-heading { font-size: 30px; } - - .price-calc-section{ + .price-calc-section { flex-direction: column; padding: 60px 10px !important; } @@ -1141,7 +1302,7 @@ color: #eb4d5c; margin-top: 20px; } .price-calc-section .text .section-heading { - font-size: 35px; + font-size: 35px; line-height: 35px; padding-bottom: 15px; text-align: center; @@ -1154,24 +1315,21 @@ color: #eb4d5c; font-size: 18px; text-align: center; } - - .price-calc-section .card .description .select-number{ + .price-calc-section .card .description .select-number { font-size: 17px; text-align: center; - width: 65px; - margin-right: 10px; + width: 60px; } - } @media(max-width:540px) { -.logo-wrap { - padding: 30px; -} -.percent-text { - font-size: 40px; - /* text-align: center; */ -} + .logo-wrap { + padding: 30px; + } + .percent-text { + font-size: 40px; + /* text-align: center; */ + } .pricing-section .card { width: 90%; } @@ -1182,10 +1340,10 @@ color: #eb4d5c; width: 90%; padding: 25px 10px; } - .intro-message > h1 { + .intro-message>h1 { font-size: 2em; } - .price-calc-section .text .section-heading { + .price-calc-section .text .section-heading { font-size: 24px; line-height: 25px; } @@ -1194,14 +1352,13 @@ color: #eb4d5c; margin-left: 0px; } .pull-left.space-middle { - width: 67%; - padding: 20px 0px; - text-align: left; -} -.pull-left.ssdimg { - width: 30%; -} - + width: 67%; + padding: 20px 0px; + text-align: left; + } + .pull-left.ssdimg { + width: 30%; + } } .network-name { @@ -1230,9 +1387,6 @@ color: #eb4d5c; border-top: 3px solid #e7e7e7; } - - - .btn-buynow { background-color: #607D8B; border-color: #607D8B; @@ -1244,10 +1398,11 @@ color: #eb4d5c; margin-top: 15px; } } + @media(min-width:1200px) { -.container-small{ - width:980px; -} + .container-small { + width: 980px; + } } footer { @@ -1259,13 +1414,10 @@ p.copyright { margin: 15px 0 0; } - a#forgotpassword { color: #ffffff; - } - .topnav a:focus { outline: none; outline-offset: 0; @@ -1281,23 +1433,23 @@ a#forgotpassword { } .content-404 h1 { - margin: 0 0 15px; - font-size: 200px; - line-height: 1; - font-weight: 700; - color: #6db97c; - + margin: 0 0 15px; + font-size: 200px; + line-height: 1; + font-weight: 700; + color: #6db97c; } .btn-buynow { background-color: #607D8B; border-color: #607D8B; } -.form-300{ + +.form-300 { width: 300px; } -.error-message-box{ +.error-message-box { margin-top: 20px; } diff --git a/datacenterlight/static/datacenterlight/js/main.js b/datacenterlight/static/datacenterlight/js/main.js index be9f1103..44b92a0c 100644 --- a/datacenterlight/static/datacenterlight/js/main.js +++ b/datacenterlight/static/datacenterlight/js/main.js @@ -1,22 +1,22 @@ -(function($){ +(function($) { "use strict"; // Start of use strict /* --------------------------------------------- Scripts initialization --------------------------------------------- */ - var cardPricing ={ + var cardPricing = { 'cpu': { 'id': 'coreValue', 'value': 1, - 'min':1, + 'min': 1, 'max': 48, 'interval': 1 }, 'ram': { 'id': 'ramValue', 'value': 2, - 'min':2, + 'min': 2, 'max': 200, 'interval': 1 }, @@ -28,21 +28,21 @@ 'interval': 10 } }; - $(window).load(function(){ + $(window).load(function() { }); - $(document).ready(function(){ + $(document).ready(function() { verifiedUrl(); - _navScroll(); - _initScroll(); - _initNavUrl(); - _initPricing(); + _navScroll(); + _initScroll(); + _initNavUrl(); + _initPricing(); }); - $(window).resize(function(){ + $(window).resize(function() { @@ -53,102 +53,112 @@ /* --------------------------------------------- Nav panel classic --------------------------------------------- */ - if (window.matchMedia("(min-width: 767px)").matches) { - $('ul.nav li.dropdown').hover(function() { - $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(500); - }, function() { - $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut(500); - }); -} else { - /* the viewport is less than 400 pixels wide */ -} - - - - function _initScroll(){ - $(window).scroll(function(){ - _navScroll(); + if (window.matchMedia("(min-width: 767px)").matches) { + $('ul.nav li.dropdown').hover(function() { + $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(500); + }, function() { + $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut(500); }); - + } else { + /* the viewport is less than 400 pixels wide */ } - function _navScroll(){ - if($(window).scrollTop() > 10 ){ + + + function _initScroll() { + $(window).scroll(function() { + _navScroll(); + }); + } + + function _navScroll() { + if ($(window).scrollTop() > 10) { $(".navbar").removeClass("navbar-transparent"); $(".navbar-default .btn-link").css("color", "#777"); $(".dropdown-menu").removeClass("navbar-transparent"); $(".dropdown-menu > li > a").css("color", "#777"); - }else{ + } else { $(".navbar").addClass("navbar-transparent"); $(".navbar-default .btn-link").css("color", "#fff"); $(".dropdown-menu").addClass("navbar-transparent"); $(".dropdown-menu > li > a").css("color", "#fff"); } } - function _initNavUrl(){ - $('.url').click(function(){ - var href = $(this).attr('data-url'); - $('.navbar-collapse').removeClass('in'); - $('.navbar-collapse').addClass('collapsing'); - $('html, body').animate({ - scrollTop: $(href).offset().top - }, 1000); + + function _initNavUrl() { + $('.url').click(function(event) { + event.preventDefault(); + var href = $(this).attr('data-url'); + $('.navbar-collapse').removeClass('in'); + $('.navbar-collapse').addClass('collapsing'); + var url = window.location.pathname; + var urlSplit = url.split('/'); + if (urlSplit.length === 3 && urlSplit[2] === 'datacenterlight') { + $('html, body').animate({ + scrollTop: $(href).offset().top + }, 1000); + } else { + var allUrl = window.location.href; + var redirect = allUrl.split('whydatacenterlight') + window.location.href = '/en-us/datacenterlight' + href; + } }); } - function verifiedUrl(){ - if(window.location.href.indexOf('#success') > -1){ + + function verifiedUrl() { + if (window.location.href.indexOf('#success') > -1) { form_success(); - console.log('epa'); } } - function _initPricing(){ + function _initPricing() { _fetchPricing(); - $('.fa-minus-circle.left').click(function(event){ + $('.fa-minus-circle.left').click(function(event) { var data = $(this).data('minus'); - if(cardPricing[data].value > cardPricing[data].min){ + if (cardPricing[data].value > cardPricing[data].min) { cardPricing[data].value = Number(cardPricing[data].value) - cardPricing[data].interval; } _fetchPricing(); }); - $('.fa-plus-circle.right').click(function(event){ + $('.fa-plus-circle.right').click(function(event) { var data = $(this).data('plus'); - if(cardPricing[data].value < cardPricing[data].max){ + if (cardPricing[data].value < cardPricing[data].max) { cardPricing[data].value = Number(cardPricing[data].value) + cardPricing[data].interval; } _fetchPricing(); }); - $('.input-price').change(function(){ + $('.input-price').change(function() { var data = $(this).attr("name"); - cardPricing[data].value = $('input[name='+data+']').val(); + cardPricing[data].value = $('input[name=' + data + ']').val(); _fetchPricing(); }); } - function _fetchPricing(){ - Object.keys(cardPricing).map(function(element){ + + function _fetchPricing() { + Object.keys(cardPricing).map(function(element) { //$('#'+cardPricing[element].id).val(cardPricing[element].value); - $('input[name='+element+']').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); + 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); } - function form_success(){ + + function form_success() { $('#sucessModal').modal('show'); } - function _calculate(numbers, price){ - $('#valueTotal').text(numbers*price*31); + + function _calculate(numbers, price) { + $('#valueTotal').text(numbers * price * 31); } - - })(jQuery); diff --git a/datacenterlight/templates/datacenterlight/calculator_form.html b/datacenterlight/templates/datacenterlight/calculator_form.html index de97f295..cdba4809 100644 --- a/datacenterlight/templates/datacenterlight/calculator_form.html +++ b/datacenterlight/templates/datacenterlight/calculator_form.html @@ -2,7 +2,7 @@ <form id="order_form" method="POST" action="" data-toggle="validator" role="form"> {% csrf_token %} <div class="title"> - <h3>{% trans "VM hosting" %} </h3> + <h3>{% trans "VM hosting" %} </h3> </div> <div class="price"> <span id="total">15</span> @@ -17,36 +17,63 @@ </div> <div class="form-group"> <div class="description input"> - <i class="fa fa-minus-circle left" data-minus="cpu" aria-hidden="true"></i> - <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> - <span> Core</span> - <i class="fa fa-plus-circle right" data-plus="cpu" aria-hidden="true"></i> + <i class="fa fa-minus-circle left" data-minus="cpu" aria-hidden="true"></i> + <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> + <span> Core</span> + <i class="fa fa-plus-circle right" data-plus="cpu" aria-hidden="true"></i> + </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 %} </div> - <div class="help-block with-errors"></div> </div> <div class="form-group"> <div class="description input"> - <i class="fa fa-minus-circle left" data-minus="ram" aria-hidden="true"></i> - <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> - <span> GB RAM</span> - <i class="fa fa-plus-circle right" data-plus="ram" aria-hidden="true"></i> + <i class="fa fa-minus-circle left" data-minus="ram" aria-hidden="true"></i> + <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> + <span> GB RAM</span> + <i class="fa fa-plus-circle right" data-plus="ram" aria-hidden="true"></i> + </div> + <div class="help-block with-errors"> + {% for message in messages %} + {% if 'memory' in message.tags %} + <ul class="list-unstyled"><li> + {{ message|safe }} + </li></ul> + {% endif %} + {% endfor %} </div> - <div class="help-block with-errors"></div> </div> <div class="form-group"> <div class="description input"> - <i class="fa fa-minus-circle left" data-minus="storage" aria-hidden="true"></i> - <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> - <span>{% trans "GB Storage (SSD)" %}</span> - <i class="fa fa-plus-circle right" data-plus="storage" aria-hidden="true"></i> + <i class="fa fa-minus-circle left" data-minus="storage" aria-hidden="true"></i> + <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> + <span>{% trans "GB Storage (SSD)" %}</span> + <i class="fa fa-plus-circle right" data-plus="storage" aria-hidden="true"></i> + </div> + <div class="help-block with-errors"> + {% for message in messages %} + {% if 'storage' in message.tags %} + <ul class="list-unstyled"><li> + {{ message|safe }} + </li></ul> + {% endif %} + {% endfor %} </div> - <div class="help-block with-errors"></div> </div> <div class="description select-configuration input form-group justify-center"> <label for="config">OS</label> <select name="config" id=""> {% for template in templates %} - <option value="{{template.id}}">{{template.name}} </option> + <option value="{{template.opennebula_vm_template_id}}">{{template.name}}</option> {% endfor %} </select> </div> @@ -56,31 +83,38 @@ </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> + <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> + {% if 'name' in message.tags %} + <ul class="list-unstyled"> + <li> {{ message|safe }} - </li></ul> - {% endif %} + </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> + <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> + {% if 'email' in message.tags %} + <ul class="list-unstyled"> + <li> {{ message|safe }} - </li></ul> - {% endif %} + </li> + </ul> + {% endif %} {% endfor %} </div> </div> diff --git a/datacenterlight/templates/datacenterlight/includes/_navbar.html b/datacenterlight/templates/datacenterlight/includes/_navbar.html index b5cfacfe..84358b4d 100644 --- a/datacenterlight/templates/datacenterlight/includes/_navbar.html +++ b/datacenterlight/templates/datacenterlight/includes/_navbar.html @@ -12,28 +12,28 @@ <span class="icon-bar"></span> </button> {% if request.resolver_match.url_name == "index" or request.resolver_match.url_name == "whydatacenterlight" %} - <a href="{% url 'datacenterlight:index' %}" id="logoBlack" class="navbar-brand topnav url" data-url="#home"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a> - <a href="{% url 'datacenterlight:index' %}" id="logoWhite" class="navbar-brand topnav url" data-url="#home"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a> + <a href="{% url 'datacenterlight:index' %}" id="logoBlack" class="navbar-brand topnav" data-url="#home"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a> + <a href="{% url 'datacenterlight:index' %}" id="logoWhite" class="navbar-brand topnav" data-url="#home"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a> {% else %} - <a href="{% url 'datacenterlight:index' %}" id="logoBlack" class="navbar-brand topnav url"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a> - <a href="{% url 'datacenterlight:index' %}" id="logoWhite" class="navbar-brand topnav url"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a> + <a href="{% url 'datacenterlight:index' %}" id="logoBlack" class="navbar-brand topnav"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a> + <a href="{% url 'datacenterlight:index' %}" id="logoWhite" class="navbar-brand topnav"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a> {% endif %} - + </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><!-- Start Navbar collapse--> <ul class="nav navbar-nav navbar-right"> {% if request.resolver_match.url_name == "index" or request.resolver_match.url_name == "whydatacenterlight" %} <li class="dropdown"> <a class="dropdown-toggle visible-mobile" href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Highlights" %}<span class="caret"></span></a> - <a class="dropdown-toggle url disabled visible-desktop" href="{% url 'datacenterlight:index' %}#how" data-url="#how" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Highlights" %}<span class="caret"></span></a> + <a class="dropdown-toggle url disabled visible-desktop menu-url" data-url="#how" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Highlights" %}<span class="caret"></span></a> <ul class="dropdown-menu"> - <li><a class="url" href="{% url 'datacenterlight:index' %}#your" data-url="#your" >{% trans "Scale out" %}</a></li> - <li><a class="url" href="{% url 'datacenterlight:index' %}#our" data-url="#our">{% trans "Reliable and light" %}</a></li> - <li> <a class="url" href="{% url 'datacenterlight:index' %}#price" data-url="#price" >{% trans "Order VM" %}</a></li> - </ul> + <li><a class="url menu-url" data-url="#your" href="#your">{% trans "Scale out" %}</a></li> + <li><a class="url menu-url" data-url="#our" href="#our">{% trans "Reliable and light" %}</a></li> + <li> <a class="url menu-url" data-url="#price" href="#price">{% trans "Order VM" %}</a></li> + </ul> </li> <li> - <a class="url" href="{% url 'datacenterlight:index' %}/whydatacenterlight" >{% trans "Why Data Center Light?" %}</a> + <a href="{% url 'datacenterlight:index' %}/whydatacenterlight" >{% trans "Why Data Center Light?" %}</a> </li> <li> <a class="url" href="{% url 'datacenterlight:index' %}#contact" data-url="#contact" >{% trans "Contact" %}</a> @@ -41,18 +41,19 @@ {% endif %} <li class="nav-language"> <div class="select-language"> - {% if LANGUAGE_CODE == 'en-us'%} + {% if LANGUAGE_CODE == 'en-us'%} <span>English</span> {% else %} <span>Deutsch</span> {% endif %} <i class="fa fa-globe" aria-hidden="true"></i> </div> - <div onclick="return true" class="drop-language"> - {% if LANGUAGE_CODE == 'en-us'%} - <a class="url" href="{% change_lang 'de' %}">Deutsch</a> + + <div class="drop-language"> + {% if LANGUAGE_CODE == 'en-us'%} + <a href="{% change_lang 'de' %}">Deutsch</a> {% else %} - <a class="url" href="{% change_lang 'en-us' %}" >English</a> + <a href="{% change_lang 'en-us' %}" >English</a> {% endif %} </div> diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 6b0e0d7e..10e2d791 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -1,7 +1,7 @@ from django.views.generic import FormView, CreateView, TemplateView, DetailView from django.http import HttpResponseRedirect from .forms import BetaAccessForm -from .models import BetaAccess, BetaAccessVMType, BetaAccessVM +from .models import BetaAccess, BetaAccessVMType, BetaAccessVM, VMTemplate from django.contrib import messages from django.core.urlresolvers import reverse from django.core.mail import EmailMessage @@ -21,7 +21,7 @@ from datetime import datetime from membership.models import CustomUser, StripeCustomer from opennebula_api.models import OpenNebulaManager -from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer +from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer class LandingProgramView(TemplateView): @@ -194,41 +194,68 @@ class IndexView(CreateView): success_url = "/datacenterlight#requestform" success_message = "Thank you, we will contact you as soon as possible" + def validate_cores(self, value): + if (value > 48) or (value < 1): + raise ValidationError(_('Not a proper cores number')) + + def validate_memory(self, value): + if (value > 200) or (value < 2): + raise ValidationError(_('Not a proper ram number')) + + def validate_storage(self, value): + if (value > 2000) or (value < 10): + raise ValidationError(_('Not a proper storage number')) + @cache_control(no_cache=True, must_revalidate=True, no_store=True) def get(self, request, *args, **kwargs): for session_var in ['specs', 'user', 'billing_address_data']: if session_var in request.session: del request.session[session_var] - try: - manager = OpenNebulaManager() - templates = manager.get_templates() - context = { - 'templates': VirtualMachineTemplateSerializer(templates, many=True).data - } - except: - messages.error(request, - 'We have a temporary problem to connect to our backend. \ - Please try again in a few minutes' - ) - context = { - 'error': 'connection' - } + + vm_templates = VMTemplate.objects.all() + context = { + 'templates': vm_templates + } return render(request, self.template_name, context) def post(self, request): cores = request.POST.get('cpu') + cores_field = forms.IntegerField(validators=[self.validate_cores]) memory = request.POST.get('ram') + memory_field = forms.IntegerField(validators=[self.validate_memory]) storage = request.POST.get('storage') + storage_field = forms.IntegerField(validators=[self.validate_storage]) price = request.POST.get('total') template_id = int(request.POST.get('config')) - manager = OpenNebulaManager() - template = manager.get_template(template_id) - template_data = VirtualMachineTemplateSerializer(template).data + template = VMTemplate.objects.filter(opennebula_vm_template_id=template_id).first() + template_data = VMTemplateSerializer(template).data name = request.POST.get('name') email = request.POST.get('email') name_field = forms.CharField() email_field = forms.EmailField() + + 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") + try: name = name_field.clean(name) except ValidationError as err: @@ -313,25 +340,6 @@ class WhyDataCenterLightView(IndexView): template_name = "datacenterlight/whydatacenterlight.html" model = BetaAccess - @cache_control(no_cache=True, must_revalidate=True, no_store=True) - def get(self, request, *args, **kwargs): - try: - manager = OpenNebulaManager() - templates = manager.get_templates() - context = { - 'templates': VirtualMachineTemplateSerializer(templates, many=True).data, - } - except: - messages.error( - request, - 'We have a temporary problem to connect to our backend. \ - Please try again in a few minutes' - ) - context = { - 'error': 'connection' - } - return render(request, self.template_name, context) - class PaymentOrderView(FormView): template_name = 'hosting/payment.html' @@ -462,9 +470,9 @@ class OrderConfirmationView(DetailView): template_id=vm_template_id, specs=specs, vm_name="{email}-{template_name}-{date}".format( - email=user.get('email'), - template_name=template.get('name'), - date=int(datetime.now().strftime("%s"))) + email=user.get('email'), + template_name=template.get('name'), + date=int(datetime.now().strftime("%s"))) ) # Create a Hosting Order diff --git a/hosting/static/hosting/css/landing-page.css b/hosting/static/hosting/css/landing-page.css index b1972eed..63a2f54a 100644 --- a/hosting/static/hosting/css/landing-page.css +++ b/hosting/static/hosting/css/landing-page.css @@ -39,6 +39,30 @@ h6 { font-size: 14px; } +.navbar-transparent { + background: transparent; + border: none; + padding: 20px; +} + +.navbar-transparent .navbar-nav>li>a { + color: #fff; + cursor: pointer; + font-family: 'Lato-Regular', sans-serif; +} +.navbar-transparent .navbar-nav>li>a:hover { + color: #fff; +} +.navbar-transparent .navbar-nav>li>a:focus, .navbar-transparent .navbar-nav>li>a:hover { + color: #fff; + background-color: transparent; +} + +.navbar-transparent #logoWhite{ + display: block; + width: 220px; +} + .lead { font-size: 18px; font-weight: 400; @@ -634,11 +658,11 @@ a.unlink:hover { .card-cvc-element { padding-left: 10px; } - + .hide-mobile{ display:none; } - + #billing-form .form-control { box-shadow: none !important; font-weight: 400; diff --git a/hosting/templates/hosting/base_short.html b/hosting/templates/hosting/base_short.html index 6a08b97b..21aa93db 100644 --- a/hosting/templates/hosting/base_short.html +++ b/hosting/templates/hosting/base_short.html @@ -48,24 +48,26 @@ <body> - <!-- Navigation --> - - <nav class="navbar navbar-default navbar-fixed-top topnav" role="navigation"> - <div class="container topnav"> - <!-- Brand and toggle get grouped for better mobile display --> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> - <span class="sr-only">Toggle navigation</span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a class="navbar-brand topnav" href="{% if site_url %}{{site_url}}{% else %}{{ request.session.hosting_url}}{% endif %}"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a> - </div> - {% if request.user.is_authenticated %} - <!-- Collect the nav links, forms, and other content for toggling --> - <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> - <ul class="nav navbar-nav navbar-right"> + {% block navbar %} + + <!-- Navigation --> + + <nav class="navbar navbar-default navbar-fixed-top topnav" role="navigation"> + <div class="container topnav"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand topnav" href="{% if site_url %}{{site_url}}{% else %}{{ request.session.hosting_url}}{% endif %}"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a> + </div> + {% if request.user.is_authenticated %} + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> + <ul class="nav navbar-nav navbar-right"> <li> <a href="{% url 'hosting:virtual_machines' %}"> <i class="fa fa-server" aria-hidden="true"></i> {% trans "My Virtual Machines"%} @@ -93,33 +95,14 @@ <li><a href="{% url 'hosting:logout' %}"><i class="glyphicon glyphicon-lock"></i>{% trans "Logout"%} </a></li> </ul> </li> - <!-- - <li> - <a href="{{ request.session.hosting_url}}#how">{% trans "How it works"%}</a> - </li> - <li> - <a href="{{ request.session.hosting_url }}#your">{% trans "Your infrastructure"%}</a> - </li> - <li> - <a href="{{ request.session.hosting_url }}#our">{% trans "Our inftrastructure"%}</a> - </li> - <li> - <a href="{{ request.session.hosting_url }}#price">{% trans "Pricing" %}</a> - </li> - <li> - <a href="{{ request.session.hosting_url }}#contact">{% trans "Contact"%}</a> - </li> - <li> - <a href="{% url 'hosting:login' %}?next={{request.current_path}}">{% trans "Login"%}</a> - </li> --> - </ul> + </ul> + </div> + {% endif %} + <!-- /.navbar-collapse --> </div> - {% endif %} - <!-- /.navbar-collapse --> - </div> - <!-- /.container --> - </nav> - + <!-- /.container --> + </nav> + {% endblock navbar %} <div class="content-dashboard"> diff --git a/hosting/templates/hosting/includes/_navbar_transparent.html b/hosting/templates/hosting/includes/_navbar_transparent.html new file mode 100644 index 00000000..31bbe6bf --- /dev/null +++ b/hosting/templates/hosting/includes/_navbar_transparent.html @@ -0,0 +1,11 @@ +{% load static i18n %} + +<nav class="navbar navbar-default navbar-fixed-top topnav navbar-transparent" role="navigation"> + <div class="container topnav"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <a id="logoWhite" class="navbar-brand topnav" href="{% if site_url %}{{site_url}}{% else %}{{ request.session.hosting_url}}{% endif %}"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a> + </div> + </div> + <!-- /.container --> +</nav> \ No newline at end of file diff --git a/hosting/templates/hosting/login.html b/hosting/templates/hosting/login.html index 3ae7b7c2..12c9eba6 100644 --- a/hosting/templates/hosting/login.html +++ b/hosting/templates/hosting/login.html @@ -1,18 +1,23 @@ {% extends "hosting/base_short.html" %} {% load i18n %} {% load staticfiles bootstrap3%} + +{% block navbar %} + {% include 'hosting/includes/_navbar_transparent.html' %} +{% endblock navbar %} + {% block content %} <div class="auth-container"> <div class="auth-bg"></div> <div class="auth-center"> - + <div class="auth-title"> <h2>{% trans "Your VM hosted in Switzerland"%}</h2> </div> <div class="auth-content"> - + <div class="intro-message auth-box"> <h2 class="section-heading">{% trans "Login"%}</h2> <form action="{% url 'hosting:login' %}" method="post" class="form" novalidated> @@ -26,8 +31,8 @@ {% trans "Login"%} </button> {% endbuttons %} - - <input type='hidden' name='next' value='{{request.GET.next}}'/> + + <input type='hidden' name='next' value='{{request.GET.next}}'/> </form> <div class="auth-footer"> <div class="text"> diff --git a/hosting/templates/hosting/reset_password.html b/hosting/templates/hosting/reset_password.html index be9fb82b..b24546c5 100644 --- a/hosting/templates/hosting/reset_password.html +++ b/hosting/templates/hosting/reset_password.html @@ -2,6 +2,11 @@ {% load staticfiles bootstrap3%} {% load i18n %} +{% block navbar %} + {% include 'hosting/includes/_navbar_transparent.html' %} +{% endblock navbar %} + + {% block content %} <div class="auth-container"> <div class="auth-bg"></div> @@ -10,7 +15,7 @@ <h2>{% trans "Your VM hosted in Switzerland"%}</h2> </div> <div class="auth-content"> - + <div class="intro-message auth-box sign-up"> <h2 class="section-heading">{% trans "Reset your password"%}</h2> <form action="{% url 'hosting:reset_password' %}" method="post" class="form" novalidate> diff --git a/hosting/templates/hosting/signup.html b/hosting/templates/hosting/signup.html index 959cf346..5d97a3b6 100644 --- a/hosting/templates/hosting/signup.html +++ b/hosting/templates/hosting/signup.html @@ -1,6 +1,10 @@ {% extends "hosting/base_short.html" %} {% load staticfiles bootstrap3 i18n %} +{% block navbar %} + {% include 'hosting/includes/_navbar_transparent.html' %} +{% endblock navbar %} + {% block content %} <div class="auth-container auth-signup"> <div class="auth-bg"></div> @@ -32,7 +36,7 @@ </div> </div> </div> - + </div> </div> {% endblock %} diff --git a/opennebula_api/models.py b/opennebula_api/models.py index 383062f1..60f3159c 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -59,7 +59,7 @@ class OpenNebulaManager(): domain=settings.OPENNEBULA_DOMAIN, port=settings.OPENNEBULA_PORT, endpoint=settings.OPENNEBULA_ENDPOINT - )) + )) def _get_opennebula_client(self, username, password): return oca.Client("{0}:{1}".format( @@ -71,7 +71,7 @@ class OpenNebulaManager(): domain=settings.OPENNEBULA_DOMAIN, port=settings.OPENNEBULA_PORT, endpoint=settings.OPENNEBULA_ENDPOINT - )) + )) def _get_user(self, user): """Get the corresponding opennebula user for a CustomUser object @@ -325,7 +325,7 @@ class OpenNebulaManager(): public_templates = [ template for template in self._get_template_pool() - if 'public-' in template.name + if template.name.startswith('public-') ] return public_templates except ConnectionRefusedError: @@ -396,7 +396,7 @@ class OpenNebulaManager(): def delete_template(self, template_id): self.oneadmin_client.call(oca.VmTemplate.METHODS[ - 'delete'], template_id, False) + 'delete'], template_id, False) def change_user_password(self, new_password): self.oneadmin_client.call( diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 16ab1e76..12b313af 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -129,6 +129,12 @@ class VirtualMachineSerializer(serializers.Serializer): return obj.name.strip('public-') +class VMTemplateSerializer(serializers.Serializer): + """Serializer to map the VMTemplate instance into JSON format.""" + id = serializers.IntegerField(read_only=True, source='opennebula_vm_template_id') + name = serializers.CharField(read_only=True) + + def hexstr2int(string): return int(string.replace(':', ''), 16)