Merge pull request #491 from tiwariav/task/3786/hosting_invoice_page
Task/3786 order-details/invoice page redesign
This commit is contained in:
		
				commit
				
					
						2385c108e1
					
				
			
		
					 13 changed files with 790 additions and 230 deletions
				
			
		|  | @ -8,7 +8,7 @@ msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2017-09-20 20:23+0000\n" | "POT-Creation-Date: 2017-09-23 19:00+0530\n" | ||||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | "Language-Team: LANGUAGE <LL@li.org>\n" | ||||||
|  | @ -321,10 +321,14 @@ msgstr "Als gelesen markieren" | ||||||
| msgid "All notifications" | msgid "All notifications" | ||||||
| msgstr "Alle Benachrichtigungen" | msgstr "Alle Benachrichtigungen" | ||||||
| 
 | 
 | ||||||
| msgid "Date" | #, python-format | ||||||
| msgstr "Datum" | msgid "%(page_header_text)s" | ||||||
|  | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "Status:" | msgid "Invoice Date" | ||||||
|  | msgstr "Rechnung Datum" | ||||||
|  | 
 | ||||||
|  | msgid "Status" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "Approved" | msgid "Approved" | ||||||
|  | @ -333,10 +337,10 @@ msgstr "Akzeptiert" | ||||||
| msgid "Declined" | msgid "Declined" | ||||||
| msgstr "Abgelehnt" | msgstr "Abgelehnt" | ||||||
| 
 | 
 | ||||||
| msgid "Billed To:" | msgid "Billed to" | ||||||
| msgstr "Rechnungsadresse" | msgstr "Rechnungsadresse" | ||||||
| 
 | 
 | ||||||
| msgid "Payment Method:" | msgid "Payment method" | ||||||
| msgstr "Bezahlmethode" | msgstr "Bezahlmethode" | ||||||
| 
 | 
 | ||||||
| msgid "ending in" | msgid "ending in" | ||||||
|  | @ -345,6 +349,9 @@ msgstr "endend in" | ||||||
| msgid "Order summary" | msgid "Order summary" | ||||||
| msgstr "Bestellungsübersicht" | msgstr "Bestellungsübersicht" | ||||||
| 
 | 
 | ||||||
|  | msgid "Product" | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "Cores" | msgid "Cores" | ||||||
| msgstr "Prozessorkerne" | msgstr "Prozessorkerne" | ||||||
| 
 | 
 | ||||||
|  | @ -354,15 +361,9 @@ msgstr "Arbeitsspeicher" | ||||||
| msgid "Disk space" | msgid "Disk space" | ||||||
| msgstr "Festplattenkapazität" | msgstr "Festplattenkapazität" | ||||||
| 
 | 
 | ||||||
| msgid "Configuration" |  | ||||||
| msgstr "Konfiguration" |  | ||||||
| 
 |  | ||||||
| msgid "Total" | msgid "Total" | ||||||
| msgstr "Gesamt" | msgstr "Gesamt" | ||||||
| 
 | 
 | ||||||
| msgid "Month" |  | ||||||
| msgstr "Monat" |  | ||||||
| 
 |  | ||||||
| #, python-format | #, python-format | ||||||
| msgid "" | msgid "" | ||||||
| "By clicking \"Place order\" this plan will charge your credit card account " | "By clicking \"Place order\" this plan will charge your credit card account " | ||||||
|  | @ -372,8 +373,10 @@ msgstr "" | ||||||
| "pro Monat belastet" | "pro Monat belastet" | ||||||
| 
 | 
 | ||||||
| msgid "Place order" | msgid "Place order" | ||||||
| msgstr "Bestelle" | msgstr "Bestellen" | ||||||
| 
 | 
 | ||||||
|  | msgid "BACK TO LIST" | ||||||
|  | msgstr "ZURÜCK ZUR LISTE" | ||||||
| 
 | 
 | ||||||
| msgid "Processing..." | msgid "Processing..." | ||||||
| msgstr "Abarbeitung..." | msgstr "Abarbeitung..." | ||||||
|  | @ -387,14 +390,14 @@ msgstr "Ein Problem ist aufgetreten. Bitte versuche es später noch einmal." | ||||||
| msgid "Order Nr." | msgid "Order Nr." | ||||||
| msgstr "Bestellung Nr." | msgstr "Bestellung Nr." | ||||||
| 
 | 
 | ||||||
|  | msgid "Date" | ||||||
|  | msgstr "Datum" | ||||||
|  | 
 | ||||||
| msgid "Amount" | msgid "Amount" | ||||||
| msgstr "Betrag" | msgstr "Betrag" | ||||||
| 
 | 
 | ||||||
| msgid "Status" |  | ||||||
| msgstr "" |  | ||||||
| 
 |  | ||||||
| msgid "See Invoice" | msgid "See Invoice" | ||||||
| msgstr "Rechnung" | msgstr "Siehe Rechnung" | ||||||
| 
 | 
 | ||||||
| msgid "Page" | msgid "Page" | ||||||
| msgstr "" | msgstr "" | ||||||
|  | @ -405,9 +408,15 @@ msgstr "" | ||||||
| msgid "Your Order" | msgid "Your Order" | ||||||
| msgstr "Deine Bestellung" | msgstr "Deine Bestellung" | ||||||
| 
 | 
 | ||||||
|  | msgid "Configuration" | ||||||
|  | msgstr "Konfiguration" | ||||||
|  | 
 | ||||||
| msgid "including VAT" | msgid "including VAT" | ||||||
| msgstr "inkl. Mehrwertsteuer" | msgstr "inkl. Mehrwertsteuer" | ||||||
| 
 | 
 | ||||||
|  | msgid "Month" | ||||||
|  | msgstr "Monat" | ||||||
|  | 
 | ||||||
| msgid "Billing Address" | msgid "Billing Address" | ||||||
| msgstr "Rechnungsadresse" | msgstr "Rechnungsadresse" | ||||||
| 
 | 
 | ||||||
|  | @ -573,9 +582,6 @@ msgstr "Wir sind hier, um Dir zu helfen!" | ||||||
| msgid "CONTACT" | msgid "CONTACT" | ||||||
| msgstr "KONTACT" | msgstr "KONTACT" | ||||||
| 
 | 
 | ||||||
| msgid "BACK TO LIST" |  | ||||||
| msgstr "ZURÜCK ZUR LISTE" |  | ||||||
| 
 |  | ||||||
| msgid "Terminate your Virtual Machine" | msgid "Terminate your Virtual Machine" | ||||||
| msgstr "Deine Virtuelle Maschine beenden" | msgstr "Deine Virtuelle Maschine beenden" | ||||||
| 
 | 
 | ||||||
|  | @ -639,6 +645,15 @@ msgstr "Ungültige Kreditkarte" | ||||||
| msgid "Confirm Order" | msgid "Confirm Order" | ||||||
| msgstr "Bestellung Bestätigen" | msgstr "Bestellung Bestätigen" | ||||||
| 
 | 
 | ||||||
|  | msgid "" | ||||||
|  | "The VM you are looking for is unavailable at the moment. Please contact Data " | ||||||
|  | "Center Light support." | ||||||
|  | msgstr "Kontaktiere den Data Center Light Support." | ||||||
|  | 
 | ||||||
|  | msgid "In order to create a VM, you need to create/upload your SSH KEY first." | ||||||
|  | msgstr "" | ||||||
|  | "Um eine VM zu erstellen musst du zuerst einen SSH-Key erstellen / hochladen." | ||||||
|  | 
 | ||||||
| msgid "Thank you for the order." | msgid "Thank you for the order." | ||||||
| msgstr "Danke für Deine Bestellung." | msgstr "Danke für Deine Bestellung." | ||||||
| 
 | 
 | ||||||
|  | @ -646,12 +661,8 @@ msgid "" | ||||||
| "Your VM will be up and running in a few moments. We will send you a " | "Your VM will be up and running in a few moments. We will send you a " | ||||||
| "confirmation email as soon as it is ready." | "confirmation email as soon as it is ready." | ||||||
| msgstr "" | msgstr "" | ||||||
| "Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, " | "Deine VM ist gleich bereit. Wir senden Dir eine Bestätigungsemail, sobald Du " | ||||||
| "sobald Du auf sie zugreifen kannst." | "auf sie zugreifen kannst." | ||||||
| 
 |  | ||||||
| msgid "In order to create a VM, you need to create/upload your SSH KEY first." |  | ||||||
| msgstr "" |  | ||||||
| "Um eine VM zu erstellen musst du zuerst einen SSH-Key erstellen / hochladen." |  | ||||||
| 
 | 
 | ||||||
| msgid "" | msgid "" | ||||||
| "We could not find the requested VM. Please                            " | "We could not find the requested VM. Please                            " | ||||||
|  |  | ||||||
|  | @ -356,3 +356,19 @@ | ||||||
| .no-cards a { | .no-cards a { | ||||||
|   color: #7ca3d0; |   color: #7ca3d0; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .btn-plain { | ||||||
|  |   background: transparent; | ||||||
|  |   border: none; | ||||||
|  |   fill: #595959; | ||||||
|  |   color: #595959; | ||||||
|  |   outline: none; | ||||||
|  | } | ||||||
|  | .btn-plain:hover, | ||||||
|  | .btn-plain:focus, | ||||||
|  | .btn-plain:active, | ||||||
|  | .btn-plain:active:focus { | ||||||
|  |   outline: none; | ||||||
|  |   color: #999; | ||||||
|  |   fill: #999; | ||||||
|  | } | ||||||
|  | @ -580,9 +580,9 @@ a.unlink:hover { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .dcl-place-order-text{ | .dcl-place-order-text{ | ||||||
|    font-size: 13px; |    /* font-size: 13px; */ | ||||||
|    color: #808080; |    color: #808080; | ||||||
|    margin-bottom: 15px; |    /* margin-bottom: 15px; */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .dcl-order-table-total .tbl-total { | .dcl-order-table-total .tbl-total { | ||||||
|  |  | ||||||
|  | @ -1,4 +1,13 @@ | ||||||
| .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) { | ||||||
|  |     padding: 30px; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| .order-detail-container .invoice-title h2, .invoice-title h3 { | .order-detail-container .invoice-title h2, .invoice-title h3 { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
|  | @ -15,3 +24,67 @@ | ||||||
| .order-detail-container .table > tbody > tr > .thick-line { | .order-detail-container .table > tbody > tr > .thick-line { | ||||||
|     border-top: 2px solid; |     border-top: 2px solid; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container .dashboard-title-thin { | ||||||
|  |     margin-top: 0; | ||||||
|  |     margin-left: -3px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container .dashboard-title-thin .un-icon { | ||||||
|  |     margin-top: -6px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container .dashboard-container-head { | ||||||
|  |     position: relative; | ||||||
|  |     padding: 0; | ||||||
|  |     margin-bottom: 38px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container .dashboard-container-options { | ||||||
|  |     position: absolute; | ||||||
|  |     top: 10px; | ||||||
|  |     right: 0; | ||||||
|  | } | ||||||
|  | .order-detail-container .dashboard-container-options .svg-img { | ||||||
|  |     height: 22px; | ||||||
|  |     width: 22px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container .order-details { | ||||||
|  |     margin-bottom: 30px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container .order-details strong { | ||||||
|  |     color: #595959; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container h4 { | ||||||
|  |     font-size: 16px; | ||||||
|  |     font-weight: bold; | ||||||
|  |     margin-bottom: 10px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container p { | ||||||
|  |     margin-bottom: 5px; | ||||||
|  |     color: #595959; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .order-detail-container hr { | ||||||
|  |     margin: 15px 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @media (max-width: 767px) { | ||||||
|  |     .order-confirm-btn { | ||||||
|  |         text-align: center; | ||||||
|  |         margin-top: 10px; | ||||||
|  |     } | ||||||
|  |     .order-detail-container .dashboard-container-options { | ||||||
|  |         position: absolute; | ||||||
|  |         top: 4px; | ||||||
|  |         right: -4px; | ||||||
|  |     } | ||||||
|  |     .order-detail-container .dashboard-container-options .svg-img { | ||||||
|  |         height: 16px; | ||||||
|  |         width: 16px; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								hosting/static/hosting/img/icon-pdf.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								hosting/static/hosting/img/icon-pdf.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <svg width="492px" height="649px" viewBox="0 0 492 649" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||||||
|  |     <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch --> | ||||||
|  |     <title>icon-pdf</title> | ||||||
|  |     <desc>Created with Sketch.</desc> | ||||||
|  |     <defs></defs> | ||||||
|  |     <g id="Page-1" stroke="none" stroke-width="1" fill-rule="evenodd"> | ||||||
|  |         <g id="icon-pdf" fill-rule="nonzero"> | ||||||
|  |             <g id="Group" transform="translate(93.000000, 269.000000)"> | ||||||
|  |                 <path d="M98,47.8 C98,54.8 97,61.7 95.1,66.6 C93.1,72.5 90.1,76.5 86.2,80.5 C82.2,84.5 76.3,87.4 70.4,89.4 C64.5,91.4 55.6,92.3 46.6,92.3 L34.7,92.3 L34.7,134 L0,134 L0,0.3 L45.5,0.3 C54.4,0.3 62.4,1.3 69.3,3.2 C76.2,5.2 81.2,8.2 85.1,12.1 C89.1,16.1 92.1,21 94,27 C96.9,32 98,38.9 98,47.8 Z M61.3,46.8 C61.3,42.8 61.3,39.9 60.3,37.9 C60.3,35.9 59.3,33.9 57.4,32 C56.4,31 54.5,30 52.4,29.1 C50.4,29.1 47.4,28.1 44.5,28.1 L34.6,28.1 L34.6,63.7 L45.5,63.7 C48.4,63.7 50.4,63.7 52.5,62.7 C54.5,61.7 56.5,61.7 57.5,59.8 C58.5,57.8 59.5,56.9 60.4,54.8 C61.3,53.8 61.3,50.8 61.3,46.8 Z" id="Shape"></path> | ||||||
|  |                 <path d="M214.8,66.6 C214.8,78.5 213.8,89.3 210.8,97.3 C208.8,106.2 204.9,113.1 199.9,118.1 C195,123.1 189,127 182.1,130 C175.2,132 167.3,134 157.3,134 L108.8,134 L108.8,0.3 L156.3,0.3 C166.2,0.3 175.1,1.3 182,4.3 C188.9,7.2 194.9,10.2 199.8,16.2 C204.8,21.2 207.7,28.1 209.7,37 C213.8,44.8 214.8,54.7 214.8,66.6 Z M178.1,65.6 C178.1,58.7 178.1,52.7 177.1,47.8 C176.1,42.8 175.1,39.9 174.2,36.9 C172.2,34 170.2,32.9 168.3,31.9 C165.4,30.9 162.4,30.9 158.4,30.9 L145.6,30.9 L145.6,103.2 L158.4,103.2 C162.4,103.2 165.4,103.2 168.3,102.2 C171.2,101.2 173.3,99.3 174.2,97.2 C176.2,94.3 177.1,91.3 178.2,86.3 C178.1,80.5 178.1,74.5 178.1,65.6 Z" id="Shape"></path> | ||||||
|  |                 <polygon id="Shape" points="264.3 32 264.3 55.8 304.9 55.8 304.9 85.5 264.3 85.5 264.3 135 229.7 135 229.7 0.3 312.9 0.3 313.9 31 264.4 31 264.4 32"></polygon> | ||||||
|  |             </g> | ||||||
|  |             <path d="M491.3,649 L0.7,649 L0.7,0 L346.1,0 L491.3,145.2 L491.3,649 L491.3,649 Z M44.7,605 L448.4,605 L448.4,162.8 L327.4,42.9 L44.7,42.9 L44.7,605 Z" id="Shape"></path> | ||||||
|  |             <polygon id="Shape" points="469.3 176 315.3 176 315.3 20.9 359.3 20.9 359.3 132 469.3 132"></polygon> | ||||||
|  |         </g> | ||||||
|  |     </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.3 KiB | 
							
								
								
									
										17
									
								
								hosting/static/hosting/img/icon-print.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								hosting/static/hosting/img/icon-print.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <svg width="612px" height="612px" viewBox="0 0 612 612" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||||||
|  |     <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch --> | ||||||
|  |     <title>54471</title> | ||||||
|  |     <desc>Created with Sketch.</desc> | ||||||
|  |     <defs></defs> | ||||||
|  |     <g id="Page-1" stroke="none" stroke-width="1" fill-rule="evenodd"> | ||||||
|  |         <g id="54471" fill-rule="nonzero"> | ||||||
|  |             <path d="M0,225.633 L0,386.367 C0,417.272 30.6,417.272 30.6,417.272 L83.454,417.272 L83.454,389.454 L27.818,389.454 L27.818,222.545 L584.181,222.545 L584.181,389.454 L528.545,389.454 L528.545,417.272 L581.4,417.272 C581.4,417.272 612,417.272 612,386.367 L612,225.633 C612,225.633 612,194.727 581.4,194.727 L30.6,194.727 C0,194.728 0,225.633 0,225.633 Z" id="Shape"></path> | ||||||
|  |             <polygon id="Shape" points="500.728 166.909 500.728 0 111.273 0 111.273 166.909 139.091 166.909 139.091 27.818 472.909 27.818 472.909 166.909"></polygon> | ||||||
|  |             <path d="M528.546,292.091 C528.546,278.182 514.358,278.182 514.358,278.182 L97.642,278.182 C97.642,278.182 83.455,278.182 83.455,292.091 C83.455,306 97.642,306 97.642,306 L514.359,306 C514.358,306 528.546,306 528.546,292.091 Z" id="Shape"></path> | ||||||
|  |             <rect id="Rectangle-path" x="166.909" y="500.728" width="278.182" height="27.818"></rect> | ||||||
|  |             <path d="M500.728,612 L500.728,389.454 L111.273,389.454 L111.273,612 L500.728,612 Z M139.091,417.272 L472.909,417.272 L472.909,584.181 L139.091,584.181 L139.091,417.272 Z" id="Shape"></path> | ||||||
|  |             <rect id="Rectangle-path" x="166.909" y="445.091" width="278.182" height="27.818"></rect> | ||||||
|  |         </g> | ||||||
|  |     </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										387
									
								
								hosting/static/hosting/js/html2pdf.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										387
									
								
								hosting/static/hosting/js/html2pdf.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,387 @@ | ||||||
|  | /** | ||||||
|  |  * @license | ||||||
|  |  * | ||||||
|  |  * MIT License | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2017 Erik Koopmans | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in all | ||||||
|  |  * copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Generate a PDF from an HTML element or string using html2canvas and jsPDF. | ||||||
|  |  * | ||||||
|  |  * @param {Element|string} source The source element or HTML string. | ||||||
|  |  * @param {Object=} opt An object of optional settings: 'margin', 'filename', | ||||||
|  |  *    'image' ('type' and 'quality'), and 'html2canvas' / 'jspdf', which are | ||||||
|  |  *    sent as settings to their corresponding functions. | ||||||
|  |  */ | ||||||
|  | var html2pdf = (function(html2canvas, jsPDF) { | ||||||
|  | 
 | ||||||
|  |   /* ---------- MAIN FUNCTION ---------- */ | ||||||
|  | 
 | ||||||
|  |   var html2pdf = function(source, opt) { | ||||||
|  |     // Handle input.
 | ||||||
|  |     opt = objType(opt) === 'object' ? opt : {}; | ||||||
|  |     var source = html2pdf.parseInput(source, opt); | ||||||
|  | 
 | ||||||
|  |     // Determine the PDF page size.
 | ||||||
|  |     var pageSize = jsPDF.getPageSize(opt.jsPDF); | ||||||
|  |     pageSize.inner = { | ||||||
|  |       width:  pageSize.width - opt.margin[1] - opt.margin[3], | ||||||
|  |       height: pageSize.height - opt.margin[0] - opt.margin[2] | ||||||
|  |     }; | ||||||
|  |     pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width; | ||||||
|  | 
 | ||||||
|  |     // Copy the source element into a PDF-styled container div.
 | ||||||
|  |     var container = html2pdf.makeContainer(source, pageSize); | ||||||
|  |     var overlay = container.parentElement; | ||||||
|  | 
 | ||||||
|  |     // Get the locations of all hyperlinks.
 | ||||||
|  |     if (opt.enableLinks) { | ||||||
|  |       // Find all anchor tags and get the container's bounds for reference.
 | ||||||
|  |       opt.links = []; | ||||||
|  |       var links = container.querySelectorAll('a'); | ||||||
|  |       var containerRect = unitConvert(container.getBoundingClientRect(), pageSize.k); | ||||||
|  | 
 | ||||||
|  |       // Treat each client rect as a separate link (for text-wrapping).
 | ||||||
|  |       Array.prototype.forEach.call(links, function(link) { | ||||||
|  |         var clientRects = link.getClientRects(); | ||||||
|  |         for (var i=0; i<clientRects.length; i++) { | ||||||
|  |           var clientRect = unitConvert(clientRects[i], pageSize.k); | ||||||
|  |           clientRect.left -= containerRect.left; | ||||||
|  |           clientRect.top -= containerRect.top; | ||||||
|  |           opt.links.push({ el: link, clientRect: clientRect }); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Render the canvas and pass the result to makePDF.
 | ||||||
|  |     var onRendered = opt.html2canvas.onrendered || function() {}; | ||||||
|  |     opt.html2canvas.onrendered = function(canvas) { | ||||||
|  |       onRendered(canvas); | ||||||
|  |       document.body.removeChild(overlay); | ||||||
|  |       html2pdf.makePDF(canvas, pageSize, opt); | ||||||
|  |     } | ||||||
|  |     html2canvas(container, opt.html2canvas); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   html2pdf.parseInput = function(source, opt) { | ||||||
|  |     // Parse the opt object.
 | ||||||
|  |     opt.jsPDF = opt.jsPDF || {}; | ||||||
|  |     opt.html2canvas = opt.html2canvas || {}; | ||||||
|  |     opt.filename = opt.filename && objType(opt.filename) === 'string' ? opt.filename : 'file.pdf'; | ||||||
|  |     opt.enableLinks = opt.hasOwnProperty('enableLinks') ? opt.enableLinks : true; | ||||||
|  |     opt.image = opt.image || {}; | ||||||
|  |     opt.image.type = opt.image.type || 'jpeg'; | ||||||
|  |     opt.image.quality = opt.image.quality || 0.95; | ||||||
|  | 
 | ||||||
|  |     // Parse the margin property of the opt object.
 | ||||||
|  |     switch (objType(opt.margin)) { | ||||||
|  |       case 'undefined': | ||||||
|  |         opt.margin = 0; | ||||||
|  |       case 'number': | ||||||
|  |         opt.margin = [opt.margin, opt.margin, opt.margin, opt.margin]; | ||||||
|  |         break; | ||||||
|  |       case 'array': | ||||||
|  |         if (opt.margin.length === 2) { | ||||||
|  |           opt.margin = [opt.margin[0], opt.margin[1], opt.margin[0], opt.margin[1]]; | ||||||
|  |         } | ||||||
|  |         if (opt.margin.length === 4) { | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       default: | ||||||
|  |         throw 'Invalid margin array.'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Parse the source element/string.
 | ||||||
|  |     if (!source) { | ||||||
|  |       throw 'Missing source element or string.'; | ||||||
|  |     } else if (objType(source) === 'string') { | ||||||
|  |       source = createElement('div', { innerHTML: source }); | ||||||
|  |     } else if (objType(source) === 'element') { | ||||||
|  |       source = cloneNode(source, opt.html2canvas.javascriptEnabled); | ||||||
|  |     } else { | ||||||
|  |       throw 'Invalid source - please specify an HTML Element or string.'; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Return the parsed input (opt is modified in-place, no need to return).
 | ||||||
|  |     return source; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   html2pdf.makeContainer = function(source, pageSize) { | ||||||
|  |     // Define the CSS styles for the container and its overlay parent.
 | ||||||
|  |     var overlayCSS = { | ||||||
|  |       position: 'fixed', overflow: 'hidden', zIndex: 1000, | ||||||
|  |       left: 0, right: 0, bottom: 0, top: 0, | ||||||
|  |       backgroundColor: 'rgba(0,0,0,0.8)' | ||||||
|  |     }; | ||||||
|  |     var containerCSS = { | ||||||
|  |       position: 'absolute', width: pageSize.inner.width + pageSize.unit, | ||||||
|  |       left: 0, right: 0, top: 0, height: 'auto', margin: 'auto', | ||||||
|  |       backgroundColor: 'white' | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // Set the overlay to hidden (could be changed in the future to provide a print preview).
 | ||||||
|  |     overlayCSS.opacity = 0; | ||||||
|  | 
 | ||||||
|  |     // Create and attach the elements.
 | ||||||
|  |     var overlay = createElement('div',   { className: 'html2pdf__overlay', style: overlayCSS }); | ||||||
|  |     var container = createElement('div', { className: 'html2pdf__container', style: containerCSS }); | ||||||
|  |     container.appendChild(source); | ||||||
|  |     overlay.appendChild(container); | ||||||
|  |     document.body.appendChild(overlay); | ||||||
|  | 
 | ||||||
|  |     // Enable page-breaks.
 | ||||||
|  |     var pageBreaks = source.querySelectorAll('.html2pdf__page-break'); | ||||||
|  |     var pxPageHeight = pageSize.inner.height * pageSize.k / 72 * 96; | ||||||
|  |     Array.prototype.forEach.call(pageBreaks, function(el) { | ||||||
|  |       el.style.display = 'block'; | ||||||
|  |       var clientRect = el.getBoundingClientRect(); | ||||||
|  |       el.style.height = pxPageHeight - (clientRect.top % pxPageHeight) + 'px'; | ||||||
|  |     }, this); | ||||||
|  | 
 | ||||||
|  |     // Return the container.
 | ||||||
|  |     return container; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   html2pdf.makePDF = function(canvas, pageSize, opt) { | ||||||
|  |     // Calculate the number of pages.
 | ||||||
|  |     var ctx = canvas.getContext('2d'); | ||||||
|  |     var pxFullHeight = canvas.height; | ||||||
|  |     var pxPageHeight = Math.floor(canvas.width * pageSize.inner.ratio); | ||||||
|  |     var nPages = Math.ceil(pxFullHeight / pxPageHeight); | ||||||
|  | 
 | ||||||
|  |     // Create a one-page canvas to split up the full image.
 | ||||||
|  |     var pageCanvas = document.createElement('canvas'); | ||||||
|  |     var pageCtx = pageCanvas.getContext('2d'); | ||||||
|  |     var pageHeight = pageSize.inner.height; | ||||||
|  |     pageCanvas.width = canvas.width; | ||||||
|  |     pageCanvas.height = pxPageHeight; | ||||||
|  | 
 | ||||||
|  |     // Initialize the PDF.
 | ||||||
|  |     var pdf = new jsPDF(opt.jsPDF); | ||||||
|  | 
 | ||||||
|  |     for (var page=0; page<nPages; page++) { | ||||||
|  |       // Trim the final page to reduce file size.
 | ||||||
|  |       if (page === nPages-1) { | ||||||
|  |         pageCanvas.height = pxFullHeight % pxPageHeight; | ||||||
|  |         pageHeight = pageCanvas.height * pageSize.inner.width / pageCanvas.width; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Display the page.
 | ||||||
|  |       var w = pageCanvas.width; | ||||||
|  |       var h = pageCanvas.height; | ||||||
|  |       pageCtx.fillStyle = 'white'; | ||||||
|  |       pageCtx.fillRect(0, 0, w, h); | ||||||
|  |       pageCtx.drawImage(canvas, 0, page*pxPageHeight, w, h, 0, 0, w, h); | ||||||
|  | 
 | ||||||
|  |       // Add the page to the PDF.
 | ||||||
|  |       if (page)  pdf.addPage(); | ||||||
|  |       var imgData = pageCanvas.toDataURL('image/' + opt.image.type, opt.image.quality); | ||||||
|  |       pdf.addImage(imgData, opt.image.type, opt.margin[1], opt.margin[0], | ||||||
|  |                    pageSize.inner.width, pageHeight); | ||||||
|  | 
 | ||||||
|  |       // Add hyperlinks.
 | ||||||
|  |       if (opt.enableLinks) { | ||||||
|  |         var pageTop = page * pageSize.inner.height; | ||||||
|  |         opt.links.forEach(function(link) { | ||||||
|  |           if (link.clientRect.top > pageTop && link.clientRect.top < pageTop + pageSize.inner.height) { | ||||||
|  |             var left = opt.margin[1] + link.clientRect.left; | ||||||
|  |             var top = opt.margin[0] + link.clientRect.top - pageTop; | ||||||
|  |             pdf.link(left, top, link.clientRect.width, link.clientRect.height, { url: link.el.href }); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Finish the PDF.
 | ||||||
|  |     pdf.save( opt.filename ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   /* ---------- UTILS ---------- */ | ||||||
|  | 
 | ||||||
|  |   // Determine the type of a variable/object.
 | ||||||
|  |   var objType = function(obj) { | ||||||
|  |     if (typeof obj === 'undefined')                             return 'undefined'; | ||||||
|  |     else if (typeof obj === 'string' || obj instanceof String)  return 'string'; | ||||||
|  |     else if (typeof obj === 'number' || obj instanceof Number)  return 'number'; | ||||||
|  |     else if (!!obj && obj.constructor === Array)                return 'array'; | ||||||
|  |     else if (obj && obj.nodeType === 1)                         return 'element'; | ||||||
|  |     else if (typeof obj === 'object')                           return 'object'; | ||||||
|  |     else                                                        return 'unknown'; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Create an HTML element with optional className, innerHTML, and style.
 | ||||||
|  |   var createElement = function(tagName, opt) { | ||||||
|  |     var el = document.createElement(tagName); | ||||||
|  |     if (opt.className)  el.className = opt.className; | ||||||
|  |     if (opt.innerHTML) { | ||||||
|  |       el.innerHTML = opt.innerHTML; | ||||||
|  |       var scripts = el.getElementsByTagName('script'); | ||||||
|  |       for (var i = scripts.length; i-- > 0; null) { | ||||||
|  |         scripts[i].parentNode.removeChild(scripts[i]); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     for (var key in opt.style) { | ||||||
|  |       el.style[key] = opt.style[key]; | ||||||
|  |     } | ||||||
|  |     return el; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Deep-clone a node and preserve contents/properties.
 | ||||||
|  |   var cloneNode = function(node, javascriptEnabled) { | ||||||
|  |     // Recursively clone the node.
 | ||||||
|  |     var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false); | ||||||
|  |     for (var child = node.firstChild; child; child = child.nextSibling) { | ||||||
|  |       if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') { | ||||||
|  |         clone.appendChild(cloneNode(child, javascriptEnabled)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (node.nodeType === 1) { | ||||||
|  |       // Preserve contents/properties of special nodes.
 | ||||||
|  |       if (node.nodeName === 'CANVAS') { | ||||||
|  |         clone.width = node.width; | ||||||
|  |         clone.height = node.height; | ||||||
|  |         clone.getContext('2d').drawImage(node, 0, 0); | ||||||
|  |       } else if (node.nodeName === 'TEXTAREA' || node.nodeName === 'SELECT') { | ||||||
|  |         clone.value = node.value; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Preserve the node's scroll position when it loads.
 | ||||||
|  |       clone.addEventListener('load', function() { | ||||||
|  |         clone.scrollTop = node.scrollTop; | ||||||
|  |         clone.scrollLeft = node.scrollLeft; | ||||||
|  |       }, true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Return the cloned node.
 | ||||||
|  |     return clone; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Convert units using the conversion value 'k' from jsPDF.
 | ||||||
|  |   var unitConvert = function(obj, k) { | ||||||
|  |     var newObj = {}; | ||||||
|  |     for (var key in obj) { | ||||||
|  |       newObj[key] = obj[key] * 72 / 96 / k; | ||||||
|  |     } | ||||||
|  |     return newObj; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Get dimensions of a PDF page, as determined by jsPDF.
 | ||||||
|  |   jsPDF.getPageSize = function(orientation, unit, format) { | ||||||
|  |     // Decode options object
 | ||||||
|  |     if (typeof orientation === 'object') { | ||||||
|  |       var options = orientation; | ||||||
|  |       orientation = options.orientation; | ||||||
|  |       unit = options.unit || unit; | ||||||
|  |       format = options.format || format; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Default options
 | ||||||
|  |     unit        = unit || 'mm'; | ||||||
|  |     format      = format || 'a4'; | ||||||
|  |     orientation = ('' + (orientation || 'P')).toLowerCase(); | ||||||
|  |     var format_as_string = ('' + format).toLowerCase(); | ||||||
|  | 
 | ||||||
|  |     // Size in pt of various paper formats
 | ||||||
|  |     pageFormats = { | ||||||
|  |       'a0'  : [2383.94, 3370.39], 'a1'  : [1683.78, 2383.94], | ||||||
|  |       'a2'  : [1190.55, 1683.78], 'a3'  : [ 841.89, 1190.55], | ||||||
|  |       'a4'  : [ 595.28,  841.89], 'a5'  : [ 419.53,  595.28], | ||||||
|  |       'a6'  : [ 297.64,  419.53], 'a7'  : [ 209.76,  297.64], | ||||||
|  |       'a8'  : [ 147.40,  209.76], 'a9'  : [ 104.88,  147.40], | ||||||
|  |       'a10' : [  73.70,  104.88], 'b0'  : [2834.65, 4008.19], | ||||||
|  |       'b1'  : [2004.09, 2834.65], 'b2'  : [1417.32, 2004.09], | ||||||
|  |       'b3'  : [1000.63, 1417.32], 'b4'  : [ 708.66, 1000.63], | ||||||
|  |       'b5'  : [ 498.90,  708.66], 'b6'  : [ 354.33,  498.90], | ||||||
|  |       'b7'  : [ 249.45,  354.33], 'b8'  : [ 175.75,  249.45], | ||||||
|  |       'b9'  : [ 124.72,  175.75], 'b10' : [  87.87,  124.72], | ||||||
|  |       'c0'  : [2599.37, 3676.54], 'c1'  : [1836.85, 2599.37], | ||||||
|  |       'c2'  : [1298.27, 1836.85], 'c3'  : [ 918.43, 1298.27], | ||||||
|  |       'c4'  : [ 649.13,  918.43], 'c5'  : [ 459.21,  649.13], | ||||||
|  |       'c6'  : [ 323.15,  459.21], 'c7'  : [ 229.61,  323.15], | ||||||
|  |       'c8'  : [ 161.57,  229.61], 'c9'  : [ 113.39,  161.57], | ||||||
|  |       'c10' : [  79.37,  113.39], 'dl'  : [ 311.81,  623.62], | ||||||
|  |       'letter'            : [612,   792], | ||||||
|  |       'government-letter' : [576,   756], | ||||||
|  |       'legal'             : [612,  1008], | ||||||
|  |       'junior-legal'      : [576,   360], | ||||||
|  |       'ledger'            : [1224,  792], | ||||||
|  |       'tabloid'           : [792,  1224], | ||||||
|  |       'credit-card'       : [153,   243] | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // Unit conversion
 | ||||||
|  |     switch (unit) { | ||||||
|  |       case 'pt':  k = 1;          break; | ||||||
|  |       case 'mm':  k = 72 / 25.4;  break; | ||||||
|  |       case 'cm':  k = 72 / 2.54;  break; | ||||||
|  |       case 'in':  k = 72;         break; | ||||||
|  |       case 'px':  k = 72 / 96;    break; | ||||||
|  |       case 'pc':  k = 12;         break; | ||||||
|  |       case 'em':  k = 12;         break; | ||||||
|  |       case 'ex':  k = 6;          break; | ||||||
|  |       default: | ||||||
|  |         throw ('Invalid unit: ' + unit); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Dimensions are stored as user units and converted to points on output
 | ||||||
|  |     if (pageFormats.hasOwnProperty(format_as_string)) { | ||||||
|  |       pageHeight = pageFormats[format_as_string][1] / k; | ||||||
|  |       pageWidth = pageFormats[format_as_string][0] / k; | ||||||
|  |     } else { | ||||||
|  |       try { | ||||||
|  |         pageHeight = format[1]; | ||||||
|  |         pageWidth = format[0]; | ||||||
|  |       } catch (err) { | ||||||
|  |         throw new Error('Invalid format: ' + format); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Handle page orientation
 | ||||||
|  |     if (orientation === 'p' || orientation === 'portrait') { | ||||||
|  |       orientation = 'p'; | ||||||
|  |       if (pageWidth > pageHeight) { | ||||||
|  |         tmp = pageWidth; | ||||||
|  |         pageWidth = pageHeight; | ||||||
|  |         pageHeight = tmp; | ||||||
|  |       } | ||||||
|  |     } else if (orientation === 'l' || orientation === 'landscape') { | ||||||
|  |       orientation = 'l'; | ||||||
|  |       if (pageHeight > pageWidth) { | ||||||
|  |         tmp = pageWidth; | ||||||
|  |         pageWidth = pageHeight; | ||||||
|  |         pageHeight = tmp; | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       throw('Invalid orientation: ' + orientation); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Return information (k is the unit conversion ratio from pts)
 | ||||||
|  |     var info = { 'width': pageWidth, 'height': pageHeight, 'unit': unit, 'k': k }; | ||||||
|  |     return info; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   // Expose the html2pdf function.
 | ||||||
|  |   return html2pdf; | ||||||
|  | }(html2canvas, jsPDF)); | ||||||
							
								
								
									
										15
									
								
								hosting/static/hosting/js/order.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								hosting/static/hosting/js/order.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | $(document).ready(function() { | ||||||
|  |     $('.btn-pdf').click(function(e) { | ||||||
|  |         e.preventDefault(); | ||||||
|  |         var $target = $($(this).attr('data-target')) || $('body'); | ||||||
|  |         var fileName = $target.attr('id') + '.pdf'; | ||||||
|  |         html2pdf($target[0], { | ||||||
|  |             filename: fileName, | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |     $('.btn-print').click(function(e) { | ||||||
|  |         e.preventDefault(); | ||||||
|  |         console.log('a'); | ||||||
|  |         window.print(); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| $(document).ready(function () { | $(document).ready(function () { | ||||||
|  |     $('.modal-text').removeClass('hide'); | ||||||
|     var create_vm_form = $('#virtual_machine_create_form'); |     var create_vm_form = $('#virtual_machine_create_form'); | ||||||
|     create_vm_form.submit(function () { |     create_vm_form.submit(function () { | ||||||
|         $('#btn-create-vm').prop('disabled', true); |         $('#btn-create-vm').prop('disabled', true); | ||||||
|  | @ -22,6 +23,7 @@ $(document).ready(function () { | ||||||
|                     fa_icon = $('.modal-icon > .fa'); |                     fa_icon = $('.modal-icon > .fa'); | ||||||
|                     fa_icon.attr('class', 'fa fa-times'); |                     fa_icon.attr('class', 'fa fa-times'); | ||||||
|                     $('.modal-header > .close').attr('class', 'close'); |                     $('.modal-header > .close').attr('class', 'close'); | ||||||
|  |                     $('.modal-text').addClass('hide'); | ||||||
|                     if (typeof(create_vm_error_message) !== 'undefined') { |                     if (typeof(create_vm_error_message) !== 'undefined') { | ||||||
|                         $('#createvm-modal-title').text(create_vm_error_message); |                         $('#createvm-modal-title').text(create_vm_error_message); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -94,6 +94,13 @@ | ||||||
|     <!-- Init JavaScript --> |     <!-- Init JavaScript --> | ||||||
|     <script src="{% static 'hosting/js/initial.js' %}"></script> |     <script src="{% static 'hosting/js/initial.js' %}"></script> | ||||||
| 
 | 
 | ||||||
|  |     {% block js_extra %} | ||||||
|  |         {% comment %} | ||||||
|  |             this block is above some files, because on stripe error scripts below the stripe | ||||||
|  |             script are not properly executed. | ||||||
|  |         {% endcomment %} | ||||||
|  |     {% endblock js_extra %} | ||||||
|  | 
 | ||||||
|     <script src="https://js.stripe.com/v3/"></script> |     <script src="https://js.stripe.com/v3/"></script> | ||||||
|     <script src="https://js.stripe.com/v2/"></script> |     <script src="https://js.stripe.com/v2/"></script> | ||||||
|     <!-- Stripe Lib --> |     <!-- Stripe Lib --> | ||||||
|  | @ -108,8 +115,6 @@ | ||||||
|     <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> |     <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> | ||||||
|     <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.js"></script> |     <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.js"></script> | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| </body> | </body> | ||||||
| 
 | 
 | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -4,175 +4,159 @@ | ||||||
| {% load custom_tags %} | {% load custom_tags %} | ||||||
| 
 | 
 | ||||||
| {% block content %} | {% block content %} | ||||||
| 
 | {{order.pk}} | ||||||
| <div class="order-detail-container"> | <div id="order-detail{{order.pk}}" class="order-detail-container"> | ||||||
|     {% if messages %} |     {% if messages %} | ||||||
|     <div class="row"> |  | ||||||
|         <div class="col-xs-12 col-md-8 col-md-offset-2"> |  | ||||||
|             <br/> |  | ||||||
|         <div class="alert alert-warning"> |         <div class="alert alert-warning"> | ||||||
|             {% for message in messages %} |             {% for message in messages %} | ||||||
|                 <span>{{ message }}</span> |                 <span>{{ message }}</span> | ||||||
|             {% endfor %} |             {% endfor %} | ||||||
|         </div> |         </div> | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
|     {% endif %} |     {% endif %} | ||||||
|     {% if not error %} |     {% if not error %} | ||||||
|     <div class="row"> |         <div class="dashboard-container-head"> | ||||||
|         <div class="col-xs-12 col-md-8 col-md-offset-2"> |             <h1 class="dashboard-title-thin"> | ||||||
|             <div class="invoice-title"> |                 <img src="{% static 'hosting/img/billing.svg' %}" class="un-icon">{% blocktrans with page_header_text=page_header_text|default:"Invoice" %}{{page_header_text}}{% endblocktrans %} | ||||||
|                 <h2>{{page_header_text}}</h2> |             </h1> | ||||||
|                 <h3 class="pull-right"> |             <div class="dashboard-container-options"> | ||||||
|                     {% if order %} |                 <button type="button" class="btn-plain btn-pdf" data-target="#order-detail{{order.pk}}"><img src="{% static 'hosting/img/icon-pdf.svg' %}" class="svg-img"></button> | ||||||
|                     {% trans "Order #"%} {{order.id}} |                 <button type="button" class="btn-plain btn-print"><img src="{% static 'hosting/img/icon-print.svg' %}" class="svg-img"></button> | ||||||
|                     {% endif %} |  | ||||||
|                 </h3> |  | ||||||
|             </div> |             </div> | ||||||
|             <hr> |         </div> | ||||||
|             <div class="row"> |         <div class="order-details"> | ||||||
|                 <div class="col-xs-12 col-md-6 pull-right order-confirm-date"> |             {% if order %} | ||||||
|                     <address> |                 <p> | ||||||
|                         <strong>{% trans "Date"%}:</strong><br> |                     <strong>{% trans "Order #" %} {{order.id}}</strong> | ||||||
|  |                 </p> | ||||||
|  |             {% endif %} | ||||||
|  |             <p> | ||||||
|  |                 <strong>{% trans "Invoice Date" %}:</strong> | ||||||
|                 <span id="order-created_at"> |                 <span id="order-created_at"> | ||||||
|                     {% if order %} |                     {% if order %} | ||||||
|                         {{order.created_at|date:'Y-m-d H:i'}} |                         {{order.created_at|date:'Y-m-d H:i'}} | ||||||
|                     {% else %} |                     {% else %} | ||||||
|                         {% now "Y-m-d H:i" %} |                         {% now "Y-m-d H:i" %} | ||||||
|                     {% endif %} |                     {% endif %} | ||||||
|                             </span><br><br> |                 </span> | ||||||
|  |             </p> | ||||||
|             {% if order %} |             {% if order %} | ||||||
|                         <strong>{% trans "Status:"%}</strong><br> |                 <p> | ||||||
|  |                     <strong>{% trans "Status" %}: </strong> | ||||||
|  |                     <strong> | ||||||
|                         {% if order.status == 'Approved' %} |                         {% if order.status == 'Approved' %} | ||||||
|                         <strong class="text-success"> |                             <span class="vm-color-online">{% trans "Approved" %}</span> | ||||||
|                             {% trans "Approved" %} |  | ||||||
|                         </strong> |  | ||||||
|                         {% else %} |                         {% else %} | ||||||
|                         <strong class="text-danger"> |                             <span class="vm-status-failed">{% trans "Declined" %}</span> | ||||||
|                             {% trans "Declined" %} |                         {% endif %} | ||||||
|                     </strong> |                     </strong> | ||||||
|  |                 </p> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|                         <br><br> |             <hr> | ||||||
|                         {% endif %} |             <div> | ||||||
|                     </address> |  | ||||||
| 
 |  | ||||||
|                 </div> |  | ||||||
|                 <div class="col-xs-12 col-md-6"> |  | ||||||
|                 <address> |                 <address> | ||||||
|                         <h3><b>{% trans "Billed To:"%}</b></h3> |                     <h4>{% trans "Billed to" %}:</h4> | ||||||
|  |                     <p> | ||||||
|                         {% if order %} |                         {% if order %} | ||||||
|                             {{user.name}}<br> |                             {{user.name}}<br> | ||||||
|                         {{order.billing_address.street_address}},{{order.billing_address.postal_code}}<br> |                             {{order.billing_address.street_address}}, {{order.billing_address.postal_code}}<br> | ||||||
|                         {{order.billing_address.city}}, |                             {{order.billing_address.city}}, {{order.billing_address.country}} | ||||||
|                         {{order.billing_address.country}}. |  | ||||||
|                         {% else %} |                         {% else %} | ||||||
|                             {% with request.session.billing_address_data as billing_address %} |                             {% with request.session.billing_address_data as billing_address %} | ||||||
|                         {{billing_address|get_value_from_dict:'cardholder_name'}}<br> |                                 {{billing_address.cardholder_name}}<br> | ||||||
|                         {{billing_address|get_value_from_dict:'street_address'}}, |                                 {{billing_address.street_address}}, {{billing_address.postal_code}}<br> | ||||||
|                         {{billing_address|get_value_from_dict:'postal_code'}}<br> |                                 {{billing_address.city}}, {{billing_address.country}} | ||||||
|                         {{billing_address|get_value_from_dict:'city'}}, |  | ||||||
|                         {{billing_address|get_value_from_dict:'country'}}. |  | ||||||
|                             {% endwith %} |                             {% endwith %} | ||||||
|                         {% endif %} |                         {% endif %} | ||||||
|  |                     </p> | ||||||
|                 </address> |                 </address> | ||||||
|             </div> |             </div> | ||||||
| 
 |             <hr> | ||||||
|             </div> |             <div> | ||||||
|             <div class="row"> |                 <h4>{% trans "Payment method" %}:</h4> | ||||||
|                 <div class="col-xs-6"> |                 <p> | ||||||
|                     <address> |  | ||||||
|                         <strong>{% trans "Payment Method:"%}</strong><br> |  | ||||||
|                     {% if order %} |                     {% if order %} | ||||||
|                         {{order.cc_brand}} {% trans "ending in" %} **** |                         {{order.cc_brand}} {% trans "ending in" %} **** | ||||||
|                         {{order.last4}}<br> |                         {{order.last4}}<br> | ||||||
|                         {{user.email}} |                         {{user.email}} | ||||||
|                     {% else %} |                     {% else %} | ||||||
|                         {{cc_brand}} {% trans "ending in" %} **** |                         {{cc_brand|default:'Card'}} {% trans "ending in" %} **** | ||||||
|                         {{cc_last4}}<br> |                         {{cc_last4}}<br> | ||||||
|  |                         {% if request.user.is_authenticated %} | ||||||
|  |                             {{request.user.email}} | ||||||
|  |                         {% else %} | ||||||
|                             {{request.session.user.email}} |                             {{request.session.user.email}} | ||||||
|                         {% endif %} |                         {% endif %} | ||||||
|                     </address> |                     {% endif %} | ||||||
|  |                 </p> | ||||||
|             </div> |             </div> | ||||||
|             </div> |             <hr> | ||||||
|         </div> |             <div> | ||||||
|     </div> |                 <h4>{% trans "Order summary" %}</h4> | ||||||
| 
 |                 <p> | ||||||
|  |                     <strong>{% trans "Product" %}:</strong> {{vm.name}} | ||||||
|  |                 </p> | ||||||
|                 <div class="row"> |                 <div class="row"> | ||||||
|         <div class="col-md-8 col-md-offset-2"> |                     <div class="col-sm-6"> | ||||||
|             <h3><b>{% trans "Order summary"%}</b></h3> |                         {% comment %} | ||||||
|             <hr> |                         <p> | ||||||
|             <div class="content"> |                             <span>{% trans "Period" %}</span> | ||||||
|                 {% if request.session.specs %} |                             <span class="pull-right">{{}}</span> | ||||||
|                 {% with request.session.specs as vm %} |  | ||||||
|                 <p><b>{% trans "Cores"%}</b> |  | ||||||
|                     <span class="pull-right">{{vm.cpu}}</span> |  | ||||||
|                         </p> |                         </p> | ||||||
|                 <hr> |                         {% endcomment %} | ||||||
|                 <p><b>{% trans "Memory"%}</b> |                         <p> | ||||||
|                     <span class="pull-right">{{vm.memory}} GB</span> |                             <span>{% trans "Cores" %}</span> | ||||||
|                 </p> |                             {% if vm.cores %} | ||||||
|                 <hr> |                                 <span class="pull-right">{{vm.cores|floatformat}}</span> | ||||||
|                 <p><b>{% trans "Disk space"%}</b> |  | ||||||
|                     <span class="pull-right">{{vm.disk_size}} GB</span> |  | ||||||
|                 </p> |  | ||||||
|                 <hr> |  | ||||||
|                 <p><b>{% trans "Configuration"%}</b> |  | ||||||
|                     <span class="pull-right">{{request.session.template.name}}</span> |  | ||||||
|                 </p> |  | ||||||
|                 <hr> |  | ||||||
|                 <h4>{% trans "Total"%} |  | ||||||
|                     <p class="pull-right"> |  | ||||||
|                         <b>{{vm.price}} CHF</b> |  | ||||||
|                         <span class="dcl-price-month"> /{% trans "Month" %} |  | ||||||
|                                 </span> |  | ||||||
|                     </p> |  | ||||||
|                 </h4> |  | ||||||
|                 {% endwith %} |  | ||||||
|                             {% else %} |                             {% else %} | ||||||
|                 <p><b>{% trans "Cores"%}</b> |                                 <span class="pull-right">{{vm.cpu|floatformat}}</span> | ||||||
|                     <span class="pull-right">{{vm.cores}}</span> |                             {% endif %} | ||||||
|                         </p> |                         </p> | ||||||
|                 <hr> |                         <p> | ||||||
|                 <p><b>{% trans "Memory"%}</b> |                             <span>{% trans "Memory" %}</span> | ||||||
|                             <span class="pull-right">{{vm.memory}} GB</span> |                             <span class="pull-right">{{vm.memory}} GB</span> | ||||||
|                         </p> |                         </p> | ||||||
|                 <hr> |                         <p> | ||||||
|                 <p><b>{% trans "Disk space"%}</b> |                             <span>{% trans "Disk space" %}</span> | ||||||
|                             <span class="pull-right">{{vm.disk_size}} GB</span> |                             <span class="pull-right">{{vm.disk_size}} GB</span> | ||||||
|                         </p> |                         </p> | ||||||
|  |                         <p> | ||||||
|  |                             <span>{% trans "Total" %}</span> | ||||||
|  |                             <span class="pull-right">{{vm.price}} CHF</span> | ||||||
|  |                         </p> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |             {% if not order %} | ||||||
|                 <hr> |                 <hr> | ||||||
|                 <h4>{% trans "Total"%}<p class="pull-right"><b>{{vm.price}} |  | ||||||
|                     CHF</b><span |  | ||||||
|                         class="dcl-price-month"> /{% trans "Month" %}</span> |  | ||||||
|                 </p></h4> |  | ||||||
|             {% endif %} |             {% endif %} | ||||||
|         </div> |         </div> | ||||||
|             <br/> |  | ||||||
|         {% if not order %} |         {% if not order %} | ||||||
|             <form method="post" id="virtual_machine_create_form"> |             <form method="post" id="virtual_machine_create_form"> | ||||||
|                 {% csrf_token %} |                 {% csrf_token %} | ||||||
|                 <div class="row"> |                 <div class="row"> | ||||||
|                     <div class="col-sm-8"> |                     <div class="col-sm-8"> | ||||||
|                         <p class="dcl-place-order-text">{% blocktrans with vm_price=request.session.specs.price %}By clicking "Place order" this plan will charge your credit card account with the fee of {{ vm_price }}CHF/month{% endblocktrans %}.</p> |                         <div class="dcl-place-order-text">{% blocktrans with vm_price=request.session.specs.price %}By clicking "Place order" this plan will charge your credit card account with the fee of {{ vm_price }}CHF/month{% endblocktrans %}.</div> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="col-sm-4 content"> |                     <div class="col-sm-4 order-confirm-btn text-right"> | ||||||
|                         <button class="btn btn-info pull-right" |                         <button class="btn choice-btn" id="btn-create-vm" data-href="{% url 'hosting:order-confirmation' %}" data-toggle="modal" data-target="#createvm-modal"> | ||||||
|                                 id="btn-create-vm" |                             {% trans "Place order" %} | ||||||
|                                 data-href="{% url 'hosting:order-confirmation' %}" |  | ||||||
|                                 data-toggle="modal" |  | ||||||
|                                 data-target="#createvm-modal"> |  | ||||||
|                             {% trans "Place order"%} |  | ||||||
|                         </button> |                         </button> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|             </form> |             </form> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
|     {% endif %} |     {% endif %} | ||||||
| </div> | </div> | ||||||
| <!-- Create VM Modal --> | 
 | ||||||
| <div class="modal fade" id="createvm-modal" tabindex="-1" role="dialog" | {% 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"> |          aria-hidden="true" data-backdrop="static" data-keyboard="false"> | ||||||
|         <div class="modal-dialog"> |         <div class="modal-dialog"> | ||||||
|             <div class="modal-content"> |             <div class="modal-content"> | ||||||
|  | @ -197,13 +181,13 @@ | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
| </div> |     </div> | ||||||
| <!-- / Create VM Modal --> |     <!-- / Create VM Modal --> | ||||||
| 
 | {% endif %} | ||||||
| 
 | 
 | ||||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||||
|     {% trans "Some problem encountered. Please try again later." as err_msg %} |     {% trans "Some problem encountered. Please try again later." as err_msg %} | ||||||
|     var create_vm_error_message = '{{err_msg|safe}}.'; |     var create_vm_error_message = '{{err_msg|safe}}'; | ||||||
| 
 | 
 | ||||||
|     window.onload = function () { |     window.onload = function () { | ||||||
|         var locale_date = moment.utc(document.getElementById("order-created_at").textContent, 'YYYY-MM-DD HH:mm').toDate(); |         var locale_date = moment.utc(document.getElementById("order-created_at").textContent, 'YYYY-MM-DD HH:mm').toDate(); | ||||||
|  | @ -211,7 +195,12 @@ | ||||||
|         document.getElementById('order-created_at').innerHTML = locale_date; |         document.getElementById('order-created_at').innerHTML = locale_date; | ||||||
| 
 | 
 | ||||||
|     }; |     }; | ||||||
| 
 |  | ||||||
| </script> | </script> | ||||||
| {%endblock%} | {%endblock%} | ||||||
| 
 | 
 | ||||||
|  | {% block js_extra %} | ||||||
|  |     <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script> | ||||||
|  |     <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script> | ||||||
|  |     <script src="{% static 'hosting/js/html2pdf.js' %}"></script> | ||||||
|  |     <script src="{% static 'hosting/js/order.js' %}"></script> | ||||||
|  | {% endblock js_extra %} | ||||||
|  | @ -41,13 +41,15 @@ | ||||||
|                         <td data-header="IPv6">{{vm.ipv6}}</td> |                         <td data-header="IPv6">{{vm.ipv6}}</td> | ||||||
|                     {% endif %} |                     {% endif %} | ||||||
|                     <td data-header="{% trans 'Status' %}"> |                     <td data-header="{% trans 'Status' %}"> | ||||||
|  |                         <strong> | ||||||
|                             {% if vm.state == 'ACTIVE' %} |                             {% if vm.state == 'ACTIVE' %} | ||||||
|                             <span class="vm-status-active"><strong>{{vm.state|title}}</strong></span> |                                 <span class="vm-status-active">{{vm.state|title}}</span> | ||||||
|                             {% elif  vm.state == 'FAILED' %} |                             {% elif  vm.state == 'FAILED' %} | ||||||
|                             <span class="vm-status-failed"><strong>{{vm.state|title}}</strong></span> |                                 <span class="vm-status-failed">{{vm.state|title}}</span> | ||||||
|                             {% else %} |                             {% else %} | ||||||
|                             <span class="vm-status"><strong>{{vm.state|title}}</strong></span> |                                 <span class="vm-status">{{vm.state|title}}</span> | ||||||
|                             {% endif %} |                             {% endif %} | ||||||
|  |                         </strong> | ||||||
|                     </td> |                     </td> | ||||||
|                     <td class="text-right last-td"> |                     <td class="text-right last-td"> | ||||||
|                         <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail" %}</a> |                         <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail" %}</a> | ||||||
|  |  | ||||||
|  | @ -644,7 +644,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, | ||||||
|     model = HostingOrder |     model = HostingOrder | ||||||
| 
 | 
 | ||||||
|     def get_object(self): |     def get_object(self): | ||||||
|         return HostingOrder.objects.filter( |         return HostingOrder.objects.get( | ||||||
|             pk=self.kwargs.get('pk')) if self.kwargs.get('pk') else None |             pk=self.kwargs.get('pk')) if self.kwargs.get('pk') else None | ||||||
| 
 | 
 | ||||||
|     def get_context_data(self, **kwargs): |     def get_context_data(self, **kwargs): | ||||||
|  | @ -652,54 +652,79 @@ class OrdersHostingDetailView(LoginRequiredMixin, | ||||||
|         context = super(DetailView, self).get_context_data(**kwargs) |         context = super(DetailView, self).get_context_data(**kwargs) | ||||||
|         obj = self.get_object() |         obj = self.get_object() | ||||||
|         owner = self.request.user |         owner = self.request.user | ||||||
|         if 'specs' not in self.request.session: |  | ||||||
|             return HttpResponseRedirect( |  | ||||||
|                 reverse('hosting:create_virtual_machine')) |  | ||||||
|         if 'token' not in self.request.session: |  | ||||||
|             return HttpResponseRedirect(reverse('hosting:payment')) |  | ||||||
|         stripe_customer_id = self.request.session.get('customer') |         stripe_customer_id = self.request.session.get('customer') | ||||||
|         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() |         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first() | ||||||
|         stripe_utils = StripeUtils() |         stripe_utils = StripeUtils() | ||||||
|         card_details = stripe_utils.get_card_details(customer.stripe_id, |         if customer: | ||||||
|                                                      self.request.session.get( |             card_details = stripe_utils.get_card_details( | ||||||
|                                                          'token')) |                 customer.stripe_id, | ||||||
|         if not card_details.get('response_object'): |                 self.request.session.get('token') | ||||||
|             msg = card_details.get('error') |             ) | ||||||
|             messages.add_message(self.request, messages.ERROR, msg, |         else: | ||||||
|                                  extra_tags='failed_payment') |             card_details = {} | ||||||
|             return HttpResponseRedirect( |  | ||||||
|                 reverse('hosting:payment') + '#payment_error') |  | ||||||
| 
 | 
 | ||||||
|         if self.request.GET.get('page', '') == 'payment': |         if self.request.GET.get('page') == 'payment': | ||||||
|             context['page_header_text'] = _('Confirm Order') |             context['page_header_text'] = _('Confirm Order') | ||||||
|         else: |         else: | ||||||
|             context['page_header_text'] = _('Invoice') |             context['page_header_text'] = _('Invoice') | ||||||
| 
 | 
 | ||||||
|         if obj is not None: |         if obj is not None: | ||||||
|  |             # invoice for previous order | ||||||
|             try: |             try: | ||||||
|                 manager = OpenNebulaManager(email=owner.email, |                 manager = OpenNebulaManager( | ||||||
|                                             password=owner.password) |                     email=owner.email, password=owner.password | ||||||
|  |                 ) | ||||||
|                 vm = manager.get_vm(obj.vm_id) |                 vm = manager.get_vm(obj.vm_id) | ||||||
|                 context['vm'] = VirtualMachineSerializer(vm).data |                 context['vm'] = VirtualMachineSerializer(vm).data | ||||||
|             except WrongIdError: |             except WrongIdError: | ||||||
|                 messages.error(self.request, |                 messages.error( | ||||||
|                                'The VM you are looking for is unavailable at the moment. \ |                     self.request, | ||||||
|                                 Please contact Data Center Light support.' |                     _('The VM you are looking for is unavailable at the ' | ||||||
|  |                       'moment. Please contact Data Center Light support.') | ||||||
|                 ) |                 ) | ||||||
|                 self.kwargs['error'] = 'WrongIdError' |                 self.kwargs['error'] = 'WrongIdError' | ||||||
|                 context['error'] = 'WrongIdError' |                 context['error'] = 'WrongIdError' | ||||||
|             except ConnectionRefusedError: |             except ConnectionRefusedError: | ||||||
|                 messages.error(self.request, |                 messages.error( | ||||||
|                                'In order to create a VM, you need to create/upload your SSH KEY first.' |                     self.request, | ||||||
|  |                     _('In order to create a VM, you need to create/upload ' | ||||||
|  |                       'your SSH KEY first.') | ||||||
|                 ) |                 ) | ||||||
|  |         elif not card_details.get('response_object'): | ||||||
|  |             # new order, failed to get card details | ||||||
|  |             context['failed_payment'] = True | ||||||
|  |             context['card_details'] = card_details | ||||||
|         else: |         else: | ||||||
|  |             # new order, confirm payment | ||||||
|             context['site_url'] = reverse('hosting:create_virtual_machine') |             context['site_url'] = reverse('hosting:create_virtual_machine') | ||||||
|             context['cc_last4'] = card_details.get('response_object').get( |             context['cc_last4'] = card_details.get('response_object').get( | ||||||
|                 'last4') |                 'last4') | ||||||
|             context['cc_brand'] = card_details.get('response_object').get( |             context['cc_brand'] = card_details.get('response_object').get( | ||||||
|                 'cc_brand') |                 'cc_brand') | ||||||
|  |             context['vm'] = self.request.session.get('specs') | ||||||
|         return context |         return context | ||||||
| 
 | 
 | ||||||
|  |     def get(self, request, *args, **kwargs): | ||||||
|  |         if not self.kwargs.get('pk'): | ||||||
|  |             if 'specs' not in self.request.session: | ||||||
|  |                 return HttpResponseRedirect( | ||||||
|  |                     reverse('hosting:create_virtual_machine') | ||||||
|  |                 ) | ||||||
|  |             if 'token' not in self.request.session: | ||||||
|  |                 return HttpResponseRedirect(reverse('hosting:payment')) | ||||||
|  |         self.object = self.get_object() | ||||||
|  |         context = self.get_context_data(object=self.object) | ||||||
|  |         if 'failed_payment' in context: | ||||||
|  |             msg = context['card_details'].get('error') | ||||||
|  |             messages.add_message( | ||||||
|  |                 self.request, messages.ERROR, msg, | ||||||
|  |                 extra_tags='failed_payment' | ||||||
|  |             ) | ||||||
|  |             return HttpResponseRedirect( | ||||||
|  |                 reverse('hosting:payment') + '#payment_error' | ||||||
|  |             ) | ||||||
|  |         return self.render_to_response(context) | ||||||
|  | 
 | ||||||
|     def post(self, request): |     def post(self, request): | ||||||
|         template = request.session.get('template') |         template = request.session.get('template') | ||||||
|         specs = request.session.get('specs') |         specs = request.session.get('specs') | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue