Added fake terminal to /nodeDetails

It doesn't do anything yet, but it should allow sending commands to servers and watching their output.
This commit is contained in:
Danielv123 committed 2017-07-13 11:59:38 +02:00
1 parent e3b8926e35
commit 512b3c66a5
5 files changed
+365 -2

No files matched your search

+1
View File
@@ -1,6 +1,7 @@
<title>Clusterio</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://code.jquery.com/jquery.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.js" type="text/javascript"></script>
<script src="http://momentjs.com/downloads/moment.min.js" type="text/javascript"></script>
<script src="main.js"></script>
+185
View File
@@ -0,0 +1,185 @@
/*! terminal.js v2.0 | (c) 2014 Erik Österberg | https://github.com/eosterberg/terminaljs */
var Terminal = (function () {
// PROMPT_TYPE
var PROMPT_INPUT = 1, PROMPT_PASSWORD = 2, PROMPT_CONFIRM = 3
var fireCursorInterval = function (inputField, terminalObj) {
var cursor = terminalObj._cursor
setTimeout(function () {
if (inputField.parentElement && terminalObj._shouldBlinkCursor) {
cursor.style.visibility = cursor.style.visibility === 'visible' ? 'hidden' : 'visible'
fireCursorInterval(inputField, terminalObj)
} else {
cursor.style.visibility = 'visible'
}
}, 500)
}
var firstPrompt = true;
promptInput = function (terminalObj, message, PROMPT_TYPE, callback) {
var shouldDisplayInput = (PROMPT_TYPE === PROMPT_INPUT)
var inputField = document.createElement('input')
inputField.style.position = 'absolute'
inputField.style.zIndex = '-100'
inputField.style.outline = 'none'
inputField.style.border = 'none'
inputField.style.opacity = '0'
inputField.style.fontSize = '0.2em'
terminalObj._inputLine.textContent = ''
terminalObj._input.style.display = 'block'
terminalObj.html.appendChild(inputField)
fireCursorInterval(inputField, terminalObj)
if (message.length) terminalObj.print(PROMPT_TYPE === PROMPT_CONFIRM ? message + ' (y/n)' : message)
inputField.onblur = function () {
terminalObj._cursor.style.display = 'none'
}
inputField.onfocus = function () {
inputField.value = terminalObj._inputLine.textContent
terminalObj._cursor.style.display = 'inline'
}
terminalObj.html.onclick = function () {
inputField.focus()
}
inputField.onkeydown = function (e) {
if (e.which === 37 || e.which === 39 || e.which === 38 || e.which === 40 || e.which === 9) {
e.preventDefault()
} else if (shouldDisplayInput && e.which !== 13) {
setTimeout(function () {
terminalObj._inputLine.textContent = inputField.value
}, 1)
}
}
inputField.onkeyup = function (e) {
if (PROMPT_TYPE === PROMPT_CONFIRM || e.which === 13) {
terminalObj._input.style.display = 'none'
var inputValue = inputField.value
if (shouldDisplayInput) terminalObj.print(inputValue)
terminalObj.html.removeChild(inputField)
if (typeof(callback) === 'function') {
if (PROMPT_TYPE === PROMPT_CONFIRM) {
callback(inputValue.toUpperCase()[0] === 'Y' ? true : false)
} else callback(inputValue)
}
}
}
if (firstPrompt) {
firstPrompt = false
setTimeout(function () { inputField.focus() }, 50)
} else {
inputField.focus()
}
}
var terminalBeep
var TerminalConstructor = function (id) {
if (!terminalBeep) {
terminalBeep = document.createElement('audio')
var source = '<source src="http://www.erikosterberg.com/terminaljs/beep.'
terminalBeep.innerHTML = source + 'mp3" type="audio/mpeg">' + source + 'ogg" type="audio/ogg">'
terminalBeep.volume = 0.05
}
this.html = document.createElement('div')
this.html.className = 'Terminal'
if (typeof(id) === 'string') { this.html.id = id }
this._innerWindow = document.createElement('div')
this._output = document.createElement('p')
this._inputLine = document.createElement('span') //the span element where the users input is put
this._cursor = document.createElement('span')
this._input = document.createElement('p') //the full element administering the user input, including cursor
this._shouldBlinkCursor = true
this.beep = function () {
terminalBeep.load()
terminalBeep.play()
}
this.print = function (message) {
var newLine = document.createElement('div')
newLine.textContent = message
this._output.appendChild(newLine)
}
this.input = function (message, callback) {
promptInput(this, message, PROMPT_INPUT, callback)
}
this.password = function (message, callback) {
promptInput(this, message, PROMPT_PASSWORD, callback)
}
this.confirm = function (message, callback) {
promptInput(this, message, PROMPT_CONFIRM, callback)
}
this.clear = function () {
this._output.innerHTML = ''
}
this.sleep = function (milliseconds, callback) {
setTimeout(callback, milliseconds)
}
this.setTextSize = function (size) {
this._output.style.fontSize = size
this._input.style.fontSize = size
}
this.setTextColor = function (col) {
this.html.style.color = col
this._cursor.style.background = col
}
this.setBackgroundColor = function (col) {
this.html.style.background = col
}
this.setWidth = function (width) {
this.html.style.width = width
}
this.setHeight = function (height) {
this.html.style.height = height
}
this.blinkingCursor = function (bool) {
bool = bool.toString().toUpperCase()
this._shouldBlinkCursor = (bool === 'TRUE' || bool === '1' || bool === 'YES')
}
this._input.appendChild(this._inputLine)
this._input.appendChild(this._cursor)
this._innerWindow.appendChild(this._output)
this._innerWindow.appendChild(this._input)
this.html.appendChild(this._innerWindow)
this.setBackgroundColor('black')
this.setTextColor('white')
this.setTextSize('1em')
this.setWidth('100%')
this.setHeight('100%')
this.html.style.fontFamily = 'Monaco, Courier'
this.html.style.margin = '0'
this._innerWindow.style.padding = '10px'
this._input.style.margin = '0'
this._output.style.margin = '0'
this._cursor.style.background = 'white'
this._cursor.innerHTML = 'C' //put something in the cursor..
this._cursor.style.display = 'none' //then hide it
this._input.style.display = 'none'
}
return TerminalConstructor
}())
+11
View File
@@ -18,5 +18,16 @@
<div id="details">
</div>
<div id="terminal">
<div class="titleBar">
<div class="title">
<p>Clusterio RCON shell</p>
</div>
<div class="titleButton close" onclick="minimizeTerminal();"></div>
<div class="titleButton maximize" onclick="maximizeTerminal();"></div>
<div class="titleButton minimize" onclick="minimizeTerminal();"></div>
</div>
<!-- JS generates a div called .Terminal that appears here with the display and typing things -->
</div>
</div>
</body>
+95 -2
View File
@@ -126,7 +126,9 @@ function populateSlaveInfo(){
HTML += "</div>" // end of left container
// chart
HTML += '<div id="' + slave.unique + '" class="productionGraph" style="width: calc(100% - 300px);"></div>'
HTML += '<div id="' + slave.unique + '" class="productionGraph" style="width: calc(100% - 300px);"></div>';
// terminal
// HTML += '<div id="terminal"></div>';
document.querySelector("#hero").innerHTML = HTML;
@@ -145,9 +147,100 @@ function populateSlaveInfo(){
// make production graph
makeGraph(slave.unique, slave.unique)
makeTerminal();
});
}
var slaveLogin = {};
function makeTerminal(){
myTerminal = new Terminal();
document.querySelector("#terminal").appendChild(myTerminal.html);
// use jQuery to allow the user to drag the window around
$("#terminal").draggable({
handle:".titleBar",
});
myTerminal.print('Welcome to Clusterio rcon!');
myTerminal.input('', handleTerminalInput);
if(localStorage.terminalMinimized && localStorage.terminalMinimized == "true"){
minimizeTerminal(true);
}
function print(string){
myTerminal.print(string);
}
function handleTerminalInput(inputString) {
// show clearly that it was a command that was typed, not terminal output
let lastLine = document.querySelector("#terminal div > p:nth-child(1) > div:last-child");
lastLine.innerHTML = "> " + lastLine.innerHTML;
argv = inputString.split(' ');
if(argv[0][0] == '/'){
if(slaveLogin && slaveLogin.name && slaveLogin.pass){
print('Running: '+inputString);
} else {
print('Not identified to communicate with any slave! Run "help" for more information.');
}
} else if(argv[0] == 'help'){
if(argv[1] == 'login'){
print('To send commands to a slave, you are required to identify yourself. You can do this with the login command. The name will be the name of the slave as displayed on master. The password is the rcon password of the slave, as per /instances/[name]/config.json');
} else if(argv[1] == "/c"){
print('To run a command, start with /. You can for example do /c game.print("hello world!")');
} else if(argv[1] == "issues"){
print("Issues are reported to Danielv123 on github or espernet IRC.");
print(" - http://github.com/Danielv123/factorioClusterio/issues");
print(" - EsperNet #factorio Danielv123");
} else {
print('To identify yourself to a slave, use "login [name] [password]"');
print(' - /c [command] - Run command');
print(' - login [name] [passs] - Connect to remote slave');
print(' - issues - Report an issue');
}
} else if(argv[0] == 'issues'){
print("Issues are reported to Danielv123 on github or espernet IRC.");
print(" - http://github.com/Danielv123/factorioClusterio/issues");
print(" - EsperNet #factorio Danielv123");
} else {
print('Invalid command!');
}
// keep handling input (unless something is seriously wrong)
myTerminal.input('',handleTerminalInput);
}
}
function minimizeTerminal(instant){
localStorage.terminalMinimized = true;
$('#terminal').draggable('disable');
if(!instant){
$('#terminal')[0].style.transition = 'left 0.2s linear, top 0.2s linear';
}
document.querySelector('.Terminal').style.height = 0;
let ter = $('#terminal')[0];
// if the window just spawned in and we are doing the first minimize, our position won't be set yet. We also don't want to save this blank position.
if(ter.style.left && ter.style.top){
localStorage.oldTerminalPosition = JSON.stringify({x:ter.style.left, y:ter.style.top});
}
ter.style.left = (window.innerWidth - ter.offsetWidth)+'px';
ter.style.top = (window.innerHeight - 25)+'px';
// if we did it instant we still want to set this property for after.
if(instant){
setTimeout(() => $('#terminal')[0].style.transition = 'left 0.2s linear, top 0.2s linear',200);
}
}
function maximizeTerminal(instant){
localStorage.terminalMinimized = false;
document.querySelector('.Terminal').style.height = '400px';
let ter = $('#terminal')[0];
// recover our old saved position
let oldTerminalPosition = JSON.parse(localStorage.oldTerminalPosition);
ter.style.left = oldTerminalPosition.x;
ter.style.top = oldTerminalPosition.y;
// remove our animation once its finished
// since instant is a true/false value, Number will convert it to 1 or 0. Since 0 is falsy, || will turn it into 200.
setTimeout(() => $('#terminal')[0].style.transition = 'none', (Number(instant) || 200));
$('#terminal').draggable('enable');
}
populateSlaveInfo();
// ID of slave, ID of canvasjs div without #
+73
View File
@@ -68,6 +68,79 @@ a:hover {
#contentGraph {
float:left;
}
/* terminal */
.Terminal p div {
color:lime;
}
.Terminal p span {
color:yellow;
}
.Terminal p > span:nth-child(1):before {
content:"> ";
}
.Terminal {
overflow-y: scroll;
position:absolute;
border-left:1px solid darkgrey;
border-bottom:1px solid darkgrey;
height:400px;
transition:height 0.2s linear;
}
#terminal {
width:640px;
height:400px;
position:fixed;
right:10px;
bottom:10px;
left:50%;
top:50%;
}
/* titleBar, the bar above windows where you can minimize, maximize etc. Mostly for the terminal. */
.titleBar {
width:100%;
height:25px;
background-color:white;
}
.titleBar > .title {
float:left;
margin-top: 3px;
margin-left: 5px;
}
.titleBar p {
color:black;
}
.titleBar > .titleButton {
width:50px;
height:100%;
float:right;
background-color:white;
color:black;
transition:0.3s;
}
.titleBar > .titleButton:hover {
background-color: lightgray;
}
.titleBar > .titleButton:before {
margin-left: 18px;
}
.titleBar > .titleButton.close:hover {
background-color: red;
color:white;
}
.titleBar > .titleButton.close:before {
content:"✕";
margin-top:5px;
}
.titleBar > .titleButton.maximize:before {
content:"⬜";
margin-top:5px;
}
.titleBar > .titleButton.minimize:before {
content:"__";
margin-left:17px;
}
/* Slave stuff */
.slaveBox {
float:left;