/* * This file is part of Linode Manager Classic. * * Linode Manager Classic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Linode Manager Classic is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Linode Manager Classic. If not, see . */ import { settings, elements, apiGet, apiPost, parseParams, setupHeader, timeString } from "/global.js"; (function() { // Element names specific to this page elements.active = "active"; elements.address = "address"; elements.balance = "balance"; elements.balanceNegative = "balance-negative"; elements.balancePositive = "balance-positive"; elements.balanceStatus = "balance-status"; elements.billingActivity = "billing-activity"; elements.ccNumber = "cc-number"; elements.ccDuration = "cc-duration"; elements.ccExpire = "cc-expire"; elements.current = "current"; elements.email = "email"; elements.gdpr = "gdpr"; elements.gdprDate = "gdpr-date"; elements.info = "info"; elements.lmcRow = "lmc-tr1"; elements.lmcRowAlt = "lmc-tr2"; elements.lmcRowStandard = "lmc-tr3"; elements.managed = "managed"; elements.managedButton = "managed-button"; elements.pay = "pay"; elements.promotions = "promotions"; elements.promotionsTable = "promotions-table"; elements.uninvoiced = "uninvoiced"; elements.uninvoicedBalance = "uninvoiced-balance"; // Data received from API calls var data = {}; data.account = {}; data.invoices = []; data.linodes = []; data.payments = []; // Static references to UI elements var ui = {}; ui.active = {}; ui.address = {}; ui.balance = {}; ui.balanceStatus = {}; ui.billingActivity = {}; ui.ccNumber = {}; ui.ccDuration = {}; ui.ccExpire = {}; ui.current = {}; ui.email = {}; ui.gdpr = []; ui.gdprDate = {}; ui.managed = {}; ui.managedButton = {}; ui.pay = {}; ui.promotions = []; ui.promotionsTable = {}; ui.uninvoiced = {}; ui.uninvoicedBalance = {}; // Temporary state var state = {}; state.haveInvoices = false; state.havePayments = false; // Creates a row for the promotion table var createPromoRow = function(promo) { var row = document.createElement("tr"); row.className = elements.lmcRowStandard; var name = document.createElement("td"); name.innerHTML = promo.summary; row.appendChild(name); var details = document.createElement("td"); var line1 = document.createElement("span"); var expire = new Date(promo.expire_dt + "Z"); line1.innerHTML = "$" + promo.credit_remaining + " remaining. Exp: " + expire.toLocaleDateString(); var br = document.createElement("br"); var line2 = document.createElement("span"); line2.innerHTML = "($" + promo.this_month_credit_remaining + " remaining this month. Monthly cap: $" + promo.credit_monthly_cap + ")"; details.appendChild(line1); details.appendChild(br); details.appendChild(line2); row.appendChild(details); var description = document.createElement("td"); description.className = elements.info; description.innerHTML = promo.description; row.appendChild(description); return row; }; // Creates a row for the recent activity table var createRecentRow = function(recent, alt) { var row = document.createElement("tr"); if (alt) row.className = elements.lmcRowAlt; else row.className = elements.lmcRow; var dateCell = document.createElement("td"); var date = document.createElement("span"); var recentDate = new Date(recent.date + "Z"); var now = new Date(); date.innerHTML = recentDate.toLocaleDateString(); var br = document.createElement("br"); var ago = document.createElement("span"); ago.className = elements.info; ago.innerHTML = timeString(now - recentDate, true); dateCell.appendChild(date); dateCell.appendChild(br); dateCell.appendChild(ago); row.appendChild(dateCell); if (recent.label) { // Invoice stuff var linkCell = document.createElement("td"); var link = document.createElement("a"); link.href = "/account/invoice?iid=" + recent.id; link.innerHTML = recent.label; linkCell.appendChild(link); row.appendChild(linkCell); var total = document.createElement("td"); if (recent.total < 0) total.innerHTML = "($" + (-recent.total).toFixed(2) + ")"; else total.innerHTML = "$" + recent.total.toFixed(2); row.appendChild(total); } else { // Payment stuff var thanks = document.createElement("td"); thanks.innerHTML = "Payment. Thank you"; row.appendChild(thanks); var total = document.createElement("td"); if (total > 0) total.innerHTML = "($" + recent.total.toFixed(2) + ")"; else total.innerHTML = "$" + (-recent.total).toFixed(2); row.appendChild(total); } return row; }; // Callback for account details API call var displayAccount = function(response) { data.account = response; // Contact info var br = document.createElement("br"); if (data.account.company.length) { var company = document.createElement("span"); company.innerHTML = data.account.company; ui.address.appendChild(company); ui.address.appendChild(br); } var name = document.createElement("span"); name.innerHTML = data.account.first_name + " " + data.account.last_name; ui.address.appendChild(name); ui.address.appendChild(br.cloneNode(true)); var address1 = document.createElement("span"); address1.innerHTML = data.account.address_1; ui.address.appendChild(address1); ui.address.appendChild(br.cloneNode(true)); if (data.account.address_2.length) { var address2 = document.createElement("span"); address2.innerHTML = data.account.address_2; ui.address.appendChild(address2); ui.address.appendChild(br.cloneNode(true)); } var address3 = document.createElement("span"); address3.innerHTML = data.account.city + ", " + data.account.state + " " + data.account.zip; ui.address.appendChild(address3); // Email ui.email.innerHTML = data.account.email; // CC info ui.ccNumber.innerHTML = data.account.credit_card.last_four; var expired = document.createElement("span"); var strong = document.createElement("strong"); strong.innerHTML = "Expired!"; var dash = document.createElement("span"); dash.innerHTML = " - "; var updateLink = document.createElement("a"); updateLink.href = "/account/creditcard"; updateLink.innerHTML = "update credit card"; expired.appendChild(strong); expired.appendChild(dash); expired.appendChild(updateLink); if (data.account.credit_card.expiry) { ui.ccExpire.innerHTML = data.account.credit_card.expiry; var monthYear = data.account.credit_card.expiry.split("/"); var expireDate = new Date(parseInt(monthYear[1]), parseInt(monthYear[0]), 0); var now = new Date(); if (expireDate - now > 0) ui.ccDuration.innerHTML = "Expires " + timeString(now - expireDate, true); else ui.ccDuration.appendChild(expired); } // Account balance if (data.account.balance == 0) { ui.balance.className = elements.balancePositive; ui.current.innerHTML = "Your account is current."; } else if (data.account.balance < 0) { ui.balance.className = elements.balancePositive; ui.balanceStatus.innerHTML = " credit"; ui.current.innerHTML = "This will be applied towards future invoices."; data.account.balance = -data.account.balance; } else { ui.balance.className = elements.balanceNegative; ui.balanceStatus.innerHTML = " due "; ui.pay.href += "?amount=" + (-data.account.balance); ui.pay.style.display = "initial"; ui.current.innerHTML = "Please pay now to avoid any service interruptions."; } ui.balance.innerHTML = "$" + data.account.balance.toFixed(2); ui.uninvoicedBalance.innerHTML = "$" + data.account.balance_uninvoiced.toFixed(2); if (data.account.balance_uninvoiced > 0) ui.uninvoiced.style.display = "table-row"; // Promotions if (data.account.active_promotions.length) { for (var i = 0; i < ui.promotions.length; i++) ui.promotions[i].style.display = "table-row-group"; } for (var i = 0; i < data.account.active_promotions.length; i++) ui.promotionsTable.appendChild(createPromoRow(data.account.active_promotions[i])); var active = new Date(data.account.active_since + "Z"); ui.active.innerHTML = active.toLocaleDateString(); }; // Callback for invoices API call var displayInvoices = function(response) { data.invoices = data.invoices.concat(response.data); // Request the next page if there are more if (response.page != response.pages) { apiGet("/account/invoices?page=" + (response.page + 1), displayInvoices, null); return; } state.haveInvoices = true; if (state.havePayments) displayRecent(); }; // Callback for linodes API call var displayLinodes = function(response) { data.linodes = data.linodes.concat(response.data); // Request the next page if there are more if (response.page != response.pages) { apiGet("/linode/instances?page=" + (response.page + 1), displayLinodes, null); return; } ui.managedButton.disabled = false; }; // Callback for payments API call var displayPayments = function(response) { data.payments = data.payments.concat(response.data); // Request the next page if there are more if (response.page != response.pages) { apiGet("/account/payments?page=" + (response.page + 1), displayPayments, null); return; } state.havePayments = true; if (state.haveInvoices) displayRecent(); }; // Populates table with recent invoices and payments var displayRecent = function() { // Combine to single array and sort by date var recent = data.invoices.concat(data.payments); recent.sort(function(a, b) { var aDate = new Date(a.date + "Z"); var bDate = new Date(b.date + "Z"); return aDate - bDate; }); // Insert items into table for (var i = recent.length - 1, count = 0; i >= 0, count < 4; i--, count++) ui.billingActivity.appendChild(createRecentRow(recent[i], ui.billingActivity.children.length % 2)); }; // Callback for account settings API call var displaySettings = function(response) { // Show managed signup if not managed if (!response.managed) ui.managed.style.display = "table"; }; // Click handler for managed button var handleManaged = function(event) { if (event.currentTarget.disabled) return; if (!confirm("Linode Managed costs an additional $100/mo per Linode. This will increase your projected monthly bill by $" + (data.linodes.length * 100) + ". Are you sure?")) return; apiPost("/account/settings/managed-enable", {}, function(response) { location.reload(); }); }; // Initial setup var setup = function() { // Parse URL parameters data.params = parseParams(); setupHeader(); // Get element references ui.active = document.getElementById(elements.active); ui.address = document.getElementById(elements.address); ui.balance = document.getElementById(elements.balance); ui.balanceStatus = document.getElementById(elements.balanceStatus); ui.billingActivity = document.getElementById(elements.billingActivity); ui.ccNumber = document.getElementById(elements.ccNumber); ui.ccDuration = document.getElementById(elements.ccDuration); ui.ccExpire = document.getElementById(elements.ccExpire); ui.current = document.getElementById(elements.current); ui.email = document.getElementById(elements.email); ui.gdpr = document.getElementsByClassName(elements.gdpr); ui.gdprDate = document.getElementById(elements.gdprDate); ui.managed = document.getElementById(elements.managed); ui.managedButton = document.getElementById(elements.managedButton); ui.pay = document.getElementById(elements.pay); ui.promotions = document.getElementsByClassName(elements.promotions); ui.promotionsTable = document.getElementById(elements.promotionsTable); ui.uninvoiced = document.getElementById(elements.uninvoiced); ui.uninvoicedBalance = document.getElementById(elements.uninvoicedBalance); // Register event handlers ui.managedButton.addEventListener("click", handleManaged); // Get data from API apiGet("/account", displayAccount, null); apiGet("/account/settings", displaySettings, null); apiGet("/account/invoices", displayInvoices, null); apiGet("/account/payments", displayPayments, null); apiGet("/linode/instances", displayLinodes, null); }; // Attach onload handler window.addEventListener("load", setup); })();