Merge branch 'master' into task/3672/cleaning_existing_tests
|
|
@ -1,16 +1,22 @@
|
|||
import datetime
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
import tempfile
|
||||
from django import forms
|
||||
from membership.models import CustomUser
|
||||
from django.contrib.auth import authenticate
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from membership.models import CustomUser
|
||||
from utils.hosting_utils import get_all_public_keys
|
||||
from .models import UserHostingKey
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def generate_ssh_key_name():
|
||||
return 'dcl-generated-key-' + datetime.datetime.now().strftime('%m%d%y%H%M')
|
||||
return 'dcl-generated-key-' + datetime.datetime.now().strftime(
|
||||
'%m%d%y%H%M')
|
||||
|
||||
|
||||
class HostingUserLoginForm(forms.Form):
|
||||
|
|
@ -38,9 +44,7 @@ class HostingUserLoginForm(forms.Form):
|
|||
CustomUser.objects.get(email=email)
|
||||
return email
|
||||
except CustomUser.DoesNotExist:
|
||||
raise forms.ValidationError("User does not exist")
|
||||
else:
|
||||
return email
|
||||
raise forms.ValidationError(_("User does not exist"))
|
||||
|
||||
|
||||
class HostingUserSignupForm(forms.ModelForm):
|
||||
|
|
@ -51,7 +55,8 @@ class HostingUserSignupForm(forms.ModelForm):
|
|||
model = CustomUser
|
||||
fields = ['name', 'email', 'password']
|
||||
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):
|
||||
|
|
@ -65,19 +70,55 @@ class HostingUserSignupForm(forms.ModelForm):
|
|||
class UserHostingKeyForm(forms.ModelForm):
|
||||
private_key = forms.CharField(widget=forms.HiddenInput(), required=False)
|
||||
public_key = forms.CharField(widget=forms.Textarea(
|
||||
attrs={'class': 'form_public_key', 'placeholder': _('Paste here your public key')}),
|
||||
attrs={'class': 'form_public_key',
|
||||
'placeholder': _('Paste here your public key')}),
|
||||
required=False,
|
||||
)
|
||||
user = forms.models.ModelChoiceField(queryset=CustomUser.objects.all(),
|
||||
required=False, widget=forms.HiddenInput())
|
||||
required=False,
|
||||
widget=forms.HiddenInput())
|
||||
name = forms.CharField(required=False, widget=forms.TextInput(
|
||||
attrs={'class': 'form_key_name', 'placeholder': _('Give a name to your key')}))
|
||||
attrs={'class': 'form_key_name',
|
||||
'placeholder': _('Give a name to your key')}))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.request = kwargs.pop("request")
|
||||
super(UserHostingKeyForm, self).__init__(*args, **kwargs)
|
||||
self.fields['name'].label = _('Key name')
|
||||
|
||||
def clean_public_key(self):
|
||||
"""
|
||||
Validates a public ssh key using `ssh-keygen -lf key.pub`
|
||||
Also checks if a given key already exists in the database and
|
||||
alerts the user of it.
|
||||
:return:
|
||||
"""
|
||||
if 'generate' in self.request.POST:
|
||||
return self.data.get('public_key')
|
||||
KEY_ERROR_MESSAGE = _("Please input a proper SSH key")
|
||||
openssh_pubkey_str = self.data.get('public_key').strip()
|
||||
|
||||
if openssh_pubkey_str in get_all_public_keys(self.request.user):
|
||||
key_name = UserHostingKey.objects.filter(
|
||||
user_id=self.request.user.id,
|
||||
public_key=openssh_pubkey_str).first().name
|
||||
KEY_EXISTS_MESSAGE = _(
|
||||
"This key exists already with the name \"%(name)s\"") % {
|
||||
'name': key_name}
|
||||
raise forms.ValidationError(KEY_EXISTS_MESSAGE)
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=True) as tmp_public_key_file:
|
||||
tmp_public_key_file.write(openssh_pubkey_str.encode('utf-8'))
|
||||
tmp_public_key_file.flush()
|
||||
try:
|
||||
subprocess.check_output(
|
||||
['ssh-keygen', '-lf', tmp_public_key_file.name])
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
logger.debug(
|
||||
"Not a correct ssh format {error}".format(error=str(cpe)))
|
||||
raise forms.ValidationError(KEY_ERROR_MESSAGE)
|
||||
return openssh_pubkey_str
|
||||
|
||||
def clean_name(self):
|
||||
return self.data.get('name')
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-24 11:12+0000\n"
|
||||
"POT-Creation-Date: 2017-09-24 12:34+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -24,29 +24,24 @@ msgstr "Dein Benutzername und/oder Dein Passwort ist falsch."
|
|||
msgid "Your account is not activated yet."
|
||||
msgstr "Dein Account wurde noch nicht aktiviert."
|
||||
|
||||
msgid "User does not exist"
|
||||
msgstr "Der Benutzer existiert nicht"
|
||||
|
||||
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"
|
||||
msgstr "Gebe deinem SSH-Key einen Name"
|
||||
msgstr "Gebe Deinem SSH-Key einen Name"
|
||||
|
||||
msgid "Key name"
|
||||
msgstr "Key-Name"
|
||||
|
||||
msgid "My Virtual Machines"
|
||||
msgstr "Meine virtuellen Maschinen"
|
||||
msgid "Please input a proper SSH key"
|
||||
msgstr "Bitte verwende einen gültigen SSH-Key"
|
||||
|
||||
msgid "My Orders"
|
||||
msgstr "Meine Bestellungen"
|
||||
|
||||
msgid "SSH Keys"
|
||||
msgstr "SSH Key"
|
||||
|
||||
msgid "Notifications "
|
||||
msgstr "Benachrichtigungen"
|
||||
|
||||
msgid "Logout"
|
||||
msgstr "Abmelden"
|
||||
#, python-format
|
||||
msgid "This key exists already with the name \"%(name)s\""
|
||||
msgstr "Der SSH-Key mit dem Name \"%(name)s\" existiert bereits"
|
||||
|
||||
msgid "All Rights Reserved"
|
||||
msgstr "Alle Rechte vorbehalten"
|
||||
|
|
@ -73,7 +68,7 @@ msgid "Mwst-Nummer: CHE-109.549.333 MWST"
|
|||
msgstr ""
|
||||
|
||||
msgid "Total:"
|
||||
msgstr ""
|
||||
msgstr "Gesamt:"
|
||||
|
||||
#, python-format
|
||||
msgid "Alles Preise in CHF mit 8%% Mehrwertsteuer."
|
||||
|
|
@ -115,6 +110,27 @@ msgstr "vorherige"
|
|||
msgid "next"
|
||||
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"
|
||||
msgstr "SSH Key"
|
||||
|
||||
|
|
@ -140,10 +156,10 @@ msgid "Upload"
|
|||
msgstr "Hochladen"
|
||||
|
||||
msgid "Your VM hosted in Switzerland"
|
||||
msgstr "deine VM in der Schweiz"
|
||||
msgstr "Deine VM in der Schweiz"
|
||||
|
||||
msgid "Set your new password"
|
||||
msgstr "Setze dein neues Passwort"
|
||||
msgstr "Setze Dein neues Passwort"
|
||||
|
||||
msgid "Reset"
|
||||
msgstr "Zurücksetzen"
|
||||
|
|
@ -154,39 +170,132 @@ msgstr "Hast Du bereits ein Benutzerkonto?"
|
|||
msgid "Login"
|
||||
msgstr "Anmelden"
|
||||
|
||||
msgid "New Virtual Machine"
|
||||
msgstr "Neue virtuelle Maschine"
|
||||
msgid "Create VM"
|
||||
msgstr "VM erstellen"
|
||||
|
||||
msgid "Step 1. Select VM Template:"
|
||||
msgstr "Wähle eine Vorlage"
|
||||
msgid "My Dashboard"
|
||||
msgstr "Mein Dashboard"
|
||||
|
||||
msgid "Step2. Select VM Configuration"
|
||||
msgstr "Wähle eine Konfiguration"
|
||||
msgid "My VMs"
|
||||
msgstr "Meine VMs"
|
||||
|
||||
msgid "Price "
|
||||
msgstr "Preis"
|
||||
msgid "My SSH Keys"
|
||||
msgstr "Meine SSH-Keys"
|
||||
|
||||
msgid "CHF/Month"
|
||||
msgstr "CHF/Monat"
|
||||
msgid "My Bills"
|
||||
msgstr "Meine Rechnungen"
|
||||
|
||||
msgid "Start VM"
|
||||
msgstr "VM jetzt starten"
|
||||
msgid "My Settings"
|
||||
msgstr "Meine Einstellungen"
|
||||
|
||||
msgid "Support / Contact"
|
||||
msgstr "Support / Kontakt"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You have ordered a new virtual machine!\n"
|
||||
"<br/>\n"
|
||||
"Your order of [%(vm_name)s] has been charged.<br/><br/>\n"
|
||||
"You can view your invoice by clicking the button below.<br/><br/>\n"
|
||||
msgstr ""
|
||||
"Du hast eine neue virtuelle Maschine bestellt!<br/>\n"
|
||||
"Deine Bestellung von [%(vm_name)s] wurde erhoben.<br/><br/>\n"
|
||||
"Um die Rechnung zu sehen, klicke auf den Button unten.<br/><br/>\n"
|
||||
|
||||
msgid "View Invoice"
|
||||
msgstr "Zur Rechnung"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You have ordered a new virtual machine!\n"
|
||||
"Your order of [%(vm_name)s] has been charged.\n"
|
||||
"You can view your invoice here.\n"
|
||||
msgstr ""
|
||||
"Du hast eine neue virtuelle Maschine bestellt!\n"
|
||||
"Deine Bestellung von [%(vm_name)s] wurde erhoben.\n"
|
||||
"Um die Rechnung zu sehen, klicke hier.\n"
|
||||
|
||||
msgid "Password Reset"
|
||||
msgstr "Passwort zurücksetzen"
|
||||
|
||||
#, 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."
|
||||
"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"
|
||||
|
||||
msgid "Please go to the following page and choose a new password:"
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You're receiving this mail because your virtual machine [%(vm_name)s] has "
|
||||
"been cancelled.<br/>\n"
|
||||
"You can see your order status by clicking [my VM page] below.<br/>\n"
|
||||
"If you want to order a new virtual machine, you can do it by clicking <a "
|
||||
"href=\"%(base_url)s%(my_virtual_machines_url)s\">this link</a>.<br/>\n"
|
||||
msgstr ""
|
||||
"Du erhälst diese E-Mail, Da Deine virtuelle Maschine [%(vm_name)s] gekündigt "
|
||||
"wurde.<br/>\n"
|
||||
"Um Deinen Auftragsstatus zu sehen, klicke auf die [my VM page] unten.<br/>\n"
|
||||
"Falls Du eine neue virtuelle Maschine bestellen möchtest, kannst Du dies "
|
||||
"tun, indem Du <a href=\"%(base_url)s%(my_virtual_machines_url)s\">diesen "
|
||||
"Link klickst</a>.<br/>\n"
|
||||
|
||||
msgid "Thanks for using our site!"
|
||||
msgid "My VM page"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgid "The %(site_name)s team"
|
||||
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"
|
||||
msgstr "Umschalten"
|
||||
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
|
||||
msgid "Logout"
|
||||
msgstr "Abmelden"
|
||||
|
||||
msgid "Don't have an account yet ? "
|
||||
msgstr "Besitzt du kein Benutzerkonto?"
|
||||
|
|
@ -197,6 +306,9 @@ msgstr "Registrieren"
|
|||
msgid "Forgot your password ? "
|
||||
msgstr "Passwort vergessen?"
|
||||
|
||||
msgid "Resend activation link"
|
||||
msgstr "Aktivierungslink noch einmal senden"
|
||||
|
||||
msgid "Notifications"
|
||||
msgstr "Benachrichtigungen"
|
||||
|
||||
|
|
@ -215,21 +327,37 @@ msgstr "Als gelesen markieren"
|
|||
msgid "All notifications"
|
||||
msgstr "Alle Benachrichtigungen"
|
||||
|
||||
msgid "Date"
|
||||
msgstr "Datum"
|
||||
|
||||
msgid "Status:"
|
||||
#, python-format
|
||||
msgid "%(page_header_text)s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Billed To:"
|
||||
msgid "Invoice Date"
|
||||
msgstr "Rechnung Datum"
|
||||
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Approved"
|
||||
msgstr "Akzeptiert"
|
||||
|
||||
msgid "Declined"
|
||||
msgstr "Abgelehnt"
|
||||
|
||||
msgid "Billed to"
|
||||
msgstr "Rechnungsadresse"
|
||||
|
||||
msgid "Payment Method:"
|
||||
msgid "Payment method"
|
||||
msgstr "Bezahlmethode"
|
||||
|
||||
msgid "ending in"
|
||||
msgstr "endend in"
|
||||
|
||||
msgid "Order summary"
|
||||
msgstr "Bestellungsübersicht"
|
||||
|
||||
msgid "Product"
|
||||
msgstr "Produkt"
|
||||
|
||||
msgid "Cores"
|
||||
msgstr "Prozessorkerne"
|
||||
|
||||
|
|
@ -242,23 +370,40 @@ msgstr "Festplattenkapazität"
|
|||
msgid "Total"
|
||||
msgstr "Gesamt"
|
||||
|
||||
msgid "Finish Configuration"
|
||||
msgstr "Konfiguration beenden"
|
||||
#, python-format
|
||||
msgid ""
|
||||
"By clicking \"Place order\" this plan will charge your credit card account "
|
||||
"with the fee of %(vm_price)sCHF/month"
|
||||
msgstr ""
|
||||
"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(vm_price)sCHF "
|
||||
"pro Monat belastet"
|
||||
|
||||
msgid "Place order"
|
||||
msgstr "Bestellen"
|
||||
|
||||
msgid "BACK TO LIST"
|
||||
msgstr "ZURÜCK ZUR LISTE"
|
||||
|
||||
msgid "Processing..."
|
||||
msgstr "Abarbeitung..."
|
||||
|
||||
msgid "Hold tight, we are processing your request"
|
||||
msgstr "Bitte warten - wir bearbeiten Deine Anfrage gerade"
|
||||
|
||||
msgid "Some problem encountered. Please try again later."
|
||||
msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal."
|
||||
|
||||
msgid "Order Nr."
|
||||
msgstr "Bestellung Nr."
|
||||
|
||||
msgid "Date"
|
||||
msgstr "Datum"
|
||||
|
||||
msgid "Amount"
|
||||
msgstr "Betrag"
|
||||
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
msgid "See Invoice"
|
||||
msgstr "Rechnung"
|
||||
|
||||
msgid "View Detail"
|
||||
msgstr "Details anzeigen"
|
||||
msgstr "Siehe Rechnung"
|
||||
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
|
|
@ -275,9 +420,6 @@ msgstr "Konfiguration"
|
|||
msgid "including VAT"
|
||||
msgstr "inkl. Mehrwertsteuer"
|
||||
|
||||
msgid "Month"
|
||||
msgstr "Monat"
|
||||
|
||||
msgid "Billing Address"
|
||||
msgstr "Rechnungsadresse"
|
||||
|
||||
|
|
@ -302,9 +444,8 @@ msgid ""
|
|||
"You are not making any payment yet. After submitting your card information, "
|
||||
"you will be taken to the Confirm Order Page."
|
||||
msgstr ""
|
||||
"Es wird noch keine Bezahlung vorgenommen. Die Bezahlung wird erst "
|
||||
"ausgelöst, nachdem Du die Bestellung auf der nächsten Seite bestätigt "
|
||||
"hast."
|
||||
"Es wird noch keine Bezahlung vorgenommen. Die Bezahlung wird erst ausgelöst, "
|
||||
"nachdem Du die Bestellung auf der nächsten Seite bestätigt hast."
|
||||
|
||||
msgid "Submit"
|
||||
msgstr "Absenden"
|
||||
|
|
@ -330,6 +471,25 @@ msgstr "Deine Kreditkartennummer"
|
|||
msgid "Reset your password"
|
||||
msgstr "Passwort zurücksetzen"
|
||||
|
||||
msgid "UPDATE"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type"
|
||||
msgstr "Kartentyp"
|
||||
|
||||
msgid "No Credit Cards Added"
|
||||
msgstr "Es wurde keine Kreditkarte hinzugefügt"
|
||||
|
||||
msgid ""
|
||||
"We are using <a href=\"https://stripe.com\">Stripe</a> for payment and do "
|
||||
"not store your information in our database."
|
||||
msgstr ""
|
||||
"Wir nutzen <a href=\"https://stripe.com\" target=\"_blank\">Stripe</a> für "
|
||||
"die Bezahlung und speichern keine Informationen in unserer Datenbank."
|
||||
|
||||
msgid "Add your public SSH key"
|
||||
msgstr "Füge deinen öffentlichen SSH-Key hinzu"
|
||||
|
||||
|
|
@ -345,16 +505,11 @@ msgstr "Erstelle dein neues Keypaar"
|
|||
msgid "Warning!"
|
||||
msgstr "Achtung!"
|
||||
|
||||
#, fuzzy
|
||||
#| msgid "You can download your SSH private key once. Don't lost your key"
|
||||
msgid "You can download your SSH private key once. Don't loose your key"
|
||||
msgstr ""
|
||||
"Du kannst deinen privaten SSH Schlüssel nur einmal herunterladen. Beware ihn "
|
||||
"sicher auf."
|
||||
|
||||
msgid "Your SSH Keys"
|
||||
msgstr "Deine SSH Keys"
|
||||
|
||||
msgid ""
|
||||
"To generate a new key pair or to upload your existing key, click 'Add Key'"
|
||||
msgstr ""
|
||||
|
|
@ -382,8 +537,6 @@ msgstr "Möchtest Du den Schlüssel löschen?"
|
|||
msgid "Show"
|
||||
msgstr "Anzeigen"
|
||||
|
||||
#, fuzzy
|
||||
#| msgid "Public SSH Key"
|
||||
msgid "Public SSH Key"
|
||||
msgstr "Public SSH Key"
|
||||
|
||||
|
|
@ -411,6 +564,9 @@ msgstr "Aktueller Preis"
|
|||
msgid "Your VM is"
|
||||
msgstr "Deine VM ist"
|
||||
|
||||
msgid "Terminating"
|
||||
msgstr "Beenden"
|
||||
|
||||
msgid "Pending"
|
||||
msgstr "In Vorbereitung"
|
||||
|
||||
|
|
@ -423,8 +579,10 @@ msgstr "Fehlgeschlagen"
|
|||
msgid "Terminate VM"
|
||||
msgstr "VM Beenden"
|
||||
|
||||
msgid "Support / Contact"
|
||||
msgstr "Support / Kontakt"
|
||||
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?"
|
||||
msgstr "Etwas funktioniert nicht?"
|
||||
|
|
@ -433,10 +591,7 @@ msgid "We are here to help you!"
|
|||
msgstr "Wir sind hier, um Dir zu helfen!"
|
||||
|
||||
msgid "CONTACT"
|
||||
msgstr "KONTACT"
|
||||
|
||||
msgid "BACK TO LIST"
|
||||
msgstr "ZURÜCK ZUR LISTE"
|
||||
msgstr "KONTAKT"
|
||||
|
||||
msgid "Terminate your Virtual Machine"
|
||||
msgstr "Deine Virtuelle Maschine beenden"
|
||||
|
|
@ -447,15 +602,26 @@ msgstr "Bist Du sicher, dass Du Deine virtuelle Maschine beenden willst"
|
|||
msgid "OK"
|
||||
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"
|
||||
msgstr "Virtuelle Maschinen"
|
||||
|
||||
msgid "To create a new virtual machine, click \"Create VM\""
|
||||
msgstr ""
|
||||
msgstr "Um eine neue VM zu erzeugen, klicke \"Neue VM erzeugen\""
|
||||
|
||||
msgid "CREATE VM"
|
||||
msgstr "NEUE VM"
|
||||
|
||||
msgid "View Detail"
|
||||
msgstr "Details anzeigen"
|
||||
|
||||
msgid "login"
|
||||
msgstr "Einloggen"
|
||||
|
||||
|
|
@ -483,57 +649,129 @@ msgstr "Du kannst dich nun"
|
|||
msgid "Sorry. Your request is invalid."
|
||||
msgstr "Entschuldigung, deine Anfrage ist ungültig."
|
||||
|
||||
msgid "Password has been reset."
|
||||
msgstr "Dein Passwort wurde erfolgreich zurückgesetzt."
|
||||
|
||||
msgid "Password reset has not been successful."
|
||||
msgstr "Dein Passwort konnte nicht zurückgesetzt werden."
|
||||
|
||||
msgid "The reset password link is no longer valid."
|
||||
msgstr "Der Link zum Zurücksetzen Deines Passwortes ist nicht mehr gültig."
|
||||
|
||||
msgid "Invalid credit card"
|
||||
msgstr "Ungültige Kreditkarte"
|
||||
|
||||
msgid "Confirm Order"
|
||||
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."
|
||||
msgstr "Danke für Deine Bestellung."
|
||||
|
||||
msgid ""
|
||||
"Your VM will be up and running in a few moments. We will send you a "
|
||||
"confirmation email as soon as it is ready."
|
||||
msgstr ""
|
||||
"Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du "
|
||||
"auf sie zugreifen kannst."
|
||||
|
||||
msgid "Invalid number of cores"
|
||||
msgstr "Ungültige Anzahle CPU-Kerne"
|
||||
|
||||
msgid "Invalid RAM size"
|
||||
msgstr "Ungültige RAM-Grösse"
|
||||
|
||||
msgid "Invalid storage size"
|
||||
msgstr "Ungültige Speicher-Grösse"
|
||||
|
||||
msgid ""
|
||||
"We could not find the requested VM. Please "
|
||||
"contact Data Center Light Support."
|
||||
msgstr ""
|
||||
msgstr "Kontaktiere den Data Center Light Support."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "\n"
|
||||
#~ " You are not making any "
|
||||
#~ "payment yet. After submitting your card\n"
|
||||
#~ " information, you will be "
|
||||
#~ "taken to the Confirm Order Page.\n"
|
||||
#~ " "
|
||||
#~ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Es wird noch keine Bezahlung vorgenommen. Nach der Eingabe Deiner "
|
||||
#~ "Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
|
||||
#~ "weitergeleitet."
|
||||
msgid "Terminated"
|
||||
msgstr "Beendet"
|
||||
|
||||
#~ msgid "Approved"
|
||||
#~ msgstr "Akzeptiert"
|
||||
msgid "Error terminating VM"
|
||||
msgstr "Fehler beenden VM"
|
||||
|
||||
#~ msgid "Declined"
|
||||
#~ msgstr "Abgelehnt"
|
||||
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 "Finish Configuration"
|
||||
#~ msgstr "Konfiguration beenden"
|
||||
|
||||
#~ msgid "Your New VM %(vm_name)s at Data Center Light"
|
||||
#~ msgstr "Deine neue VM %(vm_name)s bei Data Center Light"
|
||||
|
||||
#~ msgid "My Virtual Machines"
|
||||
#~ msgstr "Meine virtuellen Maschinen"
|
||||
|
||||
#~ msgid "My Orders"
|
||||
#~ msgstr "Meine Bestellungen"
|
||||
|
||||
#~ msgid "SSH Keys"
|
||||
#~ msgstr "SSH Keys"
|
||||
|
||||
#~ msgid "Notifications "
|
||||
#~ msgstr "Benachrichtigungen"
|
||||
|
||||
#~ msgid "REMOVE CARD"
|
||||
#~ msgstr "KARTE ENTFERNEN"
|
||||
|
||||
#~ msgid "EDIT CARD"
|
||||
#~ msgstr "BEARBEITEN"
|
||||
|
||||
#~ msgid "Add a new Card."
|
||||
#~ msgstr "Neue Kreditkarte hinzufügen."
|
||||
|
||||
#~ msgid "You are not making any payment here."
|
||||
#~ msgstr "Es wird noch keine Bezahlung vorgenommen"
|
||||
|
||||
#~ msgid "Your SSH Keys"
|
||||
#~ msgstr "Deine SSH Keys"
|
||||
|
||||
#~ msgid "Cancel Order"
|
||||
#~ msgstr "Bestellung stornieren"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Do You want to delete your order?"
|
||||
#~ msgid "Do you want to delete your order?"
|
||||
#~ msgstr "Willst du deine Bestellung löschen?"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "\n"
|
||||
#~ " You are not making any payment "
|
||||
#~ "yet. After submitting your card\n"
|
||||
#~ " information, you will be taken to "
|
||||
#~ "the Confirm Order Page.\n"
|
||||
#~ " "
|
||||
#~ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Es wird noch keine Bezahlung vorgenommen. Nach der Eingabe Deiner "
|
||||
#~ "Kreditkateninformationen wirst du auf die Bestellbestätigungsseite "
|
||||
#~ "weitergeleitet."
|
||||
|
||||
#~ msgid "Ip not assigned yet"
|
||||
#~ msgstr "Ip nicht zugewiesen"
|
||||
|
||||
|
|
@ -549,9 +787,6 @@ msgstr ""
|
|||
#~ msgid "Ipv6"
|
||||
#~ msgstr "IPv6"
|
||||
|
||||
#~ msgid "Close"
|
||||
#~ msgstr "Schliessen"
|
||||
|
||||
#~ msgid "Cancel"
|
||||
#~ msgstr "Beenden"
|
||||
|
||||
|
|
@ -559,89 +794,19 @@ msgstr ""
|
|||
#~ msgstr "Hinzufügen"
|
||||
|
||||
#~ msgid "Keys"
|
||||
#~ msgstr "Schlüssel"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Contact"
|
||||
#~ msgid "Content"
|
||||
#~ msgstr "Kontakt"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Contact"
|
||||
#~ msgid "DG.Contact"
|
||||
#~ msgstr "Kontakt"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Home"
|
||||
#~ msgid "DG.Home"
|
||||
#~ msgstr "Home"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Amount"
|
||||
#~ msgid "Country"
|
||||
#~ msgstr "Betrag"
|
||||
#~ msgstr "Keys"
|
||||
|
||||
#~ msgid "Log in"
|
||||
#~ msgstr "Anmelden"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Configuration"
|
||||
#~ msgid "Donation #"
|
||||
#~ msgstr "Konfiguration"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Billing Address"
|
||||
#~ msgid "Billing Address:"
|
||||
#~ msgstr "Rechnungsadresse"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Date"
|
||||
#~ msgid "Date:"
|
||||
#~ msgstr "Datum"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Configuration"
|
||||
#~ msgid "Donation"
|
||||
#~ msgstr "Konfiguration"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "View Detail"
|
||||
#~ msgid "View Donations"
|
||||
#~ msgstr "Details anzeigen"
|
||||
|
||||
#~ msgid "You haven been logged out"
|
||||
#~ msgstr "Sie wurden abgmeldet"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Log in"
|
||||
#~ msgid "Log in "
|
||||
#~ msgstr "Anmelden"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "View Detail"
|
||||
#~ msgid "DG.Detail"
|
||||
#~ msgstr "Details anzeigen"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Cancel"
|
||||
#~ msgid "France"
|
||||
#~ msgstr "Beenden"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Enter your credit card number"
|
||||
#~ msgid "Enter your name or company name"
|
||||
#~ msgstr "Deine Kreditkartennummer"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Card Number"
|
||||
#~ msgid "Cardholder Name"
|
||||
#~ msgstr "Kreditkartennummer"
|
||||
#~ msgstr "Du wurdest abgemeldet"
|
||||
|
||||
#~ msgid "How it works"
|
||||
#~ msgstr "So funktioniert es"
|
||||
|
||||
#~ msgid "Your infrastructure"
|
||||
#~ msgstr "deine Infrastruktur"
|
||||
#~ msgstr "Deine Infrastruktur"
|
||||
|
||||
#~ msgid "Our inftrastructure"
|
||||
#~ msgstr "Unsere Infrastruktur"
|
||||
|
|
@ -650,26 +815,20 @@ msgstr ""
|
|||
#~ msgstr "Preise"
|
||||
|
||||
#~ msgid "Access Key"
|
||||
#~ msgstr "Zugriffsschlüssel"
|
||||
#~ msgstr "SSH Key"
|
||||
|
||||
#~ msgid "Upload your own key. "
|
||||
#~ msgstr "Lade deinen Key hoch"
|
||||
#~ msgstr "Lade Deinen Key hoch"
|
||||
|
||||
#~ msgid "Generate Key Pair"
|
||||
#~ msgstr "Schlüsselpaar generieren"
|
||||
|
||||
#~ msgid "Created at"
|
||||
#~ msgstr "Erstellt am"
|
||||
|
||||
#~ msgid "Billing Amount"
|
||||
#~ msgstr "Rechnungsbetrag"
|
||||
|
||||
#~ msgid "Payment Details"
|
||||
#~ msgstr "Rechnungsdetails"
|
||||
|
||||
#~ msgid "Place Order"
|
||||
#~ msgstr "Bestelle"
|
||||
|
||||
#~ msgid "CARD NUMBER"
|
||||
#~ msgstr "Kreditkartennummer"
|
||||
|
||||
|
|
@ -683,5 +842,5 @@ msgstr ""
|
|||
#~ "Your SSH private key was already generated and downloaded, if you lost "
|
||||
#~ "it, contact us. "
|
||||
#~ msgstr ""
|
||||
#~ "Dein privater SSH Schlüssel wurde bereits generiert und heruntergeladen. "
|
||||
#~ "Falls du ihn verloren hast, kontaktiere uns."
|
||||
#~ "Dein privater SSH Key wurde bereits generiert und heruntergeladen. "
|
||||
#~ "Falls Du ihn verloren hast, kontaktiere uns."
|
||||
|
|
|
|||
|
|
@ -1,11 +1,22 @@
|
|||
@media (min-width: 768px) {
|
||||
.navbar-right {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-container {
|
||||
padding-top:70px;
|
||||
padding-top: 80px;
|
||||
padding-bottom: 70px;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
max-width: 768px;
|
||||
}
|
||||
|
||||
.dashboard-container.wide {
|
||||
padding-top: 90px;
|
||||
max-width: 980px;
|
||||
}
|
||||
|
||||
.content-dashboard{
|
||||
min-height: calc(100vh - 70px);
|
||||
width: 80%;
|
||||
|
|
@ -103,7 +114,7 @@
|
|||
text-align: center;
|
||||
width: 100%;
|
||||
float: left;
|
||||
padding: 0px 40px 15px 30px;
|
||||
padding: 0px 30px 15px 30px;
|
||||
}
|
||||
.modal-body .modal-icon i {
|
||||
font-size: 80px;
|
||||
|
|
@ -111,7 +122,7 @@
|
|||
color: #999;
|
||||
}
|
||||
.modal-body .modal-icon {
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.modal-title {
|
||||
margin: 0;
|
||||
|
|
@ -122,9 +133,16 @@
|
|||
font-weight: 300;
|
||||
}
|
||||
.modal-text {
|
||||
padding-top: 15px;
|
||||
padding-top: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.modal-text p:not(:last-of-type){
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.modal-title + .modal-footer {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.modal-footer {
|
||||
border-top: 0px solid #e5e5e5;
|
||||
width: 100%;
|
||||
|
|
@ -132,11 +150,8 @@
|
|||
text-align: center;
|
||||
padding: 15px 15px;
|
||||
}
|
||||
.modal-footer button[type="submit"] {
|
||||
min-width: 80px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
.modal-dialog {/* top: 30%; */width: 35%;}
|
||||
.modal-dialog {/* top: 30%; */width: 40%;}
|
||||
}
|
||||
@media (max-width: 1299px) {
|
||||
.modal-dialog {
|
||||
|
|
@ -233,4 +248,131 @@
|
|||
-webkit-transform: translate(-50%,-50%);
|
||||
-ms-transform: translate(-50%,-50%);
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
|
||||
.settings-container {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.settings-container h4 {
|
||||
margin-bottom: 15px;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.settings-container .card-expiry-element,
|
||||
.settings-container .card-cvc-element {
|
||||
padding: 0 15px;
|
||||
}
|
||||
.settings-container .card-cvc-element .my-input,
|
||||
.settings-container .card-cvc-element label {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.settings-container .stripe-payment-btn {
|
||||
float: none;
|
||||
position: static;
|
||||
}
|
||||
|
||||
.settings-container h3 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.settings-container hr {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.settings-container .credit-card-details {
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.settings-container .credit-card-details h5 {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.credit-card-form {
|
||||
max-width: 360px;
|
||||
}
|
||||
|
||||
.btn-wide {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.caps-link {
|
||||
font-weight: 600;
|
||||
color: #8da4c0;
|
||||
fill: #8da4c0;
|
||||
padding: 8px 0;
|
||||
display: block;
|
||||
}
|
||||
.caps-link:hover,
|
||||
.caps-link:focus,
|
||||
.caps-link:active {
|
||||
color: #627388;
|
||||
fill: #627388;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.settings-container .credit-card-details-opt {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.caps-link .svg-img {
|
||||
margin-right: 5px;
|
||||
height: 13px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.settings-container .caps-link {
|
||||
font-size: 13px;
|
||||
letter-spacing: 1.1px;
|
||||
}
|
||||
|
||||
.settings-container .btn-vm-contact {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
/* padding: 4px 15px; */
|
||||
}
|
||||
|
||||
.btn-wide {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.no-cards {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 15px;
|
||||
background: rgba(0,0,0,0.02);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 230px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.no-cards h4 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.no-cards a {
|
||||
color: #7ca3d0;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
85
hosting/static/hosting/css/dashboard.css
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
.hosting-dashboard:after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(91, 116, 173, 0.7);
|
||||
z-index: -1;
|
||||
}
|
||||
.hosting-dashboard:before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: url(../../datacenterlight/img/pattern.jpg) no-repeat center center;
|
||||
background-size: cover;
|
||||
z-index: -2;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hosting-dashboard .dashboard-container-head {
|
||||
color: #fff;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.hosting-dashboard-item {
|
||||
background: #e9ebee;
|
||||
box-shadow: 1px 3px 3px rgba(0,0,0,0.4);
|
||||
padding: 25px;
|
||||
color: rgba(124, 139, 175, 1);
|
||||
font-size: 19px;
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.hosting-dashboard-item:hover,
|
||||
.hosting-dashboard-item:focus,
|
||||
.hosting-dashboard-item:active {
|
||||
text-decoration: none;
|
||||
color: #7c8baf;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.hosting-dashboard-item h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 2px solid #acb5cf;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.hosting-dashboard-image {
|
||||
height: 120px;
|
||||
fill: #8b9bb7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.hosting-dashboard-item:hover .hosting-dashboard-image,
|
||||
.hosting-dashboard-item:focus .hosting-dashboard-image,
|
||||
.hosting-dashboard-item:active .hosting-dashboard-image {
|
||||
fill: #6D84AC;
|
||||
color: #6D84AC;
|
||||
}
|
||||
.hosting-dashboard-image img,
|
||||
.hosting-dashboard-image svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 79px;
|
||||
}
|
||||
.hosting-dashboard-image img {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.hosting-dashboard-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.hosting-dashboard-item {
|
||||
width: 31.5%;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,20 +4,6 @@
|
|||
* For details, see http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*/
|
||||
|
||||
/*@font-face {
|
||||
font-family: 'Lato-Regular';
|
||||
src: url('../fonts/Lato/Lato-Regular.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
src: url('../fonts/Lato/Lato-Black.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato-Light';
|
||||
src: url('../fonts/Lato/Lato-Light.ttf');
|
||||
}*/
|
||||
|
||||
body,
|
||||
html {
|
||||
width: 100%;
|
||||
|
|
@ -39,11 +25,29 @@ h6 {
|
|||
.topnav {
|
||||
font-size: 14px;
|
||||
}
|
||||
.topnav .navbar-fixed-top .navbar-collapse {
|
||||
max-height: 740px;
|
||||
}
|
||||
.navbar-brand {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.navbar-default {
|
||||
background: #fff;
|
||||
/* box-shadow: 0 3px 3px -2px hsla(0,0%,78%,.72); */
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.navbar-default .navbar-header {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.navbar-transparent {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 20px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navbar-transparent.topnav {
|
||||
|
|
@ -71,6 +75,48 @@ h6 {
|
|||
/* color: #fff; */
|
||||
}
|
||||
|
||||
.navbar-right .highlights-dropdown .dropdown-menu {
|
||||
left: 0 !important;
|
||||
min-width: 155px;
|
||||
margin-left: 15px;
|
||||
padding: 0 5px 8px !important;
|
||||
}
|
||||
@media(min-width: 768px) {
|
||||
.navbar-default .navbar-nav>li>a,
|
||||
.navbar-right .highlights-dropdown .dropdown-menu > li > a {
|
||||
font-weight: 300;
|
||||
}
|
||||
.navbar-right .highlights-dropdown .dropdown-menu {
|
||||
box-shadow: 0 2px 5px 0 rgba(0,0,0,0.02);
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: #e7e7e7;
|
||||
box-shadow: -8px 14px 20px -5px rgba(77, 77, 77, 0.5);
|
||||
}
|
||||
/* .navbar-right .highlights-dropdown .dropdown-menu:before {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 1px;
|
||||
background: #e7e7e7;
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
} */
|
||||
}
|
||||
.navbar-right .highlights-dropdown .dropdown-menu > li > a{
|
||||
font-size: 13px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
padding: 1px 10px 1px 18px !important;
|
||||
background: transparent;
|
||||
color: #333;
|
||||
}
|
||||
.navbar-right .highlights-dropdown .dropdown-menu > li > a:hover,
|
||||
.navbar-right .highlights-dropdown .dropdown-menu > li > a:focus,
|
||||
.navbar-right .highlights-dropdown .dropdown-menu > li > a:active {
|
||||
background: transparent;
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
.lead {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
|
|
@ -534,8 +580,9 @@ a.unlink:hover {
|
|||
}
|
||||
|
||||
.dcl-place-order-text{
|
||||
font-size: 13px;
|
||||
/* font-size: 13px; */
|
||||
color: #808080;
|
||||
/* margin-bottom: 15px; */
|
||||
}
|
||||
|
||||
.dcl-order-table-total .tbl-total {
|
||||
|
|
@ -568,6 +615,7 @@ a.unlink:hover {
|
|||
border: 1px solid #a1a1a1;
|
||||
border-radius: 3px;
|
||||
padding: 5px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.card-warning-error {
|
||||
border: 1px solid #EB4D5C;
|
||||
|
|
@ -725,12 +773,12 @@ a.unlink:hover {
|
|||
|
||||
@media (min-width: 768px) {
|
||||
.dcl-billing {
|
||||
padding-right: 50px;
|
||||
padding-right: 65px;
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
|
||||
.dcl-creditcard {
|
||||
padding-left: 50px;
|
||||
padding-left: 65px;
|
||||
}
|
||||
|
||||
.tbl-tot {
|
||||
|
|
@ -760,6 +808,30 @@ a.unlink:hover {
|
|||
color: #ddd;
|
||||
}
|
||||
|
||||
.visible-mobile {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@media(max-width:767px) {
|
||||
.visible-mobile {
|
||||
display: block !important;
|
||||
}
|
||||
.visible-desktop {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, .navbar-default .navbar-nav>.open>a:hover,
|
||||
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus, .navbar-default .navbar-nav>.active>a:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.navbar-default .navbar-nav .open .dropdown-menu>.active>a, .navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus, .navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
/* bootstrap danger color override from #a94442 */
|
||||
.text-danger,
|
||||
.has-error .help-block,
|
||||
|
|
@ -772,7 +844,6 @@ a.unlink:hover {
|
|||
.has-error.checkbox label,
|
||||
.has-error.radio-inline label,
|
||||
.has-error.checkbox-inline label,
|
||||
.has-error .form-control,
|
||||
.has-error .form-control-feedback,
|
||||
.alert-danger,
|
||||
.list-group-item-danger,
|
||||
|
|
@ -782,6 +853,10 @@ a.list-group-item-danger:focus,
|
|||
.panel-danger > .panel-heading {
|
||||
color: #eb4d5c;
|
||||
}
|
||||
.alert-danger{
|
||||
background: rgba(235, 204, 209, 0.2);
|
||||
}
|
||||
.has-error .form-control,
|
||||
.has-error .input-group-addon {
|
||||
color: #eb4d5c;
|
||||
border-color: #eb4d5c;
|
||||
|
|
@ -795,3 +870,41 @@ a.list-group-item-danger.active:focus {
|
|||
.panel-danger > .panel-heading .badge {
|
||||
background-color: #eb4d5c;
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
display: inline-block;
|
||||
}
|
||||
.checkmark:after {
|
||||
/*Add another block-level blank space*/
|
||||
content: '';
|
||||
display: block;
|
||||
/*Make it a small rectangle so the border will create an L-shape*/
|
||||
width: 25px;
|
||||
height: 60px;
|
||||
/*Add a white border on the bottom and left, creating that 'L' */
|
||||
border: solid #777;
|
||||
border-width: 0 3px 3px 0;
|
||||
/*Rotate the L 45 degrees to turn it into a checkmark*/
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.closemark {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: relative;
|
||||
}
|
||||
.closemark:before, .closemark:after {
|
||||
position: absolute;
|
||||
left: 25px;
|
||||
content: ' ';
|
||||
height: 50px;
|
||||
width: 2px;
|
||||
background-color: #777;
|
||||
}
|
||||
.closemark:before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.closemark:after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
display: inline-block;
|
||||
|
|
@ -15,3 +26,67 @@
|
|||
.order-detail-container .table > tbody > tr > .thick-line {
|
||||
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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -163,8 +163,8 @@
|
|||
/* margin-left: 0; */
|
||||
}
|
||||
.col-md-12, .col-sm-12{
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
/*padding-left: 5px;*/
|
||||
/*padding-right: 5px;*/
|
||||
}
|
||||
}
|
||||
@media (max-width: 360px){
|
||||
|
|
@ -172,8 +172,8 @@
|
|||
/* width: 100% !important; */
|
||||
}
|
||||
.container {
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
/*padding-right: 5px;
|
||||
padding-left: 5px;*/
|
||||
}
|
||||
}
|
||||
.dashboard-choice-container {
|
||||
|
|
@ -299,6 +299,7 @@
|
|||
}
|
||||
.key_contain {
|
||||
word-break: break-all;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.custom_form_button{
|
||||
border-radius: 0;
|
||||
|
|
|
|||
|
|
@ -290,6 +290,11 @@
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.vm-vmid .alert {
|
||||
margin-top: 15px;
|
||||
margin-bottom: -60px;
|
||||
}
|
||||
|
||||
.vm-item-lg {
|
||||
font-size: 22px;
|
||||
margin-top: 5px;
|
||||
|
|
@ -305,6 +310,10 @@
|
|||
color: #e47f2f;
|
||||
}
|
||||
|
||||
.vm-color-failed {
|
||||
color: #eb4d5c;
|
||||
}
|
||||
|
||||
.vm-detail-item .value{
|
||||
font-weight: 400;
|
||||
}
|
||||
|
|
@ -440,10 +449,16 @@
|
|||
}
|
||||
|
||||
.dashboard-title-thin .un-icon {
|
||||
height: 30px;
|
||||
height: 34px;
|
||||
margin-right: 5px;
|
||||
margin-top: -1px;
|
||||
width: 30px;
|
||||
margin-top: -2px;
|
||||
width: 34px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.dashboard-title-thin .un-icon.wide {
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
||||
.dashboard-subtitle {
|
||||
|
|
@ -506,7 +521,7 @@
|
|||
color: #87B6EA;
|
||||
}
|
||||
|
||||
.vm-status, .vm-status-active, .vm-status-failed {
|
||||
.vm-status, .vm-status-active, .vm-status-failed, .vm-status-pending {
|
||||
font-weight: 600;
|
||||
}
|
||||
.vm-status-active {
|
||||
|
|
@ -515,6 +530,9 @@
|
|||
.vm-status-failed {
|
||||
color: #eb4d5c;
|
||||
}
|
||||
.vm-status-pending {
|
||||
color: #e47f2f;
|
||||
}
|
||||
|
||||
@media (min-width:768px) {
|
||||
.dashboard-subtitle {
|
||||
|
|
@ -528,10 +546,15 @@
|
|||
font-size: 22px;
|
||||
}
|
||||
.dashboard-title-thin .un-icon {
|
||||
height: 20px;
|
||||
width: 18px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
.dashboard-title-thin .un-icon.wide {
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.dashboard-subtitle p {
|
||||
width: 200px;
|
||||
}
|
||||
|
|
@ -616,4 +639,28 @@
|
|||
left: auto;
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato"
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
|
@ -1,61 +1,15 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 279.525 279.525" style="enable-background:new 0 0 279.525 279.525;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M165.066,1.544c-29.272,0-56.007,11.05-76.268,29.191c4.494,7.146,7.047,15.46,7.287,24.042l0.001,0.025l0.001,0.025
|
||||
c0.102,3.867,0.333,7.735,0.664,11.597c15.368-21.117,40.258-34.88,68.315-34.88c46.571,0,84.459,37.888,84.459,84.459
|
||||
c0,46.08-37.098,83.634-82.994,84.422c4.191,3.502,8.518,6.84,12.976,9.974l0.02,0.015l0.021,0.014
|
||||
c6.07,4.282,11.014,9.896,14.483,16.317c49.133-12.861,85.493-57.633,85.493-110.742C279.525,52.89,228.18,1.544,165.066,1.544z"/>
|
||||
<path d="M162.256,234.942c-13.076-10.438-21.234-17.389-32.909-28.204c-3.435-3.182-7.633-5.164-11.944-5.164
|
||||
c-3.299,0-6.557,1.051-9.239,3.252c-2.768,2.33-5.536,4.66-8.305,6.989c-22.499-26.738-39.206-57.895-49.027-91.431
|
||||
c3.472-1.016,6.945-2.033,10.417-3.049c7.652-2.343,11.252-10.512,10.129-18.701c-2.443-17.824-3.77-26.679-5.282-43.018
|
||||
c-0.775-8.375-6.349-15.65-14.338-16.085c-1.246-0.121-2.491-0.181-3.726-0.181c-29.71,0-55.578,34.436-46.009,76.564
|
||||
c11.907,52.172,37.684,100.243,74.551,139.031c15.102,15.856,33.603,23.036,50.312,23.036c17.627,0,33.261-7.984,40.833-22.195
|
||||
C171.778,248.891,168.83,240.19,162.256,234.942z"/>
|
||||
<path d="M130.645,118.121c-7.912,7.341-13.089,13.113-15.823,17.643c-1.93,3.195-3.338,6.573-4.187,10.04
|
||||
c-0.399,1.632-0.032,3.326,1.007,4.649c1.038,1.321,2.596,2.079,4.276,2.079h37.758c4.626,0,8.39-3.764,8.39-8.39
|
||||
c0-4.626-3.764-8.39-8.39-8.39h-17.051c0.139-0.164,0.282-0.328,0.428-0.493c1.114-1.254,3.842-3.874,8.107-7.785
|
||||
c4.473-4.105,7.493-7.179,9.232-9.398c2.621-3.336,4.571-6.593,5.794-9.679c1.247-3.145,1.88-6.498,1.88-9.967
|
||||
c0-6.224-2.254-11.507-6.699-15.705c-4.416-4.164-10.495-6.274-18.071-6.274c-6.884,0-12.731,1.802-17.377,5.356
|
||||
c-2.803,2.146-4.961,5.119-6.415,8.839c-0.982,2.513-0.728,5.388,0.68,7.689c1.408,2.302,3.852,3.837,6.537,4.105
|
||||
c0.299,0.03,0.597,0.045,0.891,0.045c3.779,0,7.149-2.403,8.387-5.979c0.388-1.121,0.901-2.012,1.527-2.65
|
||||
c1.318-1.343,3.093-1.997,5.428-1.997c2.373,0,4.146,0.618,5.418,1.889c1.269,1.269,1.886,3.12,1.886,5.66
|
||||
c0,2.359-0.843,4.819-2.505,7.314C140.862,108.028,138.199,111.083,130.645,118.121z"/>
|
||||
<path d="M206.235,76.451h-6.307c-1.797,0-3.475,0.886-4.489,2.37l-29.168,42.698c-0.851,1.246-1.301,2.703-1.301,4.212v6.919
|
||||
c0,2.997,2.439,5.436,5.436,5.436h23.945v5.787c0,4.775,3.885,8.66,8.66,8.66c4.775,0,8.66-3.885,8.66-8.66v-5.787h0.865
|
||||
c4.437,0,8.047-3.61,8.047-8.047c0-4.437-3.61-8.047-8.047-8.047h-0.865V81.887C211.671,78.89,209.232,76.451,206.235,76.451z
|
||||
M194.352,121.992h-10.748l10.748-15.978V121.992z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="90px" height="90px" viewBox="0 0 90 90" 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>Slice 23</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="dashboard" stroke="none" stroke-width="1" fill-rule="evenodd">
|
||||
<g id="24-hours-support" transform="translate(5.000000, 7.000000)" fill-rule="nonzero">
|
||||
<path d="M46.5951681,0.152636732 C38.3819652,0.152636732 30.8805993,3.25307034 25.1957228,8.34311252 C26.4566594,10.3481531 27.1729858,12.6809138 27.2403255,15.0888704 C27.2695061,16.187911 27.3343206,17.2732031 27.4271933,18.3568116 C31.7391809,12.4317567 38.7228726,8.57010354 46.5951681,8.57010354 C59.662163,8.57010354 70.2928624,19.200803 70.2928624,32.2677979 C70.2928624,45.1970269 59.883823,55.7340118 47.0062211,55.9551106 C48.1821412,56.9377096 49.3962205,57.8742931 50.6470561,58.7536378 C52.3616941,59.9632278 53.7488926,61.5384164 54.7222323,63.3400349 C68.5080789,59.7314668 78.7100487,47.1692394 78.7100487,32.2677979 C78.7103293,14.5594118 64.3038348,0.152636732 46.5951681,0.152636732 Z" id="Shape"></path>
|
||||
<path d="M45.8067321,65.6399674 C42.1378389,62.7112501 39.8488491,60.760923 36.5730516,57.7264262 C35.6092516,56.8336136 34.4313674,56.2774996 33.2217774,56.2774996 C32.2961367,56.2774996 31.3819998,56.5723915 30.6294782,57.189953 C29.8528266,57.8437096 29.076175,58.4974662 28.2992428,59.1509422 C21.9864233,51.6487346 17.298736,42.9066342 14.543138,33.4970286 C15.5173195,33.2119571 16.4917816,32.9266049 17.4659631,32.6415334 C19.6129783,31.9841292 20.6230743,29.692053 20.3079804,27.3943652 C19.6225181,22.3932675 19.2501854,19.9087119 18.8259451,15.3242789 C18.6084939,12.9744028 17.0445285,10.9331671 14.8029571,10.8111138 C14.4533517,10.7771633 14.1040268,10.7603284 13.7575078,10.7603284 C5.42140979,10.7603284 -1.83669126,20.422458 0.848200072,32.242826 C4.18909265,46.881362 11.4216607,60.3692302 21.7658857,71.2524537 C26.0032385,75.7013655 31.1942903,77.7159458 35.8825387,77.7159458 C40.8283616,77.7159458 45.2149841,75.4757773 47.3395528,71.4884233 C48.478436,69.5538089 47.6512796,67.1124629 45.8067321,65.6399674 Z" id="Shape"></path>
|
||||
<path d="M36.9372473,32.862071 C34.7172807,34.9218251 33.2647065,36.5413458 32.4975947,37.8123833 C31.956071,38.7088435 31.5610112,39.6566502 31.3227969,40.6294288 C31.2108446,41.087339 31.3138183,41.5626453 31.6053432,41.9338556 C31.8965876,42.3045047 32.3337347,42.517186 32.8051128,42.517186 L43.3993366,42.517186 C44.6973099,42.517186 45.7534214,41.4610745 45.7534214,40.1631011 C45.7534214,38.8651278 44.6973099,37.8090163 43.3993366,37.8090163 L38.615129,37.8090163 C38.6541299,37.7630008 38.6942532,37.7169853 38.7352182,37.6706892 C39.0477868,37.3188391 39.8132151,36.5837137 41.0098983,35.4863566 C42.2649426,34.3345665 43.1123009,33.4720568 43.6002334,32.8494448 C44.3356394,31.9134225 44.8827748,30.9995662 45.2259269,30.1336894 C45.5758129,29.2512583 45.7534214,28.3104661 45.7534214,27.3371264 C45.7534214,25.5907826 45.1209891,24.1084667 43.8738011,22.9305825 C42.63475,21.7622381 40.9290906,21.1702096 38.8033997,21.1702096 C36.8718716,21.1702096 35.2313073,21.6758188 33.9277223,22.673008 C33.1412503,23.2751375 32.5357539,24.1093084 32.1277873,25.1530743 C31.8522556,25.8581775 31.9235235,26.6648514 32.3185832,27.3104711 C32.713643,27.9563714 33.399386,28.3870651 34.1527493,28.4622611 C34.2366433,28.4706786 34.3202569,28.4748873 34.402748,28.4748873 C35.4630683,28.4748873 36.4086304,27.8006482 36.7559912,26.7972862 C36.8648571,26.4827535 37.0087958,26.2327547 37.1844402,26.0537433 C37.5542476,25.6769213 38.0522811,25.4934206 38.7074406,25.4934206 C39.3732622,25.4934206 39.8707345,25.6668204 40.2276351,26.0234404 C40.5836939,26.3794992 40.7568131,26.8988569 40.7568131,27.6115358 C40.7568131,28.2734293 40.5202823,28.9636616 40.0539547,29.6637142 C39.8039559,30.0301546 39.0567654,30.8873333 36.9372473,32.862071 Z" id="Shape"></path>
|
||||
<path d="M58.1464578,21.1702096 L56.3768257,21.1702096 C55.8726195,21.1702096 55.4018025,21.4188055 55.1172921,21.8351895 L46.9332697,33.8154894 C46.6944942,34.1650949 46.5682322,34.5739032 46.5682322,34.9973018 L46.5682322,36.9386502 C46.5682322,37.7795551 47.2525723,38.4638952 48.0934772,38.4638952 L54.8120186,38.4638952 L54.8120186,40.0876245 C54.8120186,41.4274047 55.9020806,42.5174666 57.2418607,42.5174666 C58.5816409,42.5174666 59.6717028,41.4274047 59.6717028,40.0876245 L59.6717028,38.4638952 L59.9144064,38.4638952 C61.1593498,38.4638952 62.1722516,37.4509933 62.1722516,36.20605 C62.1722516,34.9611067 61.1593498,33.9482048 59.9144064,33.9482048 L59.6717028,33.9482048 L59.6717028,22.6954546 C59.6717028,21.8545497 58.9873628,21.1702096 58.1464578,21.1702096 Z M54.8122992,33.9482048 L51.7966014,33.9482048 L54.8122992,29.465062 L54.8122992,33.9482048 Z" id="Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
hosting/static/hosting/img/ajax-loader.gif
Normal file
|
After Width: | Height: | Size: 404 B |
|
|
@ -1 +1,13 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="symbol symbol-billing" aria-labelledby="title" role="img"><title id="title">billing icon</title><g data-name="Layer 1"><path class="cls-1" d="M.37.023v15.954l2.775-1.387 2.775 1.387L8 14.59l2.775 1.387 2.081-1.387 2.775 1.387V.023zm13.873 13.709l-1.487-.744-2.081 1.387L7.9 12.989l-2.08 1.387-2.675-1.337-1.387.694V1.41h12.485z" role="presentation"/><path class="cls-1" d="M4.206 3.617h7.741v1.348H4.206zm0 2.697h7.741v1.349H4.206zm0 2.697h7.741v1.349H4.206z" role="presentation"/></g></svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="90px" height="90px" viewBox="0 0 90 90" 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>Slice 23</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="dashboard" stroke="none" stroke-width="1" fill-rule="evenodd">
|
||||
<g id="billing.9cb6c82b" transform="translate(10.000000, 8.000000)" fill-rule="nonzero">
|
||||
<path d="M0.432900478,0.106254164 L0.432900478,73.8096859 L13.2526963,67.4020978 L26.0724922,73.8096859 L35.6815644,67.4020978 L48.5013603,73.8096859 L58.1150522,67.4020978 L70.9348481,73.8096859 L70.9348481,0.106254164 L0.432900478,0.106254164 Z M64.5226403,63.4383556 L57.6530776,60.0012643 L48.0393856,66.4088524 L35.2195898,60.0058841 L25.6105176,66.4134722 L13.2526963,60.2368714 L6.84510828,63.4429753 L6.84510828,6.51384222 L64.5226403,6.51384222 L64.5226403,63.4383556 Z" id="Shape"></path>
|
||||
<path d="M18.1542471,16.7096222 L53.9157029,16.7096222 L53.9157029,22.9370402 L18.1542471,22.9370402 L18.1542471,16.7096222 Z M18.1542471,29.1690778 L53.9157029,29.1690778 L53.9157029,35.4011155 L18.1542471,35.4011155 L18.1542471,29.1690778 Z M18.1542471,41.6285335 L53.9157029,41.6285335 L53.9157029,47.8605712 L18.1542471,47.8605712 L18.1542471,41.6285335 Z" id="Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 558 B After Width: | Height: | Size: 1.4 KiB |
14
hosting/static/hosting/img/dashboard_settings.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="90px" height="90px" viewBox="0 0 90 90" 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>Slice 23</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="dashboard" stroke="none" stroke-width="1" fill-rule="evenodd">
|
||||
<g id="62780" transform="translate(1.000000, 16.000000)" fill-rule="nonzero">
|
||||
<path d="M77.3788837,0.0166335071 L10.5054936,0.0166335071 C4.71263581,0.0166335071 0,4.72907813 0,10.5221271 L0,48.3010279 C0,54.0936945 4.71263581,58.8065215 10.5054936,58.8065215 L77.3786925,58.8065215 C83.1713591,58.8065215 87.883995,54.0936945 87.883995,48.3010279 L87.883995,10.5221271 C87.8841861,4.72907813 83.1715503,0.0166335071 77.3788837,0.0166335071 Z M82.0714446,48.3008367 C82.0714446,50.8883986 79.9662544,52.9933976 77.3788837,52.9933976 L10.5054936,52.9933976 C7.91793174,52.9933976 5.81274156,50.8883986 5.81274156,48.3008367 L5.81274156,22.983683 L82.0712534,22.983683 L82.0714446,48.3008367 L82.0714446,48.3008367 Z M82.0714446,14.6908282 L5.81293275,14.6963727 L5.81293275,10.521936 C5.81293275,7.93437406 7.91812293,5.82918387 10.5056848,5.82918387 L77.3788837,5.82918387 C79.9662544,5.82918387 82.0714446,7.93437406 82.0714446,10.521936 L82.0714446,14.6908282 Z" id="Shape"></path>
|
||||
<path d="M13.0269039,47.6024206 L28.9396256,47.6024206 C29.5093711,47.6024206 29.9716678,47.1405062 29.9716678,46.5707608 L29.9716678,43.4312341 C29.9716678,42.8612975 29.5093711,42.3993831 28.9396256,42.3993831 L13.0269039,42.3993831 C12.4569673,42.3993831 11.9948617,42.8612975 11.9948617,43.4312341 L11.9948617,46.5707608 C11.9946705,47.1405062 12.4567761,47.6024206 13.0269039,47.6024206 Z" id="Shape"></path>
|
||||
<path d="M64.6150569,47.6024206 L69.34815,47.6024206 C72.079869,47.6024206 74.2942285,45.388061 74.2942285,42.6565333 L74.2942285,37.9234402 C74.2942285,35.1919124 72.079869,32.9775529 69.34815,32.9775529 L64.6150569,32.9775529 C61.8835291,32.9775529 59.6691696,35.1919124 59.6691696,37.9234402 L59.6691696,42.6565333 C59.6691696,45.388061 61.8835291,47.6024206 64.6150569,47.6024206 Z" id="Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
7
hosting/static/hosting/img/delete.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M185,150h630c19.3,0,35-15.7,35-35s-15.7-35-35-35H605c0-38.7-31.3-70-70-70h-70c-38.7,0-70,31.3-70,70H185c-19.3,0-35,15.7-35,35S165.7,150,185,150z"/><path d="M885,220h-69.9c-0.1,0-0.3,0-0.4,0H395.1c0,0-0.1,0-0.1,0H185.3c-0.1,0-0.2,0-0.3,0h-70c-19.3,0-35,15.7-35,35c0,19.3,15.7,35,35,35h39.9l100.5,670.2C258,977.3,272.7,990,290,990h139.9c0,0,0,0,0,0c0,0,0,0,0,0h140c0,0,0,0,0,0c0,0,0,0,0,0H710c17.3,0,32-12.7,34.6-29.8L845.1,290H885c19.3,0,35-15.7,35-35C920,235.7,904.3,220,885,220z M463.3,920l-31.5-630h136.4l-31.5,630H463.3z M225.6,290h136.1l31.5,630h-73.1L225.6,290z M679.9,920h-73.1l31.5-630h136.1L679.9,920z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
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
|
|
@ -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 |
12
hosting/static/hosting/img/key.svg
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="90px" height="90px" viewBox="0 0 90 90" 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>Slice 23</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="dashboard" stroke="none" stroke-width="1" fill-rule="evenodd">
|
||||
<g id="img_16097" transform="translate(12.000000, 14.000000)" fill-rule="nonzero">
|
||||
<path d="M63.5394739,34.6343332 C59.133452,30.2283113 51.9992431,30.2283113 47.5932212,34.6343332 C47.0271224,35.200432 46.5428692,35.8142741 46.1268207,36.455398 L10.6262881,0.954865429 C9.37132214,-0.300100564 7.32518194,-0.300100564 6.07021594,0.954865429 L3.28746526,3.73761611 C2.0256788,4.9925821 2.03249927,7.03872231 3.28746526,8.2936883 L6.56811006,11.5743331 L0.920763093,17.2216801 C-0.306921031,18.4493642 -0.306921031,20.4341202 0.920763093,21.6618043 C2.14844722,22.8894884 4.13320322,22.8894884 5.36088734,21.6618043 L11.0082343,16.0144573 L12.2563798,17.2626029 L6.60903287,22.9167703 C5.38134874,24.1444544 5.38134874,26.1292104 6.60903287,27.3568946 C7.83671699,28.5845787 9.82147299,28.5845787 11.0491571,27.3568946 L16.6965041,21.7095476 L38.7811774,43.8010413 C38.1400534,44.2170899 37.5262114,44.701343 36.9601126,45.2674418 C32.5540907,49.6734637 32.5540907,56.8076726 36.9601126,61.2136945 C40.5613194,64.8149013 45.9835909,65.4628457 50.246383,63.1848096 C54.5091751,65.4696661 59.9382671,64.8149013 63.5326534,61.2136945 C67.1338602,57.6124877 67.7818046,52.1902162 65.5037685,47.9274241 C67.7954455,43.6578115 67.1406806,38.2287195 63.5394739,34.6343332 Z M58.7037625,56.3711627 C56.6780837,58.3968415 53.3906184,58.3968415 51.3649396,56.3711627 C50.9216093,55.9278323 50.5942268,55.4231177 50.34869,54.8843008 C48.1729609,56.9031591 44.7763682,56.8690568 42.6620233,54.7547119 C40.4931147,52.5858033 40.4931147,49.0732626 42.6620233,46.9111745 C44.0465782,45.5266196 45.96995,45.0355459 47.7500919,45.4174921 C47.3681458,43.6373501 47.8592194,41.7139783 49.2437743,40.3294235 C51.4126829,38.1605148 54.9252236,38.1605148 57.0873117,40.3294235 C59.2016566,42.4437683 59.235759,45.8403611 57.2169006,48.0160902 C57.7557175,48.2684475 58.2604321,48.5958299 58.7037625,49.0323398 C60.7294413,51.0580186 60.7294413,54.3454839 58.7037625,56.3711627 Z" id="Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
14
hosting/static/hosting/img/plusVM.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="90px" height="90px" viewBox="0 0 90 90" 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>Slice 23</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="dashboard" stroke="none" stroke-width="1" fill-rule="evenodd">
|
||||
<g id="img_194174" transform="translate(36.000000, 36.000000)" fill-rule="nonzero">
|
||||
<path d="M37.8716732,11.3625619 C37.8716732,12.857078 39.0853051,14.0654101 40.5745214,14.0654101 C42.0637378,14.0654101 43.2773696,12.8517783 43.2773696,11.3625619 C43.2773696,9.86804583 42.0637378,8.65971369 40.5745214,8.65971369 C39.0853051,8.65971369 37.8716732,9.86804583 37.8716732,11.3625619 Z M37.8716732,28.6713899 C37.8716732,30.165906 39.0853051,31.3742381 40.5745214,31.3742381 C42.0637378,31.3742381 43.2773696,30.1606063 43.2773696,28.6713899 C43.2773696,27.1768738 42.0637378,25.9685417 40.5745214,25.9685417 C39.0853051,25.9685417 37.8716732,27.1821735 37.8716732,28.6713899 L37.8716732,28.6713899 Z M0,35.7040949 C0,38.0942607 1.93439137,40.0339518 4.32985685,40.0339518 L22.7251238,40.0339518 L22.7251238,43.0229839 C22.1951536,43.378064 21.7393792,43.8338384 21.3842991,44.3638086 L8.11914405,44.3638086 C6.62462798,44.3638086 5.41629583,45.5774405 5.41629583,47.0666568 C5.41629583,48.5558732 6.62992768,49.7695051 8.11914405,49.7695051 L21.3842991,49.7695051 C22.25875,51.0785315 23.7426667,51.9317836 25.4332717,51.9317836 C27.1185771,51.9317836 28.6024938,51.0785315 29.4822443,49.7695051 L43.8285387,49.7695051 C45.3230548,49.7695051 46.5313869,48.5558732 46.5313869,47.0666568 C46.5313869,45.5774405 45.3177551,44.3638086 43.8285387,44.3638086 L29.4769446,44.3638086 C29.1218646,43.8338384 28.6660902,43.378064 28.1361199,43.0229839 L28.1361199,40.0392515 L47.6125262,40.0392515 C50.002692,40.0392515 51.942383,38.1048601 51.942383,35.7093946 L51.942383,4.32985685 C51.942383,1.93969107 50.0079917,0 47.6125262,0 L4.32985685,0 C1.93439137,0 0,1.93439137 0,4.32985685 L0,35.7040949 L0,35.7040949 Z M7.7905625,5.41099613 L44.1465208,5.41099613 C45.4661467,5.41099613 46.5260872,6.47093661 46.5260872,7.7905625 L46.5260872,14.9292616 C46.5260872,16.2488875 45.4661467,17.308828 44.1465208,17.308828 L7.7905625,17.308828 C6.47093661,17.308828 5.41099613,16.2488875 5.41099613,14.9292616 L5.41099613,7.7905625 C5.41099613,6.47093661 6.47093661,5.41099613 7.7905625,5.41099613 L7.7905625,5.41099613 L7.7905625,5.41099613 Z M7.7905625,22.7198241 L44.1465208,22.7198241 C45.4661467,22.7198241 46.5260872,23.7797646 46.5260872,25.0993905 L46.5260872,32.2380896 C46.5260872,33.5577155 45.4661467,34.617656 44.1465208,34.617656 L7.7905625,34.617656 C6.47093661,34.617656 5.41099613,33.5577155 5.41099613,32.2380896 L5.41099613,25.1046902 C5.41099613,23.7850643 6.47093661,22.7198241 7.7905625,22.7198241 L7.7905625,22.7198241 L7.7905625,22.7198241 Z" id="Shape"></path>
|
||||
</g>
|
||||
<rect id="Rectangle-3" x="23" y="3" width="10" height="50"></rect>
|
||||
<rect id="Rectangle-4" x="3" y="23" width="50" height="10"></rect>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
|
|
@ -1,7 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M724.6,224.4c0,28.2,22.9,51,51,51s51-22.9,51-51c0-28.2-22.9-51-51-51S724.6,196.2,724.6,224.4z M724.6,551c0,28.2,22.9,51,51,51s51-22.9,51-51c0-28.2-22.9-51-51-51S724.6,522.9,724.6,551L724.6,551z M10,683.7c0,45.1,36.5,81.7,81.7,81.7h347.1v56.4c-10,6.7-18.6,15.3-25.3,25.3l-250.3,0c-28.2,0-51,22.9-51,51s22.9,51,51,51h250.3c16.5,24.7,44.5,40.8,76.4,40.8c31.8,0,59.8-16.1,76.4-40.8h270.7c28.2,0,51-22.9,51-51s-22.9-51-51-51H566.2c-6.7-10-15.3-18.6-25.3-25.3v-56.3h367.5c45.1,0,81.7-36.5,81.7-81.7V91.7c0-45.1-36.5-81.7-81.7-81.7H91.7C46.5,10,10,46.5,10,91.7L10,683.7L10,683.7z M157,112.1h686c24.9,0,44.9,20,44.9,44.9v134.7c0,24.9-20,44.9-44.9,44.9H157c-24.9,0-44.9-20-44.9-44.9V157C112.1,132.1,132.1,112.1,157,112.1L157,112.1L157,112.1z M157,438.7h686c24.9,0,44.9,20,44.9,44.9v134.7c0,24.9-20,44.9-44.9,44.9H157c-24.9,0-44.9-20-44.9-44.9V483.7C112.1,458.8,132.1,438.7,157,438.7L157,438.7L157,438.7z"/></g>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="90px" height="90px" viewBox="0 0 90 90" 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>Slice 23</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="dashboard" stroke="none" stroke-width="1" fill-rule="evenodd">
|
||||
<g id="img_194174" transform="translate(12.000000, 12.000000)" fill-rule="nonzero">
|
||||
<path d="M49.0289809,14.7100665 C49.0289809,16.6448793 50.6001587,18.2091961 52.5281105,18.2091961 C54.4560623,18.2091961 56.0272401,16.6380183 56.0272401,14.7100665 C56.0272401,12.7752536 54.4560623,11.2109369 52.5281105,11.2109369 C50.6001587,11.2109369 49.0289809,12.7752536 49.0289809,14.7100665 Z M49.0289809,37.1182181 C49.0289809,39.053031 50.6001587,40.6173477 52.5281105,40.6173477 C54.4560623,40.6173477 56.0272401,39.0461699 56.0272401,37.1182181 C56.0272401,35.1834053 54.4560623,33.6190885 52.5281105,33.6190885 C50.6001587,33.6190885 49.0289809,35.1902663 49.0289809,37.1182181 L49.0289809,37.1182181 Z M0,46.2228162 C0,49.3171445 2.50427904,51.8282846 5.60546843,51.8282846 L29.420133,51.8282846 L29.420133,55.6979103 C28.7340291,56.1575999 28.1439798,56.7476492 27.6842902,57.433753 L10.5111109,57.433753 C8.57629809,57.433753 7.01198132,59.0049308 7.01198132,60.9328827 C7.01198132,62.8608345 8.58315913,64.4320123 10.5111109,64.4320123 L27.6842902,64.4320123 C28.8163616,66.1266888 30.7374523,67.231316 32.9261236,67.231316 C35.1079339,67.231316 37.0290246,66.1266888 38.167957,64.4320123 L56.7407882,64.4320123 C58.675601,64.4320123 60.2399178,62.8608345 60.2399178,60.9328827 C60.2399178,59.0049308 58.66874,57.433753 56.7407882,57.433753 L38.161096,57.433753 C37.7014064,56.7476492 37.1113571,56.1575999 36.4252532,55.6979103 L36.4252532,51.8351456 L61.6395696,51.8351456 C64.733898,51.8351456 67.245038,49.3308666 67.245038,46.2296772 L67.245038,5.60546843 C67.245038,2.51114008 64.740759,0 61.6395696,0 L5.60546843,0 C2.50427904,0 0,2.50427904 0,5.60546843 L0,46.2228162 L0,46.2228162 Z M10.0857266,7.00512028 L57.1524505,7.00512028 C58.860849,7.00512028 60.2330567,8.37732797 60.2330567,10.0857266 L60.2330567,19.3275454 C60.2330567,21.035944 58.860849,22.4081516 57.1524505,22.4081516 L10.0857266,22.4081516 C8.37732797,22.4081516 7.00512028,21.035944 7.00512028,19.3275454 L7.00512028,10.0857266 C7.00512028,8.37732797 8.37732797,7.00512028 10.0857266,7.00512028 L10.0857266,7.00512028 L10.0857266,7.00512028 Z M10.0857266,29.4132719 L57.1524505,29.4132719 C58.860849,29.4132719 60.2330567,30.7854796 60.2330567,32.4938782 L60.2330567,41.735697 C60.2330567,43.4440956 58.860849,44.8163033 57.1524505,44.8163033 L10.0857266,44.8163033 C8.37732797,44.8163033 7.00512028,43.4440956 7.00512028,41.735697 L7.00512028,32.5007392 C7.00512028,30.7923407 8.37732797,29.4132719 10.0857266,29.4132719 L10.0857266,29.4132719 L10.0857266,29.4132719 Z" id="Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3 KiB |
|
|
@ -1,73 +1,75 @@
|
|||
(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
|
||||
}
|
||||
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
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
})(jQuery);
|
||||
};
|
||||
|
||||
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() {
|
||||
_initPricing();
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
||||
|
||||
|
|
|
|||
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
|
|
@ -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));
|
||||
|
|
@ -1,5 +1,59 @@
|
|||
$( document ).ready(function() {
|
||||
// also declared in datacenterlight/js/main.js
|
||||
function _initNavUrl() {
|
||||
// $('.url').click(function(event) {
|
||||
// event.preventDefault();
|
||||
// var href = $(this).attr('href');
|
||||
// $('.navbar-collapse').removeClass('in');
|
||||
// $('.navbar-collapse').addClass('collapsing');
|
||||
// if ($(href).length) {
|
||||
// $('html, body').animate({
|
||||
// scrollTop: $(href).offset().top
|
||||
// }, 1000);
|
||||
// } else {
|
||||
// window.location.href = '/datacenterlight' + href;
|
||||
// }
|
||||
// });
|
||||
$('.url-init').each(function(idx, el) {
|
||||
var $this = $(el);
|
||||
var currentPath = window.location.pathname;
|
||||
var thisPaths = $this.attr('href').split('#')
|
||||
if ($this.hasClass('dropdown-toggle') && window.matchMedia("(max-width: 767px)").matches) {
|
||||
$this.removeClass('url-init');
|
||||
$this.attr('href', '');
|
||||
} else if ($('#'+thisPaths[1]).length) {
|
||||
$this.removeClass('url-init').addClass('url');
|
||||
$this.attr('href', '#' + thisPaths[1]);
|
||||
} else {
|
||||
$this.removeClass('url-init');
|
||||
}
|
||||
});
|
||||
$('.url').click(function(event) {
|
||||
event.preventDefault();
|
||||
var href = $(this).attr('href');
|
||||
$('.navbar-collapse').removeClass('in');
|
||||
$('.navbar-collapse').addClass('collapsing');
|
||||
if ($(href).length) {
|
||||
$('html, body').animate({
|
||||
scrollTop: $(href).offset().top
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------------------------------------------
|
||||
Nav panel classic
|
||||
--------------------------------------------- */
|
||||
if (window.matchMedia("(min-width: 767px)").matches) {
|
||||
$('ul.nav li.dropdown').hover(function() {
|
||||
$(this).find('.dropdown-menu').stop(true, true).fadeIn(500);
|
||||
}, function() {
|
||||
$(this).find('.dropdown-menu').stop(true, true).fadeOut(500);
|
||||
});
|
||||
} else {
|
||||
/* the viewport is less than 400 pixels wide */
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
|
|
@ -13,6 +67,44 @@ $( document ).ready(function() {
|
|||
}, 1000);
|
||||
});
|
||||
|
||||
_initNavUrl();
|
||||
|
||||
/*
|
||||
* Replace all SVG images with inline SVG
|
||||
*/
|
||||
$('.svg-img').each(function() {
|
||||
var $img = $(this);
|
||||
var imgID = $img.attr('id');
|
||||
var imgClass = $img.attr('class');
|
||||
var imgURL = $img.attr('src');
|
||||
|
||||
jQuery.get(imgURL, function(data) {
|
||||
// Get the SVG tag, ignore the rest
|
||||
var $svg = jQuery(data).find('svg');
|
||||
|
||||
// Add replaced image's ID to the new SVG
|
||||
if(typeof imgID !== 'undefined') {
|
||||
$svg = $svg.attr('id', imgID);
|
||||
}
|
||||
// Add replaced image's classes to the new SVG
|
||||
if(typeof imgClass !== 'undefined') {
|
||||
$svg = $svg.attr('class', imgClass+' replaced-svg');
|
||||
}
|
||||
|
||||
// Remove any invalid XML tags as per http://validator.w3.org
|
||||
$svg = $svg.removeAttr('xmlns:a');
|
||||
|
||||
// Check if the viewport is set, if the viewport is not set the SVG wont't scale.
|
||||
if(!$svg.attr('viewBox') && $svg.attr('height') && $svg.attr('width')) {
|
||||
$svg.attr('viewBox', '0 0 ' + $svg.attr('height') + ' ' + $svg.attr('width'))
|
||||
}
|
||||
|
||||
// Replace image with new SVG
|
||||
$img.replaceWith($svg);
|
||||
|
||||
}, 'xml');
|
||||
});
|
||||
|
||||
$('.alt-text').on('mouseenter mouseleave', function(e){
|
||||
var $this = $(this);
|
||||
var txt = $this.text();
|
||||
|
|
|
|||
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,18 +1,116 @@
|
|||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
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');
|
||||
}
|
||||
|
||||
$('#confirm-cancel').on('click', '.btn-ok', function(e) {
|
||||
$('#virtual_machine_cancel_form').trigger('submit');
|
||||
});
|
||||
function VMTerminateSuccess($container, data) {
|
||||
$container.addClass('terminate-success')
|
||||
.find('.vm-item-lg').text(data.text);
|
||||
$container.find('.btn').remove();
|
||||
$('#terminate-success').modal('show');
|
||||
}
|
||||
|
||||
var hash = window.location.hash;
|
||||
hash && $('ul.nav a[href="' + hash + '"]').tab('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');
|
||||
}
|
||||
|
||||
$('.nav-tabs a').click(function (e) {
|
||||
$(this).tab('show');
|
||||
var scrollmem = $('body').scrollTop() || $('html').scrollTop();
|
||||
window.location.hash = this.hash;
|
||||
$('html,body').scrollTop(scrollmem);
|
||||
});
|
||||
|
||||
});
|
||||
$(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);
|
||||
});
|
||||
|
||||
var create_vm_form = $('#virtual_machine_create_form');
|
||||
create_vm_form.submit(function () {
|
||||
$('#btn-create-vm').prop('disabled', true);
|
||||
$.ajax({
|
||||
url: create_vm_form.attr('action'),
|
||||
type: 'POST',
|
||||
data: create_vm_form.serialize(),
|
||||
success: function (data) {
|
||||
if (data.status === true) {
|
||||
fa_icon = $('.modal-icon > .fa');
|
||||
fa_icon.attr('class', 'checkmark');
|
||||
// $('.modal-header > .close').removeClass('hidden');
|
||||
$('#createvm-modal-title').text(data.msg_title);
|
||||
$('#createvm-modal-body').text(data.msg_body);
|
||||
$('#createvm-modal-done-btn')
|
||||
.attr('href', data.redirect)
|
||||
.removeClass('hide');
|
||||
}
|
||||
},
|
||||
error: function (xmlhttprequest, textstatus, message) {
|
||||
fa_icon = $('.modal-icon > .fa');
|
||||
fa_icon.attr('class', 'fa fa-close');
|
||||
if (typeof(create_vm_error_message) !== 'undefined') {
|
||||
$('#createvm-modal-text').text(create_vm_error_message);
|
||||
}
|
||||
$('#btn-create-vm').prop('disabled', false);
|
||||
$('#createvm-modal-close-btn').removeClass('hide');
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
$('#createvm-modal').on('hidden.bs.modal', function () {
|
||||
$(this).find('.modal-footer .btn').addClass('hide');
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,15 +24,16 @@
|
|||
<link href="{% static 'hosting/css/orders.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/dashboard.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'hosting/css/price_calculator.css' %}" rel="stylesheet">
|
||||
{% block css_extra %}
|
||||
{% endblock css_extra %}
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<link href='//fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
|
||||
<link href="//fonts.googleapis.com/css?family=Lato:300,400,500,700,300italic,400italic,700italic" rel="stylesheet" type="text/css">
|
||||
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
|
||||
<link rel="stylesheet" href="{% static 'hosting/css/owl.carousel.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'hosting/css/owl.theme.default.min.css' %}">
|
||||
|
||||
|
||||
<!-- 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:// -->
|
||||
|
|
@ -50,59 +51,7 @@
|
|||
|
||||
|
||||
{% block navbar %}
|
||||
|
||||
<!-- Navigation -->
|
||||
|
||||
<nav class="navbar navbar-default navbar-fixed-top topnav" role="navigation">
|
||||
<div class="container topnav">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand topnav" href="{% if site_url %}{{site_url}}{% else %}{{ request.session.hosting_url}}{% endif %}"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a>
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="{% url 'hosting:virtual_machines' %}">
|
||||
<i class="fa fa-server" aria-hidden="true"></i> {% trans "My Virtual Machines"%}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'hosting:orders' %}">
|
||||
<i class="fa fa-credit-card"></i> {% trans "My Orders"%}
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" role="button" data-toggle="dropdown" href="#">
|
||||
<i class="glyphicon glyphicon-user"></i> {{request.user.name}} <span class="caret"></span></a>
|
||||
<ul id="g-account-menu" class="dropdown-menu" role="menu">
|
||||
<li>
|
||||
<a href="{% url 'hosting:ssh_keys' %}">
|
||||
<i class="fa fa-key"></i> {% trans "SSH Keys" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'hosting:notifications' %}">
|
||||
<i class="fa fa-bell"></i> {% trans "Notifications "%}
|
||||
</a>
|
||||
</li>
|
||||
<li><a href="{% url 'hosting:logout' %}"><i class="glyphicon glyphicon-lock"></i>{% trans "Logout"%} </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- /.navbar-collapse -->
|
||||
</div>
|
||||
<!-- /.container -->
|
||||
</nav>
|
||||
{% include "hosting/includes/_navbar_user.html" %}
|
||||
{% endblock navbar %}
|
||||
|
||||
|
||||
|
|
@ -125,8 +74,8 @@
|
|||
{% endif %}
|
||||
<!-- jQuery -->
|
||||
<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="{% static 'hosting/js/vendor/owl.carousel.min.js'%}"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.16.0/jquery.validate.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.9/validator.min.js"></script>
|
||||
<!-- Copy Clipboard -->
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.10/clipboard.min.js"></script>
|
||||
|
||||
|
|
@ -143,6 +92,13 @@
|
|||
<!-- Init JavaScript -->
|
||||
<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/v2/"></script>
|
||||
<!-- Stripe Lib -->
|
||||
|
|
@ -157,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-with-locales.js"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
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,70 +1,30 @@
|
|||
{% extends "hosting/base_short.html" %}
|
||||
{% load staticfiles bootstrap3 i18n %}
|
||||
{% block content %}
|
||||
<div>
|
||||
<div class="dashboard-container" >
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
<br/>
|
||||
{% if messages %}
|
||||
<div class="alert alert-warning">
|
||||
{% for message in messages %}
|
||||
{% block content %}
|
||||
<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 %}
|
||||
<div class="alert alert-warning">
|
||||
{% for message in messages %}
|
||||
<span>{{ message }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not error %}
|
||||
<div class="dashboard-title">
|
||||
<h3>{% trans "New Virtual Machine"%} </h3>
|
||||
<hr/>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="step-title">
|
||||
<h4>{% trans "Step 1. Select VM Template:" %} </h4>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="parent-container">
|
||||
<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 class="col-sm-6">
|
||||
<div class="price-calc-section no-padding">
|
||||
<div class="landing card">
|
||||
<div class="caption">
|
||||
{% include "hosting/calculator_form.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{%endblock%}
|
||||
{%endblock%}
|
||||
50
hosting/templates/hosting/dashboard.html
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{% extends "hosting/base_short.html" %}
|
||||
{% load staticfiles bootstrap3 i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="hosting-dashboard">
|
||||
<div class="dashboard-container">
|
||||
<div class="dashboard-container-head">
|
||||
<h1 class="dashboard-title-thin">{% trans "My Dashboard" %}</h1>
|
||||
</div>
|
||||
<div class="hosting-dashboard-content">
|
||||
<a href="{% url 'hosting:create_virtual_machine' %}" class="hosting-dashboard-item">
|
||||
<h2>{% trans "Create VM" %}</h2>
|
||||
<div class="hosting-dashboard-image">
|
||||
<img class="svg-img" src="{% static 'hosting/img/plusVM.svg' %}">
|
||||
</div>
|
||||
</a>
|
||||
<a href="{% url 'hosting:virtual_machines' %}" class="hosting-dashboard-item">
|
||||
<h2>{% trans "My VMs" %}</h2>
|
||||
<div class="hosting-dashboard-image">
|
||||
<img class="svg-img" src="{% static 'hosting/img/vm.svg' %}">
|
||||
</div>
|
||||
</a>
|
||||
<a href="{% url 'hosting:ssh_keys' %}" class="hosting-dashboard-item">
|
||||
<h2>{% trans "My SSH Keys" %}</h2>
|
||||
<div class="hosting-dashboard-image">
|
||||
<img class="svg-img" src="{% static 'hosting/img/key.svg' %}">
|
||||
</div>
|
||||
</a>
|
||||
<a href="{% url 'hosting:orders' %}" class="hosting-dashboard-item">
|
||||
<h2>{% trans "My Bills" %}</h2>
|
||||
<div class="hosting-dashboard-image">
|
||||
<img class="svg-img" src="{% static 'hosting/img/billing.svg' %}">
|
||||
</div>
|
||||
</a>
|
||||
<a href="{% url 'hosting:settings' %}" class="hosting-dashboard-item">
|
||||
<h2>{% trans "My Settings" %}</h2>
|
||||
<div class="hosting-dashboard-image">
|
||||
<img class="svg-img" src="{% static 'hosting/img/dashboard_settings.svg' %}">
|
||||
</div>
|
||||
</a>
|
||||
<a href="mailto:support@datacenterlight.ch" class="hosting-dashboard-item">
|
||||
<h2>{% trans "Support / Contact" %}</h2>
|
||||
<div class="hosting-dashboard-image">
|
||||
<img class="svg-img" src="{% static 'hosting/img/24-hours-support.svg' %}">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{%endblock%}
|
||||
|
|
@ -1,140 +1,14 @@
|
|||
{% load static from staticfiles %}
|
||||
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Oxygen Invoice</title>
|
||||
</head>
|
||||
<body bgcolor="#f7f7f7" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; color: white; margin: 0;">
|
||||
<style type="text/css">
|
||||
@media only screen and (max-width: 480px) {
|
||||
table[class*="container-for-gmail-android"] {
|
||||
min-width: 290px !important; width: 100% !important;
|
||||
}
|
||||
img[class="force-width-gmail"] {
|
||||
display: none !important; width: 0 !important; height: 0 !important;
|
||||
}
|
||||
table[class="w320"] {
|
||||
width: 320px !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-left"] {
|
||||
width: 160px !important; padding-left: 0 !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-right"] {
|
||||
width: 160px !important; padding-right: 0 !important;
|
||||
}
|
||||
td[class="header-lg"] {
|
||||
font-size: 24px !important; padding-bottom: 5px !important;
|
||||
}
|
||||
td[class="content-padding"] {
|
||||
padding: 5px 0 5px !important;
|
||||
}
|
||||
td[class="button"] {
|
||||
padding: 5px 5px 30px !important;
|
||||
}
|
||||
td[class*="free-text"] {
|
||||
padding: 10px 18px 30px !important;
|
||||
}
|
||||
td[class~="mobile-hide-img"] {
|
||||
display: none !important; height: 0 !important; width: 0 !important; line-height: 0 !important;
|
||||
}
|
||||
td[class~="item"] {
|
||||
width: 140px !important; vertical-align: top !important;
|
||||
}
|
||||
td[class~="quantity"] {
|
||||
width: 50px !important;
|
||||
}
|
||||
td[class~="price"] {
|
||||
width: 90px !important;
|
||||
}
|
||||
td[class="item-table"] {
|
||||
padding: 30px 20px !important;
|
||||
}
|
||||
td[class="mini-container-left"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
td[class="mini-container-right"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%" style="border-collapse: collapse !important; min-width: 600px; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="left" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #ffffff url(http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg) repeat-x;" bgcolor="#ffffff">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" background="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; background: transparent;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; line-height: 21px;" align="center">
|
||||
<!--[if gte mso 9]>
|
||||
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000;height:80px; v-text-anchor:middle;">
|
||||
<v:fill type="tile" src="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" color="#ffffff" />
|
||||
<v:textbox inset="0,0,0,0">
|
||||
<![endif]-->
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellpadding="0" cellspacing="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="pull-left mobile-header-padding-left" style="vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: left; line-height: 21px; width: 290px; padding-left: 10px;" align="left" valign="middle">
|
||||
<a href="{{base_url}}" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; color: #676767; text-decoration: none !important;"><img width="137" src="{{base_url}}{% static "hosting/img/logo_black.png" %}" alt="logo" style="max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; border: none;"></a>
|
||||
</td>
|
||||
<td class="pull-right mobile-header-padding-right" style="color: #4d4d4d; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; text-align: right; line-height: 21px; width: 290px; padding-left: 10px;" align="right">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
<!--[if gte mso 9]>
|
||||
</v:textbox>
|
||||
</v:rect>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7; padding: 20px 0 5px;" class="content-padding" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="header-lg" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 32px; color: #4d4d4d; text-align: center; line-height: normal; font-weight: 700; padding: 35px 0 0;" align="center">
|
||||
You have booked a virtual machine!
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center">
|
||||
Your virtual machine {{vm.name}} subscription has been charged,
|
||||
<br/>
|
||||
we are going to contact you as soon your virtual machine has been activated.
|
||||
<br/>
|
||||
You can view your invoice clicking on the button below.
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="button" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||
<div style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<!--[if mso]>
|
||||
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
|
||||
<w:anchorlock/>
|
||||
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
|
||||
</v:roundrect>
|
||||
<![endif]--><a href="{{ base_url }}{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
|
||||
{% extends "datacenterlight/emails/base_email_datacenterlight.html" %}
|
||||
{% load i18n %}
|
||||
{% block email_head %}{{page_header}}{% endblock %}
|
||||
{% block email_body %}
|
||||
{% url 'hosting:orders' order.id as order_url %}
|
||||
{% blocktrans with vm.name as vm_name %}You have ordered a new virtual machine!
|
||||
<br/>
|
||||
Your order of [{{vm_name}}] has been charged.<br/><br/>
|
||||
You can view your invoice by clicking the button below.<br/><br/>
|
||||
{% endblocktrans %}
|
||||
<div class="button" style="border-collapse: collapse; font-family: 'Lato', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||
<a href="{{ base_url }}{{order_url}}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">{% trans 'View Invoice' %}</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="height: 100px; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7;" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 25px 0;" align="center">
|
||||
<strong style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">ungleich</strong><br style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,140 +1,11 @@
|
|||
{% load static from staticfiles %}
|
||||
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Oxygen Invoice</title>
|
||||
</head>
|
||||
<body bgcolor="#f7f7f7" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; color: white; margin: 0;">
|
||||
<style type="text/css">
|
||||
@media only screen and (max-width: 480px) {
|
||||
table[class*="container-for-gmail-android"] {
|
||||
min-width: 290px !important; width: 100% !important;
|
||||
}
|
||||
img[class="force-width-gmail"] {
|
||||
display: none !important; width: 0 !important; height: 0 !important;
|
||||
}
|
||||
table[class="w320"] {
|
||||
width: 320px !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-left"] {
|
||||
width: 160px !important; padding-left: 0 !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-right"] {
|
||||
width: 160px !important; padding-right: 0 !important;
|
||||
}
|
||||
td[class="header-lg"] {
|
||||
font-size: 24px !important; padding-bottom: 5px !important;
|
||||
}
|
||||
td[class="content-padding"] {
|
||||
padding: 5px 0 5px !important;
|
||||
}
|
||||
td[class="button"] {
|
||||
padding: 5px 5px 30px !important;
|
||||
}
|
||||
td[class*="free-text"] {
|
||||
padding: 10px 18px 30px !important;
|
||||
}
|
||||
td[class~="mobile-hide-img"] {
|
||||
display: none !important; height: 0 !important; width: 0 !important; line-height: 0 !important;
|
||||
}
|
||||
td[class~="item"] {
|
||||
width: 140px !important; vertical-align: top !important;
|
||||
}
|
||||
td[class~="quantity"] {
|
||||
width: 50px !important;
|
||||
}
|
||||
td[class~="price"] {
|
||||
width: 90px !important;
|
||||
}
|
||||
td[class="item-table"] {
|
||||
padding: 30px 20px !important;
|
||||
}
|
||||
td[class="mini-container-left"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
td[class="mini-container-right"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%" style="border-collapse: collapse !important; min-width: 600px; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="left" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #ffffff url(http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg) repeat-x;" bgcolor="#ffffff">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" background="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; background: transparent;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; line-height: 21px;" align="center">
|
||||
<!--[if gte mso 9]>
|
||||
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000;height:80px; v-text-anchor:middle;">
|
||||
<v:fill type="tile" src="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" color="#ffffff" />
|
||||
<v:textbox inset="0,0,0,0">
|
||||
<![endif]-->
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellpadding="0" cellspacing="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="pull-left mobile-header-padding-left" style="vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: left; line-height: 21px; width: 290px; padding-left: 10px;" align="left" valign="middle">
|
||||
<a href="{{base_url}}" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; color: #676767; text-decoration: none !important;"><img width="137" src="{{base_url}}{% static "hosting/img/logo_black.png" %}" alt="logo" style="max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; border: none;"></a>
|
||||
</td>
|
||||
<td class="pull-right mobile-header-padding-right" style="color: #4d4d4d; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; text-align: right; line-height: 21px; width: 290px; padding-left: 10px;" align="right">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
<!--[if gte mso 9]>
|
||||
</v:textbox>
|
||||
</v:rect>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7; padding: 20px 0 5px;" class="content-padding" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="header-lg" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 32px; color: #4d4d4d; text-align: center; line-height: normal; font-weight: 700; padding: 35px 0 0;" align="center">
|
||||
You have booked a virtual machine!
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center">
|
||||
Your virtual machine {{vm.name}} subscription has been charged,
|
||||
<br/>
|
||||
we are going to contact you as soon your virtual machine has been activated.
|
||||
<br/>
|
||||
You can view your invoice clicking on the button below.
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="button" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||
<div style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<!--[if mso]>
|
||||
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
|
||||
<w:anchorlock/>
|
||||
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
|
||||
</v:roundrect>
|
||||
<![endif]--><a href="{{ base_url }}{% url 'hosting:orders' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="height: 100px; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7;" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 25px 0;" align="center">
|
||||
<strong style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">ungleich</strong><br style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{% extends "datacenterlight/emails/base_email_datacenterlight.txt" %}
|
||||
{% load i18n %}
|
||||
{% block email_head %}{{page_header}}{% endblock %}
|
||||
{% block email_body %}
|
||||
{% url 'hosting:orders' order.id as order_url %}
|
||||
{% blocktrans with vm.name as vm_name %}You have ordered a new virtual machine!
|
||||
Your order of [{{vm_name}}] has been charged.
|
||||
You can view your invoice here.
|
||||
{% endblocktrans %}
|
||||
{{ base_url }}{{order_url}}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
{% load i18n %}{% autoescape off %}
|
||||
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
|
||||
|
||||
{% trans "Please go to the following page and choose a new password:" %}
|
||||
{% block reset_link %}
|
||||
{{ base_url }}{% url 'hosting:reset_password_confirm' uidb64=uid token=token %}
|
||||
{% endblock %}
|
||||
|
||||
{% trans "Thanks for using our site!" %}
|
||||
|
||||
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
|
||||
|
||||
{% endautoescape %}
|
||||
{% extends "datacenterlight/emails/base_email_datacenterlight.html" %}
|
||||
{% load i18n %}
|
||||
{% block email_head %}
|
||||
{% trans 'Password Reset' %}
|
||||
{% endblock %}
|
||||
{% block email_body %}
|
||||
{% url 'hosting:reset_password_confirm' uidb64=uid token=token as password_reset_url %}
|
||||
{% blocktrans %}
|
||||
You're receiving this email because you requested a password reset for your user account at {{site_name}}.<br/>
|
||||
Please go to the following page and choose a new password: {{base_url}}{{ password_reset_url }}<br/>
|
||||
If you didn't request a new password, ignore this e-mail.<br/>
|
||||
Thank you!
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
{% load i18n %}{% autoescape off %}
|
||||
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
|
||||
|
||||
{% trans "Please go to the following page and choose a new password:" %}
|
||||
{% block reset_link %}
|
||||
{{ base_url }}{% url 'hosting:reset_password_confirm' uidb64=uid token=token %}
|
||||
{% endblock %}
|
||||
|
||||
{% trans "Thanks for using our site!" %}
|
||||
|
||||
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
|
||||
|
||||
{% endautoescape %}
|
||||
{% extends "datacenterlight/emails/base_email_datacenterlight.txt" %}
|
||||
{% load i18n %}
|
||||
{% block email_head %}{% trans 'Password Reset' %}{% endblock %}
|
||||
{% block email_body %}
|
||||
{% url 'hosting:reset_password_confirm' uidb64=uid token=token as password_reset_url %}
|
||||
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{site_name}}.
|
||||
Please go to the following page and choose a new password: {{base_url}}{{ password_reset_url }}
|
||||
If you didn't request a new password, ignore this e-mail.
|
||||
Thank you!
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
15
hosting/templates/hosting/emails/vm_canceled.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "datacenterlight/emails/base_email_datacenterlight.html" %}
|
||||
{% load i18n %}
|
||||
{% block email_head %}{{page_header}}{% endblock %}
|
||||
{% block email_body %}
|
||||
{% url 'hosting:virtual_machines' as my_virtual_machines_url %}
|
||||
{% url 'hosting:orders' as vm_orders_url %}
|
||||
{% blocktrans with vm.name as vm_name %}You're receiving this mail because your virtual machine [{{vm_name}}] has been cancelled.<br/>
|
||||
You can see your order status by clicking [my VM page] below.<br/>
|
||||
If you want to order a new virtual machine, you can do it by clicking <a href="{{base_url}}{{my_virtual_machines_url}}">this link</a>.<br/>
|
||||
{% endblocktrans %}
|
||||
<div class="button" style="border-collapse: collapse; font-family: 'Lato', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||
<a href="{{ base_url }}{{vm_orders_url}}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">{% trans 'My VM page' %}</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
13
hosting/templates/hosting/emails/vm_canceled.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{% extends "datacenterlight/emails/base_email_datacenterlight.txt" %}
|
||||
{% load i18n %}
|
||||
{% block email_head %}{{page_header}}{% endblock %}
|
||||
{% block email_body %}
|
||||
{% url 'hosting:virtual_machines' as my_virtual_machines_url %}
|
||||
{% url 'hosting:orders' order.id as vm_order_url %}
|
||||
{% blocktrans with vm.name as vm_name %}You're receiving this mail because your virtual machine [{{vm_name}}] has been cancelled.
|
||||
You can see your order status by clicking here
|
||||
{{base_url}}{{vm_order_url}}
|
||||
If you want to order a new virtual machine, you can do it by clicking this link.
|
||||
{{base_url}}{{my_virtual_machines_url}}
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
{% load static from staticfiles %}
|
||||
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Oxygen Invoice</title>
|
||||
</head>
|
||||
<body bgcolor="#f7f7f7" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; color: white; margin: 0;">
|
||||
<style type="text/css">
|
||||
@media only screen and (max-width: 480px) {
|
||||
table[class*="container-for-gmail-android"] {
|
||||
min-width: 290px !important; width: 100% !important;
|
||||
}
|
||||
img[class="force-width-gmail"] {
|
||||
display: none !important; width: 0 !important; height: 0 !important;
|
||||
}
|
||||
table[class="w320"] {
|
||||
width: 320px !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-left"] {
|
||||
width: 160px !important; padding-left: 0 !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-right"] {
|
||||
width: 160px !important; padding-right: 0 !important;
|
||||
}
|
||||
td[class="header-lg"] {
|
||||
font-size: 24px !important; padding-bottom: 5px !important;
|
||||
}
|
||||
td[class="content-padding"] {
|
||||
padding: 5px 0 5px !important;
|
||||
}
|
||||
td[class="button"] {
|
||||
padding: 5px 5px 30px !important;
|
||||
}
|
||||
td[class*="free-text"] {
|
||||
padding: 10px 18px 30px !important;
|
||||
}
|
||||
td[class~="mobile-hide-img"] {
|
||||
display: none !important; height: 0 !important; width: 0 !important; line-height: 0 !important;
|
||||
}
|
||||
td[class~="item"] {
|
||||
width: 140px !important; vertical-align: top !important;
|
||||
}
|
||||
td[class~="quantity"] {
|
||||
width: 50px !important;
|
||||
}
|
||||
td[class~="price"] {
|
||||
width: 90px !important;
|
||||
}
|
||||
td[class="item-table"] {
|
||||
padding: 30px 20px !important;
|
||||
}
|
||||
td[class="mini-container-left"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
td[class="mini-container-right"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%" style="border-collapse: collapse !important; min-width: 600px; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="left" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7 url(http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg) repeat-x;" bgcolor="#ffffff">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" background="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; background: transparent;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; line-height: 21px;" align="center">
|
||||
<!--[if gte mso 9]>
|
||||
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000;height:80px; v-text-anchor:middle;">
|
||||
<v:fill type="tile" src="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" color="#ffffff" />
|
||||
<v:textbox inset="0,0,0,0">
|
||||
<![endif]-->
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellpadding="0" cellspacing="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="pull-left mobile-header-padding-left" style="vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: left; line-height: 21px; width: 290px; padding-left: 10px;" align="left" valign="middle">
|
||||
<a href="{{base_url}}" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; color: #676767; text-decoration: none !important;"><img width="137" src="{{base_url}}{% static "hosting/img/logo_black.png" %}" alt="logo" style="max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; border: none;"></a>
|
||||
</td>
|
||||
<td class="pull-right mobile-header-padding-right" style="color: #4d4d4d; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; text-align: right; line-height: 21px; width: 290px; padding-left: 10px;" align="right">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
<!--[if gte mso 9]>
|
||||
</v:textbox>
|
||||
</v:rect>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7; padding: 20px 0 5px;" class="content-padding" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="header-lg" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 32px; color: #4d4d4d; text-align: center; line-height: normal; font-weight: 700; padding: 35px 0 0;" align="center">
|
||||
Your virtual machine {{vm.name}} status has been updated to {{vm.get_status_display}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center">
|
||||
You can manage your vm clicking on the button below
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="button" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||
<div style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<!--[if mso]>
|
||||
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
|
||||
<w:anchorlock/>
|
||||
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
|
||||
</v:roundrect>
|
||||
<![endif]--><a href="{{base_url}}{% url 'hosting:virtual_machines' vm.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">VM Dashboard</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="height: 100px; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7;" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 25px 0;" align="center">
|
||||
<strong style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">ungleich</strong><br style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
{% load static from staticfiles %}
|
||||
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Oxygen Invoice</title>
|
||||
</head>
|
||||
<body bgcolor="#f7f7f7" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; color: white; margin: 0;">
|
||||
<style type="text/css">
|
||||
@media only screen and (max-width: 480px) {
|
||||
table[class*="container-for-gmail-android"] {
|
||||
min-width: 290px !important; width: 100% !important;
|
||||
}
|
||||
img[class="force-width-gmail"] {
|
||||
display: none !important; width: 0 !important; height: 0 !important;
|
||||
}
|
||||
table[class="w320"] {
|
||||
width: 320px !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-left"] {
|
||||
width: 160px !important; padding-left: 0 !important;
|
||||
}
|
||||
td[class*="mobile-header-padding-right"] {
|
||||
width: 160px !important; padding-right: 0 !important;
|
||||
}
|
||||
td[class="header-lg"] {
|
||||
font-size: 24px !important; padding-bottom: 5px !important;
|
||||
}
|
||||
td[class="content-padding"] {
|
||||
padding: 5px 0 5px !important;
|
||||
}
|
||||
td[class="button"] {
|
||||
padding: 5px 5px 30px !important;
|
||||
}
|
||||
td[class*="free-text"] {
|
||||
padding: 10px 18px 30px !important;
|
||||
}
|
||||
td[class~="mobile-hide-img"] {
|
||||
display: none !important; height: 0 !important; width: 0 !important; line-height: 0 !important;
|
||||
}
|
||||
td[class~="item"] {
|
||||
width: 140px !important; vertical-align: top !important;
|
||||
}
|
||||
td[class~="quantity"] {
|
||||
width: 50px !important;
|
||||
}
|
||||
td[class~="price"] {
|
||||
width: 90px !important;
|
||||
}
|
||||
td[class="item-table"] {
|
||||
padding: 30px 20px !important;
|
||||
}
|
||||
td[class="mini-container-left"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
td[class="mini-container-right"] {
|
||||
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%" style="border-collapse: collapse !important; min-width: 600px; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="left" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7 url(http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg) repeat-x;" bgcolor="#ffffff">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" background="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; background: transparent;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; line-height: 21px;" align="center">
|
||||
<!--[if gte mso 9]>
|
||||
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000;height:80px; v-text-anchor:middle;">
|
||||
<v:fill type="tile" src="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" color="#ffffff" />
|
||||
<v:textbox inset="0,0,0,0">
|
||||
<![endif]-->
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellpadding="0" cellspacing="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="pull-left mobile-header-padding-left" style="vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: left; line-height: 21px; width: 290px; padding-left: 10px;" align="left" valign="middle">
|
||||
<a href="{{base_url}}" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; color: #676767; text-decoration: none !important;"><img width="137" src="{{base_url}}{% static "hosting/img/logo_black.png" %}" alt="logo" style="max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; border: none;"></a>
|
||||
</td>
|
||||
<td class="pull-right mobile-header-padding-right" style="color: #4d4d4d; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; text-align: right; line-height: 21px; width: 290px; padding-left: 10px;" align="right">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
<!--[if gte mso 9]>
|
||||
</v:textbox>
|
||||
</v:rect>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7; padding: 20px 0 5px;" class="content-padding" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="header-lg" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 32px; color: #4d4d4d; text-align: center; line-height: normal; font-weight: 700; padding: 35px 0 0;" align="center">
|
||||
Your virtual machine {{vm.name}} status has been updated to {{vm.get_status_display}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center">
|
||||
You can manage your vm clicking on the button below
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td class="button" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||
<div style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<!--[if mso]>
|
||||
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
|
||||
<w:anchorlock/>
|
||||
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
|
||||
</v:roundrect>
|
||||
<![endif]--><a href="{{base_url}}{% url 'hosting:virtual_machines' vm.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">VM Dashboard</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td align="center" valign="top" width="100%" style="height: 100px; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7;" bgcolor="#f7f7f7">
|
||||
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
<td style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 25px 0;" align="center">
|
||||
<strong style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">ungleich</strong><br style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||
</td>
|
||||
</tr></table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{% load staticfiles %}
|
||||
|
||||
{% load i18n %}
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
{% load static i18n %}
|
||||
|
||||
<nav class="navbar navbar-default topnav navbar-transparent" role="navigation">
|
||||
<div class="container topnav">
|
||||
<div class="topnav">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<a id="logoWhite" class="navbar-brand topnav" href="{% if site_url %}{{site_url}}{% else %}{{ request.session.hosting_url}}{% endif %}"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a>
|
||||
<a id="logoWhite" class="navbar-brand topnav" href="{% url 'datacenterlight:index' %}"><img src="{% static 'datacenterlight/img/logo_white.svg' %}"></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.container -->
|
||||
|
|
|
|||
52
hosting/templates/hosting/includes/_navbar_user.html
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{% load staticfiles %}
|
||||
{% load i18n %}
|
||||
{% load custom_tags %}
|
||||
|
||||
<!-- Navigation -->
|
||||
|
||||
<nav class="navbar navbar-default navbar-fixed-top topnav" role="navigation">
|
||||
<div class="topnav">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
{% if request.user.is_authenticated %}
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">{% trans "Toggle navigation" %}</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
{% endif %}
|
||||
<a class="navbar-brand topnav" href="{% url 'datacenterlight:index' %}"><img src="{% static 'datacenterlight/img/logo_black.svg' %}"></a>
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<a href="{% url 'hosting:dashboard' %}">
|
||||
<i class="fa fa-fw fa-server" aria-hidden="true"></i> {% trans "Dashboard"%}
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown highlights-dropdown">
|
||||
<a class="dropdown-toggle" role="button" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-fw fa-user"></i> {{request.user.name}} <span class="fa fa-fw fa-caret-down"></span>
|
||||
</a>
|
||||
<ul id="g-account-menu" class="dropdown-menu" role="menu">
|
||||
<li><a href="{% url 'hosting:logout' %}">{% trans "Logout"%}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
{% if LANGUAGE_CODE == 'en-us'%}
|
||||
<a href="{% change_lang 'de' %}"><i class="fa fa-fw fa-globe" aria-hidden="true"></i> Deutsch</a>
|
||||
{% else %}
|
||||
<a href="{% change_lang 'en-us' %}"><i class="fa fa-fw fa-globe" aria-hidden="true"></i> English</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- /.navbar-collapse -->
|
||||
</div>
|
||||
<!-- /.container -->
|
||||
</nav>
|
||||
|
|
@ -44,6 +44,8 @@
|
|||
<a class="unlink" href="{% url 'hosting:signup' %}">{% trans "Sign up"%}</a>
|
||||
<span class="text"> or </span>
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -1,98 +1,202 @@
|
|||
{% extends "hosting/base_short.html" %}
|
||||
{% load staticfiles bootstrap3 %}
|
||||
{% load i18n %}
|
||||
{% block content %}
|
||||
{% load custom_tags %}
|
||||
|
||||
<div class="order-detail-container">
|
||||
{% if messages %}
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-8 col-md-offset-2">
|
||||
<br/>
|
||||
<div class="alert alert-warning">
|
||||
{% for message in messages %}
|
||||
<span>{{ message }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% block content %}
|
||||
<div id="order-detail{{order.pk}}" class="order-detail-container">
|
||||
{% if messages %}
|
||||
<div class="alert alert-warning">
|
||||
{% for message in messages %}
|
||||
<span>{{ message }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not error %}
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-8 col-md-offset-2">
|
||||
<div class="invoice-title">
|
||||
<h2>{{page_header_text}}</h2><h3 class="pull-right">{% trans "Order #"%} {{order.id}}</h3>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-6 pull-right order-confirm-date">
|
||||
<address>
|
||||
<strong>{% trans "Date"%}:</strong><br>
|
||||
<span id="order-created_at">{{order.created_at|date:'Y-m-d H:i'}}</span><br><br>
|
||||
<strong>{% trans "Status:"%}</strong><br>
|
||||
<strong class="{% if order.status == 'Approved' %}text-success
|
||||
{%else%} text-danger
|
||||
{% endif %}">{{order.status}}</strong>
|
||||
<br><br>
|
||||
</address>
|
||||
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<address>
|
||||
<h3><b>{% trans "Billed To:"%}</b></h3>
|
||||
{{user.name}}<br>
|
||||
{{order.billing_address.street_address}},{{order.billing_address.postal_code}}<br>
|
||||
{{order.billing_address.city}}, {{order.billing_address.country}}.
|
||||
</address>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<address>
|
||||
<strong>{% trans "Payment Method:"%}</strong><br>
|
||||
{{order.cc_brand}} ending **** {{order.last4}}<br>
|
||||
{{user.email}}
|
||||
</address>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<h3><b>{% trans "Order summary"%}</b></h3>
|
||||
<div class="dashboard-container-head">
|
||||
<h1 class="dashboard-title-thin">
|
||||
<img src="{% static 'hosting/img/billing.svg' %}" class="un-icon">{% blocktrans with page_header_text=page_header_text|default:"Invoice" %}{{page_header_text}}{% endblocktrans %}
|
||||
</h1>
|
||||
<div class="dashboard-container-options">
|
||||
<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>
|
||||
<button type="button" class="btn-plain btn-print"><img src="{% static 'hosting/img/icon-print.svg' %}" class="svg-img"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-details">
|
||||
{% if order %}
|
||||
<p>
|
||||
<strong>{% trans "Order #" %} {{order.id}}</strong>
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
<strong>{% trans "Invoice Date" %}:</strong>
|
||||
<span id="order-created_at">
|
||||
{% if order %}
|
||||
{{order.created_at|date:'Y-m-d H:i'}}
|
||||
{% else %}
|
||||
{% now "Y-m-d H:i" %}
|
||||
{% endif %}
|
||||
</span>
|
||||
</p>
|
||||
{% if order %}
|
||||
<p>
|
||||
<strong>{% trans "Status" %}: </strong>
|
||||
<strong>
|
||||
{% if order.status == 'Approved' %}
|
||||
<span class="vm-color-online">{% trans "Approved" %}</span>
|
||||
{% else %}
|
||||
<span class="vm-status-failed">{% trans "Declined" %}</span>
|
||||
{% endif %}
|
||||
</strong>
|
||||
</p>
|
||||
{% endif %}
|
||||
<hr>
|
||||
<div class="content">
|
||||
<p><b>{% trans "Cores"%}</b> <span class="pull-right">{{vm.cores}}</span></p>
|
||||
<hr>
|
||||
<p><b>{% trans "Memory"%}</b> <span class="pull-right">{{vm.memory}} GB</span></p>
|
||||
<hr>
|
||||
<p><b>{% trans "Disk space"%}</b> <span class="pull-right">{{vm.disk_size}} GB</span></p>
|
||||
<hr>
|
||||
<h4>{% trans "Total"%}<p class="pull-right"><b>{{vm.price}} CHF</b></p></h4>
|
||||
<div>
|
||||
<address>
|
||||
<h4>{% trans "Billed to" %}:</h4>
|
||||
<p>
|
||||
{% if order %}
|
||||
{{user.name}}<br>
|
||||
{{order.billing_address.street_address}}, {{order.billing_address.postal_code}}<br>
|
||||
{{order.billing_address.city}}, {{order.billing_address.country}}
|
||||
{% else %}
|
||||
{% with request.session.billing_address_data as billing_address %}
|
||||
{{billing_address.cardholder_name}}<br>
|
||||
{{billing_address.street_address}}, {{billing_address.postal_code}}<br>
|
||||
{{billing_address.city}}, {{billing_address.country}}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
</p>
|
||||
</address>
|
||||
</div>
|
||||
<br/>
|
||||
{% url 'hosting:payment' as payment_url %}
|
||||
{% if payment_url in request.META.HTTP_REFERER %}
|
||||
<div class=" content pull-right">
|
||||
<a href="{% url 'hosting:virtual_machines'%}" ><button class="btn btn-info">{% trans "Finish Configuration"%}</button></a>
|
||||
<hr>
|
||||
<div>
|
||||
<h4>{% trans "Payment method" %}:</h4>
|
||||
<p>
|
||||
{% if order %}
|
||||
{{order.cc_brand}} {% trans "ending in" %} ****
|
||||
{{order.last4}}<br>
|
||||
{{user.email}}
|
||||
{% else %}
|
||||
{{cc_brand|default:'Card'}} {% trans "ending in" %} ****
|
||||
{{cc_last4}}<br>
|
||||
{% if request.user.is_authenticated %}
|
||||
{{request.user.email}}
|
||||
{% else %}
|
||||
{{request.session.user.email}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
<h4>{% trans "Order summary" %}</h4>
|
||||
<p>
|
||||
<strong>{% trans "Product" %}:</strong> {{vm.name}}
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
{% comment %}
|
||||
<p>
|
||||
<span>{% trans "Period" %}</span>
|
||||
<span class="pull-right">{{}}</span>
|
||||
</p>
|
||||
{% endcomment %}
|
||||
<p>
|
||||
<span>{% trans "Cores" %}</span>
|
||||
{% if vm.cores %}
|
||||
<span class="pull-right">{{vm.cores|floatformat}}</span>
|
||||
{% else %}
|
||||
<span class="pull-right">{{vm.cpu|floatformat}}</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
<span>{% trans "Memory" %}</span>
|
||||
<span class="pull-right">{{vm.memory}} GB</span>
|
||||
</p>
|
||||
<p>
|
||||
<span>{% trans "Disk space" %}</span>
|
||||
<span class="pull-right">{{vm.disk_size}} GB</span>
|
||||
</p>
|
||||
<p>
|
||||
<span>{% trans "Total" %}</span>
|
||||
<span class="pull-right">{{vm.price}} CHF</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not order %}
|
||||
<hr>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if not order %}
|
||||
<form method="post" id="virtual_machine_create_form">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<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 class="col-sm-4 order-confirm-btn text-right">
|
||||
<button class="btn choice-btn" id="btn-create-vm" data-href="{% url 'hosting:order-confirmation' %}" data-toggle="modal" data-target="#createvm-modal">
|
||||
{% trans "Place order" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
{% 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 -->
|
||||
<div class="modal fade" id="createvm-modal" tabindex="-1" role="dialog"
|
||||
aria-hidden="true" data-backdrop="static" data-keyboard="false">
|
||||
<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-cog fa-spin fa-3x fa-fw"></i>
|
||||
<span class="sr-only">{% trans "Processing..." %}</span>
|
||||
</div>
|
||||
<h4 class="modal-title" id="createvm-modal-title"></h4>
|
||||
<div class="modal-text" id="createvm-modal-body">
|
||||
{% trans "Hold tight, we are processing your request" %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="createvm-modal-done-btn" class="btn btn-danger btn-ok btn-wide hide" href="{% url 'hosting:virtual_machines' %}">{% trans "OK" %}</a>
|
||||
<button id="createvm-modal-close-btn" type="button" class="btn btn-danger btn-ok btn-wide hide" data-dismiss="modal" aria-label="create-vm-close">{% trans "Close" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / Create VM Modal -->
|
||||
{% endif %}
|
||||
|
||||
<script type="text/javascript">
|
||||
{% trans "Some problem encountered. Please try again later." as err_msg %}
|
||||
var create_vm_error_message = '{{err_msg|safe}}';
|
||||
|
||||
window.onload = function () {
|
||||
var locale_date = moment.utc(document.getElementById("order-created_at").textContent,'YYYY-MM-DD HH:mm').toDate();
|
||||
locale_date = moment(locale_date).format("YYYY-MM-DD h:mm:ss a");
|
||||
document.getElementById('order-created_at').innerHTML = locale_date;
|
||||
var locale_date = moment.utc(document.getElementById("order-created_at").textContent, 'YYYY-MM-DD HH:mm').toDate();
|
||||
locale_date = moment(locale_date).format("YYYY-MM-DD h:mm:ss a");
|
||||
document.getElementById('order-created_at').innerHTML = locale_date;
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
{%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 %}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
{% block content %}
|
||||
<div class="dashboard-container">
|
||||
<div class="dashboard-container-head">
|
||||
<h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/shopping-cart.svg' %}" class="un-icon" style="margin-top: -4px; width: 30px;"> {% trans "My Orders" %}</h3>
|
||||
<h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/shopping-cart.svg' %}" class="un-icon" style="margin-top: -4px; width: 30px;"> {% trans "My Bills" %}</h3>
|
||||
{% if messages %}
|
||||
<div class="alert alert-warning">
|
||||
{% for message in messages %}
|
||||
|
|
@ -34,13 +34,13 @@
|
|||
<td class="xs-td-smallhalf" data-header="{% trans 'Amount' %}">{{ order.price }}</td>
|
||||
<td data-header="{% trans 'Status' %}">
|
||||
{% if order.approved %}
|
||||
<span class="vm-status-active"><strong>Approved</strong></span>
|
||||
<span class="vm-status-active"><strong>{% trans "Approved" %}</strong></span>
|
||||
{% else %}
|
||||
<span class="vm-status-failed"><strong>Declined</strong></span>
|
||||
<span class="vm-status-failed"><strong>{% trans "Declined" %}</strong></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right last-td">
|
||||
<a class="btn btn-order-detail alt-text" href="{% url 'hosting:orders' order.pk %}" data-alt="{% trans 'See Invoice' %}">{% trans "View Detail" %}</a>
|
||||
<a class="btn btn-order-detail" href="{% url 'hosting:orders' order.pk %}">{% trans 'See Invoice' %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
{% extends "hosting/base_short.html" %}
|
||||
{% load staticfiles bootstrap3 i18n %}
|
||||
|
||||
{% block css_extra %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
|
||||
{% endblock css_extra %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Credit card form -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
|
||||
<div class="dcl-order-container">
|
||||
<div class="payment-container">
|
||||
<div class="row">
|
||||
|
|
@ -87,7 +91,7 @@
|
|||
<div class="col-xs-12">
|
||||
{% if not messages and not form.non_field_errors %}
|
||||
<p class="card-warning-content card-warning-addtional-margin">
|
||||
{% blocktrans %}You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page.{% endblocktrans %}
|
||||
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div id='payment_error'>
|
||||
|
|
@ -144,7 +148,7 @@
|
|||
<div class="col-xs-12">
|
||||
{% if not messages and not form.non_field_errors %}
|
||||
<p class="card-warning-content">
|
||||
{% blocktrans %}You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page.{% endblocktrans %}
|
||||
{% trans "You are not making any payment yet. After submitting your card information, you will be taken to the Confirm Order Page." %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div id='payment_error'>
|
||||
|
|
@ -207,7 +211,6 @@
|
|||
window.hasCreditcard = true;
|
||||
})();
|
||||
</script>
|
||||
|
||||
{%endif%}
|
||||
|
||||
{%endblock%}
|
||||
|
|
|
|||
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 %}
|
||||
149
hosting/templates/hosting/settings.html
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
{% extends "hosting/base_short.html" %}
|
||||
{% load staticfiles bootstrap3 i18n %}
|
||||
|
||||
{% block css_extra %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/paymentfont/1.1.2/css/paymentfont.min.css"/>
|
||||
{% endblock css_extra %}
|
||||
|
||||
{% block content %}
|
||||
<div class="dashboard-container wide">
|
||||
<div class="dashboard-container-head">
|
||||
<h1 class="dashboard-title-thin"><img src="{% static 'hosting/img/dashboard_settings.svg' %}" class="un-icon wide"> {% trans "My Settings" %}</h1>
|
||||
</div>
|
||||
<!-- Credit card form -->
|
||||
<div class="settings-container">
|
||||
<div class="row">
|
||||
<div class="col-sm-5 col-md-6 billing dcl-billing">
|
||||
<h3>{%trans "Billing Address"%}</h3>
|
||||
<hr>
|
||||
<form role="form" id="billing-form" method="post" action="" novalidate>
|
||||
{% for field in form %}
|
||||
{% csrf_token %}
|
||||
{% bootstrap_field field show_label=False type='fields' bound_css_class='' %}
|
||||
{% endfor %}
|
||||
<div class="form-group text-right">
|
||||
<button type="submit" class="btn btn-vm-contact btn-wide">{% trans "UPDATE" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-sm-7 col-md-6 creditcard-box dcl-creditcard">
|
||||
<h3>{%trans "Credit Card"%}</h3>
|
||||
<hr>
|
||||
<div>
|
||||
{% if credit_card_data.last4 %}
|
||||
<div class="credit-card-details">
|
||||
<h5 class="billing-head">{% trans "Credit Card" %}</h5>
|
||||
<h5 class="membership-lead">{% trans "Last" %} 4: *****{{credit_card_data.last4}}</h5>
|
||||
<h5 class="membership-lead">{% trans "Type" %}: {{credit_card_data.cc_brand}}</h5>
|
||||
{% comment %}
|
||||
<div class="credit-card-details-opt">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<a class="caps-link" href=""><img src="{% static 'hosting/img/delete.svg' %}" class="svg-img">{% trans "REMOVE CARD" %}</a>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<a class="btn btn-vm-contact" href="">{% trans "EDIT CARD" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endcomment %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="no-cards">
|
||||
<h4>{% trans "No Credit Cards Added" %}</h4>
|
||||
<p>{% blocktrans %}We are using <a href="https://stripe.com">Stripe</a> for payment and do not store your information in our database.{% endblocktrans %}</p>
|
||||
</div>
|
||||
|
||||
{% comment %}
|
||||
<h4>{% trans "Add a new Card." %}</h4>
|
||||
<p style="margin-bottom: 15px;">
|
||||
{% blocktrans %}Please fill in your credit card information below. We are using <a href="https://stripe.com" target="_blank">Stripe</a> for payment and do not store your information in our database.{% endblocktrans %}
|
||||
</p>
|
||||
<form action="" id="payment-form-new" class="credit-card-form" method="POST">
|
||||
<input type="hidden" name="token"/>
|
||||
<div class="credit-card-goup">
|
||||
<div class="card-element card-number-element">
|
||||
<label>{%trans "Card Number" %}</label>
|
||||
<div id="card-number-element" class="field my-input"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 col-sm-4 card-element card-expiry-element">
|
||||
<label>{%trans "Expiry Date" %}</label>
|
||||
<div id="card-expiry-element" class="field my-input"></div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-sm-4 col-sm-offset-4 card-element card-cvc-element">
|
||||
<label>{%trans "CVC" %}</label>
|
||||
<div id="card-cvc-element" class="field my-input"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-element brand">
|
||||
<label>{%trans "Card Type" %}</label>
|
||||
<i class="pf pf-credit-card" id="brand-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div id="card-errors" role="alert"></div>
|
||||
<div>
|
||||
{% if not messages and not form.non_field_errors %}
|
||||
<p class="card-warning-content">
|
||||
{% blocktrans %}You are not making any payment here.{% endblocktrans %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div id='payment_error'>
|
||||
{% for message in messages %}
|
||||
{% if 'failed_payment' or 'make_charge_error' in message.tags %}
|
||||
<ul class="list-unstyled"><li>
|
||||
<p class="card-warning-content card-warning-error">{{ message|safe }}</p>
|
||||
</li></ul>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for error in form.non_field_errors %}
|
||||
<p class="card-warning-content card-warning-error">
|
||||
{{ error|escape }}
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 col-xs-offset-6 text-right">
|
||||
<button class="btn btn-success stripe-payment-btn" type="submit">{%trans "Submit" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:none;">
|
||||
<p class="payment-errors"></p>
|
||||
</div>
|
||||
</form>
|
||||
{% endcomment %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% comment %}
|
||||
<!-- stripe key data -->
|
||||
{% if stripe_key %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
<script type="text/javascript">
|
||||
window.processing_text = '{%trans "Processing" %}';
|
||||
window.enter_your_card_text = '{%trans "Enter your credit card number" %}';
|
||||
|
||||
(function () {
|
||||
window.stripeKey = "{{stripe_key}}";
|
||||
window.current_lan = "{{LANGUAGE_CODE}}";
|
||||
})();
|
||||
</script>
|
||||
{%endif%}
|
||||
|
||||
{% if credit_card_data.last4 and credit_card_data.cc_brand %}
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
window.hasCreditcard = true;
|
||||
})();
|
||||
</script>
|
||||
{%endif%}
|
||||
{% endcomment %}
|
||||
{%endblock%}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
{% extends "hosting/base_short.html" %}
|
||||
{% load staticfiles bootstrap3 i18n %}
|
||||
|
||||
{% block navbar %}
|
||||
{% include 'hosting/includes/_navbar_transparent.html' %}
|
||||
{% endblock navbar %}
|
||||
|
||||
{% block content %}
|
||||
<div class="auth-container">
|
||||
<div class="auth-bg"></div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
{% block content %}
|
||||
<div>
|
||||
<div class="container virtual-machine-container dashboard-container ">
|
||||
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i> {% trans "Your SSH Keys" %}</h1>
|
||||
<h1 class="h1-thin"><i class="fa fa-key" aria-hidden="true"></i> {% trans "My SSH Keys" %}</h1>
|
||||
{% if messages %}
|
||||
<div class="alert alert-warning">
|
||||
{% for message in messages %}
|
||||
|
|
@ -33,8 +33,7 @@
|
|||
<tr>
|
||||
<td scope="row">{{user_key.name}}</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-default btn-custom-delete" data-toggle="modal"
|
||||
data-target="#Modal{{ user_key.id }}" style="color: #717274">
|
||||
<button type="button" class="btn btn-default btn-custom-delete" data-toggle="modal" data-target="#Modal{{ user_key.id }}" style="color: #717274">
|
||||
<span class="pc-only">{% trans "Delete" %}</span>
|
||||
<span class="mob-only"><i class="fa fa-trash"></i></span>
|
||||
</button>
|
||||
|
|
@ -42,20 +41,18 @@
|
|||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-label="Confirm"><span
|
||||
aria-hidden="true">×</span>
|
||||
</button>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Confirm"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-icon"><i class="fa fa-trash" aria-hidden="true"></i></div>
|
||||
<h4 class="modal-title" id="ModalLabel">{% trans "Delete SSH Key"%}</h4>
|
||||
<p class="modal-text">{% trans "Do you want to delete this key?"%}</p>
|
||||
<div class="modal-icon"><i class="fa fa-trash" aria-hidden="true"></i></div>
|
||||
<h4 class="modal-title" id="ModalLabel">{% trans "Delete SSH Key"%}</h4>
|
||||
<div class="modal-text">
|
||||
<p>{% trans "Do you want to delete this key?"%}</p>
|
||||
</div>
|
||||
<form method="post" action="{% url 'hosting:delete_ssh_key' user_key.id %}">
|
||||
{% csrf_token %}
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-danger">{% trans "Delete"%}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-danger btn-wide">{% trans "Delete"%}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -64,23 +61,18 @@
|
|||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p type="button" data-toggle="modal" style="margin: 0" data-target="#Modal_public_key{{ user_key.id }}">
|
||||
<p data-toggle="modal" style="margin: 0" data-target="#Modal_public_key{{ user_key.id }}">
|
||||
<a href="#">{% trans "Show" %}</a>
|
||||
</p>
|
||||
<div class="modal fade" id="Modal_public_key{{user_key.id }}" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-label="Confirm"><span
|
||||
aria-hidden="true">×</span>
|
||||
</button>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Confirm"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h4 class="modal-title" id="ModalLabel_Public_Key">{% trans "Public SSH Key" %}</h4>
|
||||
<p class="key_contain" style="margin-top: 10px;">{{ user_key.public_key }}</p>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -90,10 +82,9 @@
|
|||
<td>
|
||||
{% if user_key.private_key %}
|
||||
<form action="{{ user_key.private_key.url }}">
|
||||
<button style="color: #717274" type="submit" class="btn btn-default" data-toggle="modal"
|
||||
>
|
||||
<span class="pc-only">{% trans "Download" %}</span>
|
||||
<span class="mob-only"><i class="fa fa-download"></i></span>
|
||||
<button style="color: #717274" type="submit" class="btn btn-default">
|
||||
<span class="pc-only">{% trans "Download" %}</span>
|
||||
<span class="mob-only"><i class="fa fa-download"></i></span>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -53,19 +53,26 @@
|
|||
<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-item-subtitle">{% trans "Your VM is" %}</div>
|
||||
{% if virtual_machine.state == 'PENDING' %}
|
||||
<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div>
|
||||
{% elif virtual_machine.state == 'ACTIVE' %}
|
||||
<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div>
|
||||
{% elif virtual_machine.state == 'FAILED'%}
|
||||
<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div>
|
||||
{% endif %}
|
||||
{% 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 %}">
|
||||
{% csrf_token %}
|
||||
</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>
|
||||
{% endif %}
|
||||
<div id="terminate-VM" data-alt="{% trans 'Terminating' %}">
|
||||
{% if virtual_machine.state == 'PENDING' %}
|
||||
<div class="vm-item-lg vm-color-pending">{% trans "Pending" %}</div>
|
||||
{% elif virtual_machine.state == 'ACTIVE' %}
|
||||
<div class="vm-item-lg vm-color-online">{% trans "Online" %}</div>
|
||||
{% elif virtual_machine.state == 'FAILED'%}
|
||||
<div class="vm-item-lg vm-color-failed">{% trans "Failed" %}</div>
|
||||
{% else %}
|
||||
<div class="vm-item-lg"></div>
|
||||
{% endif %}
|
||||
{% 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 %}">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
<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 %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -89,24 +96,42 @@
|
|||
</div>
|
||||
<!-- Cancel Modal -->
|
||||
<div class="modal fade" id="confirm-cancel" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Confirm"><span aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-body">
|
||||
<div class="modal-icon"><i class="fa fa-ban" aria-hidden="true"></i></div>
|
||||
<h4 class="modal-title" id="ModalLabel">{% trans "Terminate your Virtual Machine"%}</h4>
|
||||
<h4 class="modal-title" id="ModalLabel">{% trans "Terminate your Virtual Machine" %}</h4>
|
||||
<div class="modal-text">
|
||||
<p>{% trans "Do you want to cancel your Virtual Machine" %} ?</p>
|
||||
<p><strong>{{virtual_machine.name}}</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn btn-danger btn-ok">{% trans "OK" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn btn-danger btn-ok btn-wide">{% trans "OK" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- / 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="checkmark" aria-hidden="true"></i></div>
|
||||
<h4 class="modal-title"></h4>
|
||||
<div class="modal-text" id="ModalLabel">{% blocktrans with machine_name=virtual_machine.name %}Your Virtual Machine <strong>{{machine_name}}</strong> is successfully terminated!{% endblocktrans %}</div>
|
||||
<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%}
|
||||
|
|
|
|||
|
|
@ -41,13 +41,15 @@
|
|||
<td data-header="IPv6">{{vm.ipv6}}</td>
|
||||
{% endif %}
|
||||
<td data-header="{% trans 'Status' %}">
|
||||
{% if vm.state == 'ACTIVE' %}
|
||||
<span class="vm-status-active"><strong>{{vm.state|title}}</strong></span>
|
||||
{% elif vm.state == 'FAILED' %}
|
||||
<span class="vm-status-failed"><strong>{{vm.state|title}}</strong></span>
|
||||
{% else %}
|
||||
<span class="vm-status"><strong>{{vm.state|title}}</strong></span>
|
||||
{% endif %}
|
||||
<strong>
|
||||
{% if vm.state == 'ACTIVE' %}
|
||||
<span class="vm-status-active">{{vm.state|title}}</span>
|
||||
{% elif vm.state == 'FAILED' %}
|
||||
<span class="vm-status-failed">{{vm.state|title}}</span>
|
||||
{% else %}
|
||||
<span class="vm-status">{{vm.state|title}}</span>
|
||||
{% endif %}
|
||||
</strong>
|
||||
</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>
|
||||
|
|
|
|||
|
|
@ -1,25 +1,32 @@
|
|||
from django.conf.urls import url
|
||||
from django.contrib.auth import views as auth_views
|
||||
|
||||
from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
|
||||
NodeJSHostingView, LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView, \
|
||||
OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
|
||||
VirtualMachineView, OrdersHostingDeleteView, NotificationsView, \
|
||||
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\
|
||||
CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, \
|
||||
SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, SSHKeyChoiceView
|
||||
from .views import (
|
||||
DjangoHostingView, RailsHostingView, PaymentVMView, NodeJSHostingView,
|
||||
LoginView, SignupView, SignupValidateView, SignupValidatedView, IndexView,
|
||||
NotificationsView, OrdersHostingListView, OrdersHostingDetailView,
|
||||
VirtualMachinesPlanListView, VirtualMachineView, OrdersHostingDeleteView,
|
||||
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView,
|
||||
HostingPricingView, CreateVirtualMachinesView, HostingBillListView,
|
||||
HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView,
|
||||
SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'index/?$', IndexView.as_view(), name='index'),
|
||||
url(r'django/?$', DjangoHostingView.as_view(), name='djangohosting'),
|
||||
url(r'dashboard/?$', DashboardView.as_view(), name='dashboard'),
|
||||
url(r'nodejs/?$', NodeJSHostingView.as_view(), name='nodejshosting'),
|
||||
url(r'rails/?$', RailsHostingView.as_view(), name='railshosting'),
|
||||
url(r'pricing/?$', HostingPricingView.as_view(), name='pricing'),
|
||||
url(r'payment/?$', PaymentVMView.as_view(), name='payment'),
|
||||
url(r'settings/?$', SettingsView.as_view(), name='settings'),
|
||||
url(r'orders/?$', OrdersHostingListView.as_view(), name='orders'),
|
||||
url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'),
|
||||
url(r'order-confirmation/?$', OrdersHostingDetailView.as_view(),
|
||||
name='order-confirmation'),
|
||||
url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(),
|
||||
name='orders'),
|
||||
url(r'bills/?$', HostingBillListView.as_view(), name='bills'),
|
||||
url(r'bills/(?P<pk>\d+)/?$', HostingBillDetailView.as_view(), name='bills'),
|
||||
url(r'bills/(?P<pk>\d+)/?$', HostingBillDetailView.as_view(),
|
||||
name='bills'),
|
||||
url(r'cancel_order/(?P<pk>\d+)/?$',
|
||||
OrdersHostingDeleteView.as_view(), name='delete_order'),
|
||||
url(r'create_virtual_machine/?$', CreateVirtualMachinesView.as_view(),
|
||||
|
|
@ -36,13 +43,18 @@ urlpatterns = [
|
|||
name='delete_ssh_key'),
|
||||
url(r'create_ssh_key/?$', SSHKeyCreateView.as_view(),
|
||||
name='create_ssh_key'),
|
||||
url(r'^notifications/$', NotificationsView.as_view(), name='notifications'),
|
||||
url(r'^notifications/$', NotificationsView.as_view(),
|
||||
name='notifications'),
|
||||
url(r'^notifications/(?P<pk>\d+)/?$', MarkAsReadNotificationView.as_view(),
|
||||
name='read_notification'),
|
||||
url(r'login/?$', LoginView.as_view(), name='login'),
|
||||
url(r'signup/?$', SignupView.as_view(), name='signup'),
|
||||
url(r'signup-validate/?$', SignupValidateView.as_view(), name='signup-validate'),
|
||||
url(r'reset-password/?$', PasswordResetView.as_view(), name='reset_password'),
|
||||
url(r'signup-validate/?$', SignupValidateView.as_view(),
|
||||
name='signup-validate'),
|
||||
url(r'resend-activation-link/?$', ResendActivationEmailView.as_view(),
|
||||
name='resend_activation_link'),
|
||||
url(r'reset-password/?$', PasswordResetView.as_view(),
|
||||
name='reset_password'),
|
||||
url(r'reset-password-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
|
||||
PasswordResetConfirmView.as_view(), name='reset_password_confirm'),
|
||||
url(r'^logout/?$', auth_views.logout,
|
||||
|
|
|
|||
686
hosting/views.py
|
|
@ -1,43 +1,72 @@
|
|||
import json
|
||||
import logging
|
||||
import uuid
|
||||
from time import sleep
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
from oca.pool import WrongNameError, WrongIdError
|
||||
from django.shortcuts import render
|
||||
from django.http import Http404
|
||||
from django.core.urlresolvers import reverse_lazy, reverse
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.views.generic import View, CreateView, FormView, ListView, DetailView, \
|
||||
DeleteView, TemplateView, UpdateView
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib import messages
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.http import urlsafe_base64_decode
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
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.urlresolvers import reverse_lazy, reverse
|
||||
|
||||
from guardian.mixins import PermissionRequiredMixin
|
||||
from stored_messages.settings import stored_messages_settings
|
||||
from stored_messages.models import Message
|
||||
from stored_messages.api import mark_read
|
||||
from django.http import Http404, HttpResponseRedirect, HttpResponse
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils.http import urlsafe_base64_decode
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import get_language, ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
from django.views.generic import (
|
||||
View, CreateView, FormView, ListView, DetailView, DeleteView,
|
||||
TemplateView, UpdateView
|
||||
)
|
||||
from guardian.mixins import PermissionRequiredMixin
|
||||
from oca.pool import WrongIdError
|
||||
from stored_messages.api import mark_read
|
||||
from stored_messages.models import Message
|
||||
from stored_messages.settings import stored_messages_settings
|
||||
|
||||
from datacenterlight.tasks import create_vm_task
|
||||
from membership.models import CustomUser, StripeCustomer
|
||||
from utils.stripe_utils import StripeUtils
|
||||
from utils.forms import BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm
|
||||
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin
|
||||
from utils.mailer import BaseEmail
|
||||
from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
|
||||
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm, generate_ssh_key_name
|
||||
from .mixins import ProcessVMSelectionMixin
|
||||
|
||||
from opennebula_api.models import OpenNebulaManager
|
||||
from opennebula_api.serializers import VirtualMachineSerializer, \
|
||||
VirtualMachineTemplateSerializer
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
VirtualMachineTemplateSerializer, VMTemplateSerializer
|
||||
from utils.forms import (
|
||||
BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm,
|
||||
ResendActivationEmailForm
|
||||
)
|
||||
from utils.mailer import BaseEmail
|
||||
from utils.stripe_utils import StripeUtils
|
||||
from utils.views import (
|
||||
PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin,
|
||||
ResendActivationLinkViewMixin
|
||||
)
|
||||
from .forms import HostingUserSignupForm, HostingUserLoginForm, \
|
||||
UserHostingKeyForm, generate_ssh_key_name
|
||||
from .mixins import ProcessVMSelectionMixin
|
||||
from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
|
||||
from datacenterlight.models import VMTemplate
|
||||
|
||||
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a backend \
|
||||
connection error. please try again in a few minutes."
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \
|
||||
backend connection error. please try again in a few \
|
||||
minutes."
|
||||
|
||||
|
||||
class DashboardView(View):
|
||||
template_name = "hosting/dashboard.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {}
|
||||
return context
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
context = self.get_context_data()
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class DjangoHostingView(ProcessVMSelectionMixin, View):
|
||||
|
|
@ -178,7 +207,7 @@ class IndexView(View):
|
|||
class LoginView(LoginViewMixin):
|
||||
template_name = "hosting/login.html"
|
||||
form_class = HostingUserLoginForm
|
||||
success_url = reverse_lazy('hosting:virtual_machines')
|
||||
success_url = reverse_lazy('hosting:dashboard')
|
||||
|
||||
|
||||
class SignupView(CreateView):
|
||||
|
|
@ -256,6 +285,14 @@ class SignupValidatedView(SignupValidateView):
|
|||
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):
|
||||
site = 'dcl'
|
||||
template_name = 'hosting/reset_password.html'
|
||||
|
|
@ -284,27 +321,29 @@ class PasswordResetConfirmView(PasswordResetConfirmViewMixin):
|
|||
|
||||
form = self.form_class(request.POST)
|
||||
|
||||
if user is not None and default_token_generator.check_token(user, token):
|
||||
if user is not None and default_token_generator.check_token(user,
|
||||
token):
|
||||
if form.is_valid():
|
||||
new_password = form.cleaned_data['new_password2']
|
||||
user.set_password(new_password)
|
||||
user.save()
|
||||
messages.success(request, 'Password has been reset.')
|
||||
messages.success(request, _('Password has been reset.'))
|
||||
|
||||
# Change opennebula password
|
||||
opennebula_client.change_user_password(new_password)
|
||||
opennebula_client.change_user_password(user.password)
|
||||
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
messages.error(
|
||||
request, 'Password reset has not been successful.')
|
||||
form.add_error(None, 'Password reset has not been successful.')
|
||||
request, _('Password reset has not been successful.'))
|
||||
form.add_error(None,
|
||||
_('Password reset has not been successful.'))
|
||||
return self.form_invalid(form)
|
||||
|
||||
else:
|
||||
messages.error(
|
||||
request, 'The reset password link is no longer valid.')
|
||||
form.add_error(None, 'The reset password link is no longer valid.')
|
||||
error_msg = _('The reset password link is no longer valid.')
|
||||
messages.error(request, _(error_msg))
|
||||
form.add_error(None, error_msg)
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
||||
|
|
@ -354,17 +393,14 @@ class SSHKeyDeleteView(LoginRequiredMixin, DeleteView):
|
|||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
owner = self.request.user
|
||||
manager = OpenNebulaManager()
|
||||
manager = OpenNebulaManager(
|
||||
email=owner.email,
|
||||
password=owner.password
|
||||
)
|
||||
pk = self.kwargs.get('pk')
|
||||
# Get user ssh key
|
||||
public_key = UserHostingKey.objects.get(pk=pk).public_key
|
||||
# Add ssh key to user
|
||||
try:
|
||||
manager.remove_public_key(user=owner, public_key=public_key)
|
||||
except ConnectionError:
|
||||
pass
|
||||
except WrongNameError:
|
||||
pass
|
||||
manager.manage_public_key([{'value': public_key, 'state': False}])
|
||||
|
||||
return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs)
|
||||
|
||||
|
|
@ -385,7 +421,8 @@ class SSHKeyListView(LoginRequiredMixin, ListView):
|
|||
def render_to_response(self, context, **response_kwargs):
|
||||
if not self.queryset:
|
||||
return HttpResponseRedirect(reverse('hosting:choice_ssh_keys'))
|
||||
return super(SSHKeyListView, self).render_to_response(context, **response_kwargs)
|
||||
return super(SSHKeyListView, self).render_to_response(context,
|
||||
**response_kwargs)
|
||||
|
||||
|
||||
class SSHKeyChoiceView(LoginRequiredMixin, View):
|
||||
|
|
@ -404,6 +441,13 @@ class SSHKeyChoiceView(LoginRequiredMixin, View):
|
|||
user=request.user, public_key=public_key, name=name)
|
||||
filename = name + '_' + str(uuid.uuid4())[:8] + '_private.pem'
|
||||
ssh_key.private_key.save(filename, content)
|
||||
owner = self.request.user
|
||||
manager = OpenNebulaManager(
|
||||
email=owner.email,
|
||||
password=owner.password
|
||||
)
|
||||
public_key_str = public_key.decode()
|
||||
manager.manage_public_key([{'value': public_key_str, 'state': True}])
|
||||
return redirect(reverse_lazy('hosting:ssh_keys'), foo='bar')
|
||||
|
||||
|
||||
|
|
@ -448,23 +492,17 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
|
|||
})
|
||||
|
||||
owner = self.request.user
|
||||
manager = OpenNebulaManager()
|
||||
|
||||
# Get user ssh key
|
||||
public_key = str(form.cleaned_data.get('public_key', ''))
|
||||
# Add ssh key to user
|
||||
try:
|
||||
manager.add_public_key(
|
||||
user=owner, public_key=public_key, merge=True)
|
||||
except ConnectionError:
|
||||
pass
|
||||
except WrongNameError:
|
||||
pass
|
||||
|
||||
manager = OpenNebulaManager(
|
||||
email=owner.email,
|
||||
password=owner.password
|
||||
)
|
||||
public_key = form.cleaned_data['public_key']
|
||||
if type(public_key) is bytes:
|
||||
public_key = public_key.decode()
|
||||
manager.manage_public_key([{'value': public_key, 'state': True}])
|
||||
return HttpResponseRedirect(self.success_url)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
print(self.request.POST.dict())
|
||||
form = self.get_form()
|
||||
required = 'add_ssh' in self.request.POST
|
||||
form.fields['name'].required = required
|
||||
|
|
@ -475,6 +513,57 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
|
|||
return self.form_invalid(form)
|
||||
|
||||
|
||||
class SettingsView(LoginRequiredMixin, FormView):
|
||||
template_name = "hosting/settings.html"
|
||||
login_url = reverse_lazy('hosting:login')
|
||||
form_class = BillingAddressForm
|
||||
|
||||
def get_form(self, form_class):
|
||||
"""
|
||||
Check if the user already saved contact details. If so, then show
|
||||
the form populated with those details, to let user change them.
|
||||
"""
|
||||
return form_class(
|
||||
instance=self.request.user.billing_addresses.first(),
|
||||
**self.get_form_kwargs())
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(SettingsView, self).get_context_data(**kwargs)
|
||||
# Get user
|
||||
user = self.request.user
|
||||
# Get user last order
|
||||
last_hosting_order = HostingOrder.objects.filter(
|
||||
customer__user=user).last()
|
||||
# If user has already an hosting order, get the credit card data from
|
||||
# it
|
||||
if last_hosting_order:
|
||||
credit_card_data = last_hosting_order.get_cc_data()
|
||||
context.update({
|
||||
'credit_card_data': credit_card_data if credit_card_data else None,
|
||||
})
|
||||
context.update({
|
||||
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
billing_address_data = form.cleaned_data
|
||||
billing_address_data.update({
|
||||
'user': self.request.user.id
|
||||
})
|
||||
billing_address_user_form = UserBillingAddressForm(
|
||||
instance=self.request.user.billing_addresses.first(),
|
||||
data=billing_address_data)
|
||||
billing_address_user_form.save()
|
||||
return self.render_to_response(self.get_context_data())
|
||||
else:
|
||||
billing_address_data = form.cleaned_data
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
||||
class PaymentVMView(LoginRequiredMixin, FormView):
|
||||
template_name = 'hosting/payment.html'
|
||||
login_url = reverse_lazy('hosting:login')
|
||||
|
|
@ -536,157 +625,206 @@ class PaymentVMView(LoginRequiredMixin, FormView):
|
|||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
|
||||
# Get billing address data
|
||||
billing_address_data = form.cleaned_data
|
||||
|
||||
context = self.get_context_data()
|
||||
|
||||
template = request.session.get('template')
|
||||
specs = request.session.get('specs')
|
||||
|
||||
vm_template_id = template.get('id', 1)
|
||||
|
||||
final_price = specs.get('price')
|
||||
|
||||
token = form.cleaned_data.get('token')
|
||||
|
||||
owner = self.request.user
|
||||
|
||||
# Get or create stripe customer
|
||||
customer = StripeCustomer.get_or_create(email=owner.email,
|
||||
token=token)
|
||||
if not customer:
|
||||
msg = _("Invalid credit card")
|
||||
messages.add_message(self.request, messages.ERROR, msg, extra_tags='make_charge_error')
|
||||
return HttpResponseRedirect(reverse('hosting:payment') + '#payment_error')
|
||||
messages.add_message(
|
||||
self.request, messages.ERROR, msg,
|
||||
extra_tags='make_charge_error')
|
||||
return HttpResponseRedirect(
|
||||
reverse('hosting:payment') + '#payment_error')
|
||||
|
||||
# Create Billing Address
|
||||
billing_address = form.save()
|
||||
|
||||
# Make stripe charge to a customer
|
||||
stripe_utils = StripeUtils()
|
||||
charge_response = stripe_utils.make_charge(amount=final_price,
|
||||
customer=customer.stripe_id)
|
||||
|
||||
# Check if the payment was approved
|
||||
if not charge_response.get('response_object'):
|
||||
msg = charge_response.get('error')
|
||||
messages.add_message(self.request, messages.ERROR, msg, extra_tags='make_charge_error')
|
||||
return HttpResponseRedirect(reverse('hosting:payment') + '#payment_error')
|
||||
|
||||
charge = charge_response.get('response_object')
|
||||
|
||||
# Create OpenNebulaManager
|
||||
manager = OpenNebulaManager(email=owner.email,
|
||||
password=owner.password)
|
||||
# Get user ssh key
|
||||
if not UserHostingKey.objects.filter(user=self.request.user).exists():
|
||||
context.update({
|
||||
'sshError': 'error',
|
||||
'form': form
|
||||
})
|
||||
return render(request, self.template_name, context)
|
||||
# For now just get first one
|
||||
user_key = UserHostingKey.objects.filter(
|
||||
user=self.request.user).first()
|
||||
|
||||
# Create a vm using logged user
|
||||
vm_id = manager.create_vm(
|
||||
template_id=vm_template_id,
|
||||
# XXX: Confi
|
||||
specs=specs,
|
||||
ssh_key=user_key.public_key,
|
||||
)
|
||||
|
||||
# Create a Hosting Order
|
||||
order = HostingOrder.create(
|
||||
price=final_price,
|
||||
vm_id=vm_id,
|
||||
customer=customer,
|
||||
billing_address=billing_address
|
||||
)
|
||||
|
||||
# Create a Hosting Bill
|
||||
HostingBill.create(
|
||||
customer=customer, billing_address=billing_address)
|
||||
|
||||
# Create Billing Address for User if he does not have one
|
||||
if not customer.user.billing_addresses.count():
|
||||
billing_address_data.update({
|
||||
'user': customer.user.id
|
||||
})
|
||||
billing_address_user_form = UserBillingAddressForm(
|
||||
billing_address_data)
|
||||
billing_address_user_form.is_valid()
|
||||
billing_address_user_form.save()
|
||||
|
||||
# Associate an order with a stripe payment
|
||||
order.set_stripe_charge(charge)
|
||||
|
||||
# If the Stripe payment was successed, set order status approved
|
||||
order.set_approved()
|
||||
|
||||
vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
|
||||
|
||||
# Send notification to ungleich as soon as VM has been booked
|
||||
context = {
|
||||
'vm': vm,
|
||||
'order': order,
|
||||
'base_url': "{0}://{1}".format(request.scheme, request.get_host())
|
||||
|
||||
}
|
||||
email_data = {
|
||||
'subject': 'New VM request',
|
||||
'to': request.user.email,
|
||||
'context': context,
|
||||
'template_name': 'new_booked_vm',
|
||||
'template_path': 'hosting/emails/'
|
||||
}
|
||||
email = BaseEmail(**email_data)
|
||||
email.send()
|
||||
|
||||
return HttpResponseRedirect(
|
||||
"{url}?{query_params}".format(url=reverse('hosting:orders', kwargs={'pk': order.id}),
|
||||
query_params='page=payment'))
|
||||
request.session['billing_address_data'] = billing_address_data
|
||||
request.session['billing_address'] = billing_address.id
|
||||
request.session['token'] = token
|
||||
request.session['customer'] = customer.id
|
||||
return HttpResponseRedirect("{url}?{query_params}".format(
|
||||
url=reverse('hosting:order-confirmation'),
|
||||
query_params='page=payment'))
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
||||
class OrdersHostingDetailView(PermissionRequiredMixin, LoginRequiredMixin, DetailView):
|
||||
class OrdersHostingDetailView(LoginRequiredMixin,
|
||||
DetailView):
|
||||
template_name = "hosting/order_detail.html"
|
||||
context_object_name = "order"
|
||||
login_url = reverse_lazy('hosting:login')
|
||||
permission_required = ['view_hostingorder']
|
||||
model = HostingOrder
|
||||
|
||||
def get_object(self):
|
||||
return HostingOrder.objects.get(
|
||||
pk=self.kwargs.get('pk')) if self.kwargs.get('pk') else None
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
# Get context
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
obj = self.get_object()
|
||||
owner = self.request.user
|
||||
manager = OpenNebulaManager(email=owner.email,
|
||||
password=owner.password)
|
||||
if self.request.GET.get('page', '') == 'payment':
|
||||
stripe_customer_id = self.request.session.get('customer')
|
||||
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
|
||||
stripe_utils = StripeUtils()
|
||||
if customer:
|
||||
card_details = stripe_utils.get_card_details(
|
||||
customer.stripe_id,
|
||||
self.request.session.get('token')
|
||||
)
|
||||
else:
|
||||
card_details = {}
|
||||
|
||||
if self.request.GET.get('page') == 'payment':
|
||||
context['page_header_text'] = _('Confirm Order')
|
||||
else:
|
||||
context['page_header_text'] = _('Invoice')
|
||||
try:
|
||||
vm = manager.get_vm(obj.vm_id)
|
||||
context['vm'] = VirtualMachineSerializer(vm).data
|
||||
except WrongIdError:
|
||||
messages.error(self.request,
|
||||
'The VM you are looking for is unavailable at the moment. \
|
||||
Please contact Data Center Light support.'
|
||||
)
|
||||
self.kwargs['error'] = 'WrongIdError'
|
||||
context['error'] = 'WrongIdError'
|
||||
except ConnectionRefusedError:
|
||||
messages.error(self.request,
|
||||
'In order to create a VM, you need to create/upload your SSH KEY first.'
|
||||
)
|
||||
|
||||
if obj is not None:
|
||||
# invoice for previous order
|
||||
try:
|
||||
manager = OpenNebulaManager(
|
||||
email=owner.email, password=owner.password
|
||||
)
|
||||
vm = manager.get_vm(obj.vm_id)
|
||||
context['vm'] = VirtualMachineSerializer(vm).data
|
||||
except WrongIdError:
|
||||
messages.error(
|
||||
self.request,
|
||||
_('The VM you are looking for is unavailable at the '
|
||||
'moment. Please contact Data Center Light support.')
|
||||
)
|
||||
self.kwargs['error'] = 'WrongIdError'
|
||||
context['error'] = 'WrongIdError'
|
||||
except ConnectionRefusedError:
|
||||
messages.error(
|
||||
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:
|
||||
# new order, confirm payment
|
||||
context['site_url'] = reverse('hosting:create_virtual_machine')
|
||||
context['cc_last4'] = card_details.get('response_object').get(
|
||||
'last4')
|
||||
context['cc_brand'] = card_details.get('response_object').get(
|
||||
'cc_brand')
|
||||
context['vm'] = self.request.session.get('specs')
|
||||
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):
|
||||
template = request.session.get('template')
|
||||
specs = request.session.get('specs')
|
||||
stripe_customer_id = request.session.get('customer')
|
||||
customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
|
||||
billing_address_data = request.session.get('billing_address_data')
|
||||
billing_address_id = request.session.get('billing_address')
|
||||
vm_template_id = template.get('id', 1)
|
||||
|
||||
# Make stripe charge to a customer
|
||||
stripe_utils = StripeUtils()
|
||||
card_details = stripe_utils.get_card_details(customer.stripe_id,
|
||||
request.session.get(
|
||||
'token'))
|
||||
if not card_details.get('response_object'):
|
||||
msg = card_details.get('error')
|
||||
messages.add_message(self.request, messages.ERROR, msg,
|
||||
extra_tags='failed_payment')
|
||||
return HttpResponseRedirect(
|
||||
reverse('datacenterlight:payment') + '#payment_error')
|
||||
card_details_dict = card_details.get('response_object')
|
||||
cpu = specs.get('cpu')
|
||||
memory = specs.get('memory')
|
||||
disk_size = specs.get('disk_size')
|
||||
amount_to_be_charged = (cpu * 5) + (memory * 2) + (disk_size * 0.6)
|
||||
plan_name = "{cpu} Cores, {memory} GB RAM, {disk_size} GB SSD".format(
|
||||
cpu=cpu,
|
||||
memory=memory,
|
||||
disk_size=disk_size)
|
||||
|
||||
stripe_plan_id = StripeUtils.get_stripe_plan_id(cpu=cpu,
|
||||
ram=memory,
|
||||
ssd=disk_size,
|
||||
version=1,
|
||||
app='dcl')
|
||||
stripe_plan = stripe_utils.get_or_create_stripe_plan(
|
||||
amount=amount_to_be_charged,
|
||||
name=plan_name,
|
||||
stripe_plan_id=stripe_plan_id)
|
||||
subscription_result = stripe_utils.subscribe_customer_to_plan(
|
||||
customer.stripe_id,
|
||||
[{"plan": stripe_plan.get(
|
||||
'response_object').stripe_plan_id}])
|
||||
stripe_subscription_obj = subscription_result.get('response_object')
|
||||
# Check if the subscription was approved and is active
|
||||
if stripe_subscription_obj is None or stripe_subscription_obj.status != 'active':
|
||||
msg = subscription_result.get('error')
|
||||
messages.add_message(self.request, messages.ERROR, msg,
|
||||
extra_tags='failed_payment')
|
||||
return HttpResponseRedirect(
|
||||
reverse('hosting:payment') + '#payment_error')
|
||||
user = {
|
||||
'name': self.request.user.name,
|
||||
'email': self.request.user.email,
|
||||
'pass': self.request.user.password,
|
||||
'request_scheme': request.scheme,
|
||||
'request_host': request.get_host(),
|
||||
'language': get_language(),
|
||||
}
|
||||
create_vm_task.delay(vm_template_id, user, specs, template,
|
||||
stripe_customer_id, billing_address_data,
|
||||
billing_address_id,
|
||||
stripe_subscription_obj, card_details_dict)
|
||||
|
||||
for session_var in ['specs', 'template', 'billing_address',
|
||||
'billing_address_data',
|
||||
'token', 'customer']:
|
||||
if session_var in request.session:
|
||||
del request.session[session_var]
|
||||
|
||||
response = {
|
||||
'status': True,
|
||||
'redirect': reverse('hosting:virtual_machines'),
|
||||
'msg_title': str(_('Thank you for the order.')),
|
||||
'msg_body': str(_('Your VM will be up and running in a few moments.'
|
||||
' We will send you a confirmation email as soon as'
|
||||
' it is ready.'))
|
||||
}
|
||||
|
||||
return HttpResponse(json.dumps(response),
|
||||
content_type="application/json")
|
||||
|
||||
|
||||
class OrdersHostingListView(LoginRequiredMixin, ListView):
|
||||
template_name = "hosting/orders.html"
|
||||
|
|
@ -746,46 +884,80 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
|||
template_name = "hosting/create_virtual_machine.html"
|
||||
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():
|
||||
messages.success(
|
||||
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'))
|
||||
|
||||
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'
|
||||
}
|
||||
|
||||
context = {'templates': VMTemplate.objects.all()}
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
def post(self, request):
|
||||
manager = OpenNebulaManager()
|
||||
template_id = request.POST.get('vm_template_id')
|
||||
template = manager.get_template(template_id)
|
||||
configuration_id = int(request.POST.get('configuration'))
|
||||
configuration = HostingPlan.objects.get(id=configuration_id)
|
||||
request.session['template'] = VirtualMachineTemplateSerializer(
|
||||
template).data
|
||||
cores = request.POST.get('cpu')
|
||||
cores_field = forms.IntegerField(validators=[self.validate_cores])
|
||||
memory = request.POST.get('ram')
|
||||
memory_field = forms.IntegerField(validators=[self.validate_memory])
|
||||
storage = request.POST.get('storage')
|
||||
storage_field = forms.IntegerField(validators=[self.validate_storage])
|
||||
price = request.POST.get('total')
|
||||
template_id = int(request.POST.get('config'))
|
||||
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'))
|
||||
|
||||
|
||||
|
|
@ -827,19 +999,34 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
|||
def get(self, request, *args, **kwargs):
|
||||
vm = self.get_object()
|
||||
if vm is None:
|
||||
return redirect(reverse('hosting:virtual_machines'))
|
||||
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'))
|
||||
elif self.request.is_ajax():
|
||||
return HttpResponse()
|
||||
try:
|
||||
serializer = VirtualMachineSerializer(vm)
|
||||
context = {
|
||||
'virtual_machine': serializer.data,
|
||||
'order': HostingOrder.objects.get(vm_id=serializer.data['vm_id'])
|
||||
'order': HostingOrder.objects.get(
|
||||
vm_id=serializer.data['vm_id'])
|
||||
}
|
||||
except:
|
||||
except Exception as ex:
|
||||
logger.debug("Exception generated {}".format(str(ex)))
|
||||
pass
|
||||
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
response = {'status': False}
|
||||
owner = self.request.user
|
||||
vm = self.get_object()
|
||||
|
||||
|
|
@ -850,40 +1037,52 @@ class VirtualMachineView(LoginRequiredMixin, View):
|
|||
password=owner.password
|
||||
)
|
||||
|
||||
terminated = manager.delete_vm(
|
||||
vm.id
|
||||
)
|
||||
try:
|
||||
vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
|
||||
except WrongIdError:
|
||||
return redirect(reverse('hosting:virtual_machines'))
|
||||
|
||||
terminated = manager.delete_vm(vm.id)
|
||||
|
||||
if not terminated:
|
||||
messages.error(
|
||||
request,
|
||||
'Error terminating VM %s' % (opennebula_vm_id)
|
||||
)
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
context = {
|
||||
'vm': vm,
|
||||
'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host())
|
||||
}
|
||||
email_data = {
|
||||
'subject': 'Virtual machine plan canceled',
|
||||
'to': self.request.user.email,
|
||||
'context': context,
|
||||
'template_name': 'vm_status_changed',
|
||||
'template_path': 'hosting/emails/'
|
||||
}
|
||||
email = BaseEmail(**email_data)
|
||||
email.send()
|
||||
|
||||
messages.error(
|
||||
request,
|
||||
'VM %s terminated successfully' % (opennebula_vm_id)
|
||||
response['text'] = ugettext(
|
||||
'Error terminating VM') + opennebula_vm_id
|
||||
else:
|
||||
for t in range(15):
|
||||
try:
|
||||
manager.get_vm(opennebula_vm_id)
|
||||
except WrongIdError:
|
||||
response['status'] = True
|
||||
response['text'] = ugettext('Terminated')
|
||||
break
|
||||
except BaseException:
|
||||
break
|
||||
else:
|
||||
sleep(2)
|
||||
context = {
|
||||
'vm': vm_data,
|
||||
'base_url': "{0}://{1}".format(self.request.scheme,
|
||||
self.request.get_host()),
|
||||
'page_header': _('Virtual Machine Cancellation')
|
||||
}
|
||||
email_data = {
|
||||
'subject': context['page_header'],
|
||||
'to': self.request.user.email,
|
||||
'context': context,
|
||||
'template_name': 'vm_canceled',
|
||||
'template_path': 'hosting/emails/',
|
||||
'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
|
||||
}
|
||||
email = BaseEmail(**email_data)
|
||||
email.send()
|
||||
return HttpResponse(
|
||||
json.dumps(response),
|
||||
content_type="application/json"
|
||||
)
|
||||
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
|
||||
class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin, ListView):
|
||||
class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin,
|
||||
ListView):
|
||||
template_name = "hosting/bills.html"
|
||||
login_url = reverse_lazy('hosting:login')
|
||||
permission_required = ['view_hostingview']
|
||||
|
|
@ -893,7 +1092,8 @@ class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin, ListView)
|
|||
ordering = '-id'
|
||||
|
||||
|
||||
class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin, DetailView):
|
||||
class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin,
|
||||
DetailView):
|
||||
template_name = "hosting/bill_detail.html"
|
||||
login_url = reverse_lazy('hosting:login')
|
||||
permission_required = ['view_hostingview']
|
||||
|
|
|
|||