/* * 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, regionNames, apiGet, parseParams, setupHeader } from "/global.js"; (function() { // Element names specific to this page elements.backupNo = "backup-no"; elements.backupYes = "backup-yes"; elements.barRemaining = "bar-remaining"; elements.barUsed = "bar-used"; elements.centerCell = "center-cell"; elements.dashboardLink = "dashboard-link"; elements.info = "info"; elements.linodes = "linodes"; elements.linodeTagPrefix = "linode-tag-"; elements.lmcRow = "lmc-tr1"; elements.lmcRowAlt = "lmc-tr2"; elements.lmcTable = "lmc-table"; elements.loading = "loading"; elements.notification = "notification"; elements.notifications = "notifications"; elements.subLinks = "sub-links"; elements.transferQuota = "transfer-quota"; elements.transferRemaining = "transfer-remaining"; elements.transferUsed = "transfer-used"; // Data recieved from API calls var data = {}; data.params = {}; data.linodes = []; data.linodeTags = []; data.noTag = false; data.notifications = []; data.plans = []; // Static references to UI elements var ui = {}; ui.linodes = {}; ui.linodeTables = {}; ui.loading = {}; ui.notifications = {}; var createLinodeRow = function(linode, alt) { var row = document.createElement("tr"); if (alt) row.className = elements.lmcRowAlt; else row.className = elements.lmcRow; var name = document.createElement("td"); var nameLink = document.createElement("a"); nameLink.href = "/linodes/dashboard?lid=" + linode.id; nameLink.innerHTML = linode.label; name.appendChild(nameLink); var status = document.createElement("td"); status.innerHTML = linode.status.charAt(0).toUpperCase() + linode.status.slice(1).replace(/_/g, " "); var plan = document.createElement("td"); if (linode.type) plan.innerHTML = getPlanLabel(linode.type); else plan.innerHTML = "Unknown"; if (plan.innerHTML == "") translatePlan(linode.type, plan); var ip = document.createElement("td"); ip.innerHTML = linode.ipv4[0]; var ipCount = 0; for (var i = 1; i < linode.ipv4.length; i++) { if (linode.ipv4[i].startsWith("192.168.")) continue; if (linode.ipv4[i].startsWith("10.")) continue; ipCount++; } if (ipCount) { var plus = document.createElement("span"); plus.className = elements.info; plus.innerHTML = " (+" + ipCount + ")"; ip.appendChild(plus); } var region = document.createElement("td"); if (regionNames[linode.region]) region.innerHTML = regionNames[linode.region]; else region.innerHTML = linode.region; var backups = document.createElement("td"); backups.className = elements.centerCell; if (linode.backups.enabled) { var backupStatus = document.createElement("span"); backupStatus.className = elements.backupYes; backupStatus.innerHTML = "Yes"; backups.appendChild(backupStatus); } else { var backupStatus = document.createElement("span"); backupStatus.className = elements.backupNo; backupStatus.innerHTML = "No"; var backupSeparator = document.createElement("span"); backupSeparator.innerHTML = " - "; var backupLink = document.createElement("a"); backupLink.href = "/linodes/backups_enable?lid=" + linode.id; backupLink.innerHTML = "Enable"; backups.appendChild(backupStatus); backups.appendChild(backupSeparator); backups.appendChild(backupLink); } var options = document.createElement("td"); options.className = elements.centerCell; var dashboardLink = document.createElement("a"); dashboardLink.className = elements.dashboardLink; dashboardLink.href = "/linodes/dashboard?lid=" + linode.id; dashboardLink.innerHTML = "Dashboard"; var optionsSeparator = document.createElement("span"); optionsSeparator.innerHTML = " | "; var removeLink = document.createElement("a"); removeLink.href = "/linodes/remove?lid=" + linode.id; removeLink.innerHTML = "Remove"; options.appendChild(dashboardLink); options.appendChild(optionsSeparator); options.appendChild(removeLink); row.appendChild(name); row.appendChild(status); row.appendChild(plan); row.appendChild(ip); row.appendChild(region); row.appendChild(backups); row.appendChild(options); return row; }; var createLinodeTable = function(tag) { var table = document.createElement("table"); table.id = elements.linodeTagPrefix + tag; table.className = elements.lmcTable; var thead = document.createElement("thead"); var headRow1 = document.createElement("tr"); var title = document.createElement("td"); if (tag.length == 0) title.innerHTML = "Linodes"; else title.innerHTML = tag; headRow1.appendChild(title); var headRow2 = document.createElement("tr"); var cells = ["Linode", "Status", "Plan", "IP", "Location", "Backups", "Options"]; title.colSpan = cells.length; for (var i = 0; i < cells.length; i++) { var cell = document.createElement("td"); if (cells[i] == "Backups" || cells[i] == "Options") cell.className = elements.centerCell; cell.innerHTML = cells[i]; headRow2.appendChild(cell); } thead.appendChild(headRow1); thead.appendChild(headRow2); var tbody = document.createElement("tbody"); table.appendChild(thead); table.appendChild(tbody); ui.linodeTables[tag] = tbody; var subLinks = document.createElement("p"); subLinks.className = elements.subLinks; var volumes = document.createElement("a"); volumes.href = "/volumes"; volumes.innerHTML = "Manage Volumes"; var separator = document.createElement("span"); separator.innerHTML = " | "; var images = document.createElement("a"); images.href = "/images"; images.innerHTML = "Manage Images"; var stackScripts = document.createElement("a"); stackScripts.href = "/stackscripts"; stackScripts.innerHTML = "Manage StackScripts"; var addLinode = document.createElement("a"); addLinode.href = "/linodes/add"; if (tag.length > 0) addLinode.href += "?tag=" + tag; addLinode.innerHTML = "Add a Linode"; subLinks.appendChild(volumes); subLinks.appendChild(separator); subLinks.appendChild(images); subLinks.appendChild(separator.cloneNode(true)); subLinks.appendChild(stackScripts); subLinks.appendChild(separator.cloneNode(true)); subLinks.appendChild(addLinode); ui.linodes.appendChild(table); ui.linodes.appendChild(subLinks); }; var displayLinodes = function(response) { // Add linodes to array data.linodes = data.linodes.concat(response.data); // Add new tags to array for (var i = 0; i < response.data.length; i++) { if (response.data[i].tags.length == 0) data.noTag = true; for (var j = 0; j < response.data[i].tags.length; j++) { if (!data.linodeTags.includes(response.data[i].tags[j])) data.linodeTags.push(response.data[i].tags[j]); } } // Request the next page if there are more pages if (response.page != response.pages) { var progress = (response.page / response.pages) * 100; progress = progress.toFixed(0); ui.loading.innerHTML = "Loading " + progress + "%..."; var filters = null; if (data.params.tag) filters = { "tags": data.params.tag }; apiGet("/linode/instances?page=" + (response.page + 1), displayLinodes, filters); return; } // Redirect to add page if there are no linodes if (data.linodes.length == 0) location.href = "/linodes/add"; // Sort data.linodeTags.sort(); data.linodes.sort(function(a, b) { return a.label.toLowerCase().localeCompare(b.label.toLowerCase()); }); // Create tables ui.loading.remove(); if (data.noTag) createLinodeTable(""); for (var i = 0; i < data.linodeTags.length; i++) createLinodeTable(data.linodeTags[i]); // Insert linodes for (var i = 0; i < data.linodes.length; i++) { if (data.linodes[i].tags.length == 0) ui.linodeTables[""].appendChild(createLinodeRow(data.linodes[i], ui.linodeTables[""].children.length % 2)); for (var j = 0; j < data.linodes[i].tags.length; j++) ui.linodeTables[data.linodes[i].tags[j]].appendChild(createLinodeRow(data.linodes[i], ui.linodeTables[data.linodes[i].tags[j]].children.length % 2)); } }; var displayNotifications = function(response) { // Add notifications to array data.notifications = data.notifications.concat(response.data); // Request the next page if there are more pages if (response.page != response.pages) { apiGet("/account/notifications?page=" + (response.page + 1), displayNotifications, null); return; } // Display notifications for (var i = 0; i < data.notifications.length; i++) { if (data.notifications[i].entity && data.notifications[i].entity.type == "linode") continue; var notification = document.createElement("div"); notification.className = elements.notification; var header = document.createElement("h1"); header.innerHTML = data.notifications[i].label; var body = document.createElement("p"); body.innerHTML = data.notifications[i].message; notification.appendChild(header); notification.appendChild(body); ui.notifications.appendChild(notification); } }; var displayTransfer = function(response) { var barRemaining = document.getElementById(elements.barRemaining); var barUsed = document.getElementById(elements.barUsed); var transferQuota = document.getElementById(elements.transferQuota); var transferRemaining = document.getElementById(elements.transferRemaining); var transferUsed = document.getElementById(elements.transferUsed); // Get border width of bar segments from CSS sheet var remainingBorderWidth = 0; var usedBorderWidth = 0; for (var i = 0; i < document.styleSheets[0].cssRules.length; i++) { if (document.styleSheets[0].cssRules[i].selectorText == "#" + elements.barRemaining) remainingBorderWidth = Number.parseInt(document.styleSheets[0].cssRules[i].style.borderWidth) * 2; else if (document.styleSheets[0].cssRules[i].selectorText == "#" + elements.barUsed) usedBorderWidth = Number.parseInt(document.styleSheets[0].cssRules[i].style.borderWidth) * 2; } var usage = (response.used / response.quota) * 100; usage = usage.toFixed(0); if (usage != 0) { barUsed.style = "display: inline-block; width: calc(" + usage + "% - " + usedBorderWidth + "px);"; barUsed.innerHTML = usage + "% Used"; } if (usage != 100) { barRemaining.style = "display: inline-block; width: calc(" + (100 - usage) + "% - " + remainingBorderWidth + "px);"; barRemaining.innerHTML = (100 - usage) + "% Remaining"; } transferUsed.innerHTML = response.used + "GB"; transferRemaining.innerHTML = (response.quota - response.used) + "GB"; transferQuota.innerHTML = response.quota + "GB"; }; var getPlanLabel = function(id) { for (var i = 0; i < data.plans.length; i++) { if (id == data.plans[i].id) return data.plans[i].label; } return ""; }; var getPlans = function(response) { // Add plans to array data.plans = data.plans.concat(response.data); // Request the next page if there are more pages if (response.page != response.pages) { apiGet("/linode/types?page=" + (response.page + 1), getPlans, null); return; } // Get linodes var filters = null; if (data.params.tag) filters = { "tags": data.params.tag }; apiGet("/linode/instances", displayLinodes, filters); }; var setup = function() { // Parse URL parameters data.params = parseParams(); ui.linodes = document.getElementById(elements.linodes); ui.loading = document.getElementById(elements.loading); ui.notifications = document.getElementById(elements.notifications); setupHeader(); // Get linode and transfer info apiGet("/linode/types", getPlans, null); apiGet("/account/transfer", displayTransfer, null); apiGet("/account/notifications", displayNotifications, null); }; var translatePlan = function(name, cell) { var callback = function(response) { cell.innerHTML = response.label; }; apiGet("/linode/types/" + name, callback, null); }; // Attach onload handler window.addEventListener("load", setup); })();