Adding Websocket for server details

Adding Starting status on languages files
Removing all useless refresh things
This commit is contained in:
Silversthorn 2022-01-21 23:50:04 +01:00
parent b385d1add3
commit 92a65ad7f1
30 changed files with 1008 additions and 837 deletions

View File

@ -325,6 +325,32 @@ class TasksManager:
'version': srv['raw_ping_result'].get('version'), 'version': srv['raw_ping_result'].get('version'),
'icon': srv['raw_ping_result'].get('icon') 'icon': srv['raw_ping_result'].get('icon')
}) })
if (len(websocket_helper.clients) > 0):
websocket_helper.broadcast_page_params(
'/panel/server_detail',
{
'id': str(server_id)
},
'update_server_details',
{
'id': srv['raw_ping_result'].get('id'),
'started': srv['raw_ping_result'].get('started'),
'running': srv['raw_ping_result'].get('running'),
'cpu': srv['raw_ping_result'].get('cpu'),
'mem': srv['raw_ping_result'].get('mem'),
'mem_percent': srv['raw_ping_result'].get('mem_percent'),
'world_name': srv['raw_ping_result'].get('world_name'),
'world_size': srv['raw_ping_result'].get('world_size'),
'server_port': srv['raw_ping_result'].get('server_port'),
'int_ping_results': srv['raw_ping_result'].get('int_ping_results'),
'online': srv['raw_ping_result'].get('online'),
'max': srv['raw_ping_result'].get('max'),
'players': srv['raw_ping_result'].get('players'),
'desc': srv['raw_ping_result'].get('desc'),
'version': srv['raw_ping_result'].get('version'),
'icon': srv['raw_ping_result'].get('icon')
}
)
if (len(servers_ping) > 0) & (len(websocket_helper.clients) > 0): if (len(servers_ping) > 0) & (len(websocket_helper.clients) > 0):
try: try:

View File

@ -1,153 +1,162 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% block meta %}{% end %}
<title>{% block title %}{{ _('Default') }}{% end %}</title>
<!-- plugins:css --> <head>
<link rel="stylesheet" href="/static/assets/vendors/mdi/css/materialdesignicons.min.css"> <!-- Required meta tags -->
<link rel="stylesheet" href="/static/assets/vendors/flag-icon-css/css/flag-icon.min.css"> <meta charset="utf-8">
<link rel="stylesheet" href="/static/assets/vendors/ti-icons/css/themify-icons.css"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css"> {% block meta %}{% end %}
<link rel="stylesheet" href="/static/assets/vendors/fontawesome5/css/all.css"> <title>{% block title %}{{ _('Default') }}{% end %}</title>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.22/fh-3.1.7/r-2.2.6/sc-2.0.3/sp-1.2.2/datatables.min.css"/>
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- endinject --> <!-- plugins:css -->
<link rel="stylesheet" href="/static/assets/vendors/mdi/css/materialdesignicons.min.css">
<link rel="stylesheet" href="/static/assets/vendors/flag-icon-css/css/flag-icon.min.css">
<link rel="stylesheet" href="/static/assets/vendors/ti-icons/css/themify-icons.css">
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css">
<link rel="stylesheet" href="/static/assets/vendors/fontawesome5/css/all.css">
<link rel="stylesheet" type="text/css"
href="https://cdn.datatables.net/v/bs4/dt-1.10.22/fh-3.1.7/r-2.2.6/sc-2.0.3/sp-1.2.2/datatables.min.css" />
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- Plugin css for this page --> <!-- endinject -->
<link rel="stylesheet" href="/static/assets/vendors/jvectormap/jquery-jvectormap.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- End Plugin css for this page -->
<!-- Layout styles --> <!-- Plugin css for this page -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css"> <link rel="stylesheet" href="/static/assets/vendors/jvectormap/jquery-jvectormap.css">
<!-- End Layout styles --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- End Plugin css for this page -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg"> <!-- Layout styles -->
<link rel="alternate icon" href="/static/assets/images/favicon.png" /> <link rel="stylesheet" href="/static/assets/css/dark/style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css"> <!-- End Layout styles -->
</head> <link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<body class="dark-theme"> </head>
<div class="container-scroller">
<!-- partial:partials/_navbar.html --> <body class="dark-theme">
<nav class="navbar default-layout col-lg-12 col-12 p-0 fixed-top d-flex flex-row"> <div class="container-scroller">
<div class="text-center navbar-brand-wrapper d-flex align-items-top justify-content-center"> <!-- partial:partials/_navbar.html -->
<a class="navbar-brand brand-logo" href="/panel/dashboard"> <nav class="navbar default-layout col-lg-12 col-12 p-0 fixed-top d-flex flex-row">
<img src="/static/assets/images/logo_long.svg" alt="logo" /> </a> <div class="text-center navbar-brand-wrapper d-flex align-items-top justify-content-center">
<a class="navbar-brand brand-logo-mini" href="/panel/dashboard"> <a class="navbar-brand brand-logo" href="/panel/dashboard">
<img src="/static/assets/images/logo_small.svg" alt="logo" /> </a> <img src="/static/assets/images/logo_long.svg" alt="logo" /> </a>
</div> <a class="navbar-brand brand-logo-mini" href="/panel/dashboard">
<div class="navbar-menu-wrapper d-flex align-items-center"> <img src="/static/assets/images/logo_small.svg" alt="logo" /> </a>
<button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize"> </div>
<span class="mdi mdi-menu"></span> <div class="navbar-menu-wrapper d-flex align-items-center">
</button> <button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize">
<span class="mdi mdi-menu"></span>
</button>
{% include notify.html %} {% include notify.html %}
<button class="navbar-toggler navbar-toggler-right d-lg-none align-self-center" type="button" data-toggle="offcanvas"> <button class="navbar-toggler navbar-toggler-right d-lg-none align-self-center" type="button"
<span class="mdi mdi-menu"></span> data-toggle="offcanvas">
</button> <span class="mdi mdi-menu"></span>
</div> </button>
</nav>
{% include main_menu.html %}
<div class="main-panel">
<div class="warnings">
<noscript class="noscript-warning" style="padding: 20px; background-color: rgb(247, 151, 15);">
<div>{% raw translate('base', 'doesNotWorkWithoutJavascript', data['lang']) %}</div>
</noscript>
</div>
{% block content %}
{% end %}
{% include footer.html %}
</div>
<!-- main-panel ends -->
</div> </div>
<!-- page-body-wrapper ends --> </nav>
{% include main_menu.html %}
<div class="main-panel">
<div class="warnings">
<noscript class="noscript-warning" style="padding: 20px; background-color: rgb(247, 151, 15);">
<div>{% raw translate('base', 'doesNotWorkWithoutJavascript', data['lang']) %}</div>
</noscript>
</div>
{% block content %}
{% end %}
{% include footer.html %}
</div> </div>
<!-- main-panel ends -->
</div>
<!-- page-body-wrapper ends -->
</div>
<style> <style>
.notifications { .notifications {
position: fixed; position: fixed;
width: 200px; width: 200px;
top: 70px; top: 70px;
right: 0px; right: 0px;
} }
.notification {
position: relative; .notification {
box-sizing: border-box; position: relative;
padding: 0.5rem; box-sizing: border-box;
padding-left: 0.7rem; padding: 0.5rem;
width: 180px; padding-left: 0.7rem;
margin-left: 10px; width: 180px;
margin-right: 10px; margin-left: 10px;
background: #282a40; margin-right: 10px;
transition: right 0.75s, opacity 0.75s, top 0.75s; background: #282a40;
right: -6rem; transition: right 0.75s, opacity 0.75s, top 0.75s;
opacity: 0.1; right: -6rem;
margin-bottom: 1rem; opacity: 0.1;
z-index: 999; margin-bottom: 1rem;
top: 0px; z-index: 999;
} top: 0px;
.notification.active { }
right: 0rem;
opacity: 1; .notification.active {
} right: 0rem;
.notification.remove { opacity: 1;
right: 0rem; }
opacity: 0.1;
top: -2rem; .notification.remove {
} right: 0rem;
.notification p { opacity: 0.1;
margin: 0px; top: -2rem;
width: calc(160.8px - 16px); }
z-index: inherit;
} .notification p {
.notification span { margin: 0px;
position: absolute; width: calc(160.8px - 16px);
right: 0.5rem; z-index: inherit;
top: 0.46rem; }
cursor: pointer;
font-weight: bold; .notification span {
line-height: 20px; position: absolute;
font-size: 22px; right: 0.5rem;
user-select: none; top: 0.46rem;
z-index: inherit; cursor: pointer;
} font-weight: bold;
</style> line-height: 20px;
<div class="notifications"></div> font-size: 22px;
user-select: none;
z-index: inherit;
}
</style>
<div class="notifications"></div>
<script src="/static/assets/vendors/js/vendor.bundle.base.js"></script> <script src="/static/assets/vendors/js/vendor.bundle.base.js"></script>
<script src="/static/assets/js/shared/off-canvas.js"></script> <script src="/static/assets/js/shared/off-canvas.js"></script>
<script src="/static/assets/js/shared/hoverable-collapse.js"></script> <script src="/static/assets/js/shared/hoverable-collapse.js"></script>
<script src="/static/assets/js/shared/misc.js"></script> <script src="/static/assets/js/shared/misc.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.22/fh-3.1.7/r-2.2.6/sc-2.0.3/sp-1.2.2/datatables.min.js"></script> <script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.22/fh-3.1.7/r-2.2.6/sc-2.0.3/sp-1.2.2/datatables.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.0/bootbox.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.0/bootbox.min.js"></script>
<script type="text/javascript" src="/static/assets/js/motd.js"></script>
<script> <script>
$.extend($.fn.dataTable.defaults, { $.extend($.fn.dataTable.defaults, {
language: {% raw translate('datatables', 'i18n', data['lang']) %} language: {% raw translate('datatables', 'i18n', data['lang']) %}
}) })
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security //used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
function getCookie(name) { function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined; return r ? r[1] : undefined;
} }
// tool tips // tool tips
@ -156,13 +165,13 @@
}) })
// Notify // Notify
$(document).ready(function(){ $(document).ready(function () {
$("#notificationDropdown").click(function(){ $("#notificationDropdown").click(function () {
$.get("/ajax/announcements", function(data){ $.get("/ajax/announcements", function (data) {
console.log(data); console.log(data);
bootbox.alert({ bootbox.alert({
title: "Notifications", title: "Notifications",
message: data, message: data,
}); });
}); });
@ -170,146 +179,150 @@
}); });
// {% if request.protocol == 'https' %} // {% if request.protocol == 'https' %}
let usingWebSockets = true; let usingWebSockets = true;
let listenEvents = []; let listenEvents = [];
try { try {
pageQueryParams = 'page_query_params=' + encodeURIComponent(location.search) pageQueryParams = 'page_query_params=' + encodeURIComponent(location.search)
page = 'page=' + encodeURIComponent(location.pathname) page = 'page=' + encodeURIComponent(location.pathname)
var wsInternal = new WebSocket('wss://' + location.host + '/ws?' + page + '&' + pageQueryParams); var wsInternal = new WebSocket('wss://' + location.host + '/ws?' + page + '&' + pageQueryParams);
wsInternal.onopen = function() { wsInternal.onopen = function () {
console.log('opened WebSocket connection:', wsInternal) console.log('opened WebSocket connection:', wsInternal)
}; };
wsInternal.onmessage = function (rawMessage) { wsInternal.onmessage = function (rawMessage) {
var message = JSON.parse(rawMessage.data); var message = JSON.parse(rawMessage.data);
console.log('got message: ', message) console.log('got message: ', message)
listenEvents listenEvents
.filter(listenedEvent => listenedEvent.event == message.event) .filter(listenedEvent => listenedEvent.event == message.event)
.forEach(listenedEvent => listenedEvent.callback(message.data)) .forEach(listenedEvent => listenedEvent.callback(message.data))
}; };
wsInternal.onerror = function (errorEvent) { wsInternal.onerror = function (errorEvent) {
console.error('WebSocket Error', errorEvent); console.error('WebSocket Error', errorEvent);
}; };
wsInternal.onclose = function (closeEvent) { wsInternal.onclose = function (closeEvent) {
console.log('Closed WebSocket', closeEvent); console.log('Closed WebSocket', closeEvent);
}; };
webSocket = { webSocket = {
on: function (event, callback) { on: function (event, callback) {
console.log('registered ' + event + ' event'); console.log('registered ' + event + ' event');
listenEvents.push({ event: event, callback: callback }) listenEvents.push({ event: event, callback: callback })
}, },
emit: function (event, data) { emit: function (event, data) {
var message = { var message = {
event: event, event: event,
data: data data: data
}
wsInternal.send(JSON.stringify(message));
} }
wsInternal.send(JSON.stringify(message));
} }
} catch (error) {
console.error('Error while making websocket helpers', error);
usingWebSockets = false;
} }
} catch (error) {
console.error('Error while making websocket helpers', error);
usingWebSockets = false;
}
// {% else %} // {% else %}
let usingWebSockets = false; let usingWebSockets = false;
warn('WebSockets are not supported in Crafty if not using the https protocol') warn('WebSockets are not supported in Crafty if not using the https protocol')
var webSocket; var webSocket;
// {% end%} // {% end%}
if (webSocket) { if (webSocket) {
webSocket.on('send_start_error', function (start_error) { webSocket.on('send_start_error', function (start_error) {
var x = document.querySelector('.bootbox'); var x = document.querySelector('.bootbox');
if(x){ if (x) {
x.remove()} x.remove()
var x = document.querySelector('.modal-backdrop');
if(x){
x.remove()}
bootbox.alert({
message: start_error.error,
callback: function () {
location.reload();
}
})
});
}
if (webSocket) {
webSocket.on('send_logs_bootbox', function (server_id) {
var x = document.querySelector('.bootbox');
if(x){
x.remove()}
var x = document.querySelector('.modal-backdrop');
if(x){
x.remove()}
bootbox.alert({
title: "{{ translate('notify', 'downloadLogs', data['lang']) }}",
message: "{{ translate('notify', 'finishedPreparing', data['lang']) }}",
buttons: {
ok: {
label: 'Download',
className: 'btn-info'
} }
}, var x = document.querySelector('.modal-backdrop');
callback: function(){ if (x) {
console.log("in callback") x.remove()
location.href="/panel/download_support_package";
}
});
});
}
if (webSocket) {
webSocket.on('send_eula_bootbox', function (server_id) {
var x = document.querySelector('.bootbox');
if(x){
x.remove()}
var x = document.querySelector('.modal-backdrop');
if(x){
x.remove()}
bootbox.confirm({
title: '{% raw translate("error", "eulaTitle", data['lang']) %}',
message: '{% raw translate("error", "eulaMsg", data['lang']) %} <br><br><a href="https://account.mojang.com/documents/minecraft_eula" target="_blank">EULA</a><br><br>{% raw translate("error", "eulaAgree", data['lang']) %}',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-info'
},
cancel: {
label: 'No',
className: 'btn-secondary'
} }
}, bootbox.alert({
callback: function (result) { message: start_error.error,
if(result == true){ callback: function () {
eulaAgree(server_id.id) location.reload();
} }
else { })
location.reload() });
} }
if (webSocket) {
webSocket.on('send_logs_bootbox', function (server_id) {
var x = document.querySelector('.bootbox');
if (x) {
x.remove()
}
var x = document.querySelector('.modal-backdrop');
if (x) {
x.remove()
}
bootbox.alert({
title: "{{ translate('notify', 'downloadLogs', data['lang']) }}",
message: "{{ translate('notify', 'finishedPreparing', data['lang']) }}",
buttons: {
ok: {
label: 'Download',
className: 'btn-info'
}
},
callback: function () {
console.log("in callback")
location.href = "/panel/download_support_package";
}
});
});
} }
})
});
}
function eulaAgree (server_id, command){ if (webSocket) {
<!-- this getCookie function is in base.html--> webSocket.on('send_eula_bootbox', function (server_id) {
var x = document.querySelector('.bootbox');
if (x) {
x.remove()
}
var x = document.querySelector('.modal-backdrop');
if (x) {
x.remove()
}
bootbox.confirm({
title: '{% raw translate("error", "eulaTitle", data['lang']) %}',
message: '{% raw translate("error", "eulaMsg", data['lang']) %} <br><br><a href="https://account.mojang.com/documents/minecraft_eula" target="_blank">EULA</a><br><br>{% raw translate("error", "eulaAgree", data['lang']) %}',
buttons: {
confirm: {
label: 'Yes',
className: 'btn-info'
},
cancel: {
label: 'No',
className: 'btn-secondary'
}
},
callback: function (result) {
if (result == true) {
eulaAgree(server_id.id)
}
else {
location.reload()
}
}
})
});
}
function eulaAgree(server_id, command) {
//< !--this getCookie function is in base.html-- >
var token = getCookie("_xsrf"); var token = getCookie("_xsrf");
$.ajax({ $.ajax({
type: "POST", type: "POST",
headers: {'X-XSRFToken': token}, headers: { 'X-XSRFToken': token },
url: '/ajax/eula?id='+ server_id, url: '/ajax/eula?id=' + server_id,
success: function(data){ success: function (data) {
console.log("got response:"); console.log("got response:");
console.log(data); console.log(data);
location.reload(); location.reload();
} }
}); });
} }
@ -332,7 +345,7 @@ if (webSocket) {
closeEl.style.lineHeight = '20px'; closeEl.style.lineHeight = '20px';
closeEl.style.cursor = 'pointer'; closeEl.style.cursor = 'pointer';
closeEl.addEventListener('click', function () {this.parentElement.style.display='none';}); closeEl.addEventListener('click', function () { this.parentElement.style.display = 'none'; });
var parentEl = document.createElement('div'); var parentEl = document.createElement('div');
@ -360,7 +373,7 @@ if (webSocket) {
paragraphEl.textContent = message; paragraphEl.textContent = message;
closeEl.innerHTML = '&times;'; closeEl.innerHTML = '&times;';
closeEl.addEventListener('click', function () {closeNotification(this)}); closeEl.addEventListener('click', function () { closeNotification(this) });
var parentEl = document.createElement('div'); var parentEl = document.createElement('div');
parentEl.appendChild(paragraphEl); parentEl.appendChild(paragraphEl);
@ -388,25 +401,26 @@ if (webSocket) {
} }
webSocket.on('notification', notify); webSocket.on('notification', notify);
$(document).ready(function(){ $(document).ready(function () {
$('#support_logs').click(function(){ $('#support_logs').click(function () {
var dialog = bootbox.dialog({ var dialog = bootbox.dialog({
message: '<p class="text-center mb-0"><i class="fa fa-spin fa-cog"></i>{{ translate('notify', 'preparingLogs', data['lang']) }}</p>', message: '<p class="text-center mb-0"><i class="fa fa-spin fa-cog"></i>{{ translate('notify', 'preparingLogs', data['lang']) }}</p>',
closeButton: false closeButton: false
});
setTimeout(function () {
location.href = "/panel/support_logs";
}, 6000);
}); });
setTimeout(function(){ });
location.href="/panel/support_logs";
}, 6000);
}); </script>
});
</script> {% block js %}
<!-- Custom js for base.html page partial pages -->
<!-- End custom js for base.html page -->
{% end %}
{% block js %} </body>
<!-- Custom js for this page -->
<!-- End custom js for this page -->
{% end %}
</body>
</html> </html>

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Blank Page{% end %} {% block title %}Crafty Controller - Blank Page{% end %}

View File

@ -1,8 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Activity Logs{% end %} {% block title %}Crafty Controller - Activity Logs{% end %}
@ -93,7 +91,7 @@ $( document ).ready(function() {
if($(window).width() < 1000){ if($(window).width() < 1000){
$('.too_small').popover("show"); $('.too_small').popover("show");
} }
}); });
$(window).ready(function(){ $(window).ready(function(){
$('body').click(function(){ $('body').click(function(){

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Contribute{% end %} {% block title %}Crafty Controller - Contribute{% end %}
@ -73,7 +72,7 @@
<div class="media-body"> <div class="media-body">
<p class="card-text"> <p class="card-text">
Thank you for your interest in contributing to Aracdia Technology's Crafty Controller. Thank you for your interest in contributing to Aracdia Technology's Crafty Controller.
We are always thinking of new ways for our community to contribute to this awesome project. <br><br> If you don't see We are always thinking of new ways for our community to contribute to this awesome project. <br><br> If you don't see
a contribution method that peaks your interest now please check back soon. a contribution method that peaks your interest now please check back soon.
</p> </p>

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Credits{% end %} {% block title %}Crafty Controller - Credits{% end %}

View File

@ -257,6 +257,13 @@
<script src="/static/assets/js/motd.js"></script> <script src="/static/assets/js/motd.js"></script>
<script> <script>
function display_motd() {
var all_motds = Array.from(document.getElementsByClassName('input_motd'));
for (element of all_motds) {
initParser(element.id, element.id);
};
}
$(document).ready(function () { $(document).ready(function () {
$('[data-toggle="popover"]').popover(); $('[data-toggle="popover"]').popover();
if ($(window).width() < 1000) { if ($(window).width() < 1000) {
@ -292,12 +299,11 @@
success: function (data) { success: function (data) {
console.log("got response:"); console.log("got response:");
console.log(data); console.log(data);
setTimeout(function () { /*setTimeout(function () {
if (command != 'start_server') { if (command != 'start_server') {
location.reload(); location.reload();
} }
}, 10000); }, 10000);*/
} }
}); });
} }
@ -313,10 +319,9 @@
success: function (data) { success: function (data) {
console.log("got response:"); console.log("got response:");
console.log(data); console.log(data);
setTimeout(function () { /*setTimeout(function () {
location.reload(); location.reload();
}, 10000); }, 10000);*/
} }
}); });
} }

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Panel Config{% end %} {% block title %}Crafty Controller - Panel Config{% end %}

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Edit Role{% end %} {% block title %}Crafty Controller - Edit Role{% end %}
@ -58,7 +57,7 @@
{% raw xsrf_form_html() %} {% raw xsrf_form_html() %}
<input type="hidden" name="id" value="{{ data['role']['role_id'] }}"> <input type="hidden" name="id" value="{{ data['role']['role_id'] }}">
<input type="hidden" name="subpage" value="config"> <input type="hidden" name="subpage" value="config">
<div class="card"> <div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center"> <div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-user-tag"></i> Role Settings</h4> <h4 class="card-title"><i class="fas fa-user-tag"></i> Role Settings</h4>
@ -70,7 +69,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card"> <div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center"> <div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-server"></i> Allowed Servers <small class="text-muted ml-1"> - servers this role is allowed to access </small> </h4> <h4 class="card-title"><i class="fas fa-server"></i> Allowed Servers <small class="text-muted ml-1"> - servers this role is allowed to access </small> </h4>
@ -105,12 +104,12 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card"> <div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center"> <div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-user-lock"></i> Roles Permissions <small class="text-muted ml-1"> - permissions this role has on this/these servers </small></h4> <h4 class="card-title"><i class="fas fa-user-lock"></i> Roles Permissions <small class="text-muted ml-1"> - permissions this role has on this/these servers </small></h4>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="form-group"> <div class="form-group">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover"> <table class="table table-hover">

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Edit User{% end %} {% block title %}Crafty Controller - Edit User{% end %}

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - Edit User API Keys{% end %} {% block title %}Crafty Controller - Edit User API Keys{% end %}

View File

@ -1,56 +1,52 @@
<div class="row"> <div class="row">
<div class="col-sm-12 grid-margin"> <div class="col-sm-12 grid-margin">
<div class="card"> <div class="card">
<div class="card-body pt-3 pb-3"> <div class="card-body pt-3 pb-3">
<div class="row"> <div class="row">
<div class="col-sm-4 mr-2"> <div class="col-sm-4 mr-2">
{% if data['server_stats']['running'] %} {% if data['server_stats']['running'] %}
<b>{{ translate('serverStats', 'serverStatus', data['lang']) }}:</b> <span class="text-success">{{ translate('serverStats', 'online', data['lang']) }}</span><br /> <b>{{ translate('serverStats', 'serverStatus', data['lang']) }}:</b> <span id="status" class="text-success">{{ translate('serverStats', 'online', data['lang']) }}</span><br />
<b>{{ translate('serverStats', 'serverStarted', data['lang']) }}:</b> <span id="started">{{ data['server_stats']['started'] }} ({{ translate('serverStats', 'serverTime', data['lang']) }})</span><br /> <b>{{ translate('serverStats', 'serverStarted', data['lang']) }}:</b> <span id="started">{{ data['server_stats']['started'] }} ({{ translate('serverStats', 'serverTime', data['lang']) }})</span><br />
<b>{{ translate('serverStats', 'serverUptime', data['lang']) }}:</b> <span id="uptime">{{ translate('serverStats', 'errorCalculatingUptime', data['lang']) }}</span> <b>{{ translate('serverStats', 'serverUptime', data['lang']) }}:</b> <span id="uptime">{{ translate('serverStats', 'errorCalculatingUptime', data['lang']) }}</span>
{% else %} {% else %}
<b>{{ translate('serverStats', 'serverStatus', data['lang']) }}:</b> <span class="text-danger">{{ translate('serverStats', 'offline', data['lang']) }}</span><br /> <b>{{ translate('serverStats', 'serverStatus', data['lang']) }}:</b> <span id="status" class="text-danger">{{ translate('serverStats', 'offline', data['lang']) }}</span><br />
<b>{{ translate('serverStats', 'serverStarted', data['lang']) }}:</b> <span class="text-danger">{{ translate('serverStats', 'offline', data['lang']) }}</span><br /> <b>{{ translate('serverStats', 'serverStarted', data['lang']) }}:</b> <span id="started" class="text-danger">{{ translate('serverStats', 'offline', data['lang']) }}</span><br />
<b>{{ translate('serverStats', 'serverUptime', data['lang']) }}:</b> <span class="text-danger">{{ translate('serverStats', 'offline', data['lang']) }}</span> <b>{{ translate('serverStats', 'serverUptime', data['lang']) }}:</b> <span id="uptime" class="text-danger">{{ translate('serverStats', 'offline', data['lang']) }}</span>
{% end %} {% end %}
<br> <br>
<b>{{ translate('serverStats', 'serverTimeZone', data['lang']) }}:</b> <span class="text-info">{{ data['serverTZ'] }}</span> <b>{{ translate('serverStats', 'serverTimeZone', data['lang']) }}:</b> <span class="text-info">{{ data['serverTZ'] }}</span>
</div>
<div class="col-sm-3 mr-2">
<b>{{ translate('serverStats', 'cpuUsage', data['lang']) }}:</b> {{ data['server_stats']['cpu'] }}% <br />
<b>{{ translate('serverStats', 'memUsage', data['lang']) }}:</b> {{ data['server_stats']['mem'] }} <br />
{% if data['server_stats']['int_ping_results'] %}
<b>{{ translate('serverStats', 'players', data['lang']) }}:</b> {{ data['server_stats']['online'] }} / {{ data['server_stats']['max'] }}<br />
{% else %}
<b>{{ translate('serverStats', 'players', data['lang']) }}:</b> 0/0<br />
{% end %}
</div>
<div class="col-sm-3 mr-2">
{% if data['server_stats']['version'] != 'False' %}
<b>{{ translate('serverStats', 'version', data['lang']) }}:</b> {{ data['server_stats']['version'] }} <br />
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> <span id="input_motd" class="input_motd">{{ data['server_stats']['desc'] }}</span> <br />
{% else %}
<b>{{ translate('serverStats', 'version', data['lang']) }}:</b> {{ translate('serverStats', 'unableToConnect', data['lang']) }} <br />
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> {{ translate('serverStats', 'unableToConnect', data['lang']) }} <br />
{% end %}
</div>
</div>
</div> </div>
<div class="col-sm-3 mr-2">
<b>{{ translate('serverStats', 'cpuUsage', data['lang']) }}:</b> <span id="cpu">{{ data['server_stats']['cpu'] }}%</span> <br />
<b>{{ translate('serverStats', 'memUsage', data['lang']) }}:</b> <span id="mem" >{{ data['server_stats']['mem'] }}</span> <br />
{% if data['server_stats']['int_ping_results'] %}
<b>{{ translate('serverStats', 'players', data['lang']) }}:</b> <span id="players" >{{ data['server_stats']['online'] }} / {{ data['server_stats']['max'] }}</span><br />
{% else %}
<b>{{ translate('serverStats', 'players', data['lang']) }}:</b> <span id="players" >0/0</span><br />
{% end %}
</div>
<div class="col-sm-3 mr-2">
{% if data['server_stats']['version'] != 'False' %}
<b>{{ translate('serverStats', 'version', data['lang']) }}:</b> <span id="version">{{ data['server_stats']['version'] }}</span><br />
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> <span id="input_motd" class="input_motd">{{ data['server_stats']['desc'] }}</span> <br />
{% else %}
<b>{{ translate('serverStats', 'version', data['lang']) }}:</b> <span id="version">{{ translate('serverStats', 'unableToConnect', data['lang']) }}</span> <br />
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> <span id="input_motd" class="input_motd">{{ translate('serverStats', 'unableToConnect', data['lang']) }}</span> <br />
{% end %}
</div>
</div> </div>
</div> </div>
</div>
</div> </div>
</div>
<script src="/static/assets/vendors/moment/moment.min.js" type="text/javascript" charset="utf-8"></script> <script src="/static/assets/vendors/moment/moment.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/assets/js/motd.js"></script> <script src="/static/assets/js/motd.js"></script>
<script> <script>
function durationToHumanizedString(duration) {
function durationToHumanizedString (duration) {
duration._data.months += duration._data.years * 12; duration._data.months += duration._data.years * 12;
// 30.45833333333 = average month length, calculate with (31+28.5+31+30+31+30+31+31+30+31+30+31) / 12 // 30.45833333333 = average month length, calculate with (31+28.5+31+30+31+30+31+31+30+31+30+31) / 12
duration._data.days += duration._data.months * 30.45833333333; duration._data.days += duration._data.months * 30.45833333333;
@ -64,7 +60,7 @@
output = Object.entries(obj) output = Object.entries(obj)
.map(([type, num]) => { .map(([type, num]) => {
// make them strings // make them strings
returnData = num + ' ' + type; returnData = num + ' ' + type;
// remove the s in the end if the data is -1 or 1 // remove the s in the end if the data is -1 or 1
if (num == -1 || num == 1) if (num == -1 || num == 1)
@ -73,27 +69,28 @@
}) })
.map((v, i, a) => // example input: [1,2,3], output: "1, 2 and 3" .map((v, i, a) => // example input: [1,2,3], output: "1, 2 and 3"
v + (i !== a.length - 1 v + (i !== a.length - 1
? i !== a.length - 2 ? i !== a.length - 2
? ', ' ? ', '
: ' and ' : ' and '
: '')).join(''); : '')).join('');
return output; return output;
} }
let uptime = document.querySelector('#uptime');
let started = document.querySelector('#started');
let startedUTC;
let startedLocal;
let uptimeLoop;
document.body.onload = (() => { document.body.onload = (() => {
console.log('calculateTime'); console.log('calculateTime');
let uptime = document.querySelector('#uptime');
let started = document.querySelector('#started');
let startedUTC;
let startedLocal;
if (started != null) { startedUTC = '{{ data['server_stats']['started'] }}';
startedUTC = '{{ data['server_stats']['started'] }}'; if (startedUTC != 'False') {
console.log('started utc:', startedUTC); console.log('started utc:', startedUTC);
startedUTC = moment.utc(startedUTC, 'YYYY-MM-DD HH:mm:ss'); startedUTC = moment.utc(startedUTC, 'YYYY-MM-DD HH:mm:ss');
let browserUTCOffset = moment().utcOffset(); // This is in minutes var browserUTCOffset = moment().utcOffset(); // This is in minutes
startedLocal = startedUTC.utcOffset(browserUTCOffset); startedLocal = startedUTC.utcOffset(browserUTCOffset);
startedLocalFormatted = startedLocal.format('YYYY-MM-DD HH:mm:ss'); startedLocalFormatted = startedLocal.format('YYYY-MM-DD HH:mm:ss');
@ -104,23 +101,108 @@
} }
var calculateUptime = () => { var calculateUptime = () => {
var msdiff = moment() var msdiff = moment().diff(startedLocal);
.diff(startedLocal);
var diff = moment.duration(msdiff); var diff = moment.duration(msdiff);
uptime.textContent = durationToHumanizedString(diff); uptime.textContent = durationToHumanizedString(diff);
} }
if (uptime != null && started != null) { if (uptime != null && started != null) {
console.log('startedLocal', startedLocal) console.log('startedLocal', startedLocal)
if (startedLocal) { if (startedLocal) {
calculateUptime() calculateUptime();
var uptimeLoop = setInterval(calculateUptime, 1000) uptimeLoop = setInterval(calculateUptime, 1000);
} }
} }
initParser('input_motd', 'input_motd'); initParser('input_motd', 'input_motd');
}); });
function update_server_details(server) {
server_status = document.getElementById('status');
server_started = document.getElementById('started');
server_uptime = document.getElementById('uptime');
server_cpu = document.getElementById('cpu');
server_mem = document.getElementById('mem');
server_players = document.getElementById('players');
server_version = document.getElementById('version');
server_input_motd = document.getElementById('input_motd');
/* TODO Update each element */
if (server.running)
{
if (server.int_ping_results)
{
server_status.setAttribute("class", "text-success");
server_status.innerHTML = `{{ translate('serverStats', 'online', data['lang']) }}`;
}
else
{
server_status.setAttribute("class", "text-warning");
server_status.innerHTML = `{{ translate('serverStats', 'starting', data['lang']) }}`;
}
startedUTC = server.started;
startedUTC = moment.utc(startedUTC, 'YYYY-MM-DD HH:mm:ss');
var browserUTCOffset = moment().utcOffset(); // This is in minutes
startedLocal = startedUTC.utcOffset(browserUTCOffset);
startedLocalFormatted = startedLocal.format('YYYY-MM-DD HH:mm:ss');
server_started.setAttribute("class", "");
server_started.innerHTML = startedLocalFormatted +` ({{ translate('serverStats', 'serverTime', data['lang']) }})`;
server_uptime.setAttribute("class", "");
if (!uptimeLoop) {
var calculateUptime = () => {
var msdiff = moment().diff(startedLocal);
var diff = moment.duration(msdiff);
uptime.textContent = durationToHumanizedString(diff);
}
uptimeLoop = setInterval(calculateUptime, 1000);
}
}
else
{
server_status.setAttribute("class", "text-danger");
server_status.innerHTML = `{{ translate('serverStats', 'offline', data['lang']) }}`;
server_started.setAttribute("class", "text-danger");
server_started.innerHTML = `{{ translate('serverStats', 'offline', data['lang']) }}`;
clearInterval(uptimeLoop);
uptimeLoop = null;
server_uptime.setAttribute("class", "text-danger");
server_uptime.innerHTML = `{{ translate('serverStats', 'offline', data['lang']) }}`;
}
server_cpu.innerHTML = server.cpu + ` %`;
server_mem.innerHTML = server.mem;
if (server.int_ping_results)
{
server_players.innerHTML = server.online + `/` + server.max;
}
else
{
server_players.innerHTML = `0/0`;
}
if (server.version)
{
server_version.innerHTML = server.version;
server_input_motd.innerHTML = server.desc;
}
else
{
server_version.innerHTML = `{{ translate('serverStats', 'unableToConnect', data['lang']) }}`;
server_input_motd.innerHTML = `{{ translate('serverStats', 'unableToConnect', data['lang']) }}`;
}
initParser('input_motd', 'input_motd');
}
$(window).ready(function () {
console.log("ready!");
//if (webSocket) {
webSocket.on('update_server_details', update_server_details);
//}
});
</script> </script>

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
@ -33,7 +32,7 @@
<div class="card"> <div class="card">
<div class="card-body pt-0"> <div class="card-body pt-0">
{% include "parts/server_controls_list.html %} {% include "parts/server_controls_list.html %}
<div class="row"> <div class="row">
<div class="col-md-6 col-sm-12"> <div class="col-md-6 col-sm-12">
<style> <style>
@ -86,7 +85,7 @@
<li class="playerItem banned"> <li class="playerItem banned">
<h3>{{ translate('serverPlayerManagement', 'loadingBannedPlayers', data['lang']) }}</h3> <h3>{{ translate('serverPlayerManagement', 'loadingBannedPlayers', data['lang']) }}</h3>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
@ -65,7 +64,7 @@
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h4 class="card-title">{{ translate('serverBackups', 'currentBackups', data['lang']) }}</h4> <h4 class="card-title">{{ translate('serverBackups', 'currentBackups', data['lang']) }}</h4>
</div> </div>
</div> </div>
<div class="text-center"> <div class="text-center">
@ -231,7 +230,7 @@
} }
}); });
}); });
$( ".restore_button" ).click(function() { $( ".restore_button" ).click(function() {
var file_to_restore = $(this).data("file"); var file_to_restore = $(this).data("file");

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
@ -10,14 +9,15 @@
<div class="content-wrapper"> <div class="content-wrapper">
<!-- Page Title Header Starts--> <!-- Page Title Header Starts-->
<div class="row page-title-header"> <div class="row page-title-header">
<div class="col-12"> <div class="col-12">
<div class="page-header"> <div class="page-header">
<h4 class="page-title"> <h4 class="page-title">
{{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{ data['server_stats']['server_id']['server_name'] }} {{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{
<br /> data['server_stats']['server_id']['server_name'] }}
<small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small> <br />
<small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small>
</h4> </h4>
</div> </div>
</div> </div>
@ -25,132 +25,187 @@
</div> </div>
<!-- Page Title Header Ends--> <!-- Page Title Header Ends-->
{% include "parts/details_stats.html" %} {% include "parts/details_stats.html" %}
<div class="row"> <div class="row">
<div class="col-sm-12 grid-margin"> <div class="col-sm-12 grid-margin">
<div class="card"> <div class="card">
<div class="card-body pt-0"> <div class="card-body pt-0">
{% include "parts/server_controls_list.html %} {% include "parts/server_controls_list.html %}
<div class="row"> <div class="row">
<div class="col-md-6 col-sm-12"> <div class="col-md-6 col-sm-12">
<form class="forms-sample" method="post" action="/panel/server_detail"> <form class="forms-sample" method="post" action="/panel/server_detail">
{% raw xsrf_form_html() %} {% raw xsrf_form_html() %}
<input type="hidden" name="id" value="{{ data['server_stats']['server_id']['server_id'] }}"> <input type="hidden" name="id" value="{{ data['server_stats']['server_id']['server_id'] }}">
<input type="hidden" name="subpage" value="config"> <input type="hidden" name="subpage" value="config">
<div class="form-group"> <div class="form-group">
<label for="server_name">{{ translate('serverConfig', 'serverName', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverNameDesc', data['lang']) }}</small> </label> <label for="server_name">{{ translate('serverConfig', 'serverName', data['lang']) }} <small
<input type="text" class="form-control" name="server_name" id="server_name" value="{{ data['server_stats']['server_id']['server_name'] }}" placeholder="{{ translate('serverConfig', 'serverName', data['lang']) }}" required> class="text-muted ml-1"> - {{ translate('serverConfig', 'serverNameDesc', data['lang']) }}</small>
</div> </label>
<input type="text" class="form-control" name="server_name" id="server_name"
<div class="form-group"> value="{{ data['server_stats']['server_id']['server_name'] }}"
{% if data['super_user'] %} placeholder="{{ translate('serverConfig', 'serverName', data['lang']) }}" required>
<label for="server_path">{{ translate('serverConfig', 'serverPath', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverPathDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="server_path" id="server_path" value="{{ data['server_stats']['server_id']['path'] }}" placeholder="{{ translate('serverConfig', 'serverPath', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="log_path">{{ translate('serverConfig', 'serverLogLocation', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverLogLocationDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="log_path" id="log_path" value="{{ data['server_stats']['server_id']['log_path'] }}" placeholder="{{ translate('serverConfig', 'serverLogLocation', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="executable">{{ translate('serverConfig', 'serverExecutable', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverExecutableDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="executable" id="executable" value="{{ data['server_stats']['server_id']['executable'] }}" placeholder="{{ translate('serverConfig', 'serverExecutable', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="execution_command">{{ translate('serverConfig', 'serverExecutionCommand', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverExecutionCommandDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="execution_command" id="execution_command" value="{{ data['server_stats']['server_id']['execution_command'] }}" placeholder="{{ translate('serverConfig', 'serverExecutionCommand', data['lang']) }}" required>
{% end %}
</div>
<div class="form-group">
<label for="stop_command">{{ translate('serverConfig', 'serverStopCommand', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverStopCommandDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="stop_command" id="stop_command" value="{{ data['server_stats']['server_id']['stop_command'] }}" placeholder="{{ translate('serverConfig', 'serverStopCommand', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="auto_start_delay">{{ translate('serverConfig', 'serverAutostartDelay', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverAutostartDelayDesc', data['lang']) }}</small> </label>
<input type="number" class="form-control" name="auto_start_delay" id="auto_start_delay" value="{{ data['server_stats']['server_id']['auto_start_delay'] }}" step="1" max="999" min="10" required>
</div>
{% if data['super_user'] %}
<div class="form-group">
<label for="executable_update_url">{{ translate('serverConfig', 'exeUpdateURL', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'exeUpdateURLDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="executable_update_url" id="executable_update_url" value="{{ data['server_stats']['server_id']['executable_update_url'] }}" placeholder="{{ translate('serverConfig', 'exeUpdateURL', data['lang']) }}">
</div>
<div class="form-group">
<label for="server_ip">{{ translate('serverConfig', 'serverIP', data['lang']) }} <small class="text-muted ml-1">- {{ translate('serverConfig', 'serverIPDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="server_ip" id="server_ip" value="{{ data['server_stats']['server_id']['server_ip'] }}" required>
</div>
<div class="form-group">
<label for="server_port">{{ translate('serverConfig', 'serverPort', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverPortDesc', data['lang']) }} </small> </label>
<input type="number" class="form-control" name="server_port" id="server_port" value="{{ data['server_stats']['server_id']['server_port'] }}" step="1" max="65566" min="1" required>
</div>
{% end %}
<div class="form-group">
<label for="logs_delete_after">{{ translate('serverConfig', 'removeOldLogsAfter', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'removeOldLogsAfterDesc', data['lang']) }}</small> </label>
<input type="number" class="form-control" name="logs_delete_after" id="logs_delete_after" value="{{ data['server_stats']['server_id']['logs_delete_after'] }}" step="1" max="365" min="0" required>
</div>
<div class="form-check-flat">
<label for="auto_start" class="form-check-label ml-4 mb-4">
{% if data['server_stats']['server_id']['auto_start'] %}
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" checked="" value="1">{{ translate('serverConfig', 'serverAutoStart', data['lang']) }}
{% else %}
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" value="1">{{ translate('serverConfig', 'serverAutoStart', data['lang']) }}
{% end %}
</label>
<label for="crash_detection" class="form-check-label ml-4 mb-4">
{% if data['server_stats']['server_id']['crash_detection'] %}
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection" checked="" value="1">{{ translate('serverConfig', 'serverCrashDetection', data['lang']) }}
{% else %}
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection" value="1" >{{ translate('serverConfig', 'serverCrashDetection', data['lang']) }}
{% end %}
</label>
</div>
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-save"></i> {{ translate('serverConfig', 'save', data['lang']) }}</button>
<button type="reset" class="btn btn-light"><i class="fas fa-times"></i> {{ translate('serverConfig', 'cancel', data['lang']) }}</button>
</form>
</div> </div>
<div class="col-md-6 col-sm-12"> <div class="form-group">
<div class="card"> {% if data['super_user'] %}
<div class="card-body"> <label for="server_path">{{ translate('serverConfig', 'serverPath', data['lang']) }} <small
<h4 class="card-title">{{ translate('serverConfigHelp', 'title', data['lang']) }}</h4> class="text-muted ml-1"> - {{ translate('serverConfig', 'serverPathDesc', data['lang']) }}</small>
<p class="card-description"> {{ translate('serverConfigHelp', 'desc', data['lang']) }}</p> </label>
<blockquote class="blockquote"> <input type="text" class="form-control" name="server_path" id="server_path"
<p class="mb-0"> value="{{ data['server_stats']['server_id']['path'] }}"
{% raw translate('serverConfigHelp', 'perms', data['lang']) %} placeholder="{{ translate('serverConfig', 'serverPath', data['lang']) }}" required>
</p>
</blockquote>
</div>
</div>
<div class="text-center">
{% if data['server_stats']['running'] %}
<button onclick="send_command(server_id, 'update_executable');" id="update_executable" style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverConfig', 'update', data['lang']) }}</button>
<a class="btn btn-sm btn-danger disabled">{{ translate('serverConfig', 'deleteServer', data['lang']) }}</a><br />
<small>{{ translate('serverConfig', 'stopBeforeDeleting', data['lang']) }}</small>
{% else %}
<button onclick="send_command(server_id, 'update_executable');" id="update_executable" style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1">{{ translate('serverConfig', 'update', data['lang']) }}</button>
<button onclick="deleteConfirm()" class="btn btn-sm btn-danger">{{ translate('serverConfig', 'deleteServer', data['lang']) }}</button>
{% end %}
</div>
</div> </div>
<div class="form-group">
<label for="log_path">{{ translate('serverConfig', 'serverLogLocation', data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverConfig', 'serverLogLocationDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="log_path" id="log_path"
value="{{ data['server_stats']['server_id']['log_path'] }}"
placeholder="{{ translate('serverConfig', 'serverLogLocation', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="executable">{{ translate('serverConfig', 'serverExecutable', data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverConfig', 'serverExecutableDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="executable" id="executable"
value="{{ data['server_stats']['server_id']['executable'] }}"
placeholder="{{ translate('serverConfig', 'serverExecutable', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="execution_command">{{ translate('serverConfig', 'serverExecutionCommand', data['lang']) }}
<small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverExecutionCommandDesc',
data['lang']) }}</small> </label>
<input type="text" class="form-control" name="execution_command" id="execution_command"
value="{{ data['server_stats']['server_id']['execution_command'] }}"
placeholder="{{ translate('serverConfig', 'serverExecutionCommand', data['lang']) }}" required>
{% end %}
</div>
<div class="form-group">
<label for="stop_command">{{ translate('serverConfig', 'serverStopCommand', data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverConfig', 'serverStopCommandDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="stop_command" id="stop_command"
value="{{ data['server_stats']['server_id']['stop_command'] }}"
placeholder="{{ translate('serverConfig', 'serverStopCommand', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="auto_start_delay">{{ translate('serverConfig', 'serverAutostartDelay', data['lang']) }}
<small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverAutostartDelayDesc',
data['lang']) }}</small> </label>
<input type="number" class="form-control" name="auto_start_delay" id="auto_start_delay"
value="{{ data['server_stats']['server_id']['auto_start_delay'] }}" step="1" max="999" min="10"
required>
</div>
{% if data['super_user'] %}
<div class="form-group">
<label for="executable_update_url">{{ translate('serverConfig', 'exeUpdateURL', data['lang']) }}
<small class="text-muted ml-1"> - {{ translate('serverConfig', 'exeUpdateURLDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="executable_update_url" id="executable_update_url"
value="{{ data['server_stats']['server_id']['executable_update_url'] }}"
placeholder="{{ translate('serverConfig', 'exeUpdateURL', data['lang']) }}">
</div>
<div class="form-group">
<label for="server_ip">{{ translate('serverConfig', 'serverIP', data['lang']) }} <small
class="text-muted ml-1">- {{ translate('serverConfig', 'serverIPDesc', data['lang']) }}</small>
</label>
<input type="text" class="form-control" name="server_ip" id="server_ip"
value="{{ data['server_stats']['server_id']['server_ip'] }}" required>
</div>
<div class="form-group">
<label for="server_port">{{ translate('serverConfig', 'serverPort', data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverConfig', 'serverPortDesc', data['lang']) }}
</small> </label>
<input type="number" class="form-control" name="server_port" id="server_port"
value="{{ data['server_stats']['server_id']['server_port'] }}" step="1" max="65566" min="1"
required>
</div>
{% end %}
<div class="form-group">
<label for="logs_delete_after">{{ translate('serverConfig', 'removeOldLogsAfter', data['lang']) }}
<small class="text-muted ml-1"> - {{ translate('serverConfig', 'removeOldLogsAfterDesc',
data['lang']) }}</small> </label>
<input type="number" class="form-control" name="logs_delete_after" id="logs_delete_after"
value="{{ data['server_stats']['server_id']['logs_delete_after'] }}" step="1" max="365" min="0"
required>
</div>
<div class="form-check-flat">
<label for="auto_start" class="form-check-label ml-4 mb-4">
{% if data['server_stats']['server_id']['auto_start'] %}
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" checked=""
value="1">{{ translate('serverConfig', 'serverAutoStart', data['lang']) }}
{% else %}
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" value="1">{{
translate('serverConfig', 'serverAutoStart', data['lang']) }}
{% end %}
</label>
<label for="crash_detection" class="form-check-label ml-4 mb-4">
{% if data['server_stats']['server_id']['crash_detection'] %}
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection"
checked="" value="1">{{ translate('serverConfig', 'serverCrashDetection', data['lang']) }}
{% else %}
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection"
value="1">{{ translate('serverConfig', 'serverCrashDetection', data['lang']) }}
{% end %}
</label>
</div>
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-save"></i> {{
translate('serverConfig', 'save', data['lang']) }}</button>
<button type="reset" class="btn btn-light"><i class="fas fa-times"></i> {{ translate('serverConfig',
'cancel', data['lang']) }}</button>
</form>
</div> </div>
<div class="col-md-6 col-sm-12">
<div class="card">
<div class="card-body">
<h4 class="card-title">{{ translate('serverConfigHelp', 'title', data['lang']) }}</h4>
<p class="card-description"> {{ translate('serverConfigHelp', 'desc', data['lang']) }}</p>
<blockquote class="blockquote">
<p class="mb-0">
{% raw translate('serverConfigHelp', 'perms', data['lang']) %}
</p>
</blockquote>
</div>
</div>
<div class="text-center">
{% if data['server_stats']['running'] %}
<button onclick="send_command(server_id, 'update_executable');" id="update_executable"
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverConfig',
'update', data['lang']) }}</button>
<a class="btn btn-sm btn-danger disabled">{{ translate('serverConfig', 'deleteServer', data['lang'])
}}</a><br />
<small>{{ translate('serverConfig', 'stopBeforeDeleting', data['lang']) }}</small>
{% else %}
<button onclick="send_command(server_id, 'update_executable');" id="update_executable"
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1">{{ translate('serverConfig',
'update', data['lang']) }}</button>
<button onclick="deleteConfirm()" class="btn btn-sm btn-danger">{{ translate('serverConfig',
'deleteServer', data['lang']) }}</button>
{% end %}
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -167,154 +222,154 @@
<script> <script>
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security //used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
function getCookie(name) { function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined; return r ? r[1] : undefined;
} }
$( document ).ready(function() { $(document).ready(function () {
console.log( "ready!" ); console.log("ready!");
});
function deleteServerE(callback) {
var token = getCookie("_xsrf")
$.ajax({
type: "DELETE",
headers: { 'X-XSRFToken': token },
url: '/ajax/delete_server?id={{ data['server_stats']['server_id']['server_id'] }}',
data: {
},
success: function (data) {
console.log("got response:");
console.log(data);
},
}); });
}
function deleteServerE(callback) { function deleteServerFilesE(path, callback) {
var token = getCookie("_xsrf") var token = getCookie("_xsrf")
$.ajax({ $.ajax({
type: "DELETE", type: "DELETE",
headers: {'X-XSRFToken': token}, headers: { 'X-XSRFToken': token },
url: '/ajax/delete_server?id={{ data['server_stats']['server_id']['server_id'] }}', url: '/ajax/delete_server_files?id={{ data['server_stats']['server_id']['server_id'] }}',
data: { data: {
}, },
success: function(data){ success: function (data) {
console.log("got response:"); console.log("got response:");
console.log(data); console.log(data);
}, },
});
}
function deleteServerFilesE(path, callback) {
var token = getCookie("_xsrf")
$.ajax({
type: "DELETE",
headers: {'X-XSRFToken': token},
url: '/ajax/delete_server_files?id={{ data['server_stats']['server_id']['server_id'] }}',
data: {
},
success: function(data){
console.log("got response:");
console.log(data);
},
});
}
let server_id = '{{ data['server_stats']['server_id']['server_id'] }}';
function send_command (server_id, command){
<!-- this getCookie function is in base.html-->
var token = getCookie("_xsrf");
$.ajax({
type: "POST",
headers: {'X-XSRFToken': token},
url: '/server/command?command=' + command + '&id=' + server_id,
success: function(data){
console.log("got response:");
console.log(data);
setTimeout(function(){ location.reload(); }, 10000);
}
});
if(command != "delete_server" && command != "delete_server_files"){
bootbox.alert({
backdrop: true,
title: '{% raw translate("serverConfig", "sendingRequest", data['lang']) %}',
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("serverConfig", "bePatientUpdate", data['lang']) %} </div>'
}); });
}
let server_id = '{{ data['server_stats']['server_id']['server_id'] }}';
function send_command(server_id, command) {
//<!-- this getCookie function is in base.html-->
var token = getCookie("_xsrf");
$.ajax({
type: "POST",
headers: { 'X-XSRFToken': token },
url: '/server/command?command=' + command + '&id=' + server_id,
success: function (data) {
console.log("got response:");
console.log(data);
setTimeout(function () { location.reload(); }, 10000);
} }
});
if (command != "delete_server" && command != "delete_server_files") {
bootbox.alert({
backdrop: true,
title: '{% raw translate("serverConfig", "sendingRequest", data['lang']) %}',
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("serverConfig", "bePatientUpdate", data['lang']) %} </div>'
});
} }
}
function deleteServer (){ function deleteServer() {
path = "{{data['server_stats']['server_id']['path']}}"; path = "{{data['server_stats']['server_id']['path']}}";
name = "{{data['server_stats']['server_id']['server_name']}}"; name = "{{data['server_stats']['server_id']['server_name']}}";
bootbox.dialog({ bootbox.dialog({
size: "", size: "",
title: "{% raw translate('serverConfig', 'deleteFilesQuestion', data['lang']) %}", title: "{% raw translate('serverConfig', 'deleteFilesQuestion', data['lang']) %}",
closeButton: false, closeButton: false,
message: "{% raw translate('serverConfig', 'deleteFilesQuestionMessage', data['lang']) %}", message: "{% raw translate('serverConfig', 'deleteFilesQuestionMessage', data['lang']) %}",
buttons: { buttons: {
files: { files: {
label: "{{ translate('serverConfig', 'yesDeleteFiles', data['lang']) }}", label: "{{ translate('serverConfig', 'yesDeleteFiles', data['lang']) }}",
className: 'btn-danger', className: 'btn-danger',
callback: function(){ callback: function () {
deleteServerFilesE(); deleteServerFilesE();
setTimeout(function(){ window.location = '/panel/dashboard'; }, 5000); setTimeout(function () { window.location = '/panel/dashboard'; }, 5000);
bootbox.dialog({ bootbox.dialog({
backdrop: true, backdrop: true,
title: '{% raw translate("serverConfig", "sendingDelete", data['lang']) %}', title: '{% raw translate("serverConfig", "sendingDelete", data['lang']) %}',
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("serverConfig", "bePatientDeleteFiles", data['lang']) %} </div>', message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("serverConfig", "bePatientDeleteFiles", data['lang']) %} </div>',
closeButton: false closeButton: false
}) })
return; return;
}
},
noFiles: {
label: "{{ translate('serverConfig', 'noDeleteFiles', data['lang']) }}",
className: 'btn-outline-danger',
callback: function(){
deleteServerE()
setTimeout(function(){ window.location = '/panel/dashboard'; }, 5000);
bootbox.dialog({
backdrop: true,
title: '{% raw translate("serverConfig", "sendingDelete", data['lang']) %}',
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("serverConfig", "bePatientDelete", data['lang']) %} </div>',
closeButton: false
})
return;
}
},
cancel: {
label: "{{ translate('serverConfig', 'cancel', data['lang']) }}",
className: 'btn-secondary',
callback: function(){
return;
}
} }
}, },
callback: function(result) { noFiles: {
label: "{{ translate('serverConfig', 'noDeleteFiles', data['lang']) }}",
className: 'btn-outline-danger',
callback: function () {
deleteServerE()
setTimeout(function () { window.location = '/panel/dashboard'; }, 5000);
bootbox.dialog({
backdrop: true,
title: '{% raw translate("serverConfig", "sendingDelete", data['lang']) %}',
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> &nbsp; {% raw translate("serverConfig", "bePatientDelete", data['lang']) %} </div>',
closeButton: false
})
return;
} }
}); },
} cancel: {
function deleteConfirm (){ label: "{{ translate('serverConfig', 'cancel', data['lang']) }}",
path = "{{data['server_stats']['server_id']['path']}}"; className: 'btn-secondary',
name = "{{data['server_stats']['server_id']['server_name']}}"; callback: function () {
bootbox.confirm({ return;
size: "",
title: "{% raw translate('serverConfig', 'deleteServerQuestion', data['lang']) %}",
closeButton: false,
message: "{% raw translate('serverConfig', 'deleteServerQuestionMessage', data['lang']) %}",
buttons: {
confirm: {
label: "{{ translate('serverConfig', 'yesDelete', data['lang']) }}",
className: 'btn-danger',
},
cancel: {
label: "{{ translate('serverConfig', 'noDelete', data['lang']) }}",
className: 'btn-link',
}
},
callback: function(result) {
if (!result){
return;
return;}
else{
deleteServer();
}
} }
}); }
} },
callback: function (result) {
}
});
}
function deleteConfirm() {
path = "{{data['server_stats']['server_id']['path']}}";
name = "{{data['server_stats']['server_id']['server_name']}}";
bootbox.confirm({
size: "",
title: "{% raw translate('serverConfig', 'deleteServerQuestion', data['lang']) %}",
closeButton: false,
message: "{% raw translate('serverConfig', 'deleteServerQuestionMessage', data['lang']) %}",
buttons: {
confirm: {
label: "{{ translate('serverConfig', 'yesDelete', data['lang']) }}",
className: 'btn-danger',
},
cancel: {
label: "{{ translate('serverConfig', 'noDelete', data['lang']) }}",
className: 'btn-link',
}
},
callback: function (result) {
if (!result) {
return;
return;
}
else {
deleteServer();
}
}
});
}
</script> </script>

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
@ -557,7 +556,7 @@
xmlHttpRequest.addEventListener('error', (e) => { xmlHttpRequest.addEventListener('error', (e) => {
console.error('Error while uploading file', file.name + '.', 'Event:', e) console.error('Error while uploading file', file.name + '.', 'Event:', e)
}, false); }, false);
xmlHttpRequest.send(file); xmlHttpRequest.send(file);
} }
@ -637,7 +636,7 @@
} }
}); });
var fileList = document.getElementById("files"); var fileList = document.getElementById("files");
fileList.addEventListener("change", function (e) { fileList.addEventListener("change", function (e) {
@ -672,7 +671,7 @@
}catch{ }catch{
document.getElementById('files-tree').innerHTML = text; document.getElementById('files-tree').innerHTML = text;
} }
document.getElementsByClassName('files-tree-title')[0].setAttribute('data-path', serverDir); document.getElementsByClassName('files-tree-title')[0].setAttribute('data-path', serverDir);
document.getElementsByClassName('files-tree-title')[0].setAttribute('data-name', 'Files'); document.getElementsByClassName('files-tree-title')[0].setAttribute('data-name', 'Files');
@ -724,7 +723,7 @@
setTimeout(function () {setTreeViewContext()}, 1000); setTimeout(function () {setTreeViewContext()}, 1000);
var toggler = document.getElementById(path); var toggler = document.getElementById(path);
if (toggler.classList.contains('files-tree-title')){ if (toggler.classList.contains('files-tree-title')){
document.getElementById(path+"span").addEventListener("click", function caretListener() { document.getElementById(path+"span").addEventListener("click", function caretListener() {
document.getElementById(path+"ul").classList.toggle("d-block"); document.getElementById(path+"ul").classList.toggle("d-block");

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
@ -205,7 +204,7 @@
</div> </div>
<style> <style>
/* Hide scrollbar for Chrome, Safari and Opera */ /* Hide scrollbar for Chrome, Safari and Opera */
td::-webkit-scrollbar { td::-webkit-scrollbar {
display: none; display: none;
@ -246,7 +245,7 @@ $( document ).ready(function() {
document.getElementById('schedule_table_wrapper').hidden = true; document.getElementById('schedule_table_wrapper').hidden = true;
document.getElementById('mini_schedule_table_wrapper').hidden = false; document.getElementById('mini_schedule_table_wrapper').hidden = false;
} }
}); });
$(window).ready(function(){ $(window).ready(function(){
$('body').click(function(){ $('body').click(function(){

View File

@ -1,7 +1,6 @@
{% extends ../base.html %} {% extends ../base.html %}
{% block meta %} {% block meta %}
<!-- <meta http-equiv="refresh" content="60">-->
{% end %} {% end %}
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} {% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
@ -10,14 +9,14 @@
<div class="content-wrapper"> <div class="content-wrapper">
<!-- Page Title Header Starts--> <!-- Page Title Header Starts-->
<div class="row page-title-header"> <div class="row page-title-header">
<div class="col-12"> <div class="col-12">
<div class="page-header"> <div class="page-header">
<h4 class="page-title"> <h4 class="page-title">
{{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{ data['server_stats']['server_id']['server_name'] }} {{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{ data['server_stats']['server_id']['server_name'] }}
<br /> <br />
<small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small> <small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small>
</h4> </h4>
</div> </div>
</div> </div>
@ -25,66 +24,67 @@
</div> </div>
<!-- Page Title Header Ends--> <!-- Page Title Header Ends-->
{% include "parts/details_stats.html %} {% include "parts/details_stats.html %}
<div class="row"> <div class="row">
<div class="col-sm-12 grid-margin"> <div class="col-sm-12 grid-margin">
<div class="card"> <div class="card">
<div class="card-body pt-0"> <div class="card-body pt-0">
{% include "parts/server_controls_list.html %} {% include "parts/server_controls_list.html %}
<div class="col-md-12">
<div class="input-group">
<div id="virt_console" class="" style="width: 100%; font-size: .8em; padding: 5px 10px; border: 1px solid #383e5d; background-color:#2a2c44;height:500px; overflow: scroll;"></div>
</div>
<br />
<div style="gap: 0.5rem;" class="input-group flex-wrap"> <div class="col-md-12">
<input style="min-width: 10rem;" type="text" class="form-control" id="server_command" name="server_command" placeholder="{{ translate('serverTerm', 'commandInput', data['lang']) }}" autofocus=""> <div class="input-group">
<span class="input-group-btn ml-5"> <div id="virt_console" class="" style="width: 100%; font-size: .8em; padding: 5px 10px; border: 1px solid #383e5d; background-color:#2a2c44;height:500px; overflow: scroll;"></div>
<button id="submit" class="btn btn-sm btn-info" type="button">{{ translate('serverTerm', 'sendCommand', data['lang']) }}</button>
</span>
</div>
{% if data['permissions']['Commands'] in data['user_permissions'] %}
{% if data['server_stats']['updating']%}
<div id="update_control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'updating', data['lang']) }}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
</div>
{% elif data['waiting_start'] %}
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 7rem; white-space: nowrap;" class="btn btn-secondary m-1 flex-grow-1 disabled" data-toggle="tooltip" title="{{ translate('serverTerm', 'delay-explained', data['lang'])}}">{{ translate('serverTerm', 'starting', data['lang']) }}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
</div>
{% else %}
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
<button onclick="send_command(server_id, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start', data['lang']) }}</button>
<button onclick="send_command(server_id, 'restart_server');" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
<button onclick="send_command(server_id, 'stop_server');" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
</div>
{% end %}
{% end %}
</div> </div>
<br />
<div style="gap: 0.5rem;" class="input-group flex-wrap">
<input style="min-width: 10rem;" type="text" class="form-control" id="server_command" name="server_command" placeholder="{{ translate('serverTerm', 'commandInput', data['lang']) }}" autofocus="">
<span class="input-group-btn ml-5">
<button id="submit" class="btn btn-sm btn-info" type="button">{{ translate('serverTerm', 'sendCommand',
data['lang']) }}</button>
</span>
</div>
{% if data['permissions']['Commands'] in data['user_permissions'] %}
{% if data['server_stats']['updating']%}
<div id="update_control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'updating', data['lang']) }}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
</div>
{% elif data['waiting_start'] %}
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 7rem; white-space: nowrap;" class="btn btn-secondary m-1 flex-grow-1 disabled" data-toggle="tooltip" title="{{ translate('serverTerm', 'delay-explained', data['lang'])}}">{{ translate('serverTerm', 'starting', data['lang']) }}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
</div>
{% else %}
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0" style="visibility: visible">
<button onclick="send_command(server_id, 'start_server');" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start', data['lang']) }}</button>
<button onclick="send_command(server_id, 'restart_server');" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate('serverTerm', 'restart', data['lang']) %}</button>
<button onclick="send_command(server_id, 'stop_server');" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
</div>
{% end %}
{% end %}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<style> <style>
#virt_console::-webkit-scrollbar { #virt_console::-webkit-scrollbar {
display: none; display: none;
} }
/* Hide scrollbar for IE, Edge and Firefox */
#virt_console {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
/* Hide scrollbar for IE, Edge and Firefox */
#virt_console {
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
</style> </style>
<!-- content-wrapper ends --> <!-- content-wrapper ends -->
@ -93,188 +93,182 @@
{% block js %} {% block js %}
<script> <script>
function send_command (server_id, command){ function send_command(server_id, command) {
if (command == 'start_server'){ if (command == 'start_server') {
startBtn.setAttribute('disabled', 'disabled');
restartBtn.removeAttribute('disabled');
stopBtn.removeAttribute('disabled');
}
if (command == 'stop_server'){
startBtn.removeAttribute('disabled');
restartBtn.setAttribute('disabled', 'disabled');
stopBtn.setAttribute('disabled', 'disabled');
}
<!-- this getCookie function is in base.html-->
var token = getCookie("_xsrf");
$.ajax({
type: "POST",
headers: {'X-XSRFToken': token},
url: '/server/command?command=' + command + '&id=' + server_id,
success: function(data){
console.log("got response:");
console.log(data);
setTimeout(function(){
if (command != 'start_server'){
location.reload();
}
}, 10000);
}
});
}
if (webSocket) {
webSocket.on('update_button_status', function (updateButton) {
if (updateButton.isUpdating){
if(updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') {
console.log(updateButton.isUpdating)
document.getElementById('control_buttons').innerHTML = '<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "updating", data['lang']) }}</button><button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data['lang']) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data['lang']) }}</button>';
}
}
else{
if (updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') {
window.location.reload()
document.getElementById('update_control_buttons').innerHTML = '<button onclick="send_command(server_id, "start_server");" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "start", data['lang']) }}</button><button onclick="send_command(server_id, "restart_server");" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data['lang']) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data['lang']) }}</button>';
}
}
});
}
// Convert running to lower case (example: 'True' converts to 'true') and
// then to boolean via JSON.parse()
let online = JSON.parse('{{ data['server_stats']['running'] }}'.toLowerCase());
let startBtn = document.querySelector('#start-btn');
let restartBtn = document.querySelector('#restart-btn');
let stopBtn = document.querySelector('#stop-btn');
{% if data['permissions']['Commands'] in data['user_permissions'] %}
if (online) {
startBtn.setAttribute('disabled', 'disabled'); startBtn.setAttribute('disabled', 'disabled');
restartBtn.removeAttribute('disabled'); restartBtn.removeAttribute('disabled');
stopBtn.removeAttribute('disabled'); stopBtn.removeAttribute('disabled');
} else { }
if (command == 'stop_server') {
startBtn.removeAttribute('disabled'); startBtn.removeAttribute('disabled');
restartBtn.setAttribute('disabled', 'disabled'); restartBtn.setAttribute('disabled', 'disabled');
stopBtn.setAttribute('disabled', 'disabled'); stopBtn.setAttribute('disabled', 'disabled');
} }
{% end %} //<!-- this getCookie function is in base.html-->
var token = getCookie("_xsrf");
let server_id = '{{ data['server_stats']['server_id']['server_id'] }}'; $.ajax({
type: "POST",
function get_server_log(){ headers: { 'X-XSRFToken': token },
$.ajax({ url: '/server/command?command=' + command + '&id=' + server_id,
type: 'GET', success: function (data) {
url: '/ajax/server_log?id={{ data['server_stats']['server_id']['server_id'] }}', console.log("got response:");
dataType: 'text', console.log(data);
success: function (data) {
console.log('Got Log From Server')
$('#virt_console').html(data);
scrollConsole();
},
});
}
function new_line_handler(data) {
$('#virt_console').append(data.line)
const elem = document.getElementById('virt_console');
const scrollDiff = (elem.scrollHeight - elem.scrollTop) - elem.clientHeight;
if (!$("#stop_scroll").is(':checked') && scrollDiff < 450) {
scrollConsole()
}
}
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
}
$( document ).ready(function() {
console.log( "ready!" );
get_server_log()
webSocket.on('vterm_new_line', new_line_handler)
});
$('#server_command').on('keydown', function (e) {
if (e.which == 13){
$(this).attr("disabled", "disabled"); //Disable textbox to prevent multiple submit
send_command_to_server()
$(this).removeAttr("disabled"); //Enable the textbox again if needed.
$(this).focus();
}
else if (e.which == 38) {
e.preventDefault();
$('#server_command').val(cmdHistory.getPrev());
} else if (e.which == 40) {
e.preventDefault();
$('#server_command').val(cmdHistory.getNext());
}
});
$("#submit").click(function(e) {
e.preventDefault();
send_command_to_server();
});
function scrollConsole(){
var logview = $('#virt_console');
if(logview.length)
logview.scrollTop(logview[0].scrollHeight - logview.height());
}
function send_command_to_server(){
var server_command = $("#server_command").val()
console.log(server_command)
cmdHistory.push(server_command);
var token = getCookie("_xsrf")
data_to_send = { command :server_command, }
console.log('sending command: ' + server_command)
$.ajax({
type: "POST",
headers: {'X-XSRFToken': token},
url: '/ajax/send_command?id={{ data['server_stats']['server_id']['server_id'] }}',
data: data_to_send,
success: function(data){
console.log("got response:");
console.log(data);
$("#server_command").val('')
},
});
}
const cmdHistory = {
history: [],
current: 0,
push: function(cmd) {
this.history.push(cmd);
this.current = this.history.length - 1;
},
getPrev: function() {
const prevCommand = this.history[this.current];
this.current--;
if (this.current < 0) this.current = 0;
return prevCommand;
},
getNext: function() {
this.current++;
if (this.current > (this.history.length - 1)) {
this.current = (this.history.length - 1);
return '';
}
const nextCommand = this.history[this.current];
return nextCommand;
} }
});
}
if (webSocket) {
webSocket.on('update_button_status', function (updateButton) {
if (updateButton.isUpdating) {
if (updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') {
console.log(updateButton.isUpdating)
document.getElementById('control_buttons').innerHTML = '<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "updating", data['lang']) }}</button><button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data['lang']) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data['lang']) }}</button>';
}
}
else {
if (updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') {
window.location.reload()
document.getElementById('update_control_buttons').innerHTML = '<button onclick="send_command(server_id, "start_server");" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "start", data['lang']) }}</button><button onclick="send_command(server_id, "restart_server");" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data['lang']) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data['lang']) }}</button>';
}
}
});
}
// Convert running to lower case (example: 'True' converts to 'true') and
// then to boolean via JSON.parse()
let online = JSON.parse('{{ data['server_stats']['running'] }}'.toLowerCase());
let startBtn = document.querySelector('#start-btn');
let restartBtn = document.querySelector('#restart-btn');
let stopBtn = document.querySelector('#stop-btn');
{% if data['permissions']['Commands'] in data['user_permissions'] %}
if (online) {
startBtn.setAttribute('disabled', 'disabled');
restartBtn.removeAttribute('disabled');
stopBtn.removeAttribute('disabled');
} else {
startBtn.removeAttribute('disabled');
restartBtn.setAttribute('disabled', 'disabled');
stopBtn.setAttribute('disabled', 'disabled');
}
{% end %}
let server_id = '{{ data['server_stats']['server_id']['server_id'] }}';
function get_server_log() {
$.ajax({
type: 'GET',
url: '/ajax/server_log?id={{ data['server_stats']['server_id']['server_id'] }}',
dataType: 'text',
success: function (data) {
console.log('Got Log From Server')
$('#virt_console').html(data);
scrollConsole();
},
});
}
function new_line_handler(data) {
$('#virt_console').append(data.line)
const elem = document.getElementById('virt_console');
const scrollDiff = (elem.scrollHeight - elem.scrollTop) - elem.clientHeight;
if (!$("#stop_scroll").is(':checked') && scrollDiff < 450) {
scrollConsole()
}
}
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
}
$(document).ready(function () {
console.log("ready!");
get_server_log()
webSocket.on('vterm_new_line', new_line_handler)
});
$('#server_command').on('keydown', function (e) {
if (e.which == 13) {
$(this).attr("disabled", "disabled"); //Disable textbox to prevent multiple submit
send_command_to_server()
$(this).removeAttr("disabled"); //Enable the textbox again if needed.
$(this).focus();
}
else if (e.which == 38) {
e.preventDefault();
$('#server_command').val(cmdHistory.getPrev());
} else if (e.which == 40) {
e.preventDefault();
$('#server_command').val(cmdHistory.getNext());
}
});
$("#submit").click(function (e) {
e.preventDefault();
send_command_to_server();
});
function scrollConsole() {
var logview = $('#virt_console');
if (logview.length)
logview.scrollTop(logview[0].scrollHeight - logview.height());
}
function send_command_to_server() {
var server_command = $("#server_command").val()
console.log(server_command)
cmdHistory.push(server_command);
var token = getCookie("_xsrf")
data_to_send = { command: server_command, }
console.log('sending command: ' + server_command)
$.ajax({
type: "POST",
headers: { 'X-XSRFToken': token },
url: '/ajax/send_command?id={{ data['server_stats']['server_id']['server_id'] }}',
data: data_to_send,
success: function (data) {
console.log("got response:");
console.log(data);
$("#server_command").val('')
},
});
}
const cmdHistory = {
history: [],
current: 0,
push: function (cmd) {
this.history.push(cmd);
this.current = this.history.length - 1;
},
getPrev: function () {
const prevCommand = this.history[this.current];
this.current--;
if (this.current < 0) this.current = 0;
return prevCommand;
},
getNext: function () {
this.current++;
if (this.current > (this.history.length - 1)) {
this.current = (this.history.length - 1);
return '';
}
const nextCommand = this.history[this.current];
return nextCommand;
}
} }
</script> </script>

View File

@ -122,6 +122,7 @@
"serverStats": { "serverStats": {
"online": "Online", "online": "Online",
"offline": "Offline", "offline": "Offline",
"starting": "Verzögerter Start",
"serverStatus": "Server Status", "serverStatus": "Server Status",
"serverStarted": "Server gestartet", "serverStarted": "Server gestartet",
"serverUptime": "Server-Betriebszeit", "serverUptime": "Server-Betriebszeit",

View File

@ -133,6 +133,7 @@
"serverStats": { "serverStats": {
"online": "Online", "online": "Online",
"offline": "Offline", "offline": "Offline",
"starting": "Delayed-Start",
"serverStatus": "Server Status", "serverStatus": "Server Status",
"serverStarted": "Server Started", "serverStarted": "Server Started",
"serverUptime": "Server Uptime", "serverUptime": "Server Uptime",

View File

@ -123,6 +123,7 @@
"serverStats": { "serverStats": {
"online": "En línea", "online": "En línea",
"offline": "Desconectado", "offline": "Desconectado",
"starting": "Inicio-retrasado",
"serverStatus": "Estado del Servidor", "serverStatus": "Estado del Servidor",
"serverStarted": "Servidor Iniciado", "serverStarted": "Servidor Iniciado",
"serverUptime": "Actividad del Servidor", "serverUptime": "Actividad del Servidor",

View File

@ -133,6 +133,7 @@
"serverStats": { "serverStats": {
"online": "Päällä", "online": "Päällä",
"offline": "Pois päältä", "offline": "Pois päältä",
"starting": "Myöhästynyt lähtö",
"serverStatus": "Palvelimen tila", "serverStatus": "Palvelimen tila",
"serverStarted": "Palvelin käynnistyi", "serverStarted": "Palvelin käynnistyi",
"serverUptime": "Palvelimen käyttöaika", "serverUptime": "Palvelimen käyttöaika",

View File

@ -123,6 +123,7 @@
"serverStats": { "serverStats": {
"online": "En Ligne", "online": "En Ligne",
"offline": "Hors Ligne", "offline": "Hors Ligne",
"starting": "Démarrage en cours",
"serverStatus": "Statut du Serveur", "serverStatus": "Statut du Serveur",
"serverStarted": "Serveur Démarré", "serverStarted": "Serveur Démarré",
"serverUptime": "Serveur Disponible depuis", "serverUptime": "Serveur Disponible depuis",

View File

@ -122,6 +122,7 @@
"serverStats": { "serverStats": {
"online": "Na mreži", "online": "Na mreži",
"offline": "Izvan mreže", "offline": "Izvan mreže",
"starting": "Odgođeno pokretanje",
"serverStatus": "Status poslužitelja", "serverStatus": "Status poslužitelja",
"serverStarted": "Poslužitelj pokrenut", "serverStarted": "Poslužitelj pokrenut",
"serverUptime": "Vrijeme rada poslužitelja", "serverUptime": "Vrijeme rada poslužitelja",

View File

@ -122,6 +122,7 @@
"serverStats": { "serverStats": {
"online": "Online", "online": "Online",
"offline": "Offline", "offline": "Offline",
"starting": "Avvio ritardato",
"serverStatus": "Stato del server", "serverStatus": "Stato del server",
"serverStarted": "Server Avviato", "serverStarted": "Server Avviato",
"serverUptime": "Tempo di esecuzione", "serverUptime": "Tempo di esecuzione",

View File

@ -123,6 +123,7 @@
"serverStats": { "serverStats": {
"online": "Turnd on", "online": "Turnd on",
"offline": "Turnd off", "offline": "Turnd off",
"starting": "I waitz b4 I start",
"serverStatus": "Servr Status", "serverStatus": "Servr Status",
"serverStarted": "Servr Started", "serverStarted": "Servr Started",
"serverUptime": "How longz servr been awaek", "serverUptime": "How longz servr been awaek",

View File

@ -122,6 +122,7 @@
"serverStats": { "serverStats": {
"online": "Online", "online": "Online",
"offline": "Offline", "offline": "Offline",
"starting": "Vertraagde start",
"serverStatus": "Server Status", "serverStatus": "Server Status",
"serverStarted": "Server gestart", "serverStarted": "Server gestart",
"serverUptime": "Server Uptime", "serverUptime": "Server Uptime",

View File

@ -123,6 +123,7 @@
"serverStats": { "serverStats": {
"online": "运行中", "online": "运行中",
"offline": "已停止", "offline": "已停止",
"starting": "延迟启动",
"serverStatus": "服务器状态", "serverStatus": "服务器状态",
"serverStarted": "服务器已启动", "serverStarted": "服务器已启动",
"serverUptime": "服务器正常运行时间", "serverUptime": "服务器正常运行时间",