diff --git a/client/scripts/WebConsole.js b/client/scripts/WebConsole.js index 53071b5..bc43ac5 100644 --- a/client/scripts/WebConsole.js +++ b/client/scripts/WebConsole.js @@ -1,344 +1,354 @@ -/** - Main JS file for WebConsole. - https://github.com/mesacarlos - 2019-2020 Carlos Mesa under MIT License. -*/ - -/** - * Global variables - */ -const persistenceManager = new WebConsolePersistenceManager(); -const connectionManager = new WebConsoleManager(); -let lang; -let autoPasswordCompleted = false; //When true, saved password was used. If a 401 is received, then saved password is not correct -let statusCommandsInterval = -1; -let commandHistoryIndex = -1; //Saves current command history index. -1 when not browsing history. - -/** - * Load list of servers in file servers.json - * and auto update in next request when file is changed - */ -function readServerList() { - let hash = persistenceManager.getSetting('server:hash') - - /** - * Hash code function used for compare version of file servers.json - * https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript - */ - const hashCode = s => s.split('').reduce((a,b)=>{a=((a<<5)-a)+b.charCodeAt(0);return a&a},0); - - fetch('servers.json') - .then(res => res.text()) - .then(json => { - if (hash !== hashCode(json)) { - persistenceManager.setSetting('server:hash', hashCode(json)) - JSON.parse(json).forEach(server => persistenceManager.saveServer(server)) - } - }) - .then(updateServerList) - .catch(() => console.info('Ignore load new list in file servers.json.')); -} - -/** -* Prepare and show server to user -*/ -function openServer(serverName){ - //Hide welcome div if user is not in welcome page - $("#welcomeContainer").hide(); - $("#serverContainer").show(); - - //Change server name and related info - $("#serverTitle").text(serverName); - $("#consoleTextArea").text(""); - $("#commandInput").prop("disabled", false); - $("#sendCommandButton").prop("disabled", false); - - //New server, new variables: - autoPasswordCompleted = false; - commandHistoryIndex = -1; //Reset command history index - - //Create or retrieve connection - connectionManager.loadConnection(serverName); - - //Load saved messages - let i; - const messages = connectionManager.activeConnection.messages; - for(i = 0; i < messages.length; i++){ - if(messages[i].status !== 401){ - onWebSocketsMessage(messages[i]); - } - } - - //Subscribe a function - connectionManager.activeConnection.subscribe(onWebSocketsMessage); -} - -function onWebSocketsMessage(message){ - switch (message.status) { - case 10: - //Console Output - writeToWebConsole(message.message, message.time); - break; - case 200: - //LoggedIn - writeToWebConsole(message.message); - - //Show user and permissions - $("#loggedUsernameLabel").text(message.username); - $("#loggedUserTypeLabel").text(message.as); - - //Disable command bar if user is viewer - if(message.as.toLowerCase() === "viewer"){ - $("#commandInput").prop("disabled", true); - $("#sendCommandButton").prop("disabled", true); - } - - //Read log file if enabled - if(connectionManager.activeConnection.isLogged === false){ - connectionManager.activeConnection.isLogged = true; - if(persistenceManager.getSetting("retrieveLogFile") === true) - connectionManager.askForLogs(); - } - break; - case 400: - //Unknown Command - writeToWebConsole(message.message); - break; - case 401: - //Waiting for login. Show password modal or retrieve password - const savedPwd = persistenceManager.getServer(connectionManager.activeConnection.serverName).serverPassword; - if(typeof savedPwd !== "undefined" && !autoPasswordCompleted){ - connectionManager.sendPassword(savedPwd); - autoPasswordCompleted = true; - }else{ - $('#passwordModal').modal('show'); - } - break; - case 1000: - //Players - writePlayerInfo(message.connectedPlayers, message.maxPlayers); - connectionManager.activeConnection.players = JSON.parse(message.players); - break; - case 1001: - //Cpu Usage - writeCpuInfo(message.usage); - break; - case 1002: - //RAM Usage - writeRamInfo(message.free, message.used, message.max); - break; - case 1003: - //Server TPS - writeTpsInfo(message.tps, 20); - break; - default: - console.log('Unknown server response:'); - } - console.log(message); - - //Add interval for Players, CPU and RAM info, if not set - if(statusCommandsInterval === -1 && message.status !== 401){ - statusCommandsInterval = setInterval(function(){ - connectionManager.askForInfo(); - }, 2500); - } -} - -/** -* Write to console -*/ -function writeToWebConsole(msg, time){ - const isScrolledDown = document.getElementById("consoleTextArea").scrollHeight - document.getElementById("consoleTextArea").scrollTop - 40 === $("#consoleTextArea").height(); - - //Write to div, replacing < to < (to avoid XSS) and replacing new line to br. - msg = msg.replace(/"); - - //Color filter for Windows (thanks to SuperPykkon) - msg = msg.replace(/\[0;30;22m/g, ""); //&0 - msg = msg.replace(/\[0;34;22m/g, ""); //&1 - msg = msg.replace(/\[0;32;22m/g, ""); //&2 - msg = msg.replace(/\[0;36;22m/g, ""); //&3 - msg = msg.replace(/\[0;31;22m/g, ""); //&4 - msg = msg.replace(/\[0;35;22m/g, ""); //&5 - msg = msg.replace(/\[0;33;22m/g, ""); //&6 - msg = msg.replace(/\[0;37;22m/g, ""); //&7 - msg = msg.replace(/\[0;30;1m/g, ""); //&8 - msg = msg.replace(/\[0;34;1m/g, ""); //&9 - msg = msg.replace(/\[0;32;1m/g, ""); //&a - msg = msg.replace(/\[0;36;1m/g, ""); //&b - msg = msg.replace(/\[0;31;1m/g, ""); //&c - msg = msg.replace(/\[0;35;1m/g, ""); //&d - msg = msg.replace(/\[0;33;1m/g, ""); //&e - msg = msg.replace(/\[0;37;1m/g, ""); //&f - msg = msg.replace(/\[m/g, ""); //&f - - //Color filter for UNIX (This is easier!) - //span may not be closed every time but browsers will do for ourselves - msg = msg.replace(/§0/g, ""); //&0 - msg = msg.replace(/§1/g, ""); //&1 - msg = msg.replace(/§2/g, ""); //&2 - msg = msg.replace(/§3/g, ""); //&3 - msg = msg.replace(/§4/g, ""); //&4 - msg = msg.replace(/§5/g, ""); //&5 - msg = msg.replace(/§6/g, ""); //&6 - msg = msg.replace(/§7/g, ""); //&7 - msg = msg.replace(/§8/g, ""); //&8 - msg = msg.replace(/§9/g, ""); //&9 - msg = msg.replace(/§a/g, ""); //&a - msg = msg.replace(/§b/g, ""); //&b - msg = msg.replace(/§c/g, ""); //&c - msg = msg.replace(/§d/g, ""); //&d - msg = msg.replace(/§e/g, ""); //&e - msg = msg.replace(/§f/g, ""); //&f - - msg = msg.replace(/§l/g, ""); //&l - msg = msg.replace(/§m/g, ""); //&m - msg = msg.replace(/§n/g, ""); //&n - msg = msg.replace(/§o/g, ""); //&o - - msg = msg.replace(/§r/g, ""); //&r - - //Color filter for MC 1.18 (Also easy :D) - //span may not be closed every time but browsers will do for ourselves - msg = msg.replace(/0/g, ""); //&0 - msg = msg.replace(/1/g, ""); //&1 - msg = msg.replace(/2/g, ""); //&2 - msg = msg.replace(/3/g, ""); //&3 - msg = msg.replace(/4/g, ""); //&4 - msg = msg.replace(/5/g, ""); //&5 - msg = msg.replace(/6/g, ""); //&6 - msg = msg.replace(/7/g, ""); //&7 - msg = msg.replace(/8/g, ""); //&8 - msg = msg.replace(/9/g, ""); //&9 - msg = msg.replace(/a/g, ""); //&a - msg = msg.replace(/b/g, ""); //&b - msg = msg.replace(/c/g, ""); //&c - msg = msg.replace(/d/g, ""); //&d - msg = msg.replace(/e/g, ""); //&e - msg = msg.replace(/f/g, ""); //&f - - msg = msg.replace(/l/g, ""); //&l - msg = msg.replace(/m/g, ""); //&m - msg = msg.replace(/n/g, ""); //&n - msg = msg.replace(/o/g, ""); //&o - - msg = msg.replace(/r/g, ""); //&r - - //Append datetime if enabled - if(persistenceManager.getSetting("dateTimePrefix")){ - if(typeof time !== 'undefined' && time !== null) //if time is present and not null - msg = "[" + time + "] " + msg; - else if(typeof time !== 'undefined' && time === null) //if time is present and null - ; //no time (is already printed) - else - msg = "[" + new Date().toLocaleTimeString() + "] " + msg; - } - - - $("#consoleTextArea").append(msg + "
"); - - if(isScrolledDown){ - const textarea = document.getElementById('consoleTextArea'); - textarea.scrollTop = textarea.scrollHeight; - } -} - -/** -* Fill connected players card -*/ -function writePlayerInfo(connected, maximum){ - $("#connectedPlayers").text(connected); - $("#maxPlayers").text(maximum); - - const percent = (connected / maximum) * 100; - $("#playerProgressBar").width(percent + "%"); -} - -/** -* Fill CPU info card -*/ -function writeCpuInfo(usage){ - $("#cpuInfo").text(usage + "%"); - - $("#CpuProgressBar").width(usage + "%"); -} - -/** -* Fill RAM info card -*/ -function writeRamInfo(free, used, total){ - $("#usedRam").text(used); - $("#totalRam").text(total); - - const percent = (used / total) * 100; - $("#RamProgressBar").width(percent + "%"); -} - -/** - * Fill TPS info card - */ -function writeTpsInfo(tps, max){ - if(tps > 20) { - tps = 20; - } - $("#tps").text(tps); - $("#maxTps").text(max); - - const percent = (tps / max) * 100; - $("#TpsProgressBar").width(percent + "%"); -} - -/** -* Called from WebConsoleConnector only. -*/ -function closedConnection(serverName){ - if(connectionManager.activeConnection.serverName === serverName){ - //Disable command input and button - $("#commandInput").prop("disabled", true); - $("#sendCommandButton").prop("disabled", true); - - //Inform user - $('#disconnectionModal').modal('show'); - } - connectionManager.deleteConnection(serverName, true); -} - -/** -* Shows welcome screen -*/ -function backToHomepage(){ - //Stop gathering info from server - clearInterval(statusCommandsInterval); - statusCommandsInterval = -1; - - //Reset command history index - commandHistoryIndex = -1; - - //Clear all server indicators - writePlayerInfo(0, 0); - writeCpuInfo(0); - writeRamInfo(0, 0, 0); - - $("#welcomeContainer").show(); - $("#serverContainer").hide(); -} - -/** -* Update dropdown with saved server list -*/ -function updateServerList(){ - //Delete all servers in dropdown - $('.servermenuitem').remove(); - - //Add all servers - const servers = persistenceManager.getAllServers(); - for(let i = 0; i < servers.length; i++){ - $('#ServerListDropDown').append('' + servers[i].serverName.replace(//g,">").replace(/'/g,"").replace(/"/g,"") + ''); - } - - //Show a "no servers" message when no servers are added - if(servers.length === 0){ - $('#ServerListDropDown').append('No servers added'); - } -} +/** + Main JS file for WebConsole. + https://github.com/mesacarlos + 2019-2020 Carlos Mesa under MIT License. +*/ + +/** + * Global variables + */ +const persistenceManager = new WebConsolePersistenceManager(); +const connectionManager = new WebConsoleManager(); +let lang; +let autoPasswordCompleted = false; //When true, saved password was used. If a 401 is received, then saved password is not correct +let statusCommandsInterval = -1; +let commandHistoryIndex = -1; //Saves current command history index. -1 when not browsing history. +var reconnecting = false; + + +/** + * Load list of servers in file servers.json + * and auto update in next request when file is changed + */ +function readServerList() { + let hash = persistenceManager.getSetting('server:hash') + + /** + * Hash code function used for compare version of file servers.json + * https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript + */ + const hashCode = s => s.split('').reduce((a,b)=>{a=((a<<5)-a)+b.charCodeAt(0);return a&a},0); + + fetch('servers.json') + .then(res => res.text()) + .then(json => { + if (hash !== hashCode(json)) { + persistenceManager.setSetting('server:hash', hashCode(json)) + JSON.parse(json).forEach(server => persistenceManager.saveServer(server)) + } + }) + .then(updateServerList) + .catch(() => console.info('Ignore load new list in file servers.json.')); +} + + +function reconnectServer(serverName) { + $('#disconnectionModal').hide(); + reconnecting = true; + openServer(serverName); +} + +/** +* Prepare and show server to user +*/ +function openServer(serverName){ + //Hide welcome div if user is not in welcome page + $("#welcomeContainer").hide(); + $("#serverContainer").show(); + $("#serverTitle").text(serverName); //Change server name and related info + + $("#consoleTextArea").css("font-size", persistenceManager.getSetting("consoleFontSize")+"px"); + + if (!reconnecting && typeof connectionManager.activeConnection === 'undefined') $("#consoleTextArea").text(""); + + $("#commandInput").prop("disabled", false); + $("#sendCommandButton").prop("disabled", false); + + //New server, new variables: + autoPasswordCompleted = false; + commandHistoryIndex = -1; //Reset command history index + + connectionManager.loadConnection(serverName); //Create or retrieve connection + + //Load saved messages +// let i; +// const messages = connectionManager.activeConnection.messages; +// for(i = 0; i < messages.length; i++){ +// if(messages[i].status !== 401){ +// onWebSocketsMessage(messages[i]); +// } +// } + //Subscribe a function + connectionManager.activeConnection.subscribe(onWebSocketsMessage); +} + +function onWebSocketsMessage(message){ + switch (message.status) { + case 10: //Console Output + writeToWebConsole(message.message, message.time); + break; + case 200: //LoggedIn + writeToWebConsole(message.message); + //Show user and permissions + $("#loggedUsernameLabel").text(message.username); + $("#loggedUserTypeLabel").text(message.as); + //Disable command bar if user is viewer + if(message.as.toLowerCase() === "viewer"){ + $("#commandInput").prop("disabled", true); + $("#sendCommandButton").prop("disabled", true); + } + //Read log file if enabled + if(connectionManager.activeConnection.isLogged === false){ + connectionManager.activeConnection.isLogged = true; + if(persistenceManager.getSetting("retrieveLogFile") === true) { + if (reconnecting) reconnecting = false; + else connectionManager.askForLogs(); + } + } + break; + case 400: + //Unknown Command + writeToWebConsole(message.message); + break; + case 401: //Waiting for login. Show password modal or retrieve password + const savedPwd = persistenceManager.getServer(connectionManager.activeConnection.serverName).serverPassword; + if(typeof savedPwd !== "undefined" && !autoPasswordCompleted){ + connectionManager.sendPassword(savedPwd); + autoPasswordCompleted = true; + } else { $('#passwordModal').modal('show'); } + break; + case 1000: //Players + writePlayerInfo(message.connectedPlayers, message.maxPlayers); + connectionManager.activeConnection.players = JSON.parse(message.players); + break; + case 1001: //Cpu Usage + writeCpuInfo(message.usage); + break; + case 1002: //RAM Usage + writeRamInfo(message.free, message.used, message.max); + break; + case 1003: //Server TPS + writeTpsInfo(message.tps, 20); + break; + default: + console.log('Unknown server response:'); + } + console.log(message); + + //Add interval for Players, CPU and RAM info, if not set + if(statusCommandsInterval === -1 && message.status !== 401){ + statusCommandsInterval = setInterval(function(){ + connectionManager.askForInfo(); + }, persistenceManager.getSetting("infoRefreshInterval")); + } +} + +/** +* Write to console +*/ +function writeToWebConsole(msg, time){ + const textArea = document.getElementById("consoleTextArea") + const isScrolledDown = (textArea.scrollHeight-textArea.scrollTop-40) <= ($("#consoleTextArea").height()+100); + //Write to div, replacing < to < (to avoid XSS) and replacing new line to br. + msg = msg.replace(/"); + + // LINUX color codes: + msg = msg.replace(/\033\[30m/g, "
"); //&0 + msg = msg.replace(/\033\[90m/g, ""); //&0 + + msg = msg.replace(/\033\[34m/g, ""); //&1 + msg = msg.replace(/\033\[32m/g, ""); //&2 was \/ + msg = msg.replace(/\033\[92m/g, ""); //&2 was #00AA00 + // msg = msg.replace(/\033\[36m/g, ""); //&3 + msg = msg.replace(/\033\[96m/g, ""); //&3 was #00AAAA + // msg = msg.replace(/\033\[31m/g, ""); //&4 + msg = msg.replace(/\033\[91m/g, ""); //&4 was #AA0000 + + msg = msg.replace(/\033\[35m/g, ""); //&5 + msg = msg.replace(/\033\[33m/g, ""); //&6 + msg = msg.replace(/\033\[37m/g, ""); //&7 + msg = msg.replace(/\033\[30m/g, ""); //&8 + msg = msg.replace(/\033\[34m/g, ""); //&9 + msg = msg.replace(/\033\[33m/g, ""); //&a was #55FF55 + msg = msg.replace(/\033\[36m/g, ""); //&b was #55FFFF + msg = msg.replace(/\033\[31m/g, ""); //&c was #FF5555 + // msg = msg.replace(/\033\[35m/g, ""); //&d + msg = msg.replace(/\033\[95m/g, ""); //&d + // msg = msg.replace(/\033\[33m/g, ""); //&e + msg = msg.replace(/\033\[93m/g, ""); //&e + // msg = msg.replace(/\033\[37m/g, ""); //&f + msg = msg.replace(/\033\[97m/g, ""); //&f + + msg = msg.replace(/\033\[1m/g, ""); //&l + // msg = msg.replace(/\022\[2m/g, ""); //&m + msg = msg.replace(/\033\[3m/g, ""); //&o + msg = msg.replace(/\033\[4m/g, ""); //&n + + msg = msg.replace(/\033\[8m/g, ""); //crazy text + + msg = msg.replace(/\033\[0m/g, ""); //&r + + + //Color filter for Windows (thanks to SuperPykkon) + // msg = msg.replace(/\[0;30;22m/g, ""); //&0 + // msg = msg.replace(/\[0;34;22m/g, ""); //&1 + // msg = msg.replace(/\[0;32;22m/g, ""); //&2 + // msg = msg.replace(/\[0;36;22m/g, ""); //&3 + // msg = msg.replace(/\[0;31;22m/g, ""); //&4 + // msg = msg.replace(/\[0;35;22m/g, ""); //&5 + // msg = msg.replace(/\[0;33;22m/g, ""); //&6 + // msg = msg.replace(/\[0;37;22m/g, ""); //&7 + // msg = msg.replace(/\[0;30;1m/g, ""); //&8 + // msg = msg.replace(/\[0;34;1m/g, ""); //&9 + // msg = msg.replace(/\[0;32;1m/g, ""); //&a + // msg = msg.replace(/\[0;36;1m/g, ""); //&b + // msg = msg.replace(/\[0;31;1m/g, ""); //&c + // msg = msg.replace(/\[0;35;1m/g, ""); //&d + // msg = msg.replace(/\[0;33;1m/g, ""); //&e + // msg = msg.replace(/\[0;37;1m/g, ""); //&f + // // msg = msg.replace(/\[m/g, ""); //&f + + //Color filter for UNIX (This is easier!) + //span may not be closed every time but browsers will do for ourselves + // msg = msg.replace(/§0/g, ""); //&0 + // msg = msg.replace(/§1/g, ""); //&1 + // msg = msg.replace(/§2/g, ""); //&2 + // msg = msg.replace(/§3/g, ""); //&3 + // msg = msg.replace(/§4/g, ""); //&4 + // msg = msg.replace(/§5/g, ""); //&5 + // msg = msg.replace(/§6/g, ""); //&6 + // msg = msg.replace(/§7/g, ""); //&7 + // msg = msg.replace(/§8/g, ""); //&8 + // msg = msg.replace(/§9/g, ""); //&9 + // msg = msg.replace(/§a/g, ""); //&a + // msg = msg.replace(/§b/g, ""); //&b + // msg = msg.replace(/§c/g, ""); //&c + // msg = msg.replace(/§d/g, ""); //&d + // msg = msg.replace(/§e/g, ""); //&e + // msg = msg.replace(/§f/g, ""); //&f + + // msg = msg.replace(/§l/g, ""); //&l + // msg = msg.replace(/§m/g, ""); //&m + // msg = msg.replace(/§n/g, ""); //&n + // msg = msg.replace(/§o/g, ""); //&o + + // msg = msg.replace(/§r/g, ""); //&r + + + //Color filter for MC codes. + msg = msg.replace(/§0/g, ""); //&0 + msg = msg.replace(/§1/g, ""); //&1 + msg = msg.replace(/§2/g, ""); //&2 + msg = msg.replace(/§3/g, ""); //&3 + msg = msg.replace(/§4/g, ""); //&4 + msg = msg.replace(/§5/g, ""); //&5 + msg = msg.replace(/§6/g, ""); //&6 + msg = msg.replace(/§7/g, ""); //&7 + msg = msg.replace(/§8/g, ""); //&8 + msg = msg.replace(/§9/g, ""); //&9 + msg = msg.replace(/§a/g, ""); //&a + msg = msg.replace(/§b/g, ""); //&b + msg = msg.replace(/§c/g, ""); //&c + msg = msg.replace(/§d/g, ""); //&d + msg = msg.replace(/§e/g, ""); //&e + msg = msg.replace(/§f/g, ""); //&f + + msg = msg.replace(/§l/g, ""); //&l + msg = msg.replace(/§m/g, ""); //&m + msg = msg.replace(/§n/g, ""); //&n + msg = msg.replace(/§o/g, ""); //&o + + msg = msg.replace(/§r/g, ""); //&r + + //Append datetime if enabled + if(persistenceManager.getSetting("dateTimePrefix")){ + if(typeof time !== 'undefined') {//if time is present + if(time !== null) msg = "[" + time + "] " + msg; //and not null + else msg = "["+new Date().toLocaleTimeString()+"] "+msg; // and is null + } + } + $("#consoleTextArea").append(msg + "
"); + if(isScrolledDown){ textArea.scrollTop = textArea.scrollHeight; } +} +/** +* Fill connected players card +*/ +function writePlayerInfo(connected, maximum){ + $("#connectedPlayers").text(connected); $("#maxPlayers").text(maximum); + const percent = (connected / maximum) * 100; $("#playerProgressBar").width(percent + "%"); + if(connectionManager.activeConnection){ + $("#playerList").text(connectionManager.activeConnection.players.splice(",  ")); + } else $("#playerList").text(""); +} +/** +* Fill CPU info card +*/ +function writeCpuInfo(usage){ + $("#cpuInfo").text(usage + "%"); $("#CpuProgressBar").width(usage + "%"); +} +/** +* Fill RAM info card +*/ +function writeRamInfo(free, used, total){ + $("#usedRam").text(used); $("#totalRam").text(total); + const percent = (used / total) * 100; $("#RamProgressBar").width(percent + "%"); +} +/** + * Fill TPS info card + */ +function writeTpsInfo(tps, max){ + if(tps > 20) { tps = 20; } + $("#tps").text(tps); + $("#maxTps").text(max); + const percent = (tps / max) * 100; + $("#TpsProgressBar").width(percent + "%"); +} +/** +* Called from WebConsoleConnector and 'Disconnect' button +*/ +function closedConnection(serverName){ + if(connectionManager.activeConnection.serverName === serverName){ + //Disable command input and button + $("#commandInput").prop("disabled", true); + $("#sendCommandButton").prop("disabled", true); + //Inform user + $('#disconnectionModal').modal('show'); + $("#disconnectionModalReconnectButton").click(function() { + reconnectServer(serverName); + }); + } + connectionManager.deleteConnection(serverName, false); + clearInterval(statusCommandsInterval); // Stop gathering info from server + statusCommandsInterval = -1; + commandHistoryIndex = -1; //Reset command history index +} +/** +* Shows welcome screen +*/ +function backToHomepage(){ + clearInterval(statusCommandsInterval); //Stop gathering info from server + if(connectionManager.activeConnection === null) { $("#consoleTextArea").text(""); } + statusCommandsInterval = -1; + commandHistoryIndex = -1; //Reset command history index + writePlayerInfo(0, 0); writeCpuInfo(0); writeRamInfo(0, 0, 0); //Clear all server indicators + + $("#welcomeContainer").show(); + $("#serverContainer").hide(); +} +/** +* Update dropdown with saved server list +*/ +function updateServerList(){ + //Delete all servers in dropdown + $('.servermenuitem').remove(); + //Add all servers + const servers = persistenceManager.getAllServers(); + for(let i = 0; i < servers.length; i++){ + $('#ServerListDropDown').append(`${servers[i].serverName.replace(//g,">").replace(/'/g,"").replace(/"/g,"")}`); + } + //Show a "no servers" message when no servers are added + if(servers.length === 0){ + $('#ServerListDropDown').append('No servers added'); + } +} \ No newline at end of file