Add console popout option.
Popout: https://s3.kelp.in/IrTyE.png Menu: https://s3.kelp.in/JYwlC.png Menu Hover: https://s3.kelp.in/cPtSf.png
This commit is contained in:
parent
eeeb4b7580
commit
f58858206e
8 changed files with 199 additions and 104 deletions
|
@ -10,6 +10,9 @@ This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
* `[beta.1]` — Fixes panel looking for an old compiled classfile that is no longer used. This was causing errors relating to `missing class DingoAPI` when trying to upgrade the panel.
|
* `[beta.1]` — Fixes panel looking for an old compiled classfile that is no longer used. This was causing errors relating to `missing class DingoAPI` when trying to upgrade the panel.
|
||||||
* `[beta.1]` — Should fix render issues when trying to edit some files via the panel file editor.
|
* `[beta.1]` — Should fix render issues when trying to edit some files via the panel file editor.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Ability to launch the console in a new window as an individual unit. https://s3.kelp.in/IrTyE.png
|
||||||
|
|
||||||
## v0.6.0-beta.1 (Courageous Carniadactylus)
|
## v0.6.0-beta.1 (Courageous Carniadactylus)
|
||||||
### Fixed
|
### Fixed
|
||||||
* `[pre.7]` — Fixes bug with subuser checkbox display.
|
* `[pre.7]` — Fixes bug with subuser checkbox display.
|
||||||
|
|
|
@ -65,6 +65,31 @@ class ServerController extends Controller
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders server console as an individual item.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param string $uuid
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function getConsole(Request $request, $uuid)
|
||||||
|
{
|
||||||
|
\Debugbar::disable();
|
||||||
|
$server = Models\Server::byUuid($uuid);
|
||||||
|
|
||||||
|
$server->js([
|
||||||
|
'config' => [
|
||||||
|
'console_count' => config('pterodactyl.console.count'),
|
||||||
|
'console_freq' => config('pterodactyl.console.freq'),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return view('server.console', [
|
||||||
|
'server' => $server,
|
||||||
|
'node' => $server->node,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders file overview page.
|
* Renders file overview page.
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,8 +24,9 @@ var InitialLogSent = false;
|
||||||
|
|
||||||
(function initConsole() {
|
(function initConsole() {
|
||||||
window.TerminalQueue = [];
|
window.TerminalQueue = [];
|
||||||
|
window.ConsoleServerStatus = 0;
|
||||||
window.Terminal = $('#terminal').terminal(function (command, term) {
|
window.Terminal = $('#terminal').terminal(function (command, term) {
|
||||||
Socket.emit('send command', command);
|
Socket.emit((ConsoleServerStatus !== 0) ? 'send command' : 'set status', command);
|
||||||
}, {
|
}, {
|
||||||
greetings: '',
|
greetings: '',
|
||||||
name: Pterodactyl.server.uuid,
|
name: Pterodactyl.server.uuid,
|
||||||
|
@ -80,6 +81,7 @@ var InitialLogSent = false;
|
||||||
(function setupSocketListeners() {
|
(function setupSocketListeners() {
|
||||||
// Update Listings on Initial Status
|
// Update Listings on Initial Status
|
||||||
Socket.on('initial status', function (data) {
|
Socket.on('initial status', function (data) {
|
||||||
|
ConsoleServerStatus = data.status;
|
||||||
if (! InitialLogSent) {
|
if (! InitialLogSent) {
|
||||||
updateServerPowerControls(data.status);
|
updateServerPowerControls(data.status);
|
||||||
|
|
||||||
|
@ -91,6 +93,7 @@ var InitialLogSent = false;
|
||||||
|
|
||||||
// Update Listings on Status
|
// Update Listings on Status
|
||||||
Socket.on('status', function (data) {
|
Socket.on('status', function (data) {
|
||||||
|
ConsoleServerStatus = data.status;
|
||||||
updateServerPowerControls(data.status);
|
updateServerPowerControls(data.status);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -134,112 +137,117 @@ $(document).ready(function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Socket.on('proc', function (proc) {
|
(function setupChartElements() {
|
||||||
if (CPUData.length > 10) {
|
if (typeof SkipConsoleCharts !== 'undefined') {
|
||||||
CPUData.shift();
|
return;
|
||||||
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;
|
Socket.on('proc', function (proc) {
|
||||||
CPUData.push(cpuUse);
|
if (CPUData.length > 10) {
|
||||||
MemoryData.push(parseInt(proc.data.memory.total / (1024 * 1024)));
|
CPUData.shift();
|
||||||
|
MemoryData.shift();
|
||||||
TimeLabels.push($.format.date(new Date(), 'HH:mm:ss'));
|
TimeLabels.shift();
|
||||||
|
|
||||||
CPUChart.update();
|
|
||||||
MemoryChart.update();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
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: "#3c8dbc",
|
|
||||||
borderColor: "#3c8dbc",
|
|
||||||
borderCapStyle: 'butt',
|
|
||||||
borderDash: [],
|
|
||||||
borderDashOffset: 0.0,
|
|
||||||
borderJoinStyle: 'miter',
|
|
||||||
pointBorderColor: "#3c8dbc",
|
|
||||||
pointBackgroundColor: "#fff",
|
|
||||||
pointBorderWidth: 1,
|
|
||||||
pointHoverRadius: 5,
|
|
||||||
pointHoverBackgroundColor: "#3c8dbc",
|
|
||||||
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 cpuUse = (Pterodactyl.server.cpu > 0) ? parseFloat(((proc.data.cpu.total / Pterodactyl.server.cpu) * 100).toFixed(3).toString()) : proc.data.cpu.total;
|
||||||
MemoryData = [];
|
CPUData.push(cpuUse);
|
||||||
MemoryChart = new Chart(ctm, {
|
MemoryData.push(parseInt(proc.data.memory.total / (1024 * 1024)));
|
||||||
type: 'line',
|
|
||||||
data: {
|
TimeLabels.push($.format.date(new Date(), 'HH:mm:ss'));
|
||||||
labels: TimeLabels,
|
|
||||||
datasets: [
|
CPUChart.update();
|
||||||
{
|
MemoryChart.update();
|
||||||
label: "Memory Use",
|
});
|
||||||
fill: false,
|
|
||||||
lineTension: 0.03,
|
var ctc = $('#chart_cpu');
|
||||||
backgroundColor: "#3c8dbc",
|
var TimeLabels = [];
|
||||||
borderColor: "#3c8dbc",
|
var CPUData = [];
|
||||||
borderCapStyle: 'butt',
|
var CPUChart = new Chart(ctc, {
|
||||||
borderDash: [],
|
type: 'line',
|
||||||
borderDashOffset: 0.0,
|
data: {
|
||||||
borderJoinStyle: 'miter',
|
labels: TimeLabels,
|
||||||
pointBorderColor: "#3c8dbc",
|
datasets: [
|
||||||
pointBackgroundColor: "#fff",
|
{
|
||||||
pointBorderWidth: 1,
|
label: "Percent Use",
|
||||||
pointHoverRadius: 5,
|
fill: false,
|
||||||
pointHoverBackgroundColor: "#3c8dbc",
|
lineTension: 0.03,
|
||||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
backgroundColor: "#3c8dbc",
|
||||||
pointHoverBorderWidth: 2,
|
borderColor: "#3c8dbc",
|
||||||
pointRadius: 1,
|
borderCapStyle: 'butt',
|
||||||
pointHitRadius: 10,
|
borderDash: [],
|
||||||
data: MemoryData,
|
borderDashOffset: 0.0,
|
||||||
spanGaps: false,
|
borderJoinStyle: 'miter',
|
||||||
|
pointBorderColor: "#3c8dbc",
|
||||||
|
pointBackgroundColor: "#fff",
|
||||||
|
pointBorderWidth: 1,
|
||||||
|
pointHoverRadius: 5,
|
||||||
|
pointHoverBackgroundColor: "#3c8dbc",
|
||||||
|
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,
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
title: {
|
|
||||||
display: true,
|
|
||||||
text: 'Memory Usage (in Megabytes)'
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 1,
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
var ctm = $('#chart_memory');
|
||||||
|
MemoryData = [];
|
||||||
|
MemoryChart = new Chart(ctm, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: TimeLabels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Memory Use",
|
||||||
|
fill: false,
|
||||||
|
lineTension: 0.03,
|
||||||
|
backgroundColor: "#3c8dbc",
|
||||||
|
borderColor: "#3c8dbc",
|
||||||
|
borderCapStyle: 'butt',
|
||||||
|
borderDash: [],
|
||||||
|
borderDashOffset: 0.0,
|
||||||
|
borderJoinStyle: 'miter',
|
||||||
|
pointBorderColor: "#3c8dbc",
|
||||||
|
pointBackgroundColor: "#fff",
|
||||||
|
pointBorderWidth: 1,
|
||||||
|
pointHoverRadius: 5,
|
||||||
|
pointHoverBackgroundColor: "#3c8dbc",
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// 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
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
$('#console-popout').on('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
window.open($(this).attr('href'), 'Pterodactyl Console', 'width=800,height=400');
|
||||||
|
});
|
||||||
var Server = (function () {
|
var Server = (function () {
|
||||||
|
|
||||||
function initSocket() {
|
function initSocket() {
|
||||||
|
|
|
@ -12,6 +12,7 @@ return [
|
||||||
'server' => [
|
'server' => [
|
||||||
'header' => 'SERVER MANAGEMENT',
|
'header' => 'SERVER MANAGEMENT',
|
||||||
'console' => 'Console',
|
'console' => 'Console',
|
||||||
|
'console-pop' => 'Fullscreen Console',
|
||||||
'file_management' => 'File Management',
|
'file_management' => 'File Management',
|
||||||
'file_browser' => 'File Browser',
|
'file_browser' => 'File Browser',
|
||||||
'create_file' => 'Create File',
|
'create_file' => 'Create File',
|
||||||
|
|
|
@ -126,6 +126,11 @@
|
||||||
<li class="{{ Route::currentRouteName() !== 'server.index' ?: 'active' }}">
|
<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>@lang('navigation.server.console')</span>
|
<i class="fa fa-terminal"></i> <span>@lang('navigation.server.console')</span>
|
||||||
|
<span class="pull-right-container muted muted-hover" href="{{ route('server.console', $server->uuidShort) }}" id="console-popout">
|
||||||
|
<span class="label label-default pull-right" style="padding: 3px 5px 2px 5px;">
|
||||||
|
<i class="fa fa-external-link"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@can('list-files', $server)
|
@can('list-files', $server)
|
||||||
|
|
49
resources/themes/pterodactyl/server/console.blade.php
Normal file
49
resources/themes/pterodactyl/server/console.blade.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
{{-- Copyright (c) 2015 - 2017 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. --}}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ Settings::get('company', 'Pterodactyl') }} - Console → {{ $server->name }}</title>
|
||||||
|
@include('layouts.scripts')
|
||||||
|
{!! Theme::css('vendor/terminal/jquery.terminal.css') !!}
|
||||||
|
</head>
|
||||||
|
<body style="margin:0;width:100%;height:100%;">
|
||||||
|
<div id="terminal" style="width:100%"></div>
|
||||||
|
<div id="terminalNotify" class="terminal-notify hidden">
|
||||||
|
<i class="fa fa-bell"></i>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>window.SkipConsoleCharts = true</script>
|
||||||
|
{!! Theme::js('js/laroute.js') !!}
|
||||||
|
{!! Theme::js('vendor/jquery/jquery.min.js') !!}
|
||||||
|
{!! Theme::js('vendor/socketio/socket.io.min.js') !!}
|
||||||
|
{!! Theme::js('vendor/bootstrap-notify/bootstrap-notify.min.js') !!}
|
||||||
|
{!! Theme::js('js/frontend/server.socket.js') !!}
|
||||||
|
{!! Theme::js('vendor/mousewheel/jquery.mousewheel-min.js') !!}
|
||||||
|
{!! Theme::js('vendor/terminal/jquery.terminal.min.js') !!}
|
||||||
|
{!! Theme::js('vendor/terminal/unix_formatting.js') !!}
|
||||||
|
{!! Theme::js('js/frontend/console.js') !!}
|
||||||
|
<script>
|
||||||
|
Terminal.resize($(window).innerWidth() - 20, $(window).innerHeight() - 20);
|
||||||
|
$(window).on('resize', function () {
|
||||||
|
Terminal.resize($(window).innerWidth() - 20, $(window).innerHeight() - 20);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -22,6 +22,7 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
Route::get('/', 'ServerController@getIndex')->name('server.index');
|
Route::get('/', 'ServerController@getIndex')->name('server.index');
|
||||||
|
Route::get('/console', 'ServerController@getConsole')->name('server.console');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue