merged master
This commit is contained in:
		
				commit
				
					
						050f750322
					
				
			
		
					 34 changed files with 1918 additions and 551 deletions
				
			
		
							
								
								
									
										13
									
								
								Changelog
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								Changelog
									
										
									
									
									
								
							| 
						 | 
					@ -1,3 +1,16 @@
 | 
				
			||||||
 | 
					1.2.3: 2017-09-25
 | 
				
			||||||
 | 
					    * #3484: [dcl, hosting] Refactored account activation, password reset, VM order and cancellation email
 | 
				
			||||||
 | 
					    * #3731: [dcl, hosting] Added cdist ssh key handler 
 | 
				
			||||||
 | 
					    * #3628: [dcl] on hosting, VM is created at credit card info submit
 | 
				
			||||||
 | 
					    * #3772: [dcl] Updated hosting app billing into monthly subscription and added new text and translations
 | 
				
			||||||
 | 
					    * #3786: [hosting] Redesigned the hosting invoice and order-confirmation page
 | 
				
			||||||
 | 
					    * #3728: [hosting] VM Termination animation added
 | 
				
			||||||
 | 
					    * #3777: [hosting] Create new VM calculator added like dcl landing
 | 
				
			||||||
 | 
					    * #3781: [hosting] Resend activation mail
 | 
				
			||||||
 | 
					    * #3806: [hosting] Fix can not create VMs after password reset
 | 
				
			||||||
 | 
					    * Feature: [cms, blog] Added /cms prefix for all the django-cms generated urls
 | 
				
			||||||
 | 
					    * Bugfix: [dcl, hosting] added host to celery error mails
 | 
				
			||||||
 | 
					    * Bugfix: [ungleich] Fixed wrong subdomain digitalglarus.ungleich.ch
 | 
				
			||||||
1.2.2: 2017-09-08
 | 
					1.2.2: 2017-09-08
 | 
				
			||||||
    * #3704: [hosting] Added my settings page
 | 
					    * #3704: [hosting] Added my settings page
 | 
				
			||||||
    * #3771: [datacenterlight] Fixed the inconsistency in navbar style in billing page and onward
 | 
					    * #3771: [datacenterlight] Fixed the inconsistency in navbar style in billing page and onward
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -194,13 +194,13 @@ msgid "All Rights Reserved"
 | 
				
			||||||
msgstr "Alle Rechte vorbehalten"
 | 
					msgstr "Alle Rechte vorbehalten"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Toggle navigation"
 | 
					msgid "Toggle navigation"
 | 
				
			||||||
msgstr "Konfiguration"
 | 
					msgstr "Umschalten"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Why Data Center Light?"
 | 
					msgid "Why Data Center Light?"
 | 
				
			||||||
msgstr "Warum Data Center Light?"
 | 
					msgstr "Warum Data Center Light?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Login"
 | 
					msgid "Login"
 | 
				
			||||||
msgstr ""
 | 
					msgstr "Anmelden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Dashboard"
 | 
					msgid "Dashboard"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function _fetchPricing() {
 | 
					    function _fetchPricing() {
 | 
				
			||||||
        Object.keys(cardPricing).map(function(element) {
 | 
					        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();
 | 
					        _calcPricing();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,9 +49,14 @@ urlpatterns += i18n_patterns(
 | 
				
			||||||
        include('ungleich_page.urls',
 | 
					        include('ungleich_page.urls',
 | 
				
			||||||
                namespace='ungleich_page'),
 | 
					                namespace='ungleich_page'),
 | 
				
			||||||
        name='ungleich_page'),
 | 
					        name='ungleich_page'),
 | 
				
			||||||
    url(r'^blog/', include('ungleich.urls',
 | 
					    url(r'^cms/blog/',
 | 
				
			||||||
                           namespace='ungleich')),
 | 
					        include('ungleich.urls', namespace='ungleich')),
 | 
				
			||||||
    url(r'^', include('cms.urls'))
 | 
					    url(
 | 
				
			||||||
 | 
					        r'^blog/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>\w[-\w]*)/$',
 | 
				
			||||||
 | 
					        RedirectView.as_view(pattern_name='ungleich:post-detail')),
 | 
				
			||||||
 | 
					    url(r'^blog/|cms/$', RedirectView.as_view(
 | 
				
			||||||
 | 
					        url=reverse_lazy('ungleich:post-list')), name='blog_list_view'),
 | 
				
			||||||
 | 
					    url(r'^cms/', include('cms.urls')),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns += [
 | 
					urlpatterns += [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ msgid ""
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
"Project-Id-Version: PACKAGE VERSION\n"
 | 
					"Project-Id-Version: PACKAGE VERSION\n"
 | 
				
			||||||
"Report-Msgid-Bugs-To: \n"
 | 
					"Report-Msgid-Bugs-To: \n"
 | 
				
			||||||
"POT-Creation-Date: 2017-09-23 02:19+0530\n"
 | 
					"POT-Creation-Date: 2017-09-24 12:34+0000\n"
 | 
				
			||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
					"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
				
			||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
					"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
				
			||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
					"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
				
			||||||
| 
						 | 
					@ -28,10 +28,10 @@ msgid "User does not exist"
 | 
				
			||||||
msgstr "Der Benutzer existiert nicht"
 | 
					msgstr "Der Benutzer existiert nicht"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Paste here your public key"
 | 
					msgid "Paste here your public key"
 | 
				
			||||||
msgstr "Füge deinen Public Key ein"
 | 
					msgstr "Füge Deinen Public Key ein"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Give a name to your key"
 | 
					msgid "Give a name to your key"
 | 
				
			||||||
msgstr "Gebe deinem SSH-Key einen Name"
 | 
					msgstr "Gebe Deinem SSH-Key einen Name"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Key name"
 | 
					msgid "Key name"
 | 
				
			||||||
msgstr "Key-Name"
 | 
					msgstr "Key-Name"
 | 
				
			||||||
| 
						 | 
					@ -110,6 +110,27 @@ msgstr "vorherige"
 | 
				
			||||||
msgid "next"
 | 
					msgid "next"
 | 
				
			||||||
msgstr "nächste"
 | 
					msgstr "nächste"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Month"
 | 
				
			||||||
 | 
					msgstr "Monat"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "VAT included"
 | 
				
			||||||
 | 
					msgstr "MwSt. inklusive"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Please enter a value in range 1 - 48."
 | 
				
			||||||
 | 
					msgstr "Bitte gib einen Wert von 1 bis 48 ein."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Please enter a value in range 2 - 200."
 | 
				
			||||||
 | 
					msgstr "Bitte gib einen Wert von 2 bis 200 ein."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Please enter a value in range 10 - 2000."
 | 
				
			||||||
 | 
					msgstr "Bitte gib einen Wert von 10 bis 200 ein."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "GB Storage (SSD)"
 | 
				
			||||||
 | 
					msgstr "GB Storage (SSD)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Continue"
 | 
				
			||||||
 | 
					msgstr "Weiter"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "SSH Key"
 | 
					msgid "SSH Key"
 | 
				
			||||||
msgstr "SSH Key"
 | 
					msgstr "SSH Key"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,10 +156,10 @@ msgid "Upload"
 | 
				
			||||||
msgstr "Hochladen"
 | 
					msgstr "Hochladen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Your VM hosted in Switzerland"
 | 
					msgid "Your VM hosted in Switzerland"
 | 
				
			||||||
msgstr "deine VM in der Schweiz"
 | 
					msgstr "Deine VM in der Schweiz"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Set your new password"
 | 
					msgid "Set your new password"
 | 
				
			||||||
msgstr "Setze dein neues Passwort"
 | 
					msgstr "Setze Dein neues Passwort"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Reset"
 | 
					msgid "Reset"
 | 
				
			||||||
msgstr "Zurücksetzen"
 | 
					msgstr "Zurücksetzen"
 | 
				
			||||||
| 
						 | 
					@ -149,35 +170,17 @@ msgstr "Hast Du bereits ein Benutzerkonto?"
 | 
				
			||||||
msgid "Login"
 | 
					msgid "Login"
 | 
				
			||||||
msgstr "Anmelden"
 | 
					msgstr "Anmelden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "New Virtual Machine"
 | 
					msgid "Create VM"
 | 
				
			||||||
msgstr "Neue virtuelle Maschine"
 | 
					msgstr "VM erstellen"
 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "Step 1. Select VM Template:"
 | 
					 | 
				
			||||||
msgstr "Wähle eine Vorlage"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "Step2. Select VM Configuration"
 | 
					 | 
				
			||||||
msgstr "Wähle eine Konfiguration"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "Price "
 | 
					 | 
				
			||||||
msgstr "Preis"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "CHF/Month"
 | 
					 | 
				
			||||||
msgstr "CHF/Monat"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "Start VM"
 | 
					 | 
				
			||||||
msgstr "VM jetzt starten"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "My Dashboard"
 | 
					msgid "My Dashboard"
 | 
				
			||||||
msgstr "Mein Dashboard"
 | 
					msgstr "Mein Dashboard"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Create VM"
 | 
					 | 
				
			||||||
msgstr "VM erstellen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "My VMs"
 | 
					msgid "My VMs"
 | 
				
			||||||
msgstr "Meine VMs"
 | 
					msgstr "Meine VMs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "My SSH Keys"
 | 
					msgid "My SSH Keys"
 | 
				
			||||||
msgstr "Meine SSH Keys"
 | 
					msgstr "Meine SSH-Keys"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "My Bills"
 | 
					msgid "My Bills"
 | 
				
			||||||
msgstr "Meine Rechnungen"
 | 
					msgstr "Meine Rechnungen"
 | 
				
			||||||
| 
						 | 
					@ -229,6 +232,40 @@ msgstr "Dankeschön!"
 | 
				
			||||||
msgid "Virtual Machine Cancellation"
 | 
					msgid "Virtual Machine Cancellation"
 | 
				
			||||||
msgstr "VM Kündigung"
 | 
					msgstr "VM Kündigung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, python-format
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"You're receiving this email because you requested a password reset for your "
 | 
				
			||||||
 | 
					"user account at %(site_name)s.<br/>\n"
 | 
				
			||||||
 | 
					"Please go to the following page and choose a new password: %(base_url)s"
 | 
				
			||||||
 | 
					"%(password_reset_url)s<br/>\n"
 | 
				
			||||||
 | 
					"If you didn't request a new password, ignore this e-mail.<br/>\n"
 | 
				
			||||||
 | 
					"Thank you!\n"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"\n"
 | 
				
			||||||
 | 
					"Du erhälst diese E-Mail da Du Dein Passwort für Deinen Account bei "
 | 
				
			||||||
 | 
					"%(site_name)s zurücksetzen möchtest.<br/>\n"
 | 
				
			||||||
 | 
					"Bitte folge diesem Link und wähle ein neues Passwort: %(base_url)s"
 | 
				
			||||||
 | 
					"%(password_reset_url)s Solltest Du kein neues Passwort angefordert haben, "
 | 
				
			||||||
 | 
					"dann ignoriere diese E-Mail.<br/>\n"
 | 
				
			||||||
 | 
					"Dankeschön!\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, python-format
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"You're receiving this email because you requested a password reset for your "
 | 
				
			||||||
 | 
					"user account at %(site_name)s.\n"
 | 
				
			||||||
 | 
					"Please go to the following page and choose a new password: %(base_url)s"
 | 
				
			||||||
 | 
					"%(password_reset_url)s\n"
 | 
				
			||||||
 | 
					"If you didn't request a new password, ignore this e-mail.\n"
 | 
				
			||||||
 | 
					"Thank you!\n"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Du erhälst diese E-Mail da Du Dein Passwort für Deinen Account bei "
 | 
				
			||||||
 | 
					"%(site_name)s zurücksetzen möchtest.\n"
 | 
				
			||||||
 | 
					"Bitte folge diesem Link und wähle ein neues Passwort: %(base_url)s"
 | 
				
			||||||
 | 
					"%(password_reset_url)s Solltest Du kein neues Passwort angefordert haben, "
 | 
				
			||||||
 | 
					"dann ignoriere diese E-Mail.\n"
 | 
				
			||||||
 | 
					"Dankeschön!\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#, python-format
 | 
					#, python-format
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"You are receiving this email because your virutal machine [%(vm_name)s] has "
 | 
					"You are receiving this email because your virutal machine [%(vm_name)s] has "
 | 
				
			||||||
| 
						 | 
					@ -246,11 +283,29 @@ msgstr "NEUE VM"
 | 
				
			||||||
msgid "You can always order a new VM by following the link below."
 | 
					msgid "You can always order a new VM by following the link below."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, python-format
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"You're receiving this mail because your virtual machine [%(vm_name)s] has "
 | 
				
			||||||
 | 
					"been cancelled.\n"
 | 
				
			||||||
 | 
					"You can see your order status by clicking here\n"
 | 
				
			||||||
 | 
					"%(base_url)s%(vm_order_url)s\n"
 | 
				
			||||||
 | 
					"If you want to order a new virtual machine, you can do it by clicking this "
 | 
				
			||||||
 | 
					"link.\n"
 | 
				
			||||||
 | 
					"%(base_url)s%(my_virtual_machines_url)s\n"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Du erhälst diese E-Mail, da Deine virtuelle Maschine [%(vm_name)s] gekündigt "
 | 
				
			||||||
 | 
					"wurde.\n"
 | 
				
			||||||
 | 
					"Um Deinen Auftragsstatus zu sehen, klicke hier.\n"
 | 
				
			||||||
 | 
					"%(base_url)s%(vm_order_url)s\n"
 | 
				
			||||||
 | 
					"Falls Du eine neue virtuelle Maschine bestellen möchtest, kannst Du dies "
 | 
				
			||||||
 | 
					"tun, indem Du diesen Link klickst.\n"
 | 
				
			||||||
 | 
					"%(base_url)s%(my_virtual_machines_url)s\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Toggle navigation"
 | 
					msgid "Toggle navigation"
 | 
				
			||||||
msgstr "Konfiguration"
 | 
					msgstr "Umschalten"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Dashboard"
 | 
					msgid "Dashboard"
 | 
				
			||||||
msgstr "Mein Dashboard"
 | 
					msgstr "Dashboard"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Logout"
 | 
					msgid "Logout"
 | 
				
			||||||
msgstr "Abmelden"
 | 
					msgstr "Abmelden"
 | 
				
			||||||
| 
						 | 
					@ -264,6 +319,9 @@ msgstr "Registrieren"
 | 
				
			||||||
msgid "Forgot your password ? "
 | 
					msgid "Forgot your password ? "
 | 
				
			||||||
msgstr "Passwort vergessen?"
 | 
					msgstr "Passwort vergessen?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Resend activation link"
 | 
				
			||||||
 | 
					msgstr "Aktivierungslink noch einmal senden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Notifications"
 | 
					msgid "Notifications"
 | 
				
			||||||
msgstr "Benachrichtigungen"
 | 
					msgstr "Benachrichtigungen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -282,10 +340,14 @@ msgstr "Als gelesen markieren"
 | 
				
			||||||
msgid "All notifications"
 | 
					msgid "All notifications"
 | 
				
			||||||
msgstr "Alle Benachrichtigungen"
 | 
					msgstr "Alle Benachrichtigungen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Date"
 | 
					#, python-format
 | 
				
			||||||
msgstr "Datum"
 | 
					msgid "%(page_header_text)s"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Status:"
 | 
					msgid "Invoice Date"
 | 
				
			||||||
 | 
					msgstr "Rechnung Datum"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Status"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Approved"
 | 
					msgid "Approved"
 | 
				
			||||||
| 
						 | 
					@ -294,10 +356,10 @@ msgstr "Akzeptiert"
 | 
				
			||||||
msgid "Declined"
 | 
					msgid "Declined"
 | 
				
			||||||
msgstr "Abgelehnt"
 | 
					msgstr "Abgelehnt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Billed To:"
 | 
					msgid "Billed to"
 | 
				
			||||||
msgstr "Rechnungsadresse"
 | 
					msgstr "Rechnungsadresse"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Payment Method:"
 | 
					msgid "Payment method"
 | 
				
			||||||
msgstr "Bezahlmethode"
 | 
					msgstr "Bezahlmethode"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "ending in"
 | 
					msgid "ending in"
 | 
				
			||||||
| 
						 | 
					@ -306,6 +368,9 @@ msgstr "endend in"
 | 
				
			||||||
msgid "Order summary"
 | 
					msgid "Order summary"
 | 
				
			||||||
msgstr "Bestellungsübersicht"
 | 
					msgstr "Bestellungsübersicht"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Product"
 | 
				
			||||||
 | 
					msgstr "Produkt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Cores"
 | 
					msgid "Cores"
 | 
				
			||||||
msgstr "Prozessorkerne"
 | 
					msgstr "Prozessorkerne"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -315,15 +380,9 @@ msgstr "Arbeitsspeicher"
 | 
				
			||||||
msgid "Disk space"
 | 
					msgid "Disk space"
 | 
				
			||||||
msgstr "Festplattenkapazität"
 | 
					msgstr "Festplattenkapazität"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Configuration"
 | 
					 | 
				
			||||||
msgstr "Konfiguration"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "Total"
 | 
					msgid "Total"
 | 
				
			||||||
msgstr "Gesamt"
 | 
					msgstr "Gesamt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Month"
 | 
					 | 
				
			||||||
msgstr "Monat"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#, python-format
 | 
					#, python-format
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"By clicking \"Place order\" this plan will charge your credit card account "
 | 
					"By clicking \"Place order\" this plan will charge your credit card account "
 | 
				
			||||||
| 
						 | 
					@ -333,7 +392,10 @@ msgstr ""
 | 
				
			||||||
"pro Monat belastet"
 | 
					"pro Monat belastet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Place order"
 | 
					msgid "Place order"
 | 
				
			||||||
msgstr "Bestelle"
 | 
					msgstr "Bestellen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "BACK TO LIST"
 | 
				
			||||||
 | 
					msgstr "ZURÜCK ZUR LISTE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Processing..."
 | 
					msgid "Processing..."
 | 
				
			||||||
msgstr "Abarbeitung..."
 | 
					msgstr "Abarbeitung..."
 | 
				
			||||||
| 
						 | 
					@ -347,14 +409,14 @@ msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal."
 | 
				
			||||||
msgid "Order Nr."
 | 
					msgid "Order Nr."
 | 
				
			||||||
msgstr "Bestellung Nr."
 | 
					msgstr "Bestellung Nr."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Date"
 | 
				
			||||||
 | 
					msgstr "Datum"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Amount"
 | 
					msgid "Amount"
 | 
				
			||||||
msgstr "Betrag"
 | 
					msgstr "Betrag"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Status"
 | 
					 | 
				
			||||||
msgstr ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "See Invoice"
 | 
					msgid "See Invoice"
 | 
				
			||||||
msgstr "Rechnung"
 | 
					msgstr "Siehe Rechnung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Page"
 | 
					msgid "Page"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
| 
						 | 
					@ -365,6 +427,9 @@ msgstr ""
 | 
				
			||||||
msgid "Your Order"
 | 
					msgid "Your Order"
 | 
				
			||||||
msgstr "Deine Bestellung"
 | 
					msgstr "Deine Bestellung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Configuration"
 | 
				
			||||||
 | 
					msgstr "Konfiguration"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "including VAT"
 | 
					msgid "including VAT"
 | 
				
			||||||
msgstr "inkl. Mehrwertsteuer"
 | 
					msgstr "inkl. Mehrwertsteuer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -512,6 +577,9 @@ msgstr "Aktueller Preis"
 | 
				
			||||||
msgid "Your VM is"
 | 
					msgid "Your VM is"
 | 
				
			||||||
msgstr "Deine VM ist"
 | 
					msgstr "Deine VM ist"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Terminating"
 | 
				
			||||||
 | 
					msgstr "Beenden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Pending"
 | 
					msgid "Pending"
 | 
				
			||||||
msgstr "In Vorbereitung"
 | 
					msgstr "In Vorbereitung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -524,6 +592,11 @@ msgstr "Fehlgeschlagen"
 | 
				
			||||||
msgid "Terminate VM"
 | 
					msgid "Terminate VM"
 | 
				
			||||||
msgstr "VM Beenden"
 | 
					msgstr "VM Beenden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Sorry, there was an unexpected error. Kindly retry."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Bitte entschuldige, es scheint ein unerwarteter Fehler aufgetreten zu sein. "
 | 
				
			||||||
 | 
					"Versuche es doch bitte noch einmal."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Something doesn't work?"
 | 
					msgid "Something doesn't work?"
 | 
				
			||||||
msgstr "Etwas funktioniert nicht?"
 | 
					msgstr "Etwas funktioniert nicht?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -531,10 +604,7 @@ msgid "We are here to help you!"
 | 
				
			||||||
msgstr "Wir sind hier, um Dir zu helfen!"
 | 
					msgstr "Wir sind hier, um Dir zu helfen!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "CONTACT"
 | 
					msgid "CONTACT"
 | 
				
			||||||
msgstr "KONTACT"
 | 
					msgstr "KONTAKT"
 | 
				
			||||||
 | 
					 | 
				
			||||||
msgid "BACK TO LIST"
 | 
					 | 
				
			||||||
msgstr "ZURÜCK ZUR LISTE"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Terminate your Virtual Machine"
 | 
					msgid "Terminate your Virtual Machine"
 | 
				
			||||||
msgstr "Deine Virtuelle Maschine beenden"
 | 
					msgstr "Deine Virtuelle Maschine beenden"
 | 
				
			||||||
| 
						 | 
					@ -545,6 +615,14 @@ msgstr "Bist Du sicher, dass Du Deine virtuelle Maschine beenden willst"
 | 
				
			||||||
msgid "OK"
 | 
					msgid "OK"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, python-format
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"Your Virtual Machine <strong>%(machine_name)s</strong> is successfully "
 | 
				
			||||||
 | 
					"terminated!"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Deine Virtuelle Machine (VM) <strong>%(machine_name)s</strong> wurde erfolgreich "
 | 
				
			||||||
 | 
					"beendet!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Virtual Machines"
 | 
					msgid "Virtual Machines"
 | 
				
			||||||
msgstr "Virtuelle Maschinen"
 | 
					msgstr "Virtuelle Maschinen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -579,13 +657,13 @@ msgid "Sorry. Your request is invalid."
 | 
				
			||||||
msgstr "Entschuldigung, deine Anfrage ist ungültig."
 | 
					msgstr "Entschuldigung, deine Anfrage ist ungültig."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Password has been reset."
 | 
					msgid "Password has been reset."
 | 
				
			||||||
msgstr ""
 | 
					msgstr "Dein Passwort wurde erfolgreich zurückgesetzt."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Password reset has not been successful."
 | 
					msgid "Password reset has not been successful."
 | 
				
			||||||
msgstr ""
 | 
					msgstr "Dein Passwort konnte nicht zurückgesetzt werden."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "The reset password link is no longer valid."
 | 
					msgid "The reset password link is no longer valid."
 | 
				
			||||||
msgstr ""
 | 
					msgstr "Der Link zum Zurücksetzen Deines Passwortes ist nicht mehr gültig."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Invalid credit card"
 | 
					msgid "Invalid credit card"
 | 
				
			||||||
msgstr "Ungültige Kreditkarte"
 | 
					msgstr "Ungültige Kreditkarte"
 | 
				
			||||||
| 
						 | 
					@ -593,6 +671,15 @@ msgstr "Ungültige Kreditkarte"
 | 
				
			||||||
msgid "Confirm Order"
 | 
					msgid "Confirm Order"
 | 
				
			||||||
msgstr "Bestellung Bestätigen"
 | 
					msgstr "Bestellung Bestätigen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid ""
 | 
				
			||||||
 | 
					"The VM you are looking for is unavailable at the moment. Please contact Data "
 | 
				
			||||||
 | 
					"Center Light support."
 | 
				
			||||||
 | 
					msgstr "Kontaktiere den Data Center Light Support."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "In order to create a VM, you need to create/upload your SSH KEY first."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Um eine VM zu erstellen musst du zuerst einen SSH-Key erstellen / hochladen."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Thank you for the order."
 | 
					msgid "Thank you for the order."
 | 
				
			||||||
msgstr "Danke für Deine Bestellung."
 | 
					msgstr "Danke für Deine Bestellung."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -603,9 +690,14 @@ msgstr ""
 | 
				
			||||||
"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
 | 
					"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
 | 
				
			||||||
"auf sie zugreifen kannst."
 | 
					"auf sie zugreifen kannst."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "In order to create a VM, you need to create/upload your SSH KEY first."
 | 
					msgid "Invalid number of cores"
 | 
				
			||||||
msgstr ""
 | 
					msgstr "Ungültige Anzahle CPU-Kerne"
 | 
				
			||||||
"Um eine VM zu erstellen musst du zuerst einen SSH-Key erstellen / hochladen."
 | 
					
 | 
				
			||||||
 | 
					msgid "Invalid RAM size"
 | 
				
			||||||
 | 
					msgstr "Ungültige RAM-Grösse"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Invalid storage size"
 | 
				
			||||||
 | 
					msgstr "Ungültige Speicher-Grösse"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid ""
 | 
					msgid ""
 | 
				
			||||||
"We could not find the requested VM. Please                            "
 | 
					"We could not find the requested VM. Please                            "
 | 
				
			||||||
| 
						 | 
					@ -616,6 +708,42 @@ msgstr "Kontaktiere den Data Center Light Support."
 | 
				
			||||||
msgid "VM %(VM_ID)s terminated successfully"
 | 
					msgid "VM %(VM_ID)s terminated successfully"
 | 
				
			||||||
msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
					msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Terminated"
 | 
				
			||||||
 | 
					msgstr "Beendet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Error terminating VM"
 | 
				
			||||||
 | 
					msgstr "Fehler beenden VM"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Virtual Machine Cancellation"
 | 
				
			||||||
 | 
					msgstr "VM Kündigung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "Close"
 | 
				
			||||||
 | 
					#~ msgstr "Schliessen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "VM %(VM_ID)s terminated successfully"
 | 
				
			||||||
 | 
					#~ msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "days"
 | 
				
			||||||
 | 
					#~ msgstr "Tage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "New Virtual Machine"
 | 
				
			||||||
 | 
					#~ msgstr "Neue virtuelle Maschine"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "Step 1. Select VM Template:"
 | 
				
			||||||
 | 
					#~ msgstr "Wähle eine Vorlage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "Step2. Select VM Configuration"
 | 
				
			||||||
 | 
					#~ msgstr "Wähle eine Konfiguration"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "Price "
 | 
				
			||||||
 | 
					#~ msgstr "Preis"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "CHF/Month"
 | 
				
			||||||
 | 
					#~ msgstr "CHF/Monat"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#~ msgid "Start VM"
 | 
				
			||||||
 | 
					#~ msgstr "VM jetzt starten"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "View Invoice"
 | 
					#~ msgid "View Invoice"
 | 
				
			||||||
#~ msgstr "Zur Rechnung"
 | 
					#~ msgstr "Zur Rechnung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -693,7 +821,7 @@ msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
				
			||||||
#~ msgstr "Meine Bestellungen"
 | 
					#~ msgstr "Meine Bestellungen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "SSH Keys"
 | 
					#~ msgid "SSH Keys"
 | 
				
			||||||
#~ msgstr "SSH Key"
 | 
					#~ msgstr "SSH Keys"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Notifications "
 | 
					#~ msgid "Notifications "
 | 
				
			||||||
#~ msgstr "Benachrichtigungen"
 | 
					#~ msgstr "Benachrichtigungen"
 | 
				
			||||||
| 
						 | 
					@ -734,9 +862,6 @@ msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
				
			||||||
#~ msgid "Ipv6"
 | 
					#~ msgid "Ipv6"
 | 
				
			||||||
#~ msgstr "IPv6"
 | 
					#~ msgstr "IPv6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Close"
 | 
					 | 
				
			||||||
#~ msgstr "Schliessen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#~ msgid "Cancel"
 | 
					#~ msgid "Cancel"
 | 
				
			||||||
#~ msgstr "Beenden"
 | 
					#~ msgstr "Beenden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -744,19 +869,19 @@ msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
				
			||||||
#~ msgstr "Hinzufügen"
 | 
					#~ msgstr "Hinzufügen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Keys"
 | 
					#~ msgid "Keys"
 | 
				
			||||||
#~ msgstr "Schlüssel"
 | 
					#~ msgstr "Keys"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Log in"
 | 
					#~ msgid "Log in"
 | 
				
			||||||
#~ msgstr "Anmelden"
 | 
					#~ msgstr "Anmelden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "You haven been logged out"
 | 
					#~ msgid "You haven been logged out"
 | 
				
			||||||
#~ msgstr "Sie wurden abgmeldet"
 | 
					#~ msgstr "Du wurdest abgemeldet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "How it works"
 | 
					#~ msgid "How it works"
 | 
				
			||||||
#~ msgstr "So funktioniert es"
 | 
					#~ msgstr "So funktioniert es"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Your infrastructure"
 | 
					#~ msgid "Your infrastructure"
 | 
				
			||||||
#~ msgstr "deine Infrastruktur"
 | 
					#~ msgstr "Deine Infrastruktur"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Our inftrastructure"
 | 
					#~ msgid "Our inftrastructure"
 | 
				
			||||||
#~ msgstr "Unsere Infrastruktur"
 | 
					#~ msgstr "Unsere Infrastruktur"
 | 
				
			||||||
| 
						 | 
					@ -765,10 +890,10 @@ msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
				
			||||||
#~ msgstr "Preise"
 | 
					#~ msgstr "Preise"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Access Key"
 | 
					#~ msgid "Access Key"
 | 
				
			||||||
#~ msgstr "Zugriffsschlüssel"
 | 
					#~ msgstr "SSH Key"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Upload your own key. "
 | 
					#~ msgid "Upload your own key. "
 | 
				
			||||||
#~ msgstr "Lade deinen Key hoch"
 | 
					#~ msgstr "Lade Deinen Key hoch"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#~ msgid "Generate Key Pair"
 | 
					#~ msgid "Generate Key Pair"
 | 
				
			||||||
#~ msgstr "Schlüsselpaar generieren"
 | 
					#~ msgstr "Schlüsselpaar generieren"
 | 
				
			||||||
| 
						 | 
					@ -792,5 +917,5 @@ msgstr "VM %(VM_ID)s erfolgreich beendet"
 | 
				
			||||||
#~ "Your SSH private key was already generated and downloaded, if you lost "
 | 
					#~ "Your SSH private key was already generated and downloaded, if you lost "
 | 
				
			||||||
#~ "it, contact us. "
 | 
					#~ "it, contact us. "
 | 
				
			||||||
#~ msgstr ""
 | 
					#~ msgstr ""
 | 
				
			||||||
#~ "Dein privater SSH Schlüssel wurde bereits generiert und heruntergeladen. "
 | 
					#~ "Dein privater SSH Key wurde bereits generiert und heruntergeladen. "
 | 
				
			||||||
#~ "Falls du ihn verloren hast, kontaktiere uns."
 | 
					#~ "Falls Du ihn verloren hast, kontaktiere uns."
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,6 +139,10 @@
 | 
				
			||||||
.modal-text p:not(:last-of-type){
 | 
					.modal-text p:not(:last-of-type){
 | 
				
			||||||
	margin-bottom: 5px;
 | 
						margin-bottom: 5px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.modal-title + .modal-footer {
 | 
				
			||||||
 | 
					    margin-top: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.modal-footer {
 | 
					.modal-footer {
 | 
				
			||||||
    border-top: 0px solid #e5e5e5;
 | 
					    border-top: 0px solid #e5e5e5;
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
| 
						 | 
					@ -356,3 +360,19 @@
 | 
				
			||||||
.no-cards a {
 | 
					.no-cards a {
 | 
				
			||||||
  color: #7ca3d0;
 | 
					  color: #7ca3d0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.btn-plain {
 | 
				
			||||||
 | 
					  background: transparent;
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					  fill: #595959;
 | 
				
			||||||
 | 
					  color: #595959;
 | 
				
			||||||
 | 
					  outline: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.btn-plain:hover,
 | 
				
			||||||
 | 
					.btn-plain:focus,
 | 
				
			||||||
 | 
					.btn-plain:active,
 | 
				
			||||||
 | 
					.btn-plain:active:focus {
 | 
				
			||||||
 | 
					  outline: none;
 | 
				
			||||||
 | 
					  color: #999;
 | 
				
			||||||
 | 
					  fill: #999;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -580,9 +580,9 @@ a.unlink:hover {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.dcl-place-order-text{
 | 
					.dcl-place-order-text{
 | 
				
			||||||
   font-size: 13px;
 | 
					   /* font-size: 13px; */
 | 
				
			||||||
   color: #808080;
 | 
					   color: #808080;
 | 
				
			||||||
   margin-bottom: 15px;
 | 
					   /* margin-bottom: 15px; */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.dcl-order-table-total .tbl-total {
 | 
					.dcl-order-table-total .tbl-total {
 | 
				
			||||||
| 
						 | 
					@ -853,6 +853,9 @@ a.list-group-item-danger:focus,
 | 
				
			||||||
.panel-danger > .panel-heading {
 | 
					.panel-danger > .panel-heading {
 | 
				
			||||||
    color: #eb4d5c;
 | 
					    color: #eb4d5c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.alert-danger{
 | 
				
			||||||
 | 
					    background: rgba(235, 204, 209, 0.2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.has-error .form-control,
 | 
					.has-error .form-control,
 | 
				
			||||||
.has-error .input-group-addon {
 | 
					.has-error .input-group-addon {
 | 
				
			||||||
    color: #eb4d5c;
 | 
					    color: #eb4d5c;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,15 @@
 | 
				
			||||||
.order-detail-container {padding-top: 70px; padding-bottom: 70px; margin-bottom: 70px;}
 | 
					.order-detail-container {
 | 
				
			||||||
 | 
					    max-width: 600px;
 | 
				
			||||||
 | 
					    margin: 100px auto 40px;
 | 
				
			||||||
 | 
					    border: 1px solid #ccc;
 | 
				
			||||||
 | 
					    padding: 15px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media(min-width: 768px) {
 | 
				
			||||||
 | 
					    .order-detail-container {
 | 
				
			||||||
 | 
					        padding: 30px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.order-detail-container .invoice-title h2, .invoice-title h3 {
 | 
					.order-detail-container .invoice-title h2, .invoice-title h3 {
 | 
				
			||||||
    display: inline-block;
 | 
					    display: inline-block;
 | 
				
			||||||
| 
						 | 
					@ -15,3 +26,67 @@
 | 
				
			||||||
.order-detail-container .table > tbody > tr > .thick-line {
 | 
					.order-detail-container .table > tbody > tr > .thick-line {
 | 
				
			||||||
    border-top: 2px solid;
 | 
					    border-top: 2px solid;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container .dashboard-title-thin {
 | 
				
			||||||
 | 
					    margin-top: 0;
 | 
				
			||||||
 | 
					    margin-left: -3px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container .dashboard-title-thin .un-icon {
 | 
				
			||||||
 | 
					    margin-top: -6px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container .dashboard-container-head {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
 | 
					    margin-bottom: 38px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container .dashboard-container-options {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    top: 10px;
 | 
				
			||||||
 | 
					    right: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.order-detail-container .dashboard-container-options .svg-img {
 | 
				
			||||||
 | 
					    height: 22px;
 | 
				
			||||||
 | 
					    width: 22px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container .order-details {
 | 
				
			||||||
 | 
					    margin-bottom: 30px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container .order-details strong {
 | 
				
			||||||
 | 
					    color: #595959;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container h4 {
 | 
				
			||||||
 | 
					    font-size: 16px;
 | 
				
			||||||
 | 
					    font-weight: bold;
 | 
				
			||||||
 | 
					    margin-bottom: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container p {
 | 
				
			||||||
 | 
					    margin-bottom: 5px;
 | 
				
			||||||
 | 
					    color: #595959;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.order-detail-container hr {
 | 
				
			||||||
 | 
					    margin: 15px 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (max-width: 767px) {
 | 
				
			||||||
 | 
					    .order-confirm-btn {
 | 
				
			||||||
 | 
					        text-align: center;
 | 
				
			||||||
 | 
					        margin-top: 10px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .order-detail-container .dashboard-container-options {
 | 
				
			||||||
 | 
					        position: absolute;
 | 
				
			||||||
 | 
					        top: 4px;
 | 
				
			||||||
 | 
					        right: -4px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .order-detail-container .dashboard-container-options .svg-img {
 | 
				
			||||||
 | 
					        height: 16px;
 | 
				
			||||||
 | 
					        width: 16px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										237
									
								
								hosting/static/hosting/css/price_calculator.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								hosting/static/hosting/css/price_calculator.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,237 @@
 | 
				
			||||||
 | 
					/* Create VM calculator */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section {
 | 
				
			||||||
 | 
					    padding: 80px 40px !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (max-width: 768px) {
 | 
				
			||||||
 | 
					    .price-calc-section {
 | 
				
			||||||
 | 
					        margin-top: 40px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .text {
 | 
				
			||||||
 | 
					    width: 50%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .text .section-heading {
 | 
				
			||||||
 | 
					    font-size: 48px;
 | 
				
			||||||
 | 
					    line-height: 48px;
 | 
				
			||||||
 | 
					    padding-bottom: 27px;
 | 
				
			||||||
 | 
					    color: #3a3a3a;
 | 
				
			||||||
 | 
					    letter-spacing: 1px;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    text-align: right;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .text .description {
 | 
				
			||||||
 | 
					    font-size: 20px;
 | 
				
			||||||
 | 
					    text-align: right;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .text .section-heading::before {
 | 
				
			||||||
 | 
					    content: "";
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    bottom: 0;
 | 
				
			||||||
 | 
					    background: #29427A;
 | 
				
			||||||
 | 
					    height: 7px;
 | 
				
			||||||
 | 
					    width: 70px;
 | 
				
			||||||
 | 
					    right: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card {
 | 
				
			||||||
 | 
					    width: 50%;
 | 
				
			||||||
 | 
					    margin: 0 auto;
 | 
				
			||||||
 | 
					    background: #fff;
 | 
				
			||||||
 | 
					    box-shadow: 1px 3px 6px 2px rgba(0, 0, 0, 0.2);
 | 
				
			||||||
 | 
					    padding-bottom: 30px;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    max-width: 320px;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (min-width: 768px) {
 | 
				
			||||||
 | 
					    .price-calc-section .card {
 | 
				
			||||||
 | 
					        margin-left: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .landing {
 | 
				
			||||||
 | 
					    width: 100% !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.no-padding {
 | 
				
			||||||
 | 
					    padding: 0 !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .img-beta {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    top: 5px;
 | 
				
			||||||
 | 
					    width: 60px;
 | 
				
			||||||
 | 
					    left: 3px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .title {
 | 
				
			||||||
 | 
					    padding: 15px 40px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .title h3 {
 | 
				
			||||||
 | 
					    /*font-family: 'Lato', sans-serif;*/
 | 
				
			||||||
 | 
					    font-weight: normal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .price {
 | 
				
			||||||
 | 
					    background: #5A74AF;
 | 
				
			||||||
 | 
					    padding: 22px;
 | 
				
			||||||
 | 
					    color: #fff;
 | 
				
			||||||
 | 
					    font-size: 32px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .price .price-text {
 | 
				
			||||||
 | 
					    font-size: 14px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description {
 | 
				
			||||||
 | 
					    padding: 7px 8px 2px;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    justify-content: space-around !important;
 | 
				
			||||||
 | 
					    align-items: center !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description span {
 | 
				
			||||||
 | 
					    font-size: 14px;
 | 
				
			||||||
 | 
					    margin-left: 5px;
 | 
				
			||||||
 | 
					    /* margin-left: 0px; */
 | 
				
			||||||
 | 
					    /* justify-self: start; */
 | 
				
			||||||
 | 
					    width: 29%;
 | 
				
			||||||
 | 
					    text-align: left;
 | 
				
			||||||
 | 
					    line-height: 16px;
 | 
				
			||||||
 | 
					    /* font-weight: normal; */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description .select-number{
 | 
				
			||||||
 | 
					    font-size: 16px;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    width: 85px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description i {
 | 
				
			||||||
 | 
					    color: #29427a;
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    font-size: 20px;
 | 
				
			||||||
 | 
					    border: 1px solid #ccc;
 | 
				
			||||||
 | 
					    padding: 5px 6px 3px;
 | 
				
			||||||
 | 
					    border-radius: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description .left {
 | 
				
			||||||
 | 
					    margin-right: 7px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description .right {
 | 
				
			||||||
 | 
					    margin-left: 7px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .descriptions {
 | 
				
			||||||
 | 
					    padding: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description p {
 | 
				
			||||||
 | 
					    margin: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .btn {
 | 
				
			||||||
 | 
					    margin-top: 15px;
 | 
				
			||||||
 | 
					    font-size: 20px;
 | 
				
			||||||
 | 
					    width: 150px;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .select-configuration select {
 | 
				
			||||||
 | 
					    outline: none;
 | 
				
			||||||
 | 
					    background: #fff;
 | 
				
			||||||
 | 
					    border-color: #d0d0d0;
 | 
				
			||||||
 | 
					    height: 32px;
 | 
				
			||||||
 | 
					    width: 150px;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    font-size: 14px;
 | 
				
			||||||
 | 
					    margin-left: 10px;
 | 
				
			||||||
 | 
					    padding: 6px;
 | 
				
			||||||
 | 
					    border-radius: 4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .check-ip {
 | 
				
			||||||
 | 
					    font-size: 18px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .justify-center {
 | 
				
			||||||
 | 
					    justify-content: center !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .description.input label {
 | 
				
			||||||
 | 
					    font-size: 15px;
 | 
				
			||||||
 | 
					    font-weight: 700;
 | 
				
			||||||
 | 
					    /*font-weight: 800;*/
 | 
				
			||||||
 | 
					    /*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;
 | 
				
			||||||
 | 
					    padding: 4px 10px;
 | 
				
			||||||
 | 
					    border-radius: 4px;
 | 
				
			||||||
 | 
					    border: 1px solid #d0d0d0;
 | 
				
			||||||
 | 
					    background: #fff;
 | 
				
			||||||
 | 
					    margin-left: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .card .check-ip input[type=checkbox] {
 | 
				
			||||||
 | 
					    font-size: 17px;
 | 
				
			||||||
 | 
					    margin: 0 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .help-block.with-errors {
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    margin: 0 0;
 | 
				
			||||||
 | 
					    padding: 0 0 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.price-calc-section .help-block.with-errors ul {
 | 
				
			||||||
 | 
					    margin-bottom: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .form-group {
 | 
				
			||||||
 | 
					    margin: 0;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.price-calc-section .btn-primary {
 | 
				
			||||||
 | 
					    background: #29427A;
 | 
				
			||||||
 | 
					    border-color: #29427A;
 | 
				
			||||||
 | 
					    color: #fff;
 | 
				
			||||||
 | 
					    width: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media(min-width: 768px) {
 | 
				
			||||||
 | 
					    .create-vm-container {
 | 
				
			||||||
 | 
					        padding-top: 120px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -290,6 +290,11 @@
 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.vm-vmid .alert {
 | 
				
			||||||
 | 
					  margin-top: 15px;
 | 
				
			||||||
 | 
					  margin-bottom: -60px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.vm-item-lg {
 | 
					.vm-item-lg {
 | 
				
			||||||
  font-size: 22px;
 | 
					  font-size: 22px;
 | 
				
			||||||
  margin-top: 5px;
 | 
					  margin-top: 5px;
 | 
				
			||||||
| 
						 | 
					@ -305,6 +310,10 @@
 | 
				
			||||||
  color: #e47f2f;
 | 
					  color: #e47f2f;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.vm-color-failed {
 | 
				
			||||||
 | 
					  color: #eb4d5c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.vm-detail-item .value{
 | 
					.vm-detail-item .value{
 | 
				
			||||||
  font-weight: 400;
 | 
					  font-weight: 400;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -512,7 +521,7 @@
 | 
				
			||||||
  color: #87B6EA;
 | 
					  color: #87B6EA;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.vm-status, .vm-status-active, .vm-status-failed {
 | 
					.vm-status, .vm-status-active, .vm-status-failed, .vm-status-pending {
 | 
				
			||||||
  font-weight: 600;
 | 
					  font-weight: 600;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.vm-status-active {
 | 
					.vm-status-active {
 | 
				
			||||||
| 
						 | 
					@ -521,6 +530,9 @@
 | 
				
			||||||
.vm-status-failed {
 | 
					.vm-status-failed {
 | 
				
			||||||
  color: #eb4d5c;
 | 
					  color: #eb4d5c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.vm-status-pending {
 | 
				
			||||||
 | 
					  color: #e47f2f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media (min-width:768px) {
 | 
					@media (min-width:768px) {
 | 
				
			||||||
  .dashboard-subtitle {
 | 
					  .dashboard-subtitle {
 | 
				
			||||||
| 
						 | 
					@ -628,3 +640,27 @@
 | 
				
			||||||
    right: 8px;
 | 
					    right: 8px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.processing > .btn {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  border-color: #eee;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.processing > .btn:hover,
 | 
				
			||||||
 | 
					.processing > .btn:focus,
 | 
				
			||||||
 | 
					.processing > .btn:active {
 | 
				
			||||||
 | 
					  border-color: #eee;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.processing > .btn:after {
 | 
				
			||||||
 | 
					  content: ' ';
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  background-image: url('/static/hosting/img/ajax-loader.gif');
 | 
				
			||||||
 | 
					  background-repeat: no-repeat;
 | 
				
			||||||
 | 
					  background-position: center;
 | 
				
			||||||
 | 
					  background-color: #eee;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								hosting/static/hosting/img/ajax-loader.gif
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								hosting/static/hosting/img/ajax-loader.gif
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 404 B  | 
							
								
								
									
										18
									
								
								hosting/static/hosting/img/icon-pdf.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								hosting/static/hosting/img/icon-pdf.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<svg width="492px" height="649px" viewBox="0 0 492 649" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
				
			||||||
 | 
					    <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
 | 
				
			||||||
 | 
					    <title>icon-pdf</title>
 | 
				
			||||||
 | 
					    <desc>Created with Sketch.</desc>
 | 
				
			||||||
 | 
					    <defs></defs>
 | 
				
			||||||
 | 
					    <g id="Page-1" stroke="none" stroke-width="1" fill-rule="evenodd">
 | 
				
			||||||
 | 
					        <g id="icon-pdf" fill-rule="nonzero">
 | 
				
			||||||
 | 
					            <g id="Group" transform="translate(93.000000, 269.000000)">
 | 
				
			||||||
 | 
					                <path d="M98,47.8 C98,54.8 97,61.7 95.1,66.6 C93.1,72.5 90.1,76.5 86.2,80.5 C82.2,84.5 76.3,87.4 70.4,89.4 C64.5,91.4 55.6,92.3 46.6,92.3 L34.7,92.3 L34.7,134 L0,134 L0,0.3 L45.5,0.3 C54.4,0.3 62.4,1.3 69.3,3.2 C76.2,5.2 81.2,8.2 85.1,12.1 C89.1,16.1 92.1,21 94,27 C96.9,32 98,38.9 98,47.8 Z M61.3,46.8 C61.3,42.8 61.3,39.9 60.3,37.9 C60.3,35.9 59.3,33.9 57.4,32 C56.4,31 54.5,30 52.4,29.1 C50.4,29.1 47.4,28.1 44.5,28.1 L34.6,28.1 L34.6,63.7 L45.5,63.7 C48.4,63.7 50.4,63.7 52.5,62.7 C54.5,61.7 56.5,61.7 57.5,59.8 C58.5,57.8 59.5,56.9 60.4,54.8 C61.3,53.8 61.3,50.8 61.3,46.8 Z" id="Shape"></path>
 | 
				
			||||||
 | 
					                <path d="M214.8,66.6 C214.8,78.5 213.8,89.3 210.8,97.3 C208.8,106.2 204.9,113.1 199.9,118.1 C195,123.1 189,127 182.1,130 C175.2,132 167.3,134 157.3,134 L108.8,134 L108.8,0.3 L156.3,0.3 C166.2,0.3 175.1,1.3 182,4.3 C188.9,7.2 194.9,10.2 199.8,16.2 C204.8,21.2 207.7,28.1 209.7,37 C213.8,44.8 214.8,54.7 214.8,66.6 Z M178.1,65.6 C178.1,58.7 178.1,52.7 177.1,47.8 C176.1,42.8 175.1,39.9 174.2,36.9 C172.2,34 170.2,32.9 168.3,31.9 C165.4,30.9 162.4,30.9 158.4,30.9 L145.6,30.9 L145.6,103.2 L158.4,103.2 C162.4,103.2 165.4,103.2 168.3,102.2 C171.2,101.2 173.3,99.3 174.2,97.2 C176.2,94.3 177.1,91.3 178.2,86.3 C178.1,80.5 178.1,74.5 178.1,65.6 Z" id="Shape"></path>
 | 
				
			||||||
 | 
					                <polygon id="Shape" points="264.3 32 264.3 55.8 304.9 55.8 304.9 85.5 264.3 85.5 264.3 135 229.7 135 229.7 0.3 312.9 0.3 313.9 31 264.4 31 264.4 32"></polygon>
 | 
				
			||||||
 | 
					            </g>
 | 
				
			||||||
 | 
					            <path d="M491.3,649 L0.7,649 L0.7,0 L346.1,0 L491.3,145.2 L491.3,649 L491.3,649 Z M44.7,605 L448.4,605 L448.4,162.8 L327.4,42.9 L44.7,42.9 L44.7,605 Z" id="Shape"></path>
 | 
				
			||||||
 | 
					            <polygon id="Shape" points="469.3 176 315.3 176 315.3 20.9 359.3 20.9 359.3 132 469.3 132"></polygon>
 | 
				
			||||||
 | 
					        </g>
 | 
				
			||||||
 | 
					    </g>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 2.3 KiB  | 
							
								
								
									
										17
									
								
								hosting/static/hosting/img/icon-print.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								hosting/static/hosting/img/icon-print.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<svg width="612px" height="612px" viewBox="0 0 612 612" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
				
			||||||
 | 
					    <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
 | 
				
			||||||
 | 
					    <title>54471</title>
 | 
				
			||||||
 | 
					    <desc>Created with Sketch.</desc>
 | 
				
			||||||
 | 
					    <defs></defs>
 | 
				
			||||||
 | 
					    <g id="Page-1" stroke="none" stroke-width="1" fill-rule="evenodd">
 | 
				
			||||||
 | 
					        <g id="54471" fill-rule="nonzero">
 | 
				
			||||||
 | 
					            <path d="M0,225.633 L0,386.367 C0,417.272 30.6,417.272 30.6,417.272 L83.454,417.272 L83.454,389.454 L27.818,389.454 L27.818,222.545 L584.181,222.545 L584.181,389.454 L528.545,389.454 L528.545,417.272 L581.4,417.272 C581.4,417.272 612,417.272 612,386.367 L612,225.633 C612,225.633 612,194.727 581.4,194.727 L30.6,194.727 C0,194.728 0,225.633 0,225.633 Z" id="Shape"></path>
 | 
				
			||||||
 | 
					            <polygon id="Shape" points="500.728 166.909 500.728 0 111.273 0 111.273 166.909 139.091 166.909 139.091 27.818 472.909 27.818 472.909 166.909"></polygon>
 | 
				
			||||||
 | 
					            <path d="M528.546,292.091 C528.546,278.182 514.358,278.182 514.358,278.182 L97.642,278.182 C97.642,278.182 83.455,278.182 83.455,292.091 C83.455,306 97.642,306 97.642,306 L514.359,306 C514.358,306 528.546,306 528.546,292.091 Z" id="Shape"></path>
 | 
				
			||||||
 | 
					            <rect id="Rectangle-path" x="166.909" y="500.728" width="278.182" height="27.818"></rect>
 | 
				
			||||||
 | 
					            <path d="M500.728,612 L500.728,389.454 L111.273,389.454 L111.273,612 L500.728,612 Z M139.091,417.272 L472.909,417.272 L472.909,584.181 L139.091,584.181 L139.091,417.272 Z" id="Shape"></path>
 | 
				
			||||||
 | 
					            <rect id="Rectangle-path" x="166.909" y="445.091" width="278.182" height="27.818"></rect>
 | 
				
			||||||
 | 
					        </g>
 | 
				
			||||||
 | 
					    </g>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.7 KiB  | 
| 
						 | 
					@ -1,73 +1,75 @@
 | 
				
			||||||
(function($){
 | 
					(function($){
 | 
				
			||||||
    "use strict"; // Start of use strict
 | 
					    "use strict"; // Start of use strict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var cardPricing = {
 | 
				
			||||||
 | 
					        'cpu': {
 | 
				
			||||||
 | 
					            'id': 'coreValue',
 | 
				
			||||||
 | 
					            'value': 1,
 | 
				
			||||||
 | 
					            'min': 1,
 | 
				
			||||||
 | 
					            'max': 48,
 | 
				
			||||||
 | 
					            'interval': 1
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'ram': {
 | 
				
			||||||
 | 
					            'id': 'ramValue',
 | 
				
			||||||
 | 
					            'value': 2,
 | 
				
			||||||
 | 
					            'min': 2,
 | 
				
			||||||
 | 
					            'max': 200,
 | 
				
			||||||
 | 
					            'interval': 1
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'storage': {
 | 
				
			||||||
 | 
					            'id': 'storageValue',
 | 
				
			||||||
 | 
					            'value': 10,
 | 
				
			||||||
 | 
					            'min': 10,
 | 
				
			||||||
 | 
					            'max': 2000,
 | 
				
			||||||
 | 
					            'interval': 10
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $(window).load(function(){
 | 
					    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) {
 | 
				
			||||||
 | 
					            $('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() {
 | 
					    $(document).ready(function() {
 | 
				
			||||||
      _initOs();
 | 
					        _initPricing();
 | 
				
			||||||
       
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $(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);
 | 
					})(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); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										387
									
								
								hosting/static/hosting/js/html2pdf.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										387
									
								
								hosting/static/hosting/js/html2pdf.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,387 @@
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @license
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * MIT License
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2017 Erik Koopmans
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					 * copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					 * SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Generate a PDF from an HTML element or string using html2canvas and jsPDF.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {Element|string} source The source element or HTML string.
 | 
				
			||||||
 | 
					 * @param {Object=} opt An object of optional settings: 'margin', 'filename',
 | 
				
			||||||
 | 
					 *    'image' ('type' and 'quality'), and 'html2canvas' / 'jspdf', which are
 | 
				
			||||||
 | 
					 *    sent as settings to their corresponding functions.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					var html2pdf = (function(html2canvas, jsPDF) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* ---------- MAIN FUNCTION ---------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var html2pdf = function(source, opt) {
 | 
				
			||||||
 | 
					    // Handle input.
 | 
				
			||||||
 | 
					    opt = objType(opt) === 'object' ? opt : {};
 | 
				
			||||||
 | 
					    var source = html2pdf.parseInput(source, opt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Determine the PDF page size.
 | 
				
			||||||
 | 
					    var pageSize = jsPDF.getPageSize(opt.jsPDF);
 | 
				
			||||||
 | 
					    pageSize.inner = {
 | 
				
			||||||
 | 
					      width:  pageSize.width - opt.margin[1] - opt.margin[3],
 | 
				
			||||||
 | 
					      height: pageSize.height - opt.margin[0] - opt.margin[2]
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Copy the source element into a PDF-styled container div.
 | 
				
			||||||
 | 
					    var container = html2pdf.makeContainer(source, pageSize);
 | 
				
			||||||
 | 
					    var overlay = container.parentElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get the locations of all hyperlinks.
 | 
				
			||||||
 | 
					    if (opt.enableLinks) {
 | 
				
			||||||
 | 
					      // Find all anchor tags and get the container's bounds for reference.
 | 
				
			||||||
 | 
					      opt.links = [];
 | 
				
			||||||
 | 
					      var links = container.querySelectorAll('a');
 | 
				
			||||||
 | 
					      var containerRect = unitConvert(container.getBoundingClientRect(), pageSize.k);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Treat each client rect as a separate link (for text-wrapping).
 | 
				
			||||||
 | 
					      Array.prototype.forEach.call(links, function(link) {
 | 
				
			||||||
 | 
					        var clientRects = link.getClientRects();
 | 
				
			||||||
 | 
					        for (var i=0; i<clientRects.length; i++) {
 | 
				
			||||||
 | 
					          var clientRect = unitConvert(clientRects[i], pageSize.k);
 | 
				
			||||||
 | 
					          clientRect.left -= containerRect.left;
 | 
				
			||||||
 | 
					          clientRect.top -= containerRect.top;
 | 
				
			||||||
 | 
					          opt.links.push({ el: link, clientRect: clientRect });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Render the canvas and pass the result to makePDF.
 | 
				
			||||||
 | 
					    var onRendered = opt.html2canvas.onrendered || function() {};
 | 
				
			||||||
 | 
					    opt.html2canvas.onrendered = function(canvas) {
 | 
				
			||||||
 | 
					      onRendered(canvas);
 | 
				
			||||||
 | 
					      document.body.removeChild(overlay);
 | 
				
			||||||
 | 
					      html2pdf.makePDF(canvas, pageSize, opt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    html2canvas(container, opt.html2canvas);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  html2pdf.parseInput = function(source, opt) {
 | 
				
			||||||
 | 
					    // Parse the opt object.
 | 
				
			||||||
 | 
					    opt.jsPDF = opt.jsPDF || {};
 | 
				
			||||||
 | 
					    opt.html2canvas = opt.html2canvas || {};
 | 
				
			||||||
 | 
					    opt.filename = opt.filename && objType(opt.filename) === 'string' ? opt.filename : 'file.pdf';
 | 
				
			||||||
 | 
					    opt.enableLinks = opt.hasOwnProperty('enableLinks') ? opt.enableLinks : true;
 | 
				
			||||||
 | 
					    opt.image = opt.image || {};
 | 
				
			||||||
 | 
					    opt.image.type = opt.image.type || 'jpeg';
 | 
				
			||||||
 | 
					    opt.image.quality = opt.image.quality || 0.95;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Parse the margin property of the opt object.
 | 
				
			||||||
 | 
					    switch (objType(opt.margin)) {
 | 
				
			||||||
 | 
					      case 'undefined':
 | 
				
			||||||
 | 
					        opt.margin = 0;
 | 
				
			||||||
 | 
					      case 'number':
 | 
				
			||||||
 | 
					        opt.margin = [opt.margin, opt.margin, opt.margin, opt.margin];
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'array':
 | 
				
			||||||
 | 
					        if (opt.margin.length === 2) {
 | 
				
			||||||
 | 
					          opt.margin = [opt.margin[0], opt.margin[1], opt.margin[0], opt.margin[1]];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (opt.margin.length === 4) {
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw 'Invalid margin array.';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Parse the source element/string.
 | 
				
			||||||
 | 
					    if (!source) {
 | 
				
			||||||
 | 
					      throw 'Missing source element or string.';
 | 
				
			||||||
 | 
					    } else if (objType(source) === 'string') {
 | 
				
			||||||
 | 
					      source = createElement('div', { innerHTML: source });
 | 
				
			||||||
 | 
					    } else if (objType(source) === 'element') {
 | 
				
			||||||
 | 
					      source = cloneNode(source, opt.html2canvas.javascriptEnabled);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      throw 'Invalid source - please specify an HTML Element or string.';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Return the parsed input (opt is modified in-place, no need to return).
 | 
				
			||||||
 | 
					    return source;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  html2pdf.makeContainer = function(source, pageSize) {
 | 
				
			||||||
 | 
					    // Define the CSS styles for the container and its overlay parent.
 | 
				
			||||||
 | 
					    var overlayCSS = {
 | 
				
			||||||
 | 
					      position: 'fixed', overflow: 'hidden', zIndex: 1000,
 | 
				
			||||||
 | 
					      left: 0, right: 0, bottom: 0, top: 0,
 | 
				
			||||||
 | 
					      backgroundColor: 'rgba(0,0,0,0.8)'
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var containerCSS = {
 | 
				
			||||||
 | 
					      position: 'absolute', width: pageSize.inner.width + pageSize.unit,
 | 
				
			||||||
 | 
					      left: 0, right: 0, top: 0, height: 'auto', margin: 'auto',
 | 
				
			||||||
 | 
					      backgroundColor: 'white'
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Set the overlay to hidden (could be changed in the future to provide a print preview).
 | 
				
			||||||
 | 
					    overlayCSS.opacity = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Create and attach the elements.
 | 
				
			||||||
 | 
					    var overlay = createElement('div',   { className: 'html2pdf__overlay', style: overlayCSS });
 | 
				
			||||||
 | 
					    var container = createElement('div', { className: 'html2pdf__container', style: containerCSS });
 | 
				
			||||||
 | 
					    container.appendChild(source);
 | 
				
			||||||
 | 
					    overlay.appendChild(container);
 | 
				
			||||||
 | 
					    document.body.appendChild(overlay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Enable page-breaks.
 | 
				
			||||||
 | 
					    var pageBreaks = source.querySelectorAll('.html2pdf__page-break');
 | 
				
			||||||
 | 
					    var pxPageHeight = pageSize.inner.height * pageSize.k / 72 * 96;
 | 
				
			||||||
 | 
					    Array.prototype.forEach.call(pageBreaks, function(el) {
 | 
				
			||||||
 | 
					      el.style.display = 'block';
 | 
				
			||||||
 | 
					      var clientRect = el.getBoundingClientRect();
 | 
				
			||||||
 | 
					      el.style.height = pxPageHeight - (clientRect.top % pxPageHeight) + 'px';
 | 
				
			||||||
 | 
					    }, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Return the container.
 | 
				
			||||||
 | 
					    return container;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  html2pdf.makePDF = function(canvas, pageSize, opt) {
 | 
				
			||||||
 | 
					    // Calculate the number of pages.
 | 
				
			||||||
 | 
					    var ctx = canvas.getContext('2d');
 | 
				
			||||||
 | 
					    var pxFullHeight = canvas.height;
 | 
				
			||||||
 | 
					    var pxPageHeight = Math.floor(canvas.width * pageSize.inner.ratio);
 | 
				
			||||||
 | 
					    var nPages = Math.ceil(pxFullHeight / pxPageHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Create a one-page canvas to split up the full image.
 | 
				
			||||||
 | 
					    var pageCanvas = document.createElement('canvas');
 | 
				
			||||||
 | 
					    var pageCtx = pageCanvas.getContext('2d');
 | 
				
			||||||
 | 
					    var pageHeight = pageSize.inner.height;
 | 
				
			||||||
 | 
					    pageCanvas.width = canvas.width;
 | 
				
			||||||
 | 
					    pageCanvas.height = pxPageHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initialize the PDF.
 | 
				
			||||||
 | 
					    var pdf = new jsPDF(opt.jsPDF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (var page=0; page<nPages; page++) {
 | 
				
			||||||
 | 
					      // Trim the final page to reduce file size.
 | 
				
			||||||
 | 
					      if (page === nPages-1) {
 | 
				
			||||||
 | 
					        pageCanvas.height = pxFullHeight % pxPageHeight;
 | 
				
			||||||
 | 
					        pageHeight = pageCanvas.height * pageSize.inner.width / pageCanvas.width;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Display the page.
 | 
				
			||||||
 | 
					      var w = pageCanvas.width;
 | 
				
			||||||
 | 
					      var h = pageCanvas.height;
 | 
				
			||||||
 | 
					      pageCtx.fillStyle = 'white';
 | 
				
			||||||
 | 
					      pageCtx.fillRect(0, 0, w, h);
 | 
				
			||||||
 | 
					      pageCtx.drawImage(canvas, 0, page*pxPageHeight, w, h, 0, 0, w, h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Add the page to the PDF.
 | 
				
			||||||
 | 
					      if (page)  pdf.addPage();
 | 
				
			||||||
 | 
					      var imgData = pageCanvas.toDataURL('image/' + opt.image.type, opt.image.quality);
 | 
				
			||||||
 | 
					      pdf.addImage(imgData, opt.image.type, opt.margin[1], opt.margin[0],
 | 
				
			||||||
 | 
					                   pageSize.inner.width, pageHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Add hyperlinks.
 | 
				
			||||||
 | 
					      if (opt.enableLinks) {
 | 
				
			||||||
 | 
					        var pageTop = page * pageSize.inner.height;
 | 
				
			||||||
 | 
					        opt.links.forEach(function(link) {
 | 
				
			||||||
 | 
					          if (link.clientRect.top > pageTop && link.clientRect.top < pageTop + pageSize.inner.height) {
 | 
				
			||||||
 | 
					            var left = opt.margin[1] + link.clientRect.left;
 | 
				
			||||||
 | 
					            var top = opt.margin[0] + link.clientRect.top - pageTop;
 | 
				
			||||||
 | 
					            pdf.link(left, top, link.clientRect.width, link.clientRect.height, { url: link.el.href });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Finish the PDF.
 | 
				
			||||||
 | 
					    pdf.save( opt.filename );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* ---------- UTILS ---------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Determine the type of a variable/object.
 | 
				
			||||||
 | 
					  var objType = function(obj) {
 | 
				
			||||||
 | 
					    if (typeof obj === 'undefined')                             return 'undefined';
 | 
				
			||||||
 | 
					    else if (typeof obj === 'string' || obj instanceof String)  return 'string';
 | 
				
			||||||
 | 
					    else if (typeof obj === 'number' || obj instanceof Number)  return 'number';
 | 
				
			||||||
 | 
					    else if (!!obj && obj.constructor === Array)                return 'array';
 | 
				
			||||||
 | 
					    else if (obj && obj.nodeType === 1)                         return 'element';
 | 
				
			||||||
 | 
					    else if (typeof obj === 'object')                           return 'object';
 | 
				
			||||||
 | 
					    else                                                        return 'unknown';
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Create an HTML element with optional className, innerHTML, and style.
 | 
				
			||||||
 | 
					  var createElement = function(tagName, opt) {
 | 
				
			||||||
 | 
					    var el = document.createElement(tagName);
 | 
				
			||||||
 | 
					    if (opt.className)  el.className = opt.className;
 | 
				
			||||||
 | 
					    if (opt.innerHTML) {
 | 
				
			||||||
 | 
					      el.innerHTML = opt.innerHTML;
 | 
				
			||||||
 | 
					      var scripts = el.getElementsByTagName('script');
 | 
				
			||||||
 | 
					      for (var i = scripts.length; i-- > 0; null) {
 | 
				
			||||||
 | 
					        scripts[i].parentNode.removeChild(scripts[i]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (var key in opt.style) {
 | 
				
			||||||
 | 
					      el.style[key] = opt.style[key];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return el;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Deep-clone a node and preserve contents/properties.
 | 
				
			||||||
 | 
					  var cloneNode = function(node, javascriptEnabled) {
 | 
				
			||||||
 | 
					    // Recursively clone the node.
 | 
				
			||||||
 | 
					    var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
 | 
				
			||||||
 | 
					    for (var child = node.firstChild; child; child = child.nextSibling) {
 | 
				
			||||||
 | 
					      if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
 | 
				
			||||||
 | 
					        clone.appendChild(cloneNode(child, javascriptEnabled));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (node.nodeType === 1) {
 | 
				
			||||||
 | 
					      // Preserve contents/properties of special nodes.
 | 
				
			||||||
 | 
					      if (node.nodeName === 'CANVAS') {
 | 
				
			||||||
 | 
					        clone.width = node.width;
 | 
				
			||||||
 | 
					        clone.height = node.height;
 | 
				
			||||||
 | 
					        clone.getContext('2d').drawImage(node, 0, 0);
 | 
				
			||||||
 | 
					      } else if (node.nodeName === 'TEXTAREA' || node.nodeName === 'SELECT') {
 | 
				
			||||||
 | 
					        clone.value = node.value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Preserve the node's scroll position when it loads.
 | 
				
			||||||
 | 
					      clone.addEventListener('load', function() {
 | 
				
			||||||
 | 
					        clone.scrollTop = node.scrollTop;
 | 
				
			||||||
 | 
					        clone.scrollLeft = node.scrollLeft;
 | 
				
			||||||
 | 
					      }, true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Return the cloned node.
 | 
				
			||||||
 | 
					    return clone;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Convert units using the conversion value 'k' from jsPDF.
 | 
				
			||||||
 | 
					  var unitConvert = function(obj, k) {
 | 
				
			||||||
 | 
					    var newObj = {};
 | 
				
			||||||
 | 
					    for (var key in obj) {
 | 
				
			||||||
 | 
					      newObj[key] = obj[key] * 72 / 96 / k;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return newObj;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Get dimensions of a PDF page, as determined by jsPDF.
 | 
				
			||||||
 | 
					  jsPDF.getPageSize = function(orientation, unit, format) {
 | 
				
			||||||
 | 
					    // Decode options object
 | 
				
			||||||
 | 
					    if (typeof orientation === 'object') {
 | 
				
			||||||
 | 
					      var options = orientation;
 | 
				
			||||||
 | 
					      orientation = options.orientation;
 | 
				
			||||||
 | 
					      unit = options.unit || unit;
 | 
				
			||||||
 | 
					      format = options.format || format;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Default options
 | 
				
			||||||
 | 
					    unit        = unit || 'mm';
 | 
				
			||||||
 | 
					    format      = format || 'a4';
 | 
				
			||||||
 | 
					    orientation = ('' + (orientation || 'P')).toLowerCase();
 | 
				
			||||||
 | 
					    var format_as_string = ('' + format).toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Size in pt of various paper formats
 | 
				
			||||||
 | 
					    pageFormats = {
 | 
				
			||||||
 | 
					      'a0'  : [2383.94, 3370.39], 'a1'  : [1683.78, 2383.94],
 | 
				
			||||||
 | 
					      'a2'  : [1190.55, 1683.78], 'a3'  : [ 841.89, 1190.55],
 | 
				
			||||||
 | 
					      'a4'  : [ 595.28,  841.89], 'a5'  : [ 419.53,  595.28],
 | 
				
			||||||
 | 
					      'a6'  : [ 297.64,  419.53], 'a7'  : [ 209.76,  297.64],
 | 
				
			||||||
 | 
					      'a8'  : [ 147.40,  209.76], 'a9'  : [ 104.88,  147.40],
 | 
				
			||||||
 | 
					      'a10' : [  73.70,  104.88], 'b0'  : [2834.65, 4008.19],
 | 
				
			||||||
 | 
					      'b1'  : [2004.09, 2834.65], 'b2'  : [1417.32, 2004.09],
 | 
				
			||||||
 | 
					      'b3'  : [1000.63, 1417.32], 'b4'  : [ 708.66, 1000.63],
 | 
				
			||||||
 | 
					      'b5'  : [ 498.90,  708.66], 'b6'  : [ 354.33,  498.90],
 | 
				
			||||||
 | 
					      'b7'  : [ 249.45,  354.33], 'b8'  : [ 175.75,  249.45],
 | 
				
			||||||
 | 
					      'b9'  : [ 124.72,  175.75], 'b10' : [  87.87,  124.72],
 | 
				
			||||||
 | 
					      'c0'  : [2599.37, 3676.54], 'c1'  : [1836.85, 2599.37],
 | 
				
			||||||
 | 
					      'c2'  : [1298.27, 1836.85], 'c3'  : [ 918.43, 1298.27],
 | 
				
			||||||
 | 
					      'c4'  : [ 649.13,  918.43], 'c5'  : [ 459.21,  649.13],
 | 
				
			||||||
 | 
					      'c6'  : [ 323.15,  459.21], 'c7'  : [ 229.61,  323.15],
 | 
				
			||||||
 | 
					      'c8'  : [ 161.57,  229.61], 'c9'  : [ 113.39,  161.57],
 | 
				
			||||||
 | 
					      'c10' : [  79.37,  113.39], 'dl'  : [ 311.81,  623.62],
 | 
				
			||||||
 | 
					      'letter'            : [612,   792],
 | 
				
			||||||
 | 
					      'government-letter' : [576,   756],
 | 
				
			||||||
 | 
					      'legal'             : [612,  1008],
 | 
				
			||||||
 | 
					      'junior-legal'      : [576,   360],
 | 
				
			||||||
 | 
					      'ledger'            : [1224,  792],
 | 
				
			||||||
 | 
					      'tabloid'           : [792,  1224],
 | 
				
			||||||
 | 
					      'credit-card'       : [153,   243]
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Unit conversion
 | 
				
			||||||
 | 
					    switch (unit) {
 | 
				
			||||||
 | 
					      case 'pt':  k = 1;          break;
 | 
				
			||||||
 | 
					      case 'mm':  k = 72 / 25.4;  break;
 | 
				
			||||||
 | 
					      case 'cm':  k = 72 / 2.54;  break;
 | 
				
			||||||
 | 
					      case 'in':  k = 72;         break;
 | 
				
			||||||
 | 
					      case 'px':  k = 72 / 96;    break;
 | 
				
			||||||
 | 
					      case 'pc':  k = 12;         break;
 | 
				
			||||||
 | 
					      case 'em':  k = 12;         break;
 | 
				
			||||||
 | 
					      case 'ex':  k = 6;          break;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw ('Invalid unit: ' + unit);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Dimensions are stored as user units and converted to points on output
 | 
				
			||||||
 | 
					    if (pageFormats.hasOwnProperty(format_as_string)) {
 | 
				
			||||||
 | 
					      pageHeight = pageFormats[format_as_string][1] / k;
 | 
				
			||||||
 | 
					      pageWidth = pageFormats[format_as_string][0] / k;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        pageHeight = format[1];
 | 
				
			||||||
 | 
					        pageWidth = format[0];
 | 
				
			||||||
 | 
					      } catch (err) {
 | 
				
			||||||
 | 
					        throw new Error('Invalid format: ' + format);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Handle page orientation
 | 
				
			||||||
 | 
					    if (orientation === 'p' || orientation === 'portrait') {
 | 
				
			||||||
 | 
					      orientation = 'p';
 | 
				
			||||||
 | 
					      if (pageWidth > pageHeight) {
 | 
				
			||||||
 | 
					        tmp = pageWidth;
 | 
				
			||||||
 | 
					        pageWidth = pageHeight;
 | 
				
			||||||
 | 
					        pageHeight = tmp;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else if (orientation === 'l' || orientation === 'landscape') {
 | 
				
			||||||
 | 
					      orientation = 'l';
 | 
				
			||||||
 | 
					      if (pageHeight > pageWidth) {
 | 
				
			||||||
 | 
					        tmp = pageWidth;
 | 
				
			||||||
 | 
					        pageWidth = pageHeight;
 | 
				
			||||||
 | 
					        pageHeight = tmp;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      throw('Invalid orientation: ' + orientation);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Return information (k is the unit conversion ratio from pts)
 | 
				
			||||||
 | 
					    var info = { 'width': pageWidth, 'height': pageHeight, 'unit': unit, 'k': k };
 | 
				
			||||||
 | 
					    return info;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Expose the html2pdf function.
 | 
				
			||||||
 | 
					  return html2pdf;
 | 
				
			||||||
 | 
					}(html2canvas, jsPDF));
 | 
				
			||||||
							
								
								
									
										15
									
								
								hosting/static/hosting/js/order.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								hosting/static/hosting/js/order.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					$(document).ready(function() {
 | 
				
			||||||
 | 
					    $('.btn-pdf').click(function(e) {
 | 
				
			||||||
 | 
					        e.preventDefault();
 | 
				
			||||||
 | 
					        var $target = $($(this).attr('data-target')) || $('body');
 | 
				
			||||||
 | 
					        var fileName = $target.attr('id') + '.pdf';
 | 
				
			||||||
 | 
					        html2pdf($target[0], {
 | 
				
			||||||
 | 
					            filename: fileName,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    $('.btn-print').click(function(e) {
 | 
				
			||||||
 | 
					        e.preventDefault();
 | 
				
			||||||
 | 
					        console.log('a');
 | 
				
			||||||
 | 
					        window.print();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,85 @@
 | 
				
			||||||
 | 
					function VMTerminateStatus($container, url) {
 | 
				
			||||||
 | 
					    $.ajax({
 | 
				
			||||||
 | 
					        url: url,
 | 
				
			||||||
 | 
					        type: 'GET',
 | 
				
			||||||
 | 
					        dataType: 'json',
 | 
				
			||||||
 | 
					        success: function(data) {
 | 
				
			||||||
 | 
					            VMTerminateSuccess($container, data);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        error: function() {
 | 
				
			||||||
 | 
					            setTimeout(function(){
 | 
				
			||||||
 | 
					                VMTerminateStatus($container, url);
 | 
				
			||||||
 | 
					            }, 5000);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function VMTerminateActive($container, altText) {
 | 
				
			||||||
 | 
					    $container.find('.alert-danger').addClass('hide');
 | 
				
			||||||
 | 
					    $container.addClass('processing')
 | 
				
			||||||
 | 
					        .find('.vm-item-lg').attr('class', '')
 | 
				
			||||||
 | 
					        .addClass('vm-item-lg vm-color-failed')
 | 
				
			||||||
 | 
					        .text(altText);
 | 
				
			||||||
 | 
					    $container.find('.btn').prop('disabled', true);
 | 
				
			||||||
 | 
					    $('#confirm-cancel').modal('hide');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function VMTerminateSuccess($container, data) {
 | 
				
			||||||
 | 
					    $container.addClass('terminate-success')
 | 
				
			||||||
 | 
					        .find('.vm-item-lg').text(data.text);
 | 
				
			||||||
 | 
					    $container.find('.btn').remove();
 | 
				
			||||||
 | 
					    $('#terminate-success').modal('show');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function VMTerminateFail($container, data, text) {
 | 
				
			||||||
 | 
					    $container.addClass('terminate-fail')
 | 
				
			||||||
 | 
					        .find('.vm-item-lg').text(text);
 | 
				
			||||||
 | 
					    $container.find('.btn').prop('disabled', false);
 | 
				
			||||||
 | 
					    $container.find('.alert-danger').text(data.text).removeClass('hide');
 | 
				
			||||||
 | 
					    $container.removeClass('processing');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(document).ready(function() {
 | 
					$(document).ready(function() {
 | 
				
			||||||
 | 
					    $('#confirm-cancel').on('click', '.btn-ok', function(e) {
 | 
				
			||||||
 | 
					        var url = $('#virtual_machine_cancel_form').attr('action');
 | 
				
			||||||
 | 
					        var $container = $('#terminate-VM');
 | 
				
			||||||
 | 
					        var text = $container.find('.vm-item-lg').text();
 | 
				
			||||||
 | 
					        var altText = $container.attr('data-alt');
 | 
				
			||||||
 | 
					        VMTerminateActive($container, altText);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $.post(url)
 | 
				
			||||||
 | 
					            .done(function(data) {
 | 
				
			||||||
 | 
					                if (data.status == true) {
 | 
				
			||||||
 | 
					                    VMTerminateSuccess($container, data);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    if ('text' in data) {
 | 
				
			||||||
 | 
					                        VMTerminateFail($container, data, text);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        VMTerminateStatus($container, url);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .fail(function(data) {
 | 
				
			||||||
 | 
					                if (data.status==504) {
 | 
				
			||||||
 | 
					                    VMTerminateStatus($container, url);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    VMTerminateFail($container, data, text);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var hash = window.location.hash;
 | 
				
			||||||
 | 
					    hash && $('ul.nav a[href="' + hash + '"]').tab('show');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $('.nav-tabs a').click(function(e) {
 | 
				
			||||||
 | 
					        $(this).tab('show');
 | 
				
			||||||
 | 
					        var scrollmem = $('body').scrollTop() || $('html').scrollTop();
 | 
				
			||||||
 | 
					        window.location.hash = this.hash;
 | 
				
			||||||
 | 
					        $('html,body').scrollTop(scrollmem);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $('.modal-text').removeClass('hide');
 | 
				
			||||||
    var create_vm_form = $('#virtual_machine_create_form');
 | 
					    var create_vm_form = $('#virtual_machine_create_form');
 | 
				
			||||||
    create_vm_form.submit(function () {
 | 
					    create_vm_form.submit(function () {
 | 
				
			||||||
        $('#btn-create-vm').prop('disabled', true);
 | 
					        $('#btn-create-vm').prop('disabled', true);
 | 
				
			||||||
| 
						 | 
					@ -22,6 +103,7 @@ $(document).ready(function () {
 | 
				
			||||||
                    fa_icon = $('.modal-icon > .fa');
 | 
					                    fa_icon = $('.modal-icon > .fa');
 | 
				
			||||||
                    fa_icon.attr('class', 'fa fa-times');
 | 
					                    fa_icon.attr('class', 'fa fa-times');
 | 
				
			||||||
                    $('.modal-header > .close').attr('class', 'close');
 | 
					                    $('.modal-header > .close').attr('class', 'close');
 | 
				
			||||||
 | 
					                    $('.modal-text').addClass('hide');
 | 
				
			||||||
                    if (typeof(create_vm_error_message) !== 'undefined') {
 | 
					                    if (typeof(create_vm_error_message) !== 'undefined') {
 | 
				
			||||||
                        $('#createvm-modal-title').text(create_vm_error_message);
 | 
					                        $('#createvm-modal-title').text(create_vm_error_message);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -30,19 +112,4 @@ $(document).ready(function () {
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					 | 
				
			||||||
    $('#confirm-cancel').on('click', '.btn-ok', function (e) {
 | 
					 | 
				
			||||||
        $('#virtual_machine_cancel_form').trigger('submit');
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var hash = window.location.hash;
 | 
					 | 
				
			||||||
    hash && $('ul.nav a[href="' + hash + '"]').tab('show');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $('.nav-tabs a').click(function (e) {
 | 
					 | 
				
			||||||
        $(this).tab('show');
 | 
					 | 
				
			||||||
        var scrollmem = $('body').scrollTop() || $('html').scrollTop();
 | 
					 | 
				
			||||||
        window.location.hash = this.hash;
 | 
					 | 
				
			||||||
        $('html,body').scrollTop(scrollmem);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
    <link href="{% static 'hosting/css/commons.css' %}" rel="stylesheet">
 | 
					    <link href="{% static 'hosting/css/commons.css' %}" rel="stylesheet">
 | 
				
			||||||
    <link href="{% static 'hosting/css/virtual-machine.css' %}" rel="stylesheet">
 | 
					    <link href="{% static 'hosting/css/virtual-machine.css' %}" rel="stylesheet">
 | 
				
			||||||
    <link href="{% static 'hosting/css/dashboard.css' %}" rel="stylesheet">
 | 
					    <link href="{% static 'hosting/css/dashboard.css' %}" rel="stylesheet">
 | 
				
			||||||
 | 
					    <link href="{% static 'hosting/css/price_calculator.css' %}" rel="stylesheet">
 | 
				
			||||||
    {% block css_extra %}
 | 
					    {% block css_extra %}
 | 
				
			||||||
    {% endblock css_extra %}
 | 
					    {% endblock css_extra %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,9 +34,6 @@
 | 
				
			||||||
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
 | 
					    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
 | 
				
			||||||
    <link href="//fonts.googleapis.com/css?family=Lato:300,400,500,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
 | 
					    <link href="//fonts.googleapis.com/css?family=Lato:300,400,500,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
 | 
				
			||||||
    <link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
 | 
					    <link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
 | 
				
			||||||
    <link rel="stylesheet" href="{% static 'hosting/css/owl.carousel.min.css' %}">
 | 
					 | 
				
			||||||
    <link rel="stylesheet" href="{% static 'hosting/css/owl.theme.default.min.css' %}">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
 | 
					    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
 | 
				
			||||||
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
 | 
					    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
 | 
				
			||||||
| 
						 | 
					@ -76,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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,6 +92,13 @@
 | 
				
			||||||
    <!-- Init JavaScript -->
 | 
					    <!-- Init JavaScript -->
 | 
				
			||||||
    <script src="{% static 'hosting/js/initial.js' %}"></script>
 | 
					    <script src="{% static 'hosting/js/initial.js' %}"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% block js_extra %}
 | 
				
			||||||
 | 
					        {% comment %}
 | 
				
			||||||
 | 
					            this block is above some files, because on stripe error scripts below the stripe
 | 
				
			||||||
 | 
					            script are not properly executed.
 | 
				
			||||||
 | 
					        {% endcomment %}
 | 
				
			||||||
 | 
					    {% endblock js_extra %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <script src="https://js.stripe.com/v3/"></script>
 | 
					    <script src="https://js.stripe.com/v3/"></script>
 | 
				
			||||||
    <script src="https://js.stripe.com/v2/"></script>
 | 
					    <script src="https://js.stripe.com/v2/"></script>
 | 
				
			||||||
    <!-- Stripe Lib -->
 | 
					    <!-- Stripe Lib -->
 | 
				
			||||||
| 
						 | 
					@ -108,8 +113,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>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										87
									
								
								hosting/templates/hosting/calculator_form.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								hosting/templates/hosting/calculator_form.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,87 @@
 | 
				
			||||||
 | 
					{% load staticfiles i18n%}
 | 
				
			||||||
 | 
					<form id="order_form" method="POST" action="" data-toggle="validator" role="form">
 | 
				
			||||||
 | 
					    {% csrf_token %}
 | 
				
			||||||
 | 
					    <div class="price">
 | 
				
			||||||
 | 
					        <span id="total">15</span>
 | 
				
			||||||
 | 
					        <span>CHF/{% trans "Month" %}</span>
 | 
				
			||||||
 | 
					        <div class="price-text">
 | 
				
			||||||
 | 
					            <span>{% trans "VAT included" %}</span>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="descriptions">
 | 
				
			||||||
 | 
					        <div class="form-group">
 | 
				
			||||||
 | 
					            <div class="description input">
 | 
				
			||||||
 | 
					                <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" data-error="{% trans 'Please enter a value in range 1 - 48.' %}" required>
 | 
				
			||||||
 | 
					                <span> Core</span>
 | 
				
			||||||
 | 
					                <i class="fa fa-plus 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>
 | 
				
			||||||
 | 
					        <div class="form-group">
 | 
				
			||||||
 | 
					            <div class="description input">
 | 
				
			||||||
 | 
					                <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"
 | 
				
			||||||
 | 
					                       data-error="{% trans 'Please enter a value in range 2 - 200.' %}" required>
 | 
				
			||||||
 | 
					                <span> GB RAM</span>
 | 
				
			||||||
 | 
					                <i class="fa fa-plus 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>
 | 
				
			||||||
 | 
					        <div class="form-group">
 | 
				
			||||||
 | 
					            <div class="description input">
 | 
				
			||||||
 | 
					                <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"
 | 
				
			||||||
 | 
					                       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 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>
 | 
				
			||||||
 | 
					        <div class="form-group">
 | 
				
			||||||
 | 
					            <div class="description select-configuration input justify-center">
 | 
				
			||||||
 | 
					                <label for="config">OS</label>
 | 
				
			||||||
 | 
					                <select name="config" id="">
 | 
				
			||||||
 | 
					                    {% 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 %}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <input type="hidden" name="total">
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <input type="submit" class="btn btn-primary disabled" value="{% trans 'Continue' %}"></input>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
{% extends "hosting/base_short.html" %}
 | 
					{% extends "hosting/base_short.html" %}
 | 
				
			||||||
{% load staticfiles bootstrap3 i18n %}
 | 
					{% load staticfiles bootstrap3 i18n %}
 | 
				
			||||||
{% block content %} 
 | 
					 | 
				
			||||||
<div>
 | 
					 | 
				
			||||||
    <div class="dashboard-container" >
 | 
					 | 
				
			||||||
        <div class="row">
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <div class="col-md-12">
 | 
					{% block content %}
 | 
				
			||||||
                    <br/>
 | 
					<div class="dashboard-container create-vm-container">
 | 
				
			||||||
 | 
					    <div class="row">
 | 
				
			||||||
 | 
					        <div class="col-sm-5">
 | 
				
			||||||
 | 
					          <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>
 | 
				
			||||||
                {% if messages %}
 | 
					                {% if messages %}
 | 
				
			||||||
                    <div class="alert alert-warning">
 | 
					                    <div class="alert alert-warning">
 | 
				
			||||||
                        {% for message in messages %}
 | 
					                        {% for message in messages %}
 | 
				
			||||||
| 
						 | 
					@ -15,56 +15,16 @@
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                {% endif %}
 | 
					                {% endif %}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
                {% if not error %}
 | 
					 | 
				
			||||||
                <div class="dashboard-title">
 | 
					 | 
				
			||||||
                    <h3>{% trans "New Virtual Machine"%} </h3>
 | 
					 | 
				
			||||||
                    <hr/>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="col-sm-6">
 | 
				
			||||||
                <form method="POST" action="">
 | 
					            <div class="price-calc-section no-padding">
 | 
				
			||||||
                    {% csrf_token %}
 | 
					                <div class="landing card">
 | 
				
			||||||
            
 | 
					                    <div class="caption">
 | 
				
			||||||
                    <div class="step-title">
 | 
					                        {% include "hosting/calculator_form.html" %}
 | 
				
			||||||
                        <h4>{% trans "Step 1. Select VM Template:" %} </h4>
 | 
					                    </div>
 | 
				
			||||||
                    </div>
 | 
					                </div>
 | 
				
			||||||
                    <div class="parent-container">
 | 
					            </div>
 | 
				
			||||||
                        <div class="container-os owl-carousel owl-theme" id="containerOs">
 | 
					 | 
				
			||||||
                            
 | 
					 | 
				
			||||||
                            {% for template in templates %}
 | 
					 | 
				
			||||||
                                <div class="os-circle" data-id="{{template.id}}">
 | 
					 | 
				
			||||||
                                    <span class="text" >{{template.name}}</span>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            {% endfor %}
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <input type="hidden" name="vm_template_id">
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                     <div class="step-title">
 | 
					 | 
				
			||||||
                        <h4>{% trans "Step2. Select VM Configuration" %}</h4>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="parent-container">
 | 
					 | 
				
			||||||
                        <div class="container-os config owl-carousel owl-theme">
 | 
					 | 
				
			||||||
                           
 | 
					 | 
				
			||||||
                            {% for config in configuration_options %}
 | 
					 | 
				
			||||||
                                <div class="config-box" data-id="{{config.id}}" data-price="{{config.price|floatformat}}">
 | 
					 | 
				
			||||||
                                    <span>CORE: {{config.cpu|floatformat}}</span>
 | 
					 | 
				
			||||||
                                    <span>RAM: {{config.memory|floatformat}} GB</span>
 | 
					 | 
				
			||||||
                                    <span>SSD: {{config.disk_size|floatformat}} GB</span>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            {% endfor %}
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                         <input type="hidden" name="configuration">
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div class="container-button">
 | 
					 | 
				
			||||||
                          <div class="price">
 | 
					 | 
				
			||||||
                            <span class="label-price">{% trans "Price " %}<span id="priceValue">0</span>{% trans "CHF/Month" %}</span>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                         <button class="btn btn-success" >{% trans "Start VM"%} </button>   
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </form>
 | 
					 | 
				
			||||||
                {% endif %}
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
{%endblock%}
 | 
					{%endblock%}
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,8 @@
 | 
				
			||||||
                        <a class="unlink" href="{% url 'hosting:signup' %}">{% trans "Sign up"%}</a>
 | 
					                        <a class="unlink" href="{% url 'hosting:signup' %}">{% trans "Sign up"%}</a>
 | 
				
			||||||
                        <span class="text"> or </span>
 | 
					                        <span class="text"> or </span>
 | 
				
			||||||
                        <a class="unlink" href="{% url 'hosting:reset_password' %}">{% trans "Forgot your password ? "%}</a>
 | 
					                        <a class="unlink" href="{% url 'hosting:reset_password' %}">{% trans "Forgot your password ? "%}</a>
 | 
				
			||||||
 | 
					                        <span class="text"> or </span><br/>
 | 
				
			||||||
 | 
					                        <a class="unlink" href="{% url 'hosting:resend_activation_link' %}">{% trans "Resend activation link"%}</a>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,173 +4,156 @@
 | 
				
			||||||
{% load custom_tags %}
 | 
					{% load custom_tags %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block content %}
 | 
					{% block content %}
 | 
				
			||||||
 | 
					<div id="order-detail{{order.pk}}" class="order-detail-container">
 | 
				
			||||||
<div class="order-detail-container">
 | 
					 | 
				
			||||||
    {% if messages %}
 | 
					    {% if messages %}
 | 
				
			||||||
    <div class="row">
 | 
					 | 
				
			||||||
        <div class="col-xs-12 col-md-8 col-md-offset-2">
 | 
					 | 
				
			||||||
            <br/>
 | 
					 | 
				
			||||||
        <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>
 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    {% endif %}
 | 
					    {% endif %}
 | 
				
			||||||
    {% if not error %}
 | 
					    {% if not error %}
 | 
				
			||||||
    <div class="row">
 | 
					        <div class="dashboard-container-head">
 | 
				
			||||||
        <div class="col-xs-12 col-md-8 col-md-offset-2">
 | 
					            <h1 class="dashboard-title-thin">
 | 
				
			||||||
            <div class="invoice-title">
 | 
					                <img src="{% static 'hosting/img/billing.svg' %}" class="un-icon">{% blocktrans with page_header_text=page_header_text|default:"Invoice" %}{{page_header_text}}{% endblocktrans %}
 | 
				
			||||||
                <h2>{{page_header_text}}</h2>
 | 
					            </h1>
 | 
				
			||||||
                <h3 class="pull-right">
 | 
					            <div class="dashboard-container-options">
 | 
				
			||||||
                    {% if order %}
 | 
					                <button type="button" class="btn-plain btn-pdf" data-target="#order-detail{{order.pk}}"><img src="{% static 'hosting/img/icon-pdf.svg' %}" class="svg-img"></button>
 | 
				
			||||||
                    {% trans "Order #"%} {{order.id}}
 | 
					                <button type="button" class="btn-plain btn-print"><img src="{% static 'hosting/img/icon-print.svg' %}" class="svg-img"></button>
 | 
				
			||||||
                    {% endif %}
 | 
					 | 
				
			||||||
                </h3>
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <hr>
 | 
					        </div>
 | 
				
			||||||
            <div class="row">
 | 
					        <div class="order-details">
 | 
				
			||||||
                <div class="col-xs-12 col-md-6 pull-right order-confirm-date">
 | 
					            {% if order %}
 | 
				
			||||||
                    <address>
 | 
					                <p>
 | 
				
			||||||
                        <strong>{% trans "Date"%}:</strong><br>
 | 
					                    <strong>{% trans "Order #" %} {{order.id}}</strong>
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            {% endif %}
 | 
				
			||||||
 | 
					            <p>
 | 
				
			||||||
 | 
					                <strong>{% trans "Invoice Date" %}:</strong>
 | 
				
			||||||
                <span id="order-created_at">
 | 
					                <span id="order-created_at">
 | 
				
			||||||
                    {% if order %}
 | 
					                    {% if order %}
 | 
				
			||||||
                        {{order.created_at|date:'Y-m-d H:i'}}
 | 
					                        {{order.created_at|date:'Y-m-d H:i'}}
 | 
				
			||||||
                    {% else %}
 | 
					                    {% else %}
 | 
				
			||||||
                        {% now "Y-m-d H:i" %}
 | 
					                        {% now "Y-m-d H:i" %}
 | 
				
			||||||
                    {% endif %}
 | 
					                    {% endif %}
 | 
				
			||||||
                            </span><br><br>
 | 
					                </span>
 | 
				
			||||||
 | 
					            </p>
 | 
				
			||||||
            {% if order %}
 | 
					            {% if order %}
 | 
				
			||||||
                        <strong>{% trans "Status:"%}</strong><br>
 | 
					                <p>
 | 
				
			||||||
 | 
					                    <strong>{% trans "Status" %}: </strong>
 | 
				
			||||||
 | 
					                    <strong>
 | 
				
			||||||
                        {% if order.status == 'Approved' %}
 | 
					                        {% if order.status == 'Approved' %}
 | 
				
			||||||
                        <strong class="text-success">
 | 
					                            <span class="vm-color-online">{% trans "Approved" %}</span>
 | 
				
			||||||
                            {% trans "Approved" %}
 | 
					 | 
				
			||||||
                        </strong>
 | 
					 | 
				
			||||||
                        {% else %}
 | 
					                        {% else %}
 | 
				
			||||||
                        <strong class="text-danger">
 | 
					                            <span class="vm-status-failed">{% trans "Declined" %}</span>
 | 
				
			||||||
                            {% trans "Declined" %}
 | 
					                        {% endif %}
 | 
				
			||||||
                    </strong>
 | 
					                    </strong>
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
            {% endif %}
 | 
					            {% endif %}
 | 
				
			||||||
                        <br><br>
 | 
					            <hr>
 | 
				
			||||||
                        {% endif %}
 | 
					            <div>
 | 
				
			||||||
                    </address>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div class="col-xs-12 col-md-6">
 | 
					 | 
				
			||||||
                <address>
 | 
					                <address>
 | 
				
			||||||
                        <h3><b>{% trans "Billed To:"%}</b></h3>
 | 
					                    <h4>{% trans "Billed to" %}:</h4>
 | 
				
			||||||
 | 
					                    <p>
 | 
				
			||||||
                        {% if order %}
 | 
					                        {% if order %}
 | 
				
			||||||
                            {{user.name}}<br>
 | 
					                            {{user.name}}<br>
 | 
				
			||||||
                            {{order.billing_address.street_address}}, {{order.billing_address.postal_code}}<br>
 | 
					                            {{order.billing_address.street_address}}, {{order.billing_address.postal_code}}<br>
 | 
				
			||||||
                        {{order.billing_address.city}},
 | 
					                            {{order.billing_address.city}}, {{order.billing_address.country}}
 | 
				
			||||||
                        {{order.billing_address.country}}.
 | 
					 | 
				
			||||||
                        {% else %}
 | 
					                        {% else %}
 | 
				
			||||||
                            {% with request.session.billing_address_data as billing_address %}
 | 
					                            {% with request.session.billing_address_data as billing_address %}
 | 
				
			||||||
                        {{billing_address|get_value_from_dict:'cardholder_name'}}<br>
 | 
					                                {{billing_address.cardholder_name}}<br>
 | 
				
			||||||
                        {{billing_address|get_value_from_dict:'street_address'}},
 | 
					                                {{billing_address.street_address}}, {{billing_address.postal_code}}<br>
 | 
				
			||||||
                        {{billing_address|get_value_from_dict:'postal_code'}}<br>
 | 
					                                {{billing_address.city}}, {{billing_address.country}}
 | 
				
			||||||
                        {{billing_address|get_value_from_dict:'city'}},
 | 
					 | 
				
			||||||
                        {{billing_address|get_value_from_dict:'country'}}.
 | 
					 | 
				
			||||||
                            {% endwith %}
 | 
					                            {% endwith %}
 | 
				
			||||||
                        {% endif %}
 | 
					                        {% endif %}
 | 
				
			||||||
 | 
					                    </p>
 | 
				
			||||||
                </address>
 | 
					                </address>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <hr>
 | 
				
			||||||
            </div>
 | 
					            <div>
 | 
				
			||||||
            <div class="row">
 | 
					                <h4>{% trans "Payment method" %}:</h4>
 | 
				
			||||||
                <div class="col-xs-6">
 | 
					                <p>
 | 
				
			||||||
                    <address>
 | 
					 | 
				
			||||||
                        <strong>{% trans "Payment Method:"%}</strong><br>
 | 
					 | 
				
			||||||
                    {% if order %}
 | 
					                    {% if order %}
 | 
				
			||||||
                        {{order.cc_brand}} {% trans "ending in" %} ****
 | 
					                        {{order.cc_brand}} {% trans "ending in" %} ****
 | 
				
			||||||
                        {{order.last4}}<br>
 | 
					                        {{order.last4}}<br>
 | 
				
			||||||
                        {{user.email}}
 | 
					                        {{user.email}}
 | 
				
			||||||
                    {% else %}
 | 
					                    {% else %}
 | 
				
			||||||
                        {{cc_brand}} {% trans "ending in" %} ****
 | 
					                        {{cc_brand|default:'Card'}} {% trans "ending in" %} ****
 | 
				
			||||||
                        {{cc_last4}}<br>
 | 
					                        {{cc_last4}}<br>
 | 
				
			||||||
 | 
					                        {% if request.user.is_authenticated %}
 | 
				
			||||||
 | 
					                            {{request.user.email}}
 | 
				
			||||||
 | 
					                        {% else %}
 | 
				
			||||||
                            {{request.session.user.email}}
 | 
					                            {{request.session.user.email}}
 | 
				
			||||||
                        {% endif %}
 | 
					                        {% endif %}
 | 
				
			||||||
                    </address>
 | 
					                    {% endif %}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            </div>
 | 
					            <hr>
 | 
				
			||||||
        </div>
 | 
					            <div>
 | 
				
			||||||
    </div>
 | 
					                <h4>{% trans "Order summary" %}</h4>
 | 
				
			||||||
 | 
					                <p>
 | 
				
			||||||
 | 
					                    <strong>{% trans "Product" %}:</strong> {{vm.name}}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
                <div class="row">
 | 
					                <div class="row">
 | 
				
			||||||
        <div class="col-md-8 col-md-offset-2">
 | 
					                    <div class="col-sm-6">
 | 
				
			||||||
            <h3><b>{% trans "Order summary"%}</b></h3>
 | 
					                        {% comment %}
 | 
				
			||||||
            <hr>
 | 
					                        <p>
 | 
				
			||||||
            <div class="content">
 | 
					                            <span>{% trans "Period" %}</span>
 | 
				
			||||||
                {% if request.session.specs %}
 | 
					                            <span class="pull-right">{{}}</span>
 | 
				
			||||||
                {% with request.session.specs as vm %}
 | 
					 | 
				
			||||||
                <p><b>{% trans "Cores"%}</b>
 | 
					 | 
				
			||||||
                    <span class="pull-right">{{vm.cpu}}</span>
 | 
					 | 
				
			||||||
                        </p>
 | 
					                        </p>
 | 
				
			||||||
                <hr>
 | 
					                        {% endcomment %}
 | 
				
			||||||
                <p><b>{% trans "Memory"%}</b>
 | 
					                        <p>
 | 
				
			||||||
                    <span class="pull-right">{{vm.memory}} GB</span>
 | 
					                            <span>{% trans "Cores" %}</span>
 | 
				
			||||||
                </p>
 | 
					                            {% if vm.cores %}
 | 
				
			||||||
                <hr>
 | 
					                                <span class="pull-right">{{vm.cores|floatformat}}</span>
 | 
				
			||||||
                <p><b>{% trans "Disk space"%}</b>
 | 
					 | 
				
			||||||
                    <span class="pull-right">{{vm.disk_size}} GB</span>
 | 
					 | 
				
			||||||
                </p>
 | 
					 | 
				
			||||||
                <hr>
 | 
					 | 
				
			||||||
                <p><b>{% trans "Configuration"%}</b>
 | 
					 | 
				
			||||||
                    <span class="pull-right">{{request.session.template.name}}</span>
 | 
					 | 
				
			||||||
                </p>
 | 
					 | 
				
			||||||
                <hr>
 | 
					 | 
				
			||||||
                <h4>{% trans "Total"%}
 | 
					 | 
				
			||||||
                    <p class="pull-right">
 | 
					 | 
				
			||||||
                        <b>{{vm.price}} CHF</b>
 | 
					 | 
				
			||||||
                        <span class="dcl-price-month"> /{% trans "Month" %}
 | 
					 | 
				
			||||||
                                </span>
 | 
					 | 
				
			||||||
                    </p>
 | 
					 | 
				
			||||||
                </h4>
 | 
					 | 
				
			||||||
                {% endwith %}
 | 
					 | 
				
			||||||
                            {% else %}
 | 
					                            {% else %}
 | 
				
			||||||
                <p><b>{% trans "Cores"%}</b>
 | 
					                                <span class="pull-right">{{vm.cpu|floatformat}}</span>
 | 
				
			||||||
                    <span class="pull-right">{{vm.cores}}</span>
 | 
					                            {% endif %}
 | 
				
			||||||
                        </p>
 | 
					                        </p>
 | 
				
			||||||
                <hr>
 | 
					                        <p>
 | 
				
			||||||
                <p><b>{% trans "Memory"%}</b>
 | 
					                            <span>{% trans "Memory" %}</span>
 | 
				
			||||||
                            <span class="pull-right">{{vm.memory}} GB</span>
 | 
					                            <span class="pull-right">{{vm.memory}} GB</span>
 | 
				
			||||||
                        </p>
 | 
					                        </p>
 | 
				
			||||||
                <hr>
 | 
					                        <p>
 | 
				
			||||||
                <p><b>{% trans "Disk space"%}</b>
 | 
					                            <span>{% trans "Disk space" %}</span>
 | 
				
			||||||
                            <span class="pull-right">{{vm.disk_size}} GB</span>
 | 
					                            <span class="pull-right">{{vm.disk_size}} GB</span>
 | 
				
			||||||
                        </p>
 | 
					                        </p>
 | 
				
			||||||
 | 
					                        <p>
 | 
				
			||||||
 | 
					                            <span>{% trans "Total" %}</span>
 | 
				
			||||||
 | 
					                            <span class="pull-right">{{vm.price}} CHF</span>
 | 
				
			||||||
 | 
					                        </p>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            {% if not order %}
 | 
				
			||||||
                <hr>
 | 
					                <hr>
 | 
				
			||||||
                <h4>{% trans "Total"%}<p class="pull-right"><b>{{vm.price}}
 | 
					 | 
				
			||||||
                    CHF</b><span
 | 
					 | 
				
			||||||
                        class="dcl-price-month"> /{% trans "Month" %}</span>
 | 
					 | 
				
			||||||
                </p></h4>
 | 
					 | 
				
			||||||
            {% endif %}
 | 
					            {% endif %}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
            <br/>
 | 
					 | 
				
			||||||
        {% if not order %}
 | 
					        {% if not order %}
 | 
				
			||||||
            <form method="post" id="virtual_machine_create_form">
 | 
					            <form method="post" id="virtual_machine_create_form">
 | 
				
			||||||
                {% csrf_token %}
 | 
					                {% csrf_token %}
 | 
				
			||||||
                <div class="row">
 | 
					                <div class="row">
 | 
				
			||||||
                    <div class="col-sm-8">
 | 
					                    <div class="col-sm-8">
 | 
				
			||||||
                        <p class="dcl-place-order-text">{% blocktrans with vm_price=request.session.specs.price %}By clicking "Place order" this plan will charge your credit card account with the fee of {{ vm_price }}CHF/month{% endblocktrans %}.</p>
 | 
					                        <div class="dcl-place-order-text">{% blocktrans with vm_price=request.session.specs.price %}By clicking "Place order" this plan will charge your credit card account with the fee of {{ vm_price }}CHF/month{% endblocktrans %}.</div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <div class="col-sm-4 content">
 | 
					                    <div class="col-sm-4 order-confirm-btn text-right">
 | 
				
			||||||
                        <button class="btn btn-info pull-right"
 | 
					                        <button class="btn choice-btn" id="btn-create-vm" data-href="{% url 'hosting:order-confirmation' %}" data-toggle="modal" data-target="#createvm-modal">
 | 
				
			||||||
                                id="btn-create-vm"
 | 
					 | 
				
			||||||
                                data-href="{% url 'hosting:order-confirmation' %}"
 | 
					 | 
				
			||||||
                                data-toggle="modal"
 | 
					 | 
				
			||||||
                                data-target="#createvm-modal">
 | 
					 | 
				
			||||||
                            {% trans "Place order" %}
 | 
					                            {% trans "Place order" %}
 | 
				
			||||||
                        </button>
 | 
					                        </button>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </form>
 | 
					            </form>
 | 
				
			||||||
        {% endif %}
 | 
					        {% endif %}
 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    {% endif %}
 | 
					    {% endif %}
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if order %}
 | 
				
			||||||
 | 
					    <div class="text-center" style="margin-bottom: 50px;">
 | 
				
			||||||
 | 
					        <a class="btn btn-vm-back" href="{% url 'hosting:orders' %}">{% trans "BACK TO LIST" %}</a>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if not order %}
 | 
				
			||||||
    <!-- Create VM Modal -->
 | 
					    <!-- Create VM Modal -->
 | 
				
			||||||
    <div class="modal fade" id="createvm-modal" tabindex="-1" role="dialog"
 | 
					    <div class="modal fade" id="createvm-modal" tabindex="-1" role="dialog"
 | 
				
			||||||
         aria-hidden="true" data-backdrop="static" data-keyboard="false">
 | 
					         aria-hidden="true" data-backdrop="static" data-keyboard="false">
 | 
				
			||||||
| 
						 | 
					@ -199,11 +182,11 @@
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <!-- / Create VM Modal -->
 | 
					    <!-- / Create VM Modal -->
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script type="text/javascript">
 | 
					<script type="text/javascript">
 | 
				
			||||||
    {% trans "Some problem encountered. Please try again later." as err_msg %}
 | 
					    {% trans "Some problem encountered. Please try again later." as err_msg %}
 | 
				
			||||||
    var create_vm_error_message = '{{err_msg|safe}}.';
 | 
					    var create_vm_error_message = '{{err_msg|safe}}';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    window.onload = function () {
 | 
					    window.onload = function () {
 | 
				
			||||||
        var locale_date = moment.utc(document.getElementById("order-created_at").textContent, 'YYYY-MM-DD HH:mm').toDate();
 | 
					        var locale_date = moment.utc(document.getElementById("order-created_at").textContent, 'YYYY-MM-DD HH:mm').toDate();
 | 
				
			||||||
| 
						 | 
					@ -211,7 +194,12 @@
 | 
				
			||||||
        document.getElementById('order-created_at').innerHTML = locale_date;
 | 
					        document.getElementById('order-created_at').innerHTML = locale_date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
{%endblock%}
 | 
					{%endblock%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block js_extra %}
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
 | 
				
			||||||
 | 
					    <script src="{% static 'hosting/js/html2pdf.js' %}"></script>
 | 
				
			||||||
 | 
					    <script src="{% static 'hosting/js/order.js' %}"></script>
 | 
				
			||||||
 | 
					{% endblock js_extra %}
 | 
				
			||||||
							
								
								
									
										36
									
								
								hosting/templates/hosting/resend_activation_link.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								hosting/templates/hosting/resend_activation_link.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					{% extends "hosting/base_short.html" %}
 | 
				
			||||||
 | 
					{% 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>
 | 
				
			||||||
 | 
					        <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 sign-up">
 | 
				
			||||||
 | 
					                    <h2  class="section-heading">{% trans "Resend activation link"%}</h2>
 | 
				
			||||||
 | 
					                    <form action="{% url 'hosting:resend_activation_link' %}" method="post" class="form" novalidate>
 | 
				
			||||||
 | 
					                        {% csrf_token %}
 | 
				
			||||||
 | 
					                        {% for field in form %}
 | 
				
			||||||
 | 
					                            {% bootstrap_field field show_label=False %}
 | 
				
			||||||
 | 
					                        {% endfor %}
 | 
				
			||||||
 | 
					                        {% buttons %}
 | 
				
			||||||
 | 
					                            <button type="submit" class="btn btn-block btn-success">
 | 
				
			||||||
 | 
					                                {% trans "Submit"%}
 | 
				
			||||||
 | 
					                            </button>
 | 
				
			||||||
 | 
					                        {% endbuttons %}
 | 
				
			||||||
 | 
					                    </form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
| 
						 | 
					@ -53,22 +53,29 @@
 | 
				
			||||||
				<h2 class="vm-detail-title">{% trans "Status" %} <img src="{% static 'hosting/img/connected.svg' %}" class="un-icon"></h2>
 | 
									<h2 class="vm-detail-title">{% trans "Status" %} <img src="{% static 'hosting/img/connected.svg' %}" class="un-icon"></h2>
 | 
				
			||||||
				<div class="vm-vmid">
 | 
									<div class="vm-vmid">
 | 
				
			||||||
					<div class="vm-item-subtitle">{% trans "Your VM is" %}</div>
 | 
										<div class="vm-item-subtitle">{% trans "Your VM is" %}</div>
 | 
				
			||||||
 | 
											<div id="terminate-VM" data-alt="{% trans 'Terminating' %}">
 | 
				
			||||||
							{% if virtual_machine.state == 'PENDING' %}
 | 
												{% if virtual_machine.state == 'PENDING' %}
 | 
				
			||||||
								<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div>
 | 
													<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div>
 | 
				
			||||||
							{% elif  virtual_machine.state == 'ACTIVE' %}
 | 
												{% elif  virtual_machine.state == 'ACTIVE' %}
 | 
				
			||||||
								<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div>
 | 
													<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div>
 | 
				
			||||||
							{% elif  virtual_machine.state == 'FAILED'%}
 | 
												{% elif  virtual_machine.state == 'FAILED'%}
 | 
				
			||||||
								<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div>
 | 
													<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div>
 | 
				
			||||||
 | 
												{% else %}
 | 
				
			||||||
 | 
													<div class="vm-item-lg"></div>
 | 
				
			||||||
							{% endif %}
 | 
												{% endif %}
 | 
				
			||||||
							{% if not virtual_machine.status == 'canceled' %}
 | 
												{% if not virtual_machine.status == 'canceled' %}
 | 
				
			||||||
								<form method="POST" id="virtual_machine_cancel_form" class="cancel-form" action="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}">
 | 
													<form method="POST" id="virtual_machine_cancel_form" class="cancel-form" action="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}">
 | 
				
			||||||
									{% csrf_token %}
 | 
														{% csrf_token %}
 | 
				
			||||||
								</form>
 | 
													</form>
 | 
				
			||||||
						<button data-href="{% url 'hosting:virtual_machines' virtual_machine.vm_id %}" data-toggle="modal" data-target="#confirm-cancel" class="btn btn-vm-term">{% trans "Terminate VM" %}</button>
 | 
													<button data-toggle="modal" data-target="#confirm-cancel" class="btn btn-vm-term">{% trans "Terminate VM" %}</button>
 | 
				
			||||||
 | 
													<div class="alert alert-danger hide">
 | 
				
			||||||
 | 
														{% trans "Sorry, there was an unexpected error. Kindly retry." %}
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
							{% endif %}
 | 
												{% endif %}
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
		<div class="vm-contact-us">
 | 
							<div class="vm-contact-us">
 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
				<h2 class="vm-detail-title">{% trans "Support / Contact" %} <img class="un-icon visible-xs" src="{% static 'hosting/img/24-hours-support.svg' %}"></h2>
 | 
									<h2 class="vm-detail-title">{% trans "Support / Contact" %} <img class="un-icon visible-xs" src="{% static 'hosting/img/24-hours-support.svg' %}"></h2>
 | 
				
			||||||
| 
						 | 
					@ -109,4 +116,21 @@
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<!-- / Cancel Modal -->
 | 
						<!-- / Cancel Modal -->
 | 
				
			||||||
 | 
						<!-- Success Modal -->
 | 
				
			||||||
 | 
						<div class="modal fade" id="terminate-success" tabindex="-1" role="dialog" aria-hidden="true">
 | 
				
			||||||
 | 
					    <div class="modal-dialog">
 | 
				
			||||||
 | 
					      <div class="modal-content">
 | 
				
			||||||
 | 
									<div class="modal-header">
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
					        <div class="modal-body">
 | 
				
			||||||
 | 
										<div class="modal-icon"><i class="fa fa-check" aria-hidden="true"></i></div>
 | 
				
			||||||
 | 
										<h4 class="modal-title" id="ModalLabel">{% blocktrans with machine_name=virtual_machine.name %}Your Virtual Machine <strong>{{machine_name}}</strong> is successfully terminated!{% endblocktrans %}</h4>
 | 
				
			||||||
 | 
					          <div class="modal-footer">
 | 
				
			||||||
 | 
					            <a href="{% url 'hosting:virtual_machines' %}"	class="btn btn-success btn-wide">{% trans "OK" %}</a>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<!-- / Cancel Modal -->
 | 
				
			||||||
{%endblock%}
 | 
					{%endblock%}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,13 +41,15 @@
 | 
				
			||||||
                        <td data-header="IPv6">{{vm.ipv6}}</td>
 | 
					                        <td data-header="IPv6">{{vm.ipv6}}</td>
 | 
				
			||||||
                    {% endif %}
 | 
					                    {% endif %}
 | 
				
			||||||
                    <td data-header="{% trans 'Status' %}">
 | 
					                    <td data-header="{% trans 'Status' %}">
 | 
				
			||||||
 | 
					                        <strong>
 | 
				
			||||||
                            {% if vm.state == 'ACTIVE' %}
 | 
					                            {% if vm.state == 'ACTIVE' %}
 | 
				
			||||||
                            <span class="vm-status-active"><strong>{{vm.state|title}}</strong></span>
 | 
					                                <span class="vm-status-active">{{vm.state|title}}</span>
 | 
				
			||||||
                            {% elif  vm.state == 'FAILED' %}
 | 
					                            {% elif  vm.state == 'FAILED' %}
 | 
				
			||||||
                            <span class="vm-status-failed"><strong>{{vm.state|title}}</strong></span>
 | 
					                                <span class="vm-status-failed">{{vm.state|title}}</span>
 | 
				
			||||||
                            {% else %}
 | 
					                            {% else %}
 | 
				
			||||||
                            <span class="vm-status"><strong>{{vm.state|title}}</strong></span>
 | 
					                                <span class="vm-status">{{vm.state|title}}</span>
 | 
				
			||||||
                            {% endif %}
 | 
					                            {% endif %}
 | 
				
			||||||
 | 
					                        </strong>
 | 
				
			||||||
                    </td>
 | 
					                    </td>
 | 
				
			||||||
                    <td class="text-right last-td">
 | 
					                    <td class="text-right last-td">
 | 
				
			||||||
                        <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail" %}</a>
 | 
					                        <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail" %}</a>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,8 +8,7 @@ from .views import (
 | 
				
			||||||
    MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView,
 | 
					    MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView,
 | 
				
			||||||
    HostingPricingView, CreateVirtualMachinesView, HostingBillListView,
 | 
					    HostingPricingView, CreateVirtualMachinesView, HostingBillListView,
 | 
				
			||||||
    HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView,
 | 
					    HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView,
 | 
				
			||||||
    SSHKeyChoiceView, DashboardView, SettingsView)
 | 
					    SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns = [
 | 
					urlpatterns = [
 | 
				
			||||||
    url(r'index/?$', IndexView.as_view(), name='index'),
 | 
					    url(r'index/?$', IndexView.as_view(), name='index'),
 | 
				
			||||||
| 
						 | 
					@ -52,6 +51,8 @@ urlpatterns = [
 | 
				
			||||||
    url(r'signup/?$', SignupView.as_view(), name='signup'),
 | 
					    url(r'signup/?$', SignupView.as_view(), name='signup'),
 | 
				
			||||||
    url(r'signup-validate/?$', SignupValidateView.as_view(),
 | 
					    url(r'signup-validate/?$', SignupValidateView.as_view(),
 | 
				
			||||||
        name='signup-validate'),
 | 
					        name='signup-validate'),
 | 
				
			||||||
 | 
					    url(r'resend-activation-link/?$', ResendActivationEmailView.as_view(),
 | 
				
			||||||
 | 
					        name='resend_activation_link'),
 | 
				
			||||||
    url(r'reset-password/?$', PasswordResetView.as_view(),
 | 
					    url(r'reset-password/?$', PasswordResetView.as_view(),
 | 
				
			||||||
        name='reset_password'),
 | 
					        name='reset_password'),
 | 
				
			||||||
    url(r'reset-password-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
 | 
					    url(r'reset-password-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										260
									
								
								hosting/views.py
									
										
									
									
									
								
							
							
						
						
									
										260
									
								
								hosting/views.py
									
										
									
									
									
								
							| 
						 | 
					@ -1,23 +1,27 @@
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import uuid
 | 
					import uuid
 | 
				
			||||||
 | 
					from time import sleep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 HttpResponseRedirect, HttpResponse
 | 
					from django.http import Http404, HttpResponseRedirect, HttpResponse
 | 
				
			||||||
from django.shortcuts import redirect
 | 
					from django.shortcuts import redirect, render
 | 
				
			||||||
from django.shortcuts import render
 | 
					 | 
				
			||||||
from django.utils.http import urlsafe_base64_decode
 | 
					from django.utils.http import urlsafe_base64_decode
 | 
				
			||||||
from django.utils.safestring import mark_safe
 | 
					from django.utils.safestring import mark_safe
 | 
				
			||||||
from django.utils.translation import get_language, ugettext_lazy as _
 | 
					from django.utils.translation import get_language, ugettext_lazy as _
 | 
				
			||||||
from django.views.generic import View, CreateView, FormView, ListView, \
 | 
					from django.utils.translation import ugettext
 | 
				
			||||||
    DetailView, \
 | 
					from django.views.generic import (
 | 
				
			||||||
    DeleteView, TemplateView, UpdateView
 | 
					    View, CreateView, FormView, ListView, DetailView, DeleteView,
 | 
				
			||||||
 | 
					    TemplateView, UpdateView
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
from guardian.mixins import PermissionRequiredMixin
 | 
					from guardian.mixins import PermissionRequiredMixin
 | 
				
			||||||
from oca.pool import WrongIdError
 | 
					from oca.pool import WrongIdError
 | 
				
			||||||
from stored_messages.api import mark_read
 | 
					from stored_messages.api import mark_read
 | 
				
			||||||
| 
						 | 
					@ -28,17 +32,23 @@ from datacenterlight.tasks import create_vm_task
 | 
				
			||||||
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 (
 | 
				
			||||||
    UserBillingAddressForm
 | 
					    BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm,
 | 
				
			||||||
 | 
					    ResendActivationEmailForm
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
from utils.mailer import BaseEmail
 | 
					from utils.mailer import BaseEmail
 | 
				
			||||||
from utils.stripe_utils import StripeUtils
 | 
					from utils.stripe_utils import StripeUtils
 | 
				
			||||||
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, \
 | 
					from utils.views import (
 | 
				
			||||||
    LoginViewMixin
 | 
					    PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin,
 | 
				
			||||||
 | 
					    ResendActivationLinkViewMixin
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
from .forms import HostingUserSignupForm, HostingUserLoginForm, \
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger = logging.getLogger(__name__)
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -294,6 +304,14 @@ class SignupValidatedView(SignupValidateView):
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResendActivationEmailView(ResendActivationLinkViewMixin):
 | 
				
			||||||
 | 
					    template_name = 'hosting/resend_activation_link.html'
 | 
				
			||||||
 | 
					    form_class = ResendActivationEmailForm
 | 
				
			||||||
 | 
					    success_url = reverse_lazy('hosting:login')
 | 
				
			||||||
 | 
					    email_template_path = 'datacenterlight/emails/'
 | 
				
			||||||
 | 
					    email_template_name = 'user_activation'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordResetView(PasswordResetViewMixin):
 | 
					class PasswordResetView(PasswordResetViewMixin):
 | 
				
			||||||
    site = 'dcl'
 | 
					    site = 'dcl'
 | 
				
			||||||
    template_name = 'hosting/reset_password.html'
 | 
					    template_name = 'hosting/reset_password.html'
 | 
				
			||||||
| 
						 | 
					@ -331,7 +349,7 @@ class PasswordResetConfirmView(PasswordResetConfirmViewMixin):
 | 
				
			||||||
                messages.success(request, _('Password has been reset.'))
 | 
					                messages.success(request, _('Password has been reset.'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Change opennebula password
 | 
					                # Change opennebula password
 | 
				
			||||||
                opennebula_client.change_user_password(new_password)
 | 
					                opennebula_client.change_user_password(user.password)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return self.form_valid(form)
 | 
					                return self.form_valid(form)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
| 
						 | 
					@ -663,7 +681,7 @@ class OrdersHostingDetailView(LoginRequiredMixin,
 | 
				
			||||||
    model = HostingOrder
 | 
					    model = HostingOrder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_object(self):
 | 
					    def get_object(self):
 | 
				
			||||||
        return HostingOrder.objects.filter(
 | 
					        return HostingOrder.objects.get(
 | 
				
			||||||
            pk=self.kwargs.get('pk')) if self.kwargs.get('pk') else None
 | 
					            pk=self.kwargs.get('pk')) if self.kwargs.get('pk') else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_context_data(self, **kwargs):
 | 
					    def get_context_data(self, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -671,54 +689,79 @@ class OrdersHostingDetailView(LoginRequiredMixin,
 | 
				
			||||||
        context = super(DetailView, self).get_context_data(**kwargs)
 | 
					        context = super(DetailView, self).get_context_data(**kwargs)
 | 
				
			||||||
        obj = self.get_object()
 | 
					        obj = self.get_object()
 | 
				
			||||||
        owner = self.request.user
 | 
					        owner = self.request.user
 | 
				
			||||||
        if 'specs' not in self.request.session:
 | 
					 | 
				
			||||||
            return HttpResponseRedirect(
 | 
					 | 
				
			||||||
                reverse('hosting:create_virtual_machine'))
 | 
					 | 
				
			||||||
        if 'token' not in self.request.session:
 | 
					 | 
				
			||||||
            return HttpResponseRedirect(reverse('hosting:payment'))
 | 
					 | 
				
			||||||
        stripe_customer_id = self.request.session.get('customer')
 | 
					        stripe_customer_id = self.request.session.get('customer')
 | 
				
			||||||
        customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
 | 
					        customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
 | 
				
			||||||
        stripe_utils = StripeUtils()
 | 
					        stripe_utils = StripeUtils()
 | 
				
			||||||
        card_details = stripe_utils.get_card_details(customer.stripe_id,
 | 
					        if customer:
 | 
				
			||||||
                                                     self.request.session.get(
 | 
					            card_details = stripe_utils.get_card_details(
 | 
				
			||||||
                                                         'token'))
 | 
					                customer.stripe_id,
 | 
				
			||||||
        if not card_details.get('response_object'):
 | 
					                self.request.session.get('token')
 | 
				
			||||||
            msg = card_details.get('error')
 | 
					            )
 | 
				
			||||||
            messages.add_message(self.request, messages.ERROR, msg,
 | 
					        else:
 | 
				
			||||||
                                 extra_tags='failed_payment')
 | 
					            card_details = {}
 | 
				
			||||||
            return HttpResponseRedirect(
 | 
					 | 
				
			||||||
                reverse('hosting:payment') + '#payment_error')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.request.GET.get('page', '') == 'payment':
 | 
					        if self.request.GET.get('page') == 'payment':
 | 
				
			||||||
            context['page_header_text'] = _('Confirm Order')
 | 
					            context['page_header_text'] = _('Confirm Order')
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            context['page_header_text'] = _('Invoice')
 | 
					            context['page_header_text'] = _('Invoice')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if obj is not None:
 | 
					        if obj is not None:
 | 
				
			||||||
 | 
					            # invoice for previous order
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                manager = OpenNebulaManager(email=owner.email,
 | 
					                manager = OpenNebulaManager(
 | 
				
			||||||
                                            password=owner.password)
 | 
					                    email=owner.email, password=owner.password
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
                vm = manager.get_vm(obj.vm_id)
 | 
					                vm = manager.get_vm(obj.vm_id)
 | 
				
			||||||
                context['vm'] = VirtualMachineSerializer(vm).data
 | 
					                context['vm'] = VirtualMachineSerializer(vm).data
 | 
				
			||||||
            except WrongIdError:
 | 
					            except WrongIdError:
 | 
				
			||||||
                messages.error(self.request,
 | 
					                messages.error(
 | 
				
			||||||
                               'The VM you are looking for is unavailable at the moment. \
 | 
					                    self.request,
 | 
				
			||||||
                                Please contact Data Center Light support.'
 | 
					                    _('The VM you are looking for is unavailable at the '
 | 
				
			||||||
 | 
					                      'moment. Please contact Data Center Light support.')
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                self.kwargs['error'] = 'WrongIdError'
 | 
					                self.kwargs['error'] = 'WrongIdError'
 | 
				
			||||||
                context['error'] = 'WrongIdError'
 | 
					                context['error'] = 'WrongIdError'
 | 
				
			||||||
            except ConnectionRefusedError:
 | 
					            except ConnectionRefusedError:
 | 
				
			||||||
                messages.error(self.request,
 | 
					                messages.error(
 | 
				
			||||||
                               'In order to create a VM, you need to create/upload your SSH KEY first.'
 | 
					                    self.request,
 | 
				
			||||||
 | 
					                    _('In order to create a VM, you need to create/upload '
 | 
				
			||||||
 | 
					                      'your SSH KEY first.')
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					        elif not card_details.get('response_object'):
 | 
				
			||||||
 | 
					            # new order, failed to get card details
 | 
				
			||||||
 | 
					            context['failed_payment'] = True
 | 
				
			||||||
 | 
					            context['card_details'] = card_details
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
 | 
					            # new order, confirm payment
 | 
				
			||||||
            context['site_url'] = reverse('hosting:create_virtual_machine')
 | 
					            context['site_url'] = reverse('hosting:create_virtual_machine')
 | 
				
			||||||
            context['cc_last4'] = card_details.get('response_object').get(
 | 
					            context['cc_last4'] = card_details.get('response_object').get(
 | 
				
			||||||
                'last4')
 | 
					                'last4')
 | 
				
			||||||
            context['cc_brand'] = card_details.get('response_object').get(
 | 
					            context['cc_brand'] = card_details.get('response_object').get(
 | 
				
			||||||
                'cc_brand')
 | 
					                'cc_brand')
 | 
				
			||||||
 | 
					            context['vm'] = self.request.session.get('specs')
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get(self, request, *args, **kwargs):
 | 
				
			||||||
 | 
					        if not self.kwargs.get('pk'):
 | 
				
			||||||
 | 
					            if 'specs' not in self.request.session:
 | 
				
			||||||
 | 
					                return HttpResponseRedirect(
 | 
				
			||||||
 | 
					                    reverse('hosting:create_virtual_machine')
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            if 'token' not in self.request.session:
 | 
				
			||||||
 | 
					                return HttpResponseRedirect(reverse('hosting:payment'))
 | 
				
			||||||
 | 
					        self.object = self.get_object()
 | 
				
			||||||
 | 
					        context = self.get_context_data(object=self.object)
 | 
				
			||||||
 | 
					        if 'failed_payment' in context:
 | 
				
			||||||
 | 
					            msg = context['card_details'].get('error')
 | 
				
			||||||
 | 
					            messages.add_message(
 | 
				
			||||||
 | 
					                self.request, messages.ERROR, msg,
 | 
				
			||||||
 | 
					                extra_tags='failed_payment'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            return HttpResponseRedirect(
 | 
				
			||||||
 | 
					                reverse('hosting:payment') + '#payment_error'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        return self.render_to_response(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def post(self, request):
 | 
					    def post(self, request):
 | 
				
			||||||
        template = request.session.get('template')
 | 
					        template = request.session.get('template')
 | 
				
			||||||
        specs = request.session.get('specs')
 | 
					        specs = request.session.get('specs')
 | 
				
			||||||
| 
						 | 
					@ -860,48 +903,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'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -943,7 +1018,19 @@ class VirtualMachineView(LoginRequiredMixin, View):
 | 
				
			||||||
    def get(self, request, *args, **kwargs):
 | 
					    def get(self, request, *args, **kwargs):
 | 
				
			||||||
        vm = self.get_object()
 | 
					        vm = self.get_object()
 | 
				
			||||||
        if vm is None:
 | 
					        if vm is None:
 | 
				
			||||||
 | 
					            if self.request.is_ajax():
 | 
				
			||||||
 | 
					                storage = messages.get_messages(request)
 | 
				
			||||||
 | 
					                for m in storage:
 | 
				
			||||||
 | 
					                    pass
 | 
				
			||||||
 | 
					                storage.used = True
 | 
				
			||||||
 | 
					                return HttpResponse(
 | 
				
			||||||
 | 
					                    json.dumps({'text': ugettext('Terminated')}),
 | 
				
			||||||
 | 
					                    content_type="application/json"
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
                return redirect(reverse('hosting:virtual_machines'))
 | 
					                return redirect(reverse('hosting:virtual_machines'))
 | 
				
			||||||
 | 
					        elif self.request.is_ajax():
 | 
				
			||||||
 | 
					            return HttpResponse()
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            serializer = VirtualMachineSerializer(vm)
 | 
					            serializer = VirtualMachineSerializer(vm)
 | 
				
			||||||
            context = {
 | 
					            context = {
 | 
				
			||||||
| 
						 | 
					@ -958,6 +1045,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
 | 
				
			||||||
        return render(request, self.template_name, context)
 | 
					        return render(request, self.template_name, context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def post(self, request, *args, **kwargs):
 | 
					    def post(self, request, *args, **kwargs):
 | 
				
			||||||
 | 
					        response = {'status': False}
 | 
				
			||||||
        owner = self.request.user
 | 
					        owner = self.request.user
 | 
				
			||||||
        vm = self.get_object()
 | 
					        vm = self.get_object()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -967,17 +1055,29 @@ class VirtualMachineView(LoginRequiredMixin, View):
 | 
				
			||||||
            email=owner.email,
 | 
					            email=owner.email,
 | 
				
			||||||
            password=owner.password
 | 
					            password=owner.password
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
            vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
 | 
					            vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
 | 
				
			||||||
        terminated = manager.delete_vm(
 | 
					        except WrongIdError:
 | 
				
			||||||
            vm.id
 | 
					            return redirect(reverse('hosting:virtual_machines'))
 | 
				
			||||||
        )
 | 
					
 | 
				
			||||||
 | 
					        terminated = manager.delete_vm(vm.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not terminated:
 | 
					        if not terminated:
 | 
				
			||||||
            messages.error(
 | 
					            response['text'] = ugettext(
 | 
				
			||||||
                request,
 | 
					                'Error terminating VM') + opennebula_vm_id
 | 
				
			||||||
                'Error terminating VM %s' % (opennebula_vm_id)
 | 
					        else:
 | 
				
			||||||
            )
 | 
					            for t in range(15):
 | 
				
			||||||
            return HttpResponseRedirect(self.get_success_url())
 | 
					                try:
 | 
				
			||||||
 | 
					                    manager.get_vm(opennebula_vm_id)
 | 
				
			||||||
 | 
					                except WrongIdError:
 | 
				
			||||||
 | 
					                    response['status'] = True
 | 
				
			||||||
 | 
					                    response['text'] = ugettext('Terminated')
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					                except BaseException:
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    sleep(2)
 | 
				
			||||||
            context = {
 | 
					            context = {
 | 
				
			||||||
                'vm': vm_data,
 | 
					                'vm': vm_data,
 | 
				
			||||||
                'base_url': "{0}://{1}".format(self.request.scheme,
 | 
					                'base_url': "{0}://{1}".format(self.request.scheme,
 | 
				
			||||||
| 
						 | 
					@ -994,15 +1094,11 @@ class VirtualMachineView(LoginRequiredMixin, View):
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            email = BaseEmail(**email_data)
 | 
					            email = BaseEmail(**email_data)
 | 
				
			||||||
            email.send()
 | 
					            email.send()
 | 
				
			||||||
 | 
					        return HttpResponse(
 | 
				
			||||||
        messages.error(
 | 
					            json.dumps(response),
 | 
				
			||||||
            request,
 | 
					            content_type="application/json"
 | 
				
			||||||
            _('VM %(VM_ID)s terminated successfully') % {
 | 
					 | 
				
			||||||
                'VM_ID': opennebula_vm_id}
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return HttpResponseRedirect(self.get_success_url())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin,
 | 
					class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin,
 | 
				
			||||||
                          ListView):
 | 
					                          ListView):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -438,11 +438,11 @@ class OpenNebulaManager():
 | 
				
			||||||
        self.oneadmin_client.call(oca.VmTemplate.METHODS[
 | 
					        self.oneadmin_client.call(oca.VmTemplate.METHODS[
 | 
				
			||||||
                                      'delete'], template_id, False)
 | 
					                                      'delete'], template_id, False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def change_user_password(self, new_password):
 | 
					    def change_user_password(self, passwd_hash):
 | 
				
			||||||
        self.oneadmin_client.call(
 | 
					        self.oneadmin_client.call(
 | 
				
			||||||
            oca.User.METHODS['passwd'],
 | 
					            oca.User.METHODS['passwd'],
 | 
				
			||||||
            self.opennebula_user.id,
 | 
					            self.opennebula_user.id,
 | 
				
			||||||
            new_password
 | 
					            passwd_hash
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_public_key(self, user, public_key='', merge=False):
 | 
					    def add_public_key(self, user, public_key='', merge=False):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,5 +96,4 @@ pyflakes==1.5.0
 | 
				
			||||||
billiard==3.5.0.3
 | 
					billiard==3.5.0.3
 | 
				
			||||||
amqp==2.2.1
 | 
					amqp==2.2.1
 | 
				
			||||||
vine==1.1.4
 | 
					vine==1.1.4
 | 
				
			||||||
#git+https://github.com/ungleich/cdist.git#egg=cdist
 | 
					cdist==4.7.0
 | 
				
			||||||
file:///home/app/cdist#egg=cdist
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,8 @@ class SignupFormMixin(forms.ModelForm):
 | 
				
			||||||
        model = CustomUser
 | 
					        model = CustomUser
 | 
				
			||||||
        fields = ['name', 'email', 'password']
 | 
					        fields = ['name', 'email', 'password']
 | 
				
			||||||
        widgets = {
 | 
					        widgets = {
 | 
				
			||||||
            'name': forms.TextInput(attrs={'placeholder': _('Enter your name or company name')}),
 | 
					            'name': forms.TextInput(
 | 
				
			||||||
 | 
					                attrs={'placeholder': _('Enter your name or company name')}),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def clean_confirm_password(self):
 | 
					    def clean_confirm_password(self):
 | 
				
			||||||
| 
						 | 
					@ -42,7 +43,7 @@ class LoginFormMixin(forms.Form):
 | 
				
			||||||
        is_auth = authenticate(email=email, password=password)
 | 
					        is_auth = authenticate(email=email, password=password)
 | 
				
			||||||
        if not is_auth:
 | 
					        if not is_auth:
 | 
				
			||||||
            raise forms.ValidationError(
 | 
					            raise forms.ValidationError(
 | 
				
			||||||
                "Your username and/or password were incorrect.")
 | 
					                _("Your username and/or password were incorrect."))
 | 
				
			||||||
        return self.cleaned_data
 | 
					        return self.cleaned_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def clean_email(self):
 | 
					    def clean_email(self):
 | 
				
			||||||
| 
						 | 
					@ -51,7 +52,24 @@ class LoginFormMixin(forms.Form):
 | 
				
			||||||
            CustomUser.objects.get(email=email)
 | 
					            CustomUser.objects.get(email=email)
 | 
				
			||||||
            return email
 | 
					            return email
 | 
				
			||||||
        except CustomUser.DoesNotExist:
 | 
					        except CustomUser.DoesNotExist:
 | 
				
			||||||
            raise forms.ValidationError("User does not exist")
 | 
					            raise forms.ValidationError(_("User does not exist"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResendActivationEmailForm(forms.Form):
 | 
				
			||||||
 | 
					    email = forms.CharField(widget=forms.EmailInput())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        fields = ['email']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean_email(self):
 | 
				
			||||||
 | 
					        email = self.cleaned_data.get('email')
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            c = CustomUser.objects.get(email=email)
 | 
				
			||||||
 | 
					            if c.validated == 1:
 | 
				
			||||||
 | 
					                raise forms.ValidationError(_("The account is already active."))
 | 
				
			||||||
 | 
					            return email
 | 
				
			||||||
 | 
					        except CustomUser.DoesNotExist:
 | 
				
			||||||
 | 
					            raise forms.ValidationError(_("User does not exist"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordResetRequestForm(forms.Form):
 | 
					class PasswordResetRequestForm(forms.Form):
 | 
				
			||||||
| 
						 | 
					@ -66,7 +84,7 @@ class PasswordResetRequestForm(forms.Form):
 | 
				
			||||||
            CustomUser.objects.get(email=email)
 | 
					            CustomUser.objects.get(email=email)
 | 
				
			||||||
            return email
 | 
					            return email
 | 
				
			||||||
        except CustomUser.DoesNotExist:
 | 
					        except CustomUser.DoesNotExist:
 | 
				
			||||||
            raise forms.ValidationError("User does not exist")
 | 
					            raise forms.ValidationError(_("User does not exist"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SetPasswordForm(forms.Form):
 | 
					class SetPasswordForm(forms.Form):
 | 
				
			||||||
| 
						 | 
					@ -75,11 +93,11 @@ class SetPasswordForm(forms.Form):
 | 
				
			||||||
    password
 | 
					    password
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    error_messages = {
 | 
					    error_messages = {
 | 
				
			||||||
        'password_mismatch': ("The two password fields didn't match."),
 | 
					        'password_mismatch': _("The two password fields didn't match."),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    new_password1 = forms.CharField(label=("New password"),
 | 
					    new_password1 = forms.CharField(label=_("New password"),
 | 
				
			||||||
                                    widget=forms.PasswordInput)
 | 
					                                    widget=forms.PasswordInput)
 | 
				
			||||||
    new_password2 = forms.CharField(label=("New password confirmation"),
 | 
					    new_password2 = forms.CharField(label=_("New password confirmation"),
 | 
				
			||||||
                                    widget=forms.PasswordInput)
 | 
					                                    widget=forms.PasswordInput)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def clean_new_password2(self):
 | 
					    def clean_new_password2(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ msgid ""
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
"Project-Id-Version: PACKAGE VERSION\n"
 | 
					"Project-Id-Version: PACKAGE VERSION\n"
 | 
				
			||||||
"Report-Msgid-Bugs-To: \n"
 | 
					"Report-Msgid-Bugs-To: \n"
 | 
				
			||||||
"POT-Creation-Date: 2017-09-02 11:50+0000\n"
 | 
					"POT-Creation-Date: 2017-09-25 20:11+0000\n"
 | 
				
			||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
					"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
				
			||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
					"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
				
			||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
					"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
				
			||||||
| 
						 | 
					@ -738,6 +738,24 @@ msgstr ""
 | 
				
			||||||
msgid "Enter your name or company name"
 | 
					msgid "Enter your name or company name"
 | 
				
			||||||
msgstr "Geben Sie Ihren Namen oder der Ihrer Firma ein"
 | 
					msgstr "Geben Sie Ihren Namen oder der Ihrer Firma ein"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Your username and/or password were incorrect."
 | 
				
			||||||
 | 
					msgstr "Dein Benutzername und/oder Dein Passwort ist falsch."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "User does not exist"
 | 
				
			||||||
 | 
					msgstr "Der Benutzer existiert nicht"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "The account is already active."
 | 
				
			||||||
 | 
					msgstr "Das Benutzerkonto ist bereits aktiv."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "The two password fields didn't match."
 | 
				
			||||||
 | 
					msgstr "Die beiden Passwörter stimmen nicht überein."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "New password"
 | 
				
			||||||
 | 
					msgstr "Neues Passwort"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "New password confirmation"
 | 
				
			||||||
 | 
					msgstr "Neues Passwort Bestätigung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Cardholder Name"
 | 
					msgid "Cardholder Name"
 | 
				
			||||||
msgstr "Name des Kartenbesitzer"
 | 
					msgstr "Name des Kartenbesitzer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -768,17 +786,25 @@ msgstr "Telefon"
 | 
				
			||||||
msgid "Message"
 | 
					msgid "Message"
 | 
				
			||||||
msgstr "Nachricht"
 | 
					msgstr "Nachricht"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "An email with the activation link has been sent to your email"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Der Link zum Zurücksetzen deines Passwortes wurde an deine E-Mail gesendet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msgid "Account Activation"
 | 
				
			||||||
 | 
					msgstr "Accountaktivierung"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "The link to reset your email has been sent to your email"
 | 
					msgid "The link to reset your email has been sent to your email"
 | 
				
			||||||
msgstr "Der Link zum Zur?cksetzen deines Passwortes wurde an deine E-Mail gesendet"
 | 
					msgstr ""
 | 
				
			||||||
 | 
					"Der Link zum Zurücksetzen deines Passwortes wurde an deine E-Mail gesendet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Password Reset"
 | 
					msgid "Password Reset"
 | 
				
			||||||
msgstr ""
 | 
					msgstr "Passwort zurücksetzen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Password has been reset."
 | 
					msgid "Password has been reset."
 | 
				
			||||||
msgstr "Das Passwort wurde zur?ckgesetzt."
 | 
					msgstr "Das Passwort wurde zurückgesetzt."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "Password reset has not been successful."
 | 
					msgid "Password reset has not been successful."
 | 
				
			||||||
msgstr "Das Zur?cksetzen war nicht erfolgreich."
 | 
					msgstr "Das Zurücksetzen war nicht erfolgreich."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
msgid "The reset password link is no longer valid."
 | 
					msgid "The reset password link is no longer valid."
 | 
				
			||||||
msgstr "Der Link zum Zur?cksetzen deines Passwortes ist nicht l?nger g?ltig."
 | 
					msgstr "Der Link zum Zurücksetzen Deines Passwortes ist nicht länger gültig."
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ from django.conf import settings
 | 
				
			||||||
from django.contrib import messages
 | 
					from django.contrib import messages
 | 
				
			||||||
from django.contrib.auth import authenticate, login
 | 
					from django.contrib.auth import authenticate, login
 | 
				
			||||||
from django.contrib.auth.tokens import default_token_generator
 | 
					from django.contrib.auth.tokens import default_token_generator
 | 
				
			||||||
 | 
					from django.core.urlresolvers import reverse_lazy
 | 
				
			||||||
from django.http import HttpResponseRedirect
 | 
					from django.http import HttpResponseRedirect
 | 
				
			||||||
from django.utils.encoding import force_bytes
 | 
					from django.utils.encoding import force_bytes
 | 
				
			||||||
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
 | 
					from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
 | 
				
			||||||
| 
						 | 
					@ -63,9 +64,45 @@ class LoginViewMixin(FormView):
 | 
				
			||||||
        return super(LoginViewMixin, self).get(request, *args, **kwargs)
 | 
					        return super(LoginViewMixin, self).get(request, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResendActivationLinkViewMixin(FormView):
 | 
				
			||||||
 | 
					    success_message = _(
 | 
				
			||||||
 | 
					        "An email with the activation link has been sent to your email")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def generate_email_context(self, user):
 | 
				
			||||||
 | 
					        context = {
 | 
				
			||||||
 | 
					            'base_url': "{0}://{1}".format(self.request.scheme,
 | 
				
			||||||
 | 
					                                           self.request.get_host()),
 | 
				
			||||||
 | 
					            'activation_link': reverse_lazy(
 | 
				
			||||||
 | 
					                'hosting:validate',
 | 
				
			||||||
 | 
					                kwargs={'validate_slug': user.validation_slug}
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            'dcl_text': settings.DCL_TEXT,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def form_valid(self, form):
 | 
				
			||||||
 | 
					        email = form.cleaned_data.get('email')
 | 
				
			||||||
 | 
					        user = CustomUser.objects.get(email=email)
 | 
				
			||||||
 | 
					        messages.add_message(self.request, messages.SUCCESS,
 | 
				
			||||||
 | 
					                             self.success_message)
 | 
				
			||||||
 | 
					        context = self.generate_email_context(user)
 | 
				
			||||||
 | 
					        email_data = {
 | 
				
			||||||
 | 
					            'subject': '{dcl_text} {account_activation}'.format(
 | 
				
			||||||
 | 
					                dcl_text=settings.DCL_TEXT,
 | 
				
			||||||
 | 
					                account_activation=_('Account Activation')
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            'to': email,
 | 
				
			||||||
 | 
					            'context': context,
 | 
				
			||||||
 | 
					            'template_name': self.email_template_name,
 | 
				
			||||||
 | 
					            'template_path': self.email_template_path,
 | 
				
			||||||
 | 
					            'from_address': settings.DCL_SUPPORT_FROM_ADDRESS
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        email = BaseEmail(**email_data)
 | 
				
			||||||
 | 
					        email.send()
 | 
				
			||||||
 | 
					        return HttpResponseRedirect(self.get_success_url())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordResetViewMixin(FormView):
 | 
					class PasswordResetViewMixin(FormView):
 | 
				
			||||||
    # template_name = 'hosting/reset_password.html'
 | 
					 | 
				
			||||||
    # form_class = PasswordResetRequestForm
 | 
					 | 
				
			||||||
    success_message = _(
 | 
					    success_message = _(
 | 
				
			||||||
        "The link to reset your email has been sent to your email")
 | 
					        "The link to reset your email has been sent to your email")
 | 
				
			||||||
    site = ''
 | 
					    site = ''
 | 
				
			||||||
| 
						 | 
					@ -78,7 +115,6 @@ class PasswordResetViewMixin(FormView):
 | 
				
			||||||
            'site_name': 'ungleich' if self.site != 'dcl' else settings.DCL_TEXT,
 | 
					            'site_name': 'ungleich' if self.site != 'dcl' else settings.DCL_TEXT,
 | 
				
			||||||
            'base_url': "{0}://{1}".format(self.request.scheme,
 | 
					            'base_url': "{0}://{1}".format(self.request.scheme,
 | 
				
			||||||
                                           self.request.get_host())
 | 
					                                           self.request.get_host())
 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,11 +140,8 @@ class PasswordResetViewMixin(FormView):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PasswordResetConfirmViewMixin(FormView):
 | 
					class PasswordResetConfirmViewMixin(FormView):
 | 
				
			||||||
    # template_name = 'hosting/confirm_reset_password.html'
 | 
					 | 
				
			||||||
    form_class = SetPasswordForm
 | 
					    form_class = SetPasswordForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # success_url = reverse_lazy('hosting:login')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def post(self, request, uidb64=None, token=None, *arg, **kwargs):
 | 
					    def post(self, request, uidb64=None, token=None, *arg, **kwargs):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            uid = urlsafe_base64_decode(uidb64)
 | 
					            uid = urlsafe_base64_decode(uidb64)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue