New theme assigned to server console page.

This commit is contained in:
Dane Everitt 2017-01-15 18:52:22 -05:00
parent 4cc9f7447c
commit c7f3bb5112
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
8 changed files with 390 additions and 6 deletions

View file

@ -58,8 +58,19 @@ class ServerController extends Controller
public function getIndex(Request $request) public function getIndex(Request $request)
{ {
$server = Models\Server::getByUUID($request->route()->server); $server = Models\Server::getByUUID($request->route()->server);
$node = Models\Node::find($server->node);
Javascript::put([ Javascript::put([
'server' => [
'uuid' => $server->uuid,
'daemonSecret' => $server->daemonSecret,
'username' => $server->username,
],
'node' => [
'scheme' => $node->scheme,
'fqdn' => $node->fqdn,
'daemonListen' => $node->daemonListen,
],
'meta' => [ 'meta' => [
'saveFile' => route('server.files.save', $server->uuidShort), 'saveFile' => route('server.files.save', $server->uuidShort),
'csrfToken' => csrf_token(), 'csrfToken' => csrf_token(),
@ -69,7 +80,7 @@ class ServerController extends Controller
return view('server.index', [ return view('server.index', [
'server' => $server, 'server' => $server,
'allocations' => Models\Allocation::where('assigned_to', $server->id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(), 'allocations' => Models\Allocation::where('assigned_to', $server->id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(),
'node' => Models\Node::find($server->node), 'node' => $node,
]); ]);
} }

View file

@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
$(window).load(function () { $(window).load(function () {
socket.on('console', function (data) { Socket.on('console', function (data) {
if (data.line.indexOf('You need to agree to the EULA in order to run the server') > -1) { if (data.line.indexOf('You need to agree to the EULA in order to run the server') > -1) {
swal({ swal({
title: 'EULA Acceptance', title: 'EULA Acceptance',

View file

@ -0,0 +1,203 @@
// Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
var CONSOLE_PUSH_COUNT = 50;
var CONSOLE_PUSH_FREQ = 200;
(function initConsole() {
window.TerminalQueue = [];
window.Terminal = $('#terminal').terminal(function (command, term) {
Socket.emit('send command', command);
}, {
greetings: '',
name: Pterodactyl.server.uuid,
height: 450,
exit: false,
prompt: Pterodactyl.server.username + ':~$ ',
scrollOnEcho: false,
scrollBottomOffset: 5,
onBlur: function (terminal) {
return false;
}
});
Socket.on('initial status', function (data) {
Terminal.clear();
if (data.status === 1 || data.status === 2) {
Socket.emit('send server log');
}
});
})();
(function pushOutputQueue() {
if (TerminalQueue.length > CONSOLE_PUSH_COUNT) {
// console throttled warning show
}
if (TerminalQueue.length > 0) {
for (var i = 0; i < CONSOLE_PUSH_COUNT && TerminalQueue.length > 0; i++) {
Terminal.echo(TerminalQueue[0]);
TerminalQueue.shift();
}
}
window.setTimeout(pushOutputQueue, CONSOLE_PUSH_FREQ);
})();
$(document).ready(function () {
$('[data-attr="power"]').click(function (event) {
Socket.emit('set status', $(this).data('action'));
});
var ctc = $('#chart_cpu');
var timeLabels = [];
var cpuData = [];
var CPUChart = new Chart(ctc, {
type: 'line',
data: {
labels: timeLabels,
datasets: [
{
label: "Percent Use",
fill: false,
lineTension: 0.03,
backgroundColor: "#00A1CB",
borderColor: "#00A1CB",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: cpuData,
spanGaps: false,
}
]
},
options: {
title: {
display: true,
text: 'CPU Usage (as Percent Total)'
},
legend: {
display: false,
},
animation: {
duration: 1,
}
}
});
var ctm = $('#chart_memory');
var memoryData = [];
var MemoryChart = new Chart(ctm, {
type: 'line',
data: {
labels: timeLabels,
datasets: [
{
label: "Memory Use",
fill: false,
lineTension: 0.03,
backgroundColor: "#01A4A4",
borderColor: "#01A4A4",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: memoryData,
spanGaps: false,
}
]
},
options: {
title: {
display: true,
text: 'Memory Usage (in Megabytes)'
},
legend: {
display: false,
},
animation: {
duration: 1,
}
}
});
Socket.on('proc', function (proc) {
if (cpuData.length > 10) {
cpuData.shift();
memoryData.shift();
timeLabels.shift();
}
var cpuUse = (Pterodactyl.server.cpu > 0) ? parseFloat(((proc.data.cpu.total / Pterodactyl.server.cpu) * 100).toFixed(3).toString()) : proc.data.cpu.total;
cpuData.push(cpuUse);
memoryData.push(parseInt(proc.data.memory.total / (1024 * 1024)));
var m = new Date();
timeLabels.push($.format.date(new Date(), 'HH:mm:ss'));
CPUChart.update();
MemoryChart.update();
});
// Update Listings on Initial Status
Socket.on('initial status', function (data) {
updateServerPowerControls(data.status);
});
// Update Listings on Status
Socket.on('status', function (data) {
updateServerPowerControls(data.status);
});
function updateServerPowerControls (data) {
// Server is On or Starting
if(data == 1 || data == 2) {
$('[data-attr="power"][data-action="start"]').addClass('disabled');
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').removeClass('disabled');
} else {
if (data == 0) {
$('[data-attr="power"][data-action="start"]').removeClass('disabled');
}
$('[data-attr="power"][data-action="stop"], [data-attr="power"][data-action="restart"]').addClass('disabled');
}
if(data !== 0) {
$('[data-attr="power"][data-action="kill"]').removeClass('disabled');
} else {
$('[data-attr="power"][data-action="kill"]').addClass('disabled');
}
}
});

View file

@ -0,0 +1,69 @@
// Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
(function initSocket() {
if (typeof io !== 'function') {
console.error('Socket.io is reqired to use this panel.');
return;
}
window.Socket = io(Pterodactyl.node.scheme + '://' + Pterodactyl.node.fqdn + ':' + Pterodactyl.node.daemonListen + '/ws/' + Pterodactyl.server.uuid, {
'query': 'token=' + Pterodactyl.server.daemonSecret,
});
Socket.io.on('connect_error', function (err) {
console.error('Could not connect to socket.io.', err);
});
// Connected to Socket Successfully
Socket.on('connect', function () {
console.log('connected to socket');
});
Socket.on('initial status', function (data) {
setStatusIcon(data.status);
});
Socket.on('status', function (data) {
setStatusIcon(data.status);
});
Socket.on('console', function (data) {
TerminalQueue.push(data.line);
});
})();
function setStatusIcon(status) {
switch (status) {
case 0:
$('#server_status_icon').html('<i class="fa fa-circle text-danger"></i> Offline');
break;
case 1:
$('#server_status_icon').html('<i class="fa fa-circle text-success"></i> Online');
break;
case 2:
$('#server_status_icon').html('<i class="fa fa-circle text-warning"></i> Starting');
break;
case 3:
$('#server_status_icon').html('<i class="fa fa-circle text-warning"></i> Stopping');
break;
default:
break;
}
}

View file

@ -0,0 +1,9 @@
<?php
return [
'index' => [
'title' => 'Viewing Server :name',
'header' => 'Server Console',
'header_sub' => 'Control your server in real time.',
]
];

View file

@ -61,7 +61,7 @@
@foreach($servers as $server) @foreach($servers as $server)
<tr class="dynamic-update" data-server="{{ $server->uuidShort }}"> <tr class="dynamic-update" data-server="{{ $server->uuidShort }}">
<td><code>{{ $server->uuidShort }}</code></td> <td><code>{{ $server->uuidShort }}</code></td>
<td><a href="/server/{{ $server->uuidShort }}">{{ $server->name }}</a></td> <td><a href="{{ route('server.index', $server->uuidShort) }}">{{ $server->name }}</a></td>
<td>{{ $server->nodeName }}</td> <td>{{ $server->nodeName }}</td>
<td><code>@if(!is_null($server->ip_alias)){{ $server->ip_alias }}@else{{ $server->ip }}@endif:{{ $server->port }}</code></td> <td><code>@if(!is_null($server->ip_alias)){{ $server->ip_alias }}@else{{ $server->ip }}@endif:{{ $server->port }}</code></td>
<td class="text-center hidden-sm hidden-xs"><span data-action="memory">--</span> / {{ $server->memory === 0 ? '&infin;' : $server->memory }} MB</td> <td class="text-center hidden-sm hidden-xs"><span data-action="memory">--</span> / {{ $server->memory === 0 ? '&infin;' : $server->memory }} MB</td>

View file

@ -101,7 +101,7 @@
<div class="user-panel"> <div class="user-panel">
<div class="info"> <div class="info">
<p>{{ $server->name }}</p> <p>{{ $server->name }}</p>
<a href="#"><i class="fa fa-circle text-success"></i> Online</a> <a href="#" id="server_status_icon"><i class="fa fa-circle text-default"></i> Checking...</a>
</div> </div>
</div> </div>
@endif @endif
@ -129,12 +129,12 @@
</li> </li>
@if (isset($server->name) && isset($node->name)) @if (isset($server->name) && isset($node->name))
<li class="header">SERVER MANAGEMENT</li> <li class="header">SERVER MANAGEMENT</li>
<li> <li class="{{ Route::currentRouteName() !== 'server.index' ?: 'active' }}">
<a href="{{ route('server.index', $server->uuidShort) }}"> <a href="{{ route('server.index', $server->uuidShort) }}">
<i class="fa fa-terminal"></i> <span>Console</span> <i class="fa fa-terminal"></i> <span>Console</span>
</a> </a>
</li> </li>
<li class="treeview"> <li class="treeview {{ Route::currentRouteName() !== 'server.files.index' ?: 'active' }}">
<a href="#"> <a href="#">
<i class="fa fa-files-o"></i> <i class="fa fa-files-o"></i>
<span>File Management</span> <span>File Management</span>
@ -248,6 +248,7 @@
{!! Theme::js('vendor/bootstrap/bootstrap.min.js') !!} {!! Theme::js('vendor/bootstrap/bootstrap.min.js') !!}
{!! Theme::js('vendor/slimscroll/jquery.slimscroll.min.js') !!} {!! Theme::js('vendor/slimscroll/jquery.slimscroll.min.js') !!}
{!! Theme::js('vendor/adminlte/app.min.js') !!} {!! Theme::js('vendor/adminlte/app.min.js') !!}
{!! Theme::js('js/vendor/socketio/socket.io.min.js') !!}
@show @show
</body> </body>
</html> </html>

View file

@ -0,0 +1,91 @@
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
{{-- of this software and associated documentation files (the "Software"), to deal --}}
{{-- in the Software without restriction, including without limitation the rights --}}
{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
{{-- copies of the Software, and to permit persons to whom the Software is --}}
{{-- furnished to do so, subject to the following conditions: --}}
{{-- The above copyright notice and this permission notice shall be included in all --}}
{{-- copies or substantial portions of the Software. --}}
{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
{{-- SOFTWARE. --}}
@extends('layouts.master')
@section('title')
{{ trans('server.index.title', [ 'name' => $server->name]) }}
@endsection
@section('scripts')
@parent
{!! Theme::css('css/jquery.terminal.css') !!}
@endsection
@section('content-header')
<h1>{{ trans('server.index.header') }}<small>{{ trans('server.index.header_sub')}}</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('index') }}">{{ trans('strings.servers') }}</a></li>
<li class="active">{{ $server->name }}</li>
</ol>
@endsection
@section('content')
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-body">
<div id="terminal" style="width:100%;"></div>
</div>
<div class="box-footer text-center">
<button class="btn btn-success" data-attr="power" data-action="start">Start</button>
<button class="btn btn-primary" data-attr="power" data-action="restart">Restart</button>
<button class="btn btn-danger" data-attr="power" data-action="stop">Stop</button>
<button class="btn btn-danger" data-attr="power" data-action="kill">Kill</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Memory Usage</h3>
</div>
<div class="box-body">
<canvas id="chart_memory" style="max-height:300px;"></canvas>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">CPU Usage</h3>
</div>
<div class="box-body">
<canvas id="chart_cpu" style="max-height:300px;"></canvas>
</div>
</div>
</div>
</div>
@endsection
@section('footer-scripts')
@parent
{!! Theme::js('js/frontend/server.socket.js') !!}
{!! Theme::js('js/jquery.mousewheel-min.js') !!}
{!! Theme::js('js/jquery.terminal-0.11.23.min.js') !!}
{!! Theme::js('js/unix_formatting.js') !!}
{!! Theme::js('js/frontend/console.js') !!}
{!! Theme::js('js/vendor/chartjs/chart.min.js') !!}
{!! Theme::js('js/vendor/jquery/jquery-dateFormat.min.js') !!}
@if($server->a_serviceFile === 'minecraft')
{!! Theme::js('js/plugins/minecraft/eula.js') !!}
@endif
@endsection