diff --git a/global.js b/global.js index 424a595..58f9404 100644 --- a/global.js +++ b/global.js @@ -35,36 +35,38 @@ var elements = { "username": "username" }; -// Regions (Linode doesn't provide "friendly" names via the API) +// Region names for legacy DCs no longer in the API var regionNames = { - "us-central": "Dallas, TX, USA", - "us-west": "Fremont, CA, USA", - "us-southeast": "Atlanta, GA, USA", - "us-east": "Newark, NJ, USA", - "us-east-1b": "Newark 2, NJ, USA", - "eu-west": "London, England, UK", - "ap-south": "Singapore, SG", - "eu-central": "Frankfurt, DE", - "ap-northeast": "Tokyo, JP", - "ap-northeast-1a": "Tokyo 2, JP", - "ca-central": "Toronto, ON, CA", - "ap-west": "Mumbai, IN", - "ap-southeast": "Sydney, NSW, AU", - "philadelphia": "Philadelphia, PA, USA", - "absecon": "Absecon, NJ, USA", - "us-iad": "Washington DC, USA", - "us-ord": "Chicago, IL, USA", - "fr-par": "Paris, FR", - "in-maa": "Chennai, IN", - "us-sea": "Seattle, WA, USA", - "br-gru": "San Paulo, BR", - "nl-ams": "Amsterdam, NL", - "se-sto": "Stockholm, SE", - "jp-osa": "Osaka, JP", - "it-mil": "Milan, IT", - "id-cgk": "Jakarta, ID", - "us-lax": "Los Angeles, CA, USA", - "us-mia": "Miami, FL, USA" + "us-east-1b": "Newark 2, NJ", + "philadelphia": "Philadelphia, PA", + "absecon": "Absecon, NJ" +}; + +// Group contries into regions for easier selection +var countryContinents = { + "us": "na", + "gb": "eu", + "jp": "ap", + "sg": "ap", + "de": "eu", + "in": "ap", + "ca": "na", + "au": "ap", + "fr": "eu", + "br": "sa", + "nl": "eu", + "se": "eu", + "es": "eu", + "it": "eu", + "id": "ap", + "nz": "ap", + "pl": "eu", + "za": "af", + "my": "ap", + "hk": "ap", + "co": "sa", + "mx": "na", + "cl": "sa" }; // Human-readable event titles @@ -862,4 +864,4 @@ function translateKernel(slug, element) apiGet("/linode/kernels/" + slug, callback, null); } -export { settings, elements, regionNames, apiDelete, apiGet, apiPost, apiPut, drawSeries, md5, migrateETA, oauthPost, oauthScopes, objPut, parseParams, setupHeader, eventTitles, timeString, translateKernel }; +export { settings, elements, regionNames, countryContinents, apiDelete, apiGet, apiPost, apiPut, drawSeries, md5, migrateETA, oauthPost, oauthScopes, objPut, parseParams, setupHeader, eventTitles, timeString, translateKernel }; diff --git a/images/create/create.js b/images/create/create.js index a1cc525..145e385 100644 --- a/images/create/create.js +++ b/images/create/create.js @@ -15,7 +15,7 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, regionNames, apiGet, apiPost, parseParams, setupHeader, timeString } from "/global.js"; +import { settings, elements, apiGet, apiPost, parseParams, setupHeader, timeString } from "/global.js"; (function() { diff --git a/images/delete/delete.js b/images/delete/delete.js index 73f0528..e25f674 100644 --- a/images/delete/delete.js +++ b/images/delete/delete.js @@ -15,7 +15,7 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, regionNames, apiGet, apiDelete, parseParams, setupHeader, timeString } from "/global.js"; +import { settings, elements, apiGet, apiDelete, parseParams, setupHeader, timeString } from "/global.js"; (function() { diff --git a/images/edit/edit.js b/images/edit/edit.js index bc693e4..ac4d4da 100644 --- a/images/edit/edit.js +++ b/images/edit/edit.js @@ -15,7 +15,7 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, regionNames, apiGet, apiPut, parseParams, setupHeader, timeString } from "/global.js"; +import { settings, elements, apiGet, apiPut, parseParams, setupHeader, timeString } from "/global.js"; (function() { diff --git a/images/images.js b/images/images.js index 801063f..3c1ca68 100644 --- a/images/images.js +++ b/images/images.js @@ -15,7 +15,7 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, regionNames, apiGet, parseParams, setupHeader, timeString } from "/global.js"; +import { settings, elements, apiGet, parseParams, setupHeader, timeString } from "/global.js"; (function() { diff --git a/images/upload/index.shtml b/images/upload/index.shtml index 34659fa..4319655 100644 --- a/images/upload/index.shtml +++ b/images/upload/index.shtml @@ -46,7 +46,14 @@ along with Linode Manager Classic. If not, see . Region - + For fastest initial upload, select the region that is geographically closest to you.
Once uploaded you will be able to deploy the image to other regions. diff --git a/images/upload/upload.css b/images/upload/upload.css index 85a77b1..7648a45 100644 --- a/images/upload/upload.css +++ b/images/upload/upload.css @@ -17,6 +17,10 @@ @import url('/global.css'); +optgroup { + display: none; +} + .step-2 { display: none; } diff --git a/images/upload/upload.js b/images/upload/upload.js index e3e1f45..20b538f 100644 --- a/images/upload/upload.js +++ b/images/upload/upload.js @@ -15,11 +15,12 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, regionNames, apiGet, apiPost, objPut, parseParams, setupHeader } from "/global.js"; +import { settings, elements, regionNames, countryContinents, apiGet, apiPost, objPut, parseParams, setupHeader } from "/global.js"; (function() { // Element names specific to this page + elements.dcOther = "dc-other"; elements.description = "description"; elements.imageFile = "image-file"; elements.label = "label"; @@ -35,6 +36,7 @@ import { settings, elements, regionNames, apiGet, apiPost, objPut, parseParams, // Static references to UI elements var ui = {}; + ui.dcOther = {}; ui.description = {}; ui.imageFile = {}; ui.label = {}; @@ -49,11 +51,19 @@ import { settings, elements, regionNames, apiGet, apiPost, objPut, parseParams, for (var i = 0; i < response.data.length; i++) { var dc = document.createElement("option"); dc.value = response.data[i].id; - if (regionNames[response.data[i].id]) + if (response.data[i].label && response.data[i].label.length) + dc.innerHTML = response.data[i].label; + else if (regionNames[response.data[i].id]) dc.innerHTML = regionNames[response.data[i].id]; else dc.innerHTML = response.data[i].id; - ui.region.appendChild(dc); + var optgroup = null; + if (countryContinents[response.data[i].country]) + optgroup = document.getElementById(countryContinents[response.data[i].country]); + if (!optgroup) + optgroup = ui.dcOther; + optgroup.style.display = "initial"; + optgroup.appendChild(dc); } ui.nextButton.disabled = false; @@ -126,6 +136,7 @@ import { settings, elements, regionNames, apiGet, apiPost, objPut, parseParams, } // Get element references + ui.dcOther = document.getElementById(elements.dcOther); ui.description = document.getElementById(elements.description); ui.imageFile = document.getElementById(elements.imageFile); ui.label = document.getElementById(elements.label); diff --git a/linodes/add/add.css b/linodes/add/add.css index 6ba0b41..d5d77e6 100644 --- a/linodes/add/add.css +++ b/linodes/add/add.css @@ -89,6 +89,10 @@ h3 { padding: 15px; } +optgroup { + display: none; +} + #right-links { float: right; } diff --git a/linodes/add/add.js b/linodes/add/add.js index a09b23f..21c4ef6 100644 --- a/linodes/add/add.js +++ b/linodes/add/add.js @@ -15,13 +15,14 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, regionNames, apiGet, apiPost, parseParams, setupHeader } from "/global.js"; +import { settings, elements, regionNames, countryContinents, apiGet, apiPost, parseParams, setupHeader } from "/global.js"; (function() { // Element names specific to this page elements.addButton = "add-button"; elements.datacenters = "datacenters"; + elements.dcOther = "dc-other"; elements.instanceType = "instance-type"; elements.instanceTypeActive = "instance-type-active"; @@ -33,6 +34,7 @@ import { settings, elements, regionNames, apiGet, apiPost, parseParams, setupHea // Static references to UI elements var ui = {}; ui.datacenters = {}; + ui.dcOther = {}; var createLinodeTypeButton = function(type) { @@ -67,16 +69,26 @@ import { settings, elements, regionNames, apiGet, apiPost, parseParams, setupHea for (var i = 0; i < response.data.length; i++) { var dc = document.createElement("option"); dc.value = response.data[i].id; - if (regionNames[response.data[i].id]) + if (response.data[i].label && response.data[i].label.length) + dc.innerHTML = response.data[i].label; + else if (regionNames[response.data[i].id]) dc.innerHTML = regionNames[response.data[i].id]; else dc.innerHTML = response.data[i].id; - ui.datacenters.appendChild(dc); + var optgroup = null; + if (countryContinents[response.data[i].country]) + optgroup = document.getElementById(countryContinents[response.data[i].country]); + if (!optgroup) + optgroup = ui.dcOther; + optgroup.style.display = "initial"; + optgroup.appendChild(dc); } // Request the next page if there are more pages - if (response.page != response.pages) + if (response.page != response.pages) { apiGet("/regions?page=" + (response.page + 1), displayRegions, null); + return; + } }; var displayTypes = function(response) @@ -135,6 +147,7 @@ import { settings, elements, regionNames, apiGet, apiPost, parseParams, setupHea data.params = parseParams(); ui.datacenters = document.getElementById(elements.datacenters); + ui.dcOther = document.getElementById(elements.dcOther); // Register add button handler document.getElementById(elements.addButton).addEventListener("click", handleAddLinode); diff --git a/linodes/add/index.shtml b/linodes/add/index.shtml index e38050b..e162b97 100644 --- a/linodes/add/index.shtml +++ b/linodes/add/index.shtml @@ -65,7 +65,14 @@ along with Linode Manager Classic. If not, see .

Location

- +
diff --git a/linodes/backup_details/backup_details.js b/linodes/backup_details/backup_details.js index 2c8cf0f..74a9057 100644 --- a/linodes/backup_details/backup_details.js +++ b/linodes/backup_details/backup_details.js @@ -50,6 +50,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea data.backup = {}; data.linode = {}; data.linodes = []; + data.region = {}; data.types = []; // Static references to UI elements @@ -89,6 +90,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea var plan = document.createElement("td"); if (linode.type) { + plan.innerHTML = linode.type; for (var i = 0; i < data.types.length; i++) { if (data.types[i].id == linode.type) { plan.innerHTML = data.types[i].label; @@ -103,7 +105,9 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea row.appendChild(plan); var location = document.createElement("td"); - if (regionNames[linode.region]) + if (data.region.label && data.region.label.length) + location.innerHTML = data.region.label; + else if (regionNames[linode.region]) location.innerHTML = regionNames[linode.region]; else location.innerHTML = linode.region; @@ -136,6 +140,15 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea ui.backupType.innerHTML = data.backup.type; + if (regionNames[data.backup.region]) { + ui.backupLocation.innerHTML = regionNames[data.backup.region]; + ui.destLocation.innerHTML = regionNames[data.backup.region]; + } else { + ui.backupLocation.innerHTML = data.backup.region; + ui.destLocation.innerHTML = data.backup.region; + } + apiGet("/regions/" + data.backup.region, displayRegion, null); + for (var i = 0; i < data.backup.configs.length; i++) { var li = document.createElement("li"); li.innerHTML = data.backup.configs[i]; @@ -152,7 +165,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea ui.backupSize.innerHTML = data.backup.totalSize + " MB"; - if (state.haveTypes && data.linode.id) + if (state.haveTypes) insertTypes(); }; @@ -169,18 +182,6 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea ui.linodeTagLink.innerHTML = "(" + data.linode.tags[0] + ")"; ui.linodeTag.style.display = "inline"; } - - // Display location - if (regionNames[data.linode.region]) { - ui.backupLocation.innerHTML = regionNames[data.linode.region]; - ui.destLocation.innerHTML = regionNames[data.linode.region]; - } else { - ui.backupLocation.innerHTML = data.linode.region; - ui.destLocation.innerHTML = data.linode.region; - } - - if (state.haveTypes && data.backup.id) - insertTypes(); }; // Callback for linode disks API call @@ -238,7 +239,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea // Request the next page if there are more pages if (response.page != response.pages) { var filter = { - "region": data.linode.region + "region": data.backup.region }; apiGet("/linode/instances?page=" + (response.page + 1), displayLinodes, filter); return; @@ -254,6 +255,17 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea } }; + // Callback for region API call + var displayRegion = function(response) + { + data.region = response; + + if (data.region.label && data.region.label.length) { + ui.backupLocation.innerHTML = response.label; + ui.destLocation.innerHTML = response.label; + } + }; + // Callback for linode types API call var displayTypes = function(response) { @@ -267,7 +279,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea } state.haveTypes = true; - if (data.backup.id && data.linode.id) + if (data.backup.id) insertTypes(); }; @@ -295,7 +307,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea var req = { "label": ui.destLabel.value, "type": ui.destPlan.value, - "region": data.linode.region, + "region": data.backup.region, "backup_id": data.backup.id }; var callback = function(response) @@ -348,11 +360,11 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea ui.destPlan.appendChild(option); } - updatePrice(null); + updateSpace(null); ui.newLinode.disabled = false; var filter = { - "region": data.linode.region + "region": data.backup.region }; apiGet("/linode/instances", displayLinodes, filter); }; @@ -410,7 +422,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea ui.newLinode = document.getElementById(elements.newLinode); // Register event handlers - ui.destPlan.addEventListener("input", updatePrice); + ui.destPlan.addEventListener("input", updateSpace); ui.newLinode.addEventListener("click", handleCreate); // Get data from API @@ -431,7 +443,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea }; // Update the price display - var updatePrice = function(event) + var updateSpace = function(event) { // Find the selected type var type = null; diff --git a/linodes/clone/clone.js b/linodes/clone/clone.js index 411d2a9..84cc8e3 100644 --- a/linodes/clone/clone.js +++ b/linodes/clone/clone.js @@ -15,7 +15,7 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNames, setupHeader, translateKernel } from "/global.js"; +import { settings, elements, apiGet, apiPost, countryContinents, migrateETA, parseParams, regionNames, setupHeader, translateKernel } from "/global.js"; (function() { @@ -25,6 +25,7 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam elements.configDiskRow = "config-disk-row"; elements.configsNone = "configs-none"; elements.configTable = "config-table-body"; + elements.dcOther = "dc-other"; elements.destBackups = "dest-backups"; elements.destBackupsPrice = "dest-backups-price"; elements.destLabel = "dest-label"; @@ -54,6 +55,7 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam data.configs = []; data.disks = []; data.linode = {}; + data.regions = []; data.types = []; // Static references to UI elements @@ -62,6 +64,7 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam ui.configCloneTable = {}; ui.configsNone = {}; ui.configTable = {}; + ui.dcOther = {}; ui.destBackups = {}; ui.destBackupsPrice = {}; ui.destLabel = {}; @@ -241,7 +244,17 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam } // Display the source location - if (regionNames[data.linode.region]) + var region = null; + for (var i = 0; i < data.regions.length; i++) { + if (data.regions[i].id == data.linode.region) { + region = data.regions[i]; + break; + } + } + + if (region && region.label && region.label.length) + ui.sourceLocation.innerHTML = region.label; + else if (regionNames[data.linode.region]) ui.sourceLocation.innerHTML = regionNames[data.linode.region]; else ui.sourceLocation.innerHTML = data.linode.region; @@ -290,25 +303,8 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam // Callback for regions API call var displayRegions = function(response) { - for (var i = 0; i < response.data.length; i++) { - // Add regions to selector - var dc = document.createElement("option"); - dc.value = response.data[i].id; - if (regionNames[response.data[i].id]) - dc.innerHTML = regionNames[response.data[i].id]; - else - dc.innerHTML = response.data[i].id; - ui.destLocation.appendChild(dc); - - // Add optgroups to linode selector - var optgroup = document.createElement("optgroup"); - optgroup.id = response.data[i].id; - if (regionNames[response.data[i].id]) - optgroup.label = regionNames[response.data[i].id]; - else - optgroup.label = response.data[i].label; - ui.destLinode.appendChild(optgroup); - } + // Add regions to array + data.regions = data.regions.concat(response.data); // Request the next page if there are more pages if (response.page != response.pages) { @@ -316,6 +312,37 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam return; } + for (var i = 0; i < data.regions.length; i++) { + // Add regions to selector + var dc = document.createElement("option"); + dc.value = data.regions[i].id; + if (data.regions[i].label && data.regions[i].label.length) + dc.innerHTML = data.regions[i].label; + else if (regionNames[data.regions[i].id]) + dc.innerHTML = regionNames[data.regions[i].id]; + else + dc.innerHTML = data.regions[i].id; + var group = null; + if (countryContinents[data.regions[i].country]) + group = document.getElementById(countryContinents[data.regions[i].country]); + if (!group) + group = ui.dcOther; + group.style.display = "initial"; + group.appendChild(dc); + + // Add optgroups to linode selector + var optgroup = document.createElement("optgroup"); + optgroup.id = data.regions[i].id; + if (data.regions[i].label && data.regions[i].label.length) + optgroup.label = data.regions[i].label; + else if (regionNames[data.regions[i].id]) + optgroup.label = regionNames[data.regions[i].id]; + else + optgroup.label = data.regions[i].label; + ui.destLinode.appendChild(optgroup); + } + + apiGet("/linode/instances/" + data.params.lid, displayDetails, null); apiGet("/linode/instances", displayLinodes, null); }; @@ -415,6 +442,7 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam ui.configCloneTable = document.getElementById(elements.configCloneTable); ui.configsNone = document.getElementById(elements.configsNone); ui.configTable = document.getElementById(elements.configTable); + ui.dcOther = document.getElementById(elements.dcOther); ui.destBackups = document.getElementById(elements.destBackups); ui.destBackupsPrice = document.getElementById(elements.destBackupsPrice); ui.destLabel = document.getElementById(elements.destLabel); @@ -442,7 +470,6 @@ import { settings, elements, apiGet, apiPost, migrateETA, parseParams, regionNam ui.destPlan.addEventListener("input", updatePrices); // Get data from API - apiGet("/linode/instances/" + data.params.lid, displayDetails, null); apiGet("/linode/instances/" + data.params.lid + "/configs", displayConfigs, null); apiGet("/linode/instances/" + data.params.lid + "/disks", displayDisks, null); apiGet("/linode/types", displayTypes, null); diff --git a/linodes/clone/index.shtml b/linodes/clone/index.shtml index 2ab1c05..c17d282 100644 --- a/linodes/clone/index.shtml +++ b/linodes/clone/index.shtml @@ -142,7 +142,14 @@ along with Linode Manager Classic. If not, see . Location - + Plan diff --git a/linodes/linodes.js b/linodes/linodes.js index 22c71e2..b30a435 100644 --- a/linodes/linodes.js +++ b/linodes/linodes.js @@ -48,6 +48,7 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro data.noTag = false; data.notifications = []; data.plans = []; + data.regions = []; // Static references to UI elements var ui = {}; @@ -60,6 +61,8 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro var state = {}; state.haveLinodes = false; state.haveNotifications = false; + state.haveRegions = false; + state.haveTypes = false; var createLinodeRow = function(linode, alt) { @@ -92,8 +95,10 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro plan.innerHTML = getPlanLabel(linode.type); else plan.innerHTML = "Unknown"; - if (plan.innerHTML == "") + if (plan.innerHTML == "") { + plan.innerHTML = linode.type; translatePlan(linode.type, plan); + } var ip = document.createElement("td"); ip.innerHTML = linode.ipv4[0]; var ipCount = 0; @@ -110,8 +115,17 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro plus.innerHTML = " (+" + ipCount + ")"; ip.appendChild(plus); } + var regionData = null; + for (var i = 0; i < data.regions.length; i++) { + if (data.regions[i].id == linode.region) { + regionData = data.regions[i]; + break; + } + } var region = document.createElement("td"); - if (regionNames[linode.region]) + if (regionData && regionData.label && regionData.label.length) + region.innerHTML = regionData.label; + else if (regionNames[linode.region]) region.innerHTML = regionNames[linode.region]; else region.innerHTML = linode.region; @@ -312,8 +326,19 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro body.innerHTML = data.notifications[i].message; } // Replace "this facility" with actual location for outages - if (data.notifications[i].type == "outage" && data.notifications[i].entity && data.notifications[i].entity.type == "region" && regionNames[data.notifications[i].entity.id]) - header.innerHTML = header.innerHTML.replace("this facility", regionNames[data.notifications[i].entity.id]); + if (data.notifications[i].type == "outage" && data.notifications[i].entity && data.notifications[i].entity.type == "region") { + var region = null; + for (var j = 0; j < data.regions.length; j++) { + if (data.regions[j].id == data.notifications[i].entity.id) { + region = data.regions[j]; + break; + } + } + if (region && region.label && region.label.length) + header.innerHTML = header.innerHTML.replace("this facility", region.label); + else if (regionNames[data.notifications[i].entity.id]) + header.innerHTML = header.innerHTML.replace("this facility", regionNames[data.notifications[i].entity.id]); + } notification.appendChild(header); notification.appendChild(body); ui.notifications.appendChild(notification); @@ -379,13 +404,42 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro return; } - // Get linodes - var filters = null; - if (data.params.tag) - filters = { - "tags": data.params.tag - }; - apiGet("/linode/instances", displayLinodes, filters); + state.haveTypes = true; + if (state.haveRegions) { + // Get linodes + var filters = null; + if (data.params.tag) + filters = { + "tags": data.params.tag + }; + apiGet("/linode/instances", displayLinodes, filters); + } + }; + + var getRegions = function(response) + { + // Add regions to array + data.regions = data.regions.concat(response.data); + + // Request the next page if there are more pages + if (response.page != response.pages) { + apiGet("/regions?page=" + (response.page + 1), getRegions, null); + return; + } + + state.haveRegions = true; + if (state.haveTypes) { + // Get linodes + var filters = null; + if (data.params.tag) + filters = { + "tags": data.params.tag + }; + apiGet("/linode/instances", displayLinodes, filters); + } + + // Get notifications + apiGet("/account/notifications", displayNotifications, null); }; var insertLinodes = function() @@ -425,9 +479,9 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro setupHeader(); // Get linode and transfer info + apiGet("/regions", getRegions, null); apiGet("/linode/types", getPlans, null); apiGet("/account/transfer", displayTransfer, null); - apiGet("/account/notifications", displayNotifications, null); }; var translatePlan = function(name, cell) diff --git a/volumes/add/add.css b/volumes/add/add.css index e58ee40..0ec827c 100644 --- a/volumes/add/add.css +++ b/volumes/add/add.css @@ -21,6 +21,10 @@ padding: 0px 15px 15px; } +optgroup { + display: none; +} + tbody tr td:first-of-type { font-weight: bold; text-align: right; diff --git a/volumes/add/add.js b/volumes/add/add.js index d006857..5070bf2 100644 --- a/volumes/add/add.js +++ b/volumes/add/add.js @@ -15,13 +15,14 @@ * along with Linode Manager Classic. If not, see . */ -import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHeader } from "/global.js"; +import { settings, elements, apiGet, apiPost, countryContinents, parseParams, regionNames, setupHeader } from "/global.js"; (function() { // Element names specific to this page elements.addButton = "add-button"; elements.attachment = "attachment"; + elements.dcOther = "dc-other"; elements.label = "label"; elements.location = "location"; elements.size = "size"; @@ -35,6 +36,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea var ui = {}; ui.addButton = {}; ui.attachment = {}; + ui.dcOther = {}; ui.label = {}; ui.location = {}; ui.size = {}; @@ -90,11 +92,19 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea for (var i = 0; i < data.regions.length; i++) { var loc = document.createElement("option"); loc.value = data.regions[i].id; - if (regionNames[data.regions[i].id]) + if (data.regions[i].label && data.regions[i].label.length) + loc.innerHTML = data.regions[i].label; + else if (regionNames[data.regions[i].id]) loc.innerHTML = regionNames[data.regions[i].id]; else loc.innerHTML = data.regions[i].id; - ui.location.appendChild(loc); + var optgroup = null; + if (countryContinents[data.regions[i].country]) + optgroup = document.getElementById(countryContinents[data.regions[i].country]); + if (!optgroup) + optgroup = ui.dcOther; + optgroup.style.display = "initial"; + optgroup.appendChild(loc); } // Request linodes in all the supported regions @@ -180,6 +190,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea // Get element references ui.addButton = document.getElementById(elements.addButton); ui.attachment = document.getElementById(elements.attachment); + ui.dcOther = document.getElementById(elements.dcOther); ui.label = document.getElementById(elements.label); ui.location = document.getElementById(elements.location); ui.size = document.getElementById(elements.size); diff --git a/volumes/add/index.shtml b/volumes/add/index.shtml index ccb64d7..937543c 100644 --- a/volumes/add/index.shtml +++ b/volumes/add/index.shtml @@ -50,6 +50,12 @@ along with Linode Manager Classic. If not, see . The datacenter where the new volume should be created diff --git a/volumes/clone/clone.js b/volumes/clone/clone.js index b85cb60..1e499b6 100644 --- a/volumes/clone/clone.js +++ b/volumes/clone/clone.js @@ -39,6 +39,13 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea ui.size = {}; ui.volumeLabel = {}; + // Callback for region API call + var displayRegion = function(response) + { + if (response.label && response.label.length) + ui.location.innerHTML = response.label; + }; + // Callback for volume API call var displayVolume = function(response) { @@ -55,6 +62,7 @@ import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHea ui.location.innerHTML = response.region; ui.cloneButton.disabled = false; + apiGet("/regions/" + response.region, displayRegion, null); }; // Click handler for clone button diff --git a/volumes/settings/settings.js b/volumes/settings/settings.js index 2816787..b89cf87 100644 --- a/volumes/settings/settings.js +++ b/volumes/settings/settings.js @@ -83,6 +83,13 @@ import { settings, elements, regionNames, apiGet, apiPost, apiPut, parseParams, } }; + // Callback for region API call + var displayRegion = function(response) + { + if (response.label && response.label.length) + ui.location.innerHTML = response.label; + }; + // Callback for volume API call var displayVolume = function(response) { @@ -117,6 +124,8 @@ import { settings, elements, regionNames, apiGet, apiPost, apiPut, parseParams, } ui.saveButton.disabled = false; + + apiGet("/regions/" + data.volume.region, displayRegion, null); }; // Click handler for save button diff --git a/volumes/volumes.js b/volumes/volumes.js index e20f838..e44457f 100644 --- a/volumes/volumes.js +++ b/volumes/volumes.js @@ -28,6 +28,7 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro // Data recieved from API calls var data = {}; data.linodes = {}; + data.regions = []; data.volumes = []; // Static references to UI elements @@ -35,6 +36,11 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro ui.loading = {}; ui.volumeBody = {}; + // Temporary state + var state = {}; + state.haveRegions = false; + state.haveVolumes = false; + // Generates a table row for a volume var createVolumeRow = function(volume, alt) { @@ -59,8 +65,17 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro size.innerHTML = volume.size + " GiB"; row.appendChild(size); + var regionData = null; + for (var i = 0; i < data.regions.length; i++) { + if (data.regions[i].id == volume.region) { + regionData = data.regions[i]; + break; + } + } var region = document.createElement("td"); - if (regionNames[volume.region]) + if (regionData && regionData.label && regionData.label.length) + region.innerHTML = regionData.label; + else if (regionNames[volume.region]) region.innerHTML = regionNames[volume.region]; else region.innerHTML = volume.region; @@ -108,6 +123,27 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro return row; }; + // Callback for regions API call + var displayRegions = function(response) + { + // Add regions to array + data.regions = data.regions.concat(response.data); + + // Request the next page if there are more pages + if (response.page != response.pages) { + apiGet("/regions?page=" + (response.page + 1), displayRegions, null); + return; + } + + state.haveRegions = true; + if (state.haveVolumes) { + // Insert volumes + ui.loading.remove(); + for (var i = 0; i < data.volumes.length; i++) + ui.volumeBody.appendChild(createVolumeRow(data.volumes[i], i % 2)); + } + }; + // Callback for volumes API call var displayVolumes = function(response) { @@ -127,10 +163,13 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro if (data.volumes.length == 0) location.href = "/volumes/add"; - // Insert volumes - ui.loading.remove(); - for (var i = 0; i < data.volumes.length; i++) - ui.volumeBody.appendChild(createVolumeRow(data.volumes[i], i % 2)); + state.haveVolumes = true; + if (state.haveRegions) { + // Insert volumes + ui.loading.remove(); + for (var i = 0; i < data.volumes.length; i++) + ui.volumeBody.appendChild(createVolumeRow(data.volumes[i], i % 2)); + } }; // Initial setup @@ -147,6 +186,7 @@ import { settings, elements, regionNames, apiGet, parseParams, setupHeader } fro // Get data from API apiGet("/volumes", displayVolumes, null); + apiGet("/regions", displayRegions, null); }; // Get the label of a given linode ID and update a cell's contents