2020-03-13 23:01:39 -04:00
/ *
* 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 < https : //www.gnu.org/licenses/>.
* /
2024-06-17 18:21:01 -04:00
import { settings , elements , apiDelete , apiGet , apiPost , parseParams , setupHeader , timeString } from "/global.js" ;
2020-03-13 23:01:39 -04:00
( 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 . current = "current" ;
2024-06-17 18:21:01 -04:00
elements . defaultPrefix = "default-payment-" ;
elements . deletePrefix = "delete-payment-" ;
2020-03-13 23:01:39 -04:00
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" ;
2024-06-17 18:21:01 -04:00
elements . paymentMethods = "payment-methods" ;
2020-03-13 23:01:39 -04:00
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 = [ ] ;
2024-06-17 18:21:01 -04:00
data . numLinodes = 0 ;
data . paymentMethods = [ ] ;
2020-03-13 23:01:39 -04:00
data . payments = [ ] ;
// Static references to UI elements
var ui = { } ;
ui . active = { } ;
ui . address = { } ;
ui . balance = { } ;
ui . balanceStatus = { } ;
ui . billingActivity = { } ;
ui . current = { } ;
ui . email = { } ;
ui . gdpr = [ ] ;
ui . gdprDate = { } ;
ui . managed = { } ;
ui . managedButton = { } ;
ui . pay = { } ;
2024-06-17 18:21:01 -04:00
ui . paymentMethods = { } ;
2020-03-13 23:01:39 -04:00
ui . promotions = [ ] ;
ui . promotionsTable = { } ;
ui . uninvoiced = { } ;
ui . uninvoicedBalance = { } ;
// Temporary state
var state = { } ;
state . haveInvoices = false ;
state . havePayments = false ;
2024-06-17 18:21:01 -04:00
// Creates a row for the payment methods table
var createMethodRow = function ( method )
{
var typeNames = {
"credit_card" : "Credit Card" ,
"google_pay" : "Google Pay" ,
"paypal" : "PayPal"
} ;
var row = document . createElement ( "tr" ) ;
row . className = elements . lmcRowStandard ;
var type = document . createElement ( "td" ) ;
if ( typeNames [ method . type ] )
type . innerHTML = typeNames [ method . type ] ;
else
type . innerHTML = method . type ;
row . appendChild ( type ) ;
var details = document . createElement ( "td" ) ;
if ( method . type == "credit_card" || method . type == "google_pay" ) {
var ccInfo = document . createElement ( "span" ) ;
ccInfo . innerHTML = method . data . card _type + " xxxxxxxxxxxx" + method . data . last _four + " Exp: " + method . data . expiry ;
var br = document . createElement ( "br" ) ;
details . appendChild ( ccInfo ) ;
details . appendChild ( br ) ;
var monthYear = method . data . expiry . split ( "/" ) ;
var expireDate = new Date ( parseInt ( monthYear [ 1 ] ) , parseInt ( monthYear [ 0 ] ) , 0 ) ;
var now = new Date ( ) ;
if ( expireDate - now > 0 ) {
var duration = document . createElement ( "span" ) ;
duration . innerHTML = "Expires " + timeString ( now - expireDate , true ) ;
details . appendChild ( duration ) ;
} else {
var expired = document . createElement ( "strong" ) ;
expired . innerHTML = "Expired!" ;
details . appendChild ( expired ) ;
}
} else if ( method . type == "paypal" ) {
var email = document . createElement ( "span" ) ;
email . innerHTML = method . data . email ;
details . appendChild ( email ) ;
}
row . appendChild ( details ) ;
var options = document . createElement ( "td" ) ;
if ( method . is _default ) {
var defaultMsg = document . createElement ( "strong" ) ;
defaultMsg . innerHTML = "This is the default payment method" ;
options . appendChild ( defaultMsg ) ;
} else {
var defaultLink = document . createElement ( "a" ) ;
defaultLink . id = elements . defaultPrefix + method . id ;
defaultLink . href = "#" ;
defaultLink . innerHTML = "Make default" ;
defaultLink . addEventListener ( "click" , defaultMethod ) ;
var separator = document . createElement ( "span" ) ;
separator . innerHTML = " | " ;
var deleteLink = document . createElement ( "a" ) ;
deleteLink . id = elements . deletePrefix + method . id ;
deleteLink . href = "#" ;
deleteLink . innerHTML = "Delete" ;
deleteLink . addEventListener ( "click" , deleteMethod ) ;
options . appendChild ( defaultLink ) ;
options . appendChild ( separator ) ;
options . appendChild ( deleteLink ) ;
}
row . appendChild ( options ) ;
return row ;
} ;
2020-03-13 23:01:39 -04:00
// 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 ;
} ;
2024-06-17 18:21:01 -04:00
// Handler for making a payment method default
var defaultMethod = function ( event )
{
var id = event . currentTarget . id . slice ( elements . defaultPrefix . length ) ;
if ( ! confirm ( "Make this the default payment method?" ) )
return ;
apiPost ( "/account/payment-methods/" + id + "/make-default" , { } , function ( response )
{
location . reload ( ) ;
} ) ;
} ;
// Handler for deleting a payment method
var deleteMethod = function ( event )
{
var id = event . currentTarget . id . slice ( elements . deletePrefix . length ) ;
if ( ! confirm ( "Delete this payment method?" ) )
return ;
apiDelete ( "/account/payment-methods/" + id , function ( response )
{
location . reload ( ) ;
} ) ;
} ;
2020-03-13 23:01:39 -04:00
// 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 ;
// 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 )
{
2024-06-17 18:21:01 -04:00
data . numLinodes = response . results ;
ui . managedButton . disabled = false ;
} ;
// Callback for payment methods API call
var displayMethods = function ( response )
{
data . paymentMethods = data . paymentMethods . concat ( response . data ) ;
2020-03-13 23:01:39 -04:00
// Request the next page if there are more
if ( response . page != response . pages ) {
2024-06-17 18:21:01 -04:00
apiGet ( "/account/payment-methods?page=" + ( response . page + 1 ) , displayMethods , null ) ;
2020-03-13 23:01:39 -04:00
return ;
}
2024-06-17 18:21:01 -04:00
for ( var i = 0 ; i < data . paymentMethods . length ; i ++ )
ui . paymentMethods . appendChild ( createMethodRow ( data . paymentMethods [ i ] ) ) ;
2020-03-13 23:01:39 -04:00
} ;
// 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 ;
2024-06-17 18:21:01 -04:00
if ( ! confirm ( "Linode Managed costs an additional $100/mo per Linode. This will increase your projected monthly bill by $" + ( data . numLinodes * 100 ) + ". Are you sure?" ) )
2020-03-13 23:01:39 -04:00
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 . 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 ) ;
2024-06-17 18:21:01 -04:00
ui . paymentMethods = document . getElementById ( elements . paymentMethods ) ;
2020-03-13 23:01:39 -04:00
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 ) ;
2024-06-17 18:21:01 -04:00
apiGet ( "/account/payment-methods" , displayMethods , null ) ;
2020-03-13 23:01:39 -04:00
apiGet ( "/linode/instances" , displayLinodes , null ) ;
} ;
// Attach onload handler
window . addEventListener ( "load" , setup ) ;
} ) ( ) ;