You've already forked factorio-server-manager
mirror of
https://github.com/OpenFactorioServerManager/factorio-server-manager.git
synced 2026-06-19 20:06:55 +02:00
add component for console, add routes for websocket message events
This commit is contained in:
+49
@@ -10,3 +10,52 @@
|
||||
position: absolute;
|
||||
top: 0; left: 0; bottom: 0; right: 0;
|
||||
}
|
||||
|
||||
div.react-console-container {
|
||||
font-size: 0.85em;
|
||||
font-family: "Menlo", "Consolas", "DejaVu Sans Mono", monospace;
|
||||
width: 60em;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 20em;
|
||||
background: #efefef;
|
||||
padding: 0.5em;
|
||||
overflow: auto;
|
||||
white-space: pre; }
|
||||
|
||||
div.react-console-prompt-box {
|
||||
color: #444; }
|
||||
|
||||
span.react-console-prompt-label {
|
||||
font-weight: bold; }
|
||||
|
||||
div.react-console-focus span.react-console-cursor {
|
||||
background: #333;
|
||||
color: #eee; }
|
||||
|
||||
div.react-console-nofocus span.react-console-cursor {
|
||||
background: none;
|
||||
color: #444;
|
||||
outline: 0.1em solid #333;
|
||||
outline-offset: -0.1em; }
|
||||
|
||||
div.react-console-focus span.react-console-cursor-idle {
|
||||
animation: react-console-cursor-animation 1s infinite; }
|
||||
|
||||
@keyframes react-console-cursor-animation {
|
||||
0% {
|
||||
background: #333;
|
||||
color: #eee; }
|
||||
50% {
|
||||
background: #333;
|
||||
color: #eee; }
|
||||
51% {
|
||||
background: none;
|
||||
color: #444; }
|
||||
100% {
|
||||
background: none;
|
||||
color: #444; } }
|
||||
|
||||
div.react-console-message {
|
||||
color: #999;
|
||||
padding: 0.1em; }
|
||||
|
||||
+1
-1
@@ -5,5 +5,5 @@
|
||||
"cookie_encryption_key": "topsecretkey",
|
||||
"settings_file": "server-settings.json",
|
||||
"log_file": "factorio-server-manager.log",
|
||||
"rcon_pass": "factorio_rcon",
|
||||
"rcon_pass": "factorio_rcon"
|
||||
}
|
||||
|
||||
@@ -40,9 +40,6 @@ func randomPort() int {
|
||||
func initFactorio() (f *FactorioServer, err error) {
|
||||
f = new(FactorioServer)
|
||||
f.Settings = make(map[string]interface{})
|
||||
config.FactorioRconPort = randomPort()
|
||||
|
||||
log.Printf("%v", config)
|
||||
|
||||
if err = os.MkdirAll(config.FactorioConfigDir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create config directory: %v", err)
|
||||
|
||||
@@ -55,6 +55,9 @@ func loadServerConfig(f string) {
|
||||
|
||||
decoder := json.NewDecoder(file)
|
||||
err = decoder.Decode(&config)
|
||||
failOnError(err, "Error decoding JSON config file.")
|
||||
|
||||
config.FactorioRconPort = randomPort()
|
||||
}
|
||||
|
||||
func parseFlags() {
|
||||
|
||||
@@ -58,6 +58,7 @@ func NewRouter() *mux.Router {
|
||||
Methods("GET").
|
||||
Name("Websocket").
|
||||
Handler(AuthorizeHandler(ws))
|
||||
ws.Handle("log subscribe", logSubscribe)
|
||||
|
||||
// Serves the frontend application from the app directory
|
||||
// Uses basic file server to serve index.html and Javascript application
|
||||
@@ -90,6 +91,10 @@ func NewRouter() *mux.Router {
|
||||
Methods("GET").
|
||||
Name("Server").
|
||||
Handler(AuthorizeHandler(http.StripPrefix("/server", http.FileServer(http.Dir("./app/")))))
|
||||
r.Path("/console").
|
||||
Methods("GET").
|
||||
Name("Server").
|
||||
Handler(AuthorizeHandler(http.StripPrefix("/console", http.FileServer(http.Dir("./app/")))))
|
||||
r.PathPrefix("/").
|
||||
Methods("GET").
|
||||
Name("Index").
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/hpcloud/tail"
|
||||
)
|
||||
|
||||
func logSubscribe(client *Client, data interface{}) {
|
||||
t, err := tail.TailFile(config.FactorioLog, tail.Config{Follow: true})
|
||||
if err != nil {
|
||||
log.Printf("Error subscribing to tail log %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
for line := range t.Lines {
|
||||
client.send <- Message{"log update", line.Text}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,7 @@ class ConfigContent extends React.Component {
|
||||
var comment = this.state.serverSettings["_comment_" + key]
|
||||
return(
|
||||
<div className="form-group">
|
||||
<label for={key} className="control-label col-md-3">{setting_key}</label>
|
||||
<label htmlFor={key} className="control-label col-md-3">{setting_key}</label>
|
||||
<div className="col-md-6">
|
||||
{this.formTypeField(key, setting)}
|
||||
<p className="help-block">{comment}</p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import {IndexLink} from 'react-router';
|
||||
import Console from 'react-console-component'
|
||||
import Socket from '../../socket.js';
|
||||
|
||||
class ConsoleContent extends React.Component {
|
||||
@@ -7,17 +8,67 @@ class ConsoleContent extends React.Component {
|
||||
super(props);
|
||||
this.componentDidMount = this.componentDidMount.bind(this);
|
||||
this.connectWebsocket = this.connectWebsocket.bind(this);
|
||||
this.handleCommand = this.handleCommand.bind(this);
|
||||
this.onConnect = this.onConnect.bind(this);
|
||||
this.onNewLogLine = this.onNewLogLine.bind(this);
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.connectWebsocket()
|
||||
this.connectWebsocket();
|
||||
}
|
||||
|
||||
connectWebsocket() {
|
||||
var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
|
||||
let ws = new WebSocket(ws_scheme + "://" + window.location.host + "/ws");
|
||||
let socket = this.socket = new Socket(ws);
|
||||
socket.on('connect', this.onConnect.bind(this));
|
||||
socket.on('log update', this.onNewLogLine.bind(this));
|
||||
}
|
||||
|
||||
|
||||
handleCommand(command) {
|
||||
this.refs.console.log(command);
|
||||
this.refs.console.return();
|
||||
}
|
||||
|
||||
onConnect() {
|
||||
this.setState({connected: true});
|
||||
this.socket.emit("log subscribe");
|
||||
this.refs.console.log("connected to Factorio Server")
|
||||
}
|
||||
|
||||
onNewLogLine(logline) {
|
||||
console.log(logline);
|
||||
console.log(this.refs.console);
|
||||
this.refs.console.log({message: logline});
|
||||
this.refs.console.return();
|
||||
}
|
||||
|
||||
render() {
|
||||
return(
|
||||
<div className="content-wrapper">
|
||||
<section className="content-header">
|
||||
<h1>
|
||||
Server Console
|
||||
<small>Send commands and messages to the Factorio server</small>
|
||||
</h1>
|
||||
<ol className="breadcrumb">
|
||||
<li><IndexLink to="/"><i className="fa fa-dashboard"></i>Server Control</IndexLink></li>
|
||||
<li className="active">Here</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section className="content">
|
||||
|
||||
<Console ref="console"
|
||||
autofocus={true}
|
||||
handler={this.handleCommand}
|
||||
/>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ConsoleContent;
|
||||
|
||||
@@ -50,6 +50,7 @@ class Sidebar extends React.Component {
|
||||
<li><Link to="/saves" activeClassName="active"><i className="fa fa-floppy-o"></i> <span>Saves</span></Link></li>
|
||||
<li><Link to="/config" activeClassName="active"><i className="fa fa-cogs"></i> <span>Game Configuration</span></Link></li>
|
||||
<li><Link to="/settings" activeClassName="active"><i className="fa fa-cog"></i> <span>Settings</span></Link></li>
|
||||
<li><Link to="/console" activeClassName="active"><i className="fa fa-terminal"></i> <span>Console</span></Link></li>
|
||||
</ul>
|
||||
</section>
|
||||
<div style={{height: "100%"}}></div>
|
||||
|
||||
@@ -61,7 +61,7 @@ class AddUser extends React.Component {
|
||||
<div className="col-md-4">
|
||||
<form action="" onSubmit={this.createUser}>
|
||||
<div className="form-group">
|
||||
<label for="username">Username</label>
|
||||
<label htmlFor="username">Username</label>
|
||||
<input ref="username" type="text" className="form-control" id="username" placeholder="Enter username" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
"babel-preset-es2015": "^6.3.13",
|
||||
"babel-preset-react": "^6.3.13",
|
||||
"react": "^15.0.1",
|
||||
"react-console-component": "^0.6.1",
|
||||
"react-dom": "^15.0.1",
|
||||
"react-router": "^2.3.0",
|
||||
"sweetalert": "^1.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"css-loader": "^0.23.1",
|
||||
"react-console-component": "^0.6.1",
|
||||
"style-loader": "^0.13.1",
|
||||
"webpack": "^1.13.0"
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,18 +1,18 @@
|
||||
import {EventEmitter} from 'events';
|
||||
|
||||
class Socket {
|
||||
constructor(ws = new Websocket(), ee = new EventEmitter()){
|
||||
constructor(ws = new WebSocket(), ee = new EventEmitter()){
|
||||
this.ws = ws;
|
||||
this.ee = ee;
|
||||
ws.onmessage = this.message.bind(this);
|
||||
ws.onopen = this.message.bind(this);
|
||||
ws.onopen = this.open.bind(this);
|
||||
ws.onclose = this.close.bind(this);
|
||||
}
|
||||
on(name, fn){
|
||||
this.ee.on(name, fn);
|
||||
}
|
||||
off(name, fn){
|
||||
this.ee.RemoveListener(name, fn);
|
||||
this.ee.removeListener(name, fn);
|
||||
}
|
||||
emit(name, data){
|
||||
const message = JSON.stringify({name, data});
|
||||
@@ -20,11 +20,12 @@ class Socket {
|
||||
}
|
||||
message(e){
|
||||
try{
|
||||
const message = JSON.parse(e.data);
|
||||
let message = JSON.parse(e.data);
|
||||
console.log(message.name, message.data);
|
||||
this.ee.emit(message.name, message.data);
|
||||
}
|
||||
catch(err){
|
||||
this.ee.emit('error', err)
|
||||
this.ee.emit('error', err);
|
||||
}
|
||||
}
|
||||
open(){
|
||||
|
||||
Reference in New Issue
Block a user