From 93a7d11c28d8423741b6d01d57e6dfaf5de97e0e Mon Sep 17 00:00:00 2001 From: stanjg Date: Fri, 4 May 2018 18:45:37 +0200 Subject: [PATCH 1/8] Made a base --- .../Admin/StatisticsController.php | 59 ++++++++++ public/themes/pterodactyl/css/pterodactyl.css | 4 + .../themes/pterodactyl/js/admin/statistics.js | 101 +++++++++++++++++ .../pterodactyl/admin/statistics.blade.php | 103 ++++++++++++++++++ .../pterodactyl/layouts/admin.blade.php | 5 + routes/admin.php | 1 + 6 files changed, 273 insertions(+) create mode 100644 app/Http/Controllers/Admin/StatisticsController.php create mode 100644 public/themes/pterodactyl/js/admin/statistics.js create mode 100644 resources/themes/pterodactyl/admin/statistics.blade.php diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php new file mode 100644 index 000000000..499b52cd4 --- /dev/null +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -0,0 +1,59 @@ +sum('memory'); + $totalNodeRam = DB::table('nodes')->sum('memory'); + $totalServerDisk = DB::table('servers')->sum('disk'); + $totalNodeDisk = DB::table('nodes')->sum('disk'); + $totalAllocations = Allocation::count(); + + $suspendedServersCount = Server::where('suspended', true)->count(); + + Javascript::put([ + 'servers' => Server::all(), + 'serverCount' => $serversCount, + 'suspendedServers' => $suspendedServersCount, + 'totalServerRam' => $totalServerRam, + 'totalNodeRam' => $totalNodeRam, + 'totalServerDisk' => $totalServerDisk, + 'totalNodeDisk' => $totalNodeDisk, + ]); + + return view('admin.statistics', [ + 'serversCount' => $serversCount, + 'nodesCount' => $nodesCount, + 'usersCount' => $usersCount, + 'eggsCount' => $eggsCount, + 'totalServerRam' => $totalServerRam, + 'databasesCount' => $databasesCount, + 'totalNodeRam' => $totalNodeRam, + 'totalNodeDisk' => $totalNodeDisk, + 'totalServerDisk' => $totalServerDisk, + 'totalAllocations' => $totalAllocations, + ]); + } + +} diff --git a/public/themes/pterodactyl/css/pterodactyl.css b/public/themes/pterodactyl/css/pterodactyl.css index 9e7e6a822..41f163f3b 100644 --- a/public/themes/pterodactyl/css/pterodactyl.css +++ b/public/themes/pterodactyl/css/pterodactyl.css @@ -473,3 +473,7 @@ label.control-label > span.field-optional:before { height: 42px; width: auto; } + +.number-info-box-content { + padding: 15px 10px 0; +} diff --git a/public/themes/pterodactyl/js/admin/statistics.js b/public/themes/pterodactyl/js/admin/statistics.js new file mode 100644 index 000000000..b5bdbe4a1 --- /dev/null +++ b/public/themes/pterodactyl/js/admin/statistics.js @@ -0,0 +1,101 @@ +var freeDisk = Pterodactyl.totalNodeDisk - Pterodactyl.totalServerDisk; +let diskChart = new Chart($('#disk_chart'), { + type: 'pie', + data: { + labels: ['Free Disk', 'Used Disk'], + datasets: [ + { + label: 'Disk in MBs', + backgroundColor: ['#51B060', '#ff0000'], + data: [freeDisk, Pterodactyl.totalServerDisk] + } + ] + } +}); + +var freeRam = Pterodactyl.totalNodeRam - Pterodactyl.totalServerRam; +let ramChart = new Chart($('#ram_chart'), { + type: 'pie', + data: { + labels: ['Free RAM', 'Used RAM'], + datasets: [ + { + label: 'RAM in MBs', + backgroundColor: ['#51B060', '#ff0000'], + data: [freeRam, Pterodactyl.totalServerRam] + } + ] + } +}); + +var activeServers = Pterodactyl.serverCount - Pterodactyl.suspendedServers; +let serversChart = new Chart($('#servers_chart'), { + type: 'pie', + data: { + labels: ['Active', 'Suspended'], + datasets: [ + { + label: 'Servers', + backgroundColor: ['#51B060', '#E08E0B'], + data: [activeServers, Pterodactyl.suspendedServers] + } + ] + } +}); + +let statusChart = new Chart($('#status_chart'), { + type: 'pie', + data: { + labels: ['Online', 'Offline', 'Installing', 'Error'], + datasets: [ + { + label: '', + backgroundColor: ['#51B060', '#b7b7b7', '#E08E0B', '#ff0000'], + data: [0,0,0,0] + } + ] + } +}); + +var servers = Pterodactyl.servers; +servers.forEach(function (server) { + $.ajax({ + type: 'GET', + url: Router.route('index.status', { server: server.uuidShort}), + timeout: 5000, + headers: { + 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content'), + } + }).done(function (data) { + + if (typeof data.status === 'undefined') { + // Error + statusChart.data.datasets[0].data[3]++; + return; + } + + switch (data.status) { + case 0: + case 3: + case 30: + // Offline + statusChart.data.datasets[0].data[1]++; + break; + case 1: + case 2: + // Online + console.log('online'); + statusChart.data.datasets[0].data[0]++; + break; + case 20: + // Installing + statusChart.data.datasets[0].data[2]++; + break; + } + statusChart.update(); + }).fail(function (jqXHR) { + // Error + statusChart.data.datasets[0].data[3]++; + statusChart.update(); + }); +}); \ No newline at end of file diff --git a/resources/themes/pterodactyl/admin/statistics.blade.php b/resources/themes/pterodactyl/admin/statistics.blade.php new file mode 100644 index 000000000..0579093af --- /dev/null +++ b/resources/themes/pterodactyl/admin/statistics.blade.php @@ -0,0 +1,103 @@ +@extends('layouts.admin') +@include('partials/admin.settings.nav', ['activeTab' => 'basic']) + +@section('title') + Statistics Overview +@endsection + +@section('content-header') +

Statistics OverviewMonitor your panel usage.

+ +@endsection + +@section('content') +
+
+
+
+ Servers +
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+ Servers + {{ $serversCount }} +
+
+
+ +
+ Total used RAM + {{ $totalServerRam }}MB +
+
+
+ +
+ Total used disk space + {{ $totalServerDisk }}MB +
+
+
+
+
+
+
+
+ Nodes +
+ +
+ +
+
+ +
+
+
+
+
+
+ +
+ Total RAM + {{ $totalNodeRam }}MB +
+
+
+ +
+ Total Disk Space + {{ $totalNodeDisk }}MB +
+
+
+ +
+ Total Allocations + {{ $totalAllocations }} +
+
+
+
+@endsection + +@section('footer-scripts') + @parent + {!! Theme::js('vendor/chartjs/chart.min.js') !!} + {!! Theme::js('js/admin/statistics.js') !!} +@endsection \ No newline at end of file diff --git a/resources/themes/pterodactyl/layouts/admin.blade.php b/resources/themes/pterodactyl/layouts/admin.blade.php index d67eb6b41..aaf8f4cac 100644 --- a/resources/themes/pterodactyl/layouts/admin.blade.php +++ b/resources/themes/pterodactyl/layouts/admin.blade.php @@ -80,6 +80,11 @@ Overview +
  • + + Statistics + +
  • Settings diff --git a/routes/admin.php b/routes/admin.php index 7dfa94f09..70ba7e3d1 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -1,6 +1,7 @@ name('admin.index'); +Route::get('/statistics', 'StatisticsController@index')->name('admin.statistics'); /* |-------------------------------------------------------------------------- From 28a97fea54351d8d00f64220483688202b9efd07 Mon Sep 17 00:00:00 2001 From: stanjg Date: Fri, 4 May 2018 22:48:43 +0200 Subject: [PATCH 2/8] Polished it up --- .../Admin/StatisticsController.php | 22 ++++++++++- .../themes/pterodactyl/js/admin/statistics.js | 30 ++++++++++++--- .../pterodactyl/admin/statistics.blade.php | 38 +++++++++++++++++++ 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index 499b52cd4..119adb086 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -12,13 +12,22 @@ use Pterodactyl\Models\Server; use Pterodactyl\Models\User; use JavaScript; use Illuminate\Support\Facades\DB; +use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService; class StatisticsController extends Controller { + private $keyProviderService; + + function __construct(DaemonKeyProviderService $keyProviderService) + { + $this->keyProviderService = $keyProviderService; + } + public function index(Request $request) { $servers = Server::all(); + $nodes = Node::all(); $serversCount = count($servers); $nodesCount = Node::count(); $usersCount = User::count(); @@ -29,17 +38,26 @@ class StatisticsController extends Controller $totalServerDisk = DB::table('servers')->sum('disk'); $totalNodeDisk = DB::table('nodes')->sum('disk'); $totalAllocations = Allocation::count(); + $totalUsersCount = User::count(); + $totalDBCount = Database::count(); $suspendedServersCount = Server::where('suspended', true)->count(); + $tokens = []; + foreach ($nodes as $node) { + $tokens[$node->id] = $this->keyProviderService->handle($node->servers->get(0), $request->user()); + } + Javascript::put([ - 'servers' => Server::all(), + 'servers' => $servers, 'serverCount' => $serversCount, 'suspendedServers' => $suspendedServersCount, 'totalServerRam' => $totalServerRam, 'totalNodeRam' => $totalNodeRam, 'totalServerDisk' => $totalServerDisk, 'totalNodeDisk' => $totalNodeDisk, + 'nodes' => $nodes, + 'tokens' => $tokens, ]); return view('admin.statistics', [ @@ -53,6 +71,8 @@ class StatisticsController extends Controller 'totalNodeDisk' => $totalNodeDisk, 'totalServerDisk' => $totalServerDisk, 'totalAllocations' => $totalAllocations, + 'totalUsersCount' => $totalUsersCount, + 'totalDBCount' => $totalDBCount, ]); } diff --git a/public/themes/pterodactyl/js/admin/statistics.js b/public/themes/pterodactyl/js/admin/statistics.js index b5bdbe4a1..f2c1c13dd 100644 --- a/public/themes/pterodactyl/js/admin/statistics.js +++ b/public/themes/pterodactyl/js/admin/statistics.js @@ -58,13 +58,25 @@ let statusChart = new Chart($('#status_chart'), { }); var servers = Pterodactyl.servers; -servers.forEach(function (server) { +var nodes = Pterodactyl.nodes; + +for (let i = 0; i < servers.length; i++) { + setTimeout(getStatus, 200 * i); +} + +var index = 0; +function getStatus() { + var server = servers[index]; + var uuid = server.uuid; + var node = getNodeByID(server.node_id); + $.ajax({ type: 'GET', - url: Router.route('index.status', { server: server.uuidShort}), + url: node.scheme + '://' + node.fqdn + ':'+node.daemonListen+'/v1/server', timeout: 5000, headers: { - 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content'), + 'X-Access-Server': uuid, + 'X-Access-Token': Pterodactyl.tokens[node.id], } }).done(function (data) { @@ -84,7 +96,6 @@ servers.forEach(function (server) { case 1: case 2: // Online - console.log('online'); statusChart.data.datasets[0].data[0]++; break; case 20: @@ -98,4 +109,13 @@ servers.forEach(function (server) { statusChart.data.datasets[0].data[3]++; statusChart.update(); }); -}); \ No newline at end of file + + index++; +} + +function getNodeByID(id) { + for (var i = 0; i < nodes.length; i++) { + if (nodes[i].id === id) + return nodes[i]; + } +} \ No newline at end of file diff --git a/resources/themes/pterodactyl/admin/statistics.blade.php b/resources/themes/pterodactyl/admin/statistics.blade.php index 0579093af..e8e7cc255 100644 --- a/resources/themes/pterodactyl/admin/statistics.blade.php +++ b/resources/themes/pterodactyl/admin/statistics.blade.php @@ -94,6 +94,44 @@ +
    +
    +
    + +
    + Total Eggs + {{ $eggsCount }} +
    +
    +
    +
    +
    + +
    + Total Users + {{ $totalUsersCount }} +
    +
    +
    +
    +
    + +
    + Total Nodes + {{ $nodesCount }} +
    +
    +
    +
    +
    + +
    + Total Databases + {{ $totalDBCount }} +
    +
    +
    +
    @endsection @section('footer-scripts') From ee50da0a7c2538fa7ed337424833b431d54280b3 Mon Sep 17 00:00:00 2001 From: stanjg Date: Fri, 4 May 2018 23:35:45 +0200 Subject: [PATCH 3/8] Fixed a typo --- resources/themes/pterodactyl/admin/statistics.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/themes/pterodactyl/admin/statistics.blade.php b/resources/themes/pterodactyl/admin/statistics.blade.php index e8e7cc255..dff5019e4 100644 --- a/resources/themes/pterodactyl/admin/statistics.blade.php +++ b/resources/themes/pterodactyl/admin/statistics.blade.php @@ -60,14 +60,14 @@
    Nodes
    - +
    - +
    From 06a67bb4bb2a786132f4731a14168446eb403356 Mon Sep 17 00:00:00 2001 From: stanjg Date: Sat, 5 May 2018 10:39:20 +0200 Subject: [PATCH 4/8] Cleaned up some duplicate code --- app/Http/Controllers/Admin/StatisticsController.php | 4 ---- resources/themes/pterodactyl/admin/statistics.blade.php | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index 119adb086..a3777e4e7 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -38,8 +38,6 @@ class StatisticsController extends Controller $totalServerDisk = DB::table('servers')->sum('disk'); $totalNodeDisk = DB::table('nodes')->sum('disk'); $totalAllocations = Allocation::count(); - $totalUsersCount = User::count(); - $totalDBCount = Database::count(); $suspendedServersCount = Server::where('suspended', true)->count(); @@ -71,8 +69,6 @@ class StatisticsController extends Controller 'totalNodeDisk' => $totalNodeDisk, 'totalServerDisk' => $totalServerDisk, 'totalAllocations' => $totalAllocations, - 'totalUsersCount' => $totalUsersCount, - 'totalDBCount' => $totalDBCount, ]); } diff --git a/resources/themes/pterodactyl/admin/statistics.blade.php b/resources/themes/pterodactyl/admin/statistics.blade.php index dff5019e4..46e112336 100644 --- a/resources/themes/pterodactyl/admin/statistics.blade.php +++ b/resources/themes/pterodactyl/admin/statistics.blade.php @@ -109,7 +109,7 @@
    Total Users - {{ $totalUsersCount }} + {{ $usersCount }}
    @@ -127,7 +127,7 @@
    Total Databases - {{ $totalDBCount }} + {{ $databasesCount }}
    From 095d85bb60cb283596ff7879bcc567924157da53 Mon Sep 17 00:00:00 2001 From: stanjg Date: Sun, 6 May 2018 17:59:11 +0200 Subject: [PATCH 5/8] Added the server as argument, and improved the bug fix --- app/Http/Controllers/Admin/StatisticsController.php | 12 ++++++++---- public/themes/pterodactyl/js/admin/statistics.js | 11 ++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index a3777e4e7..aedca3d6b 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -3,6 +3,8 @@ namespace Pterodactyl\Http\Controllers\Admin; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; +use JavaScript; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Models\Allocation; use Pterodactyl\Models\Database; @@ -10,8 +12,6 @@ use Pterodactyl\Models\Egg; use Pterodactyl\Models\Node; use Pterodactyl\Models\Server; use Pterodactyl\Models\User; -use JavaScript; -use Illuminate\Support\Facades\DB; use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService; class StatisticsController extends Controller @@ -29,7 +29,7 @@ class StatisticsController extends Controller $servers = Server::all(); $nodes = Node::all(); $serversCount = count($servers); - $nodesCount = Node::count(); + $nodesCount = count($nodes); $usersCount = User::count(); $eggsCount = Egg::count(); $databasesCount = Database::count(); @@ -43,7 +43,11 @@ class StatisticsController extends Controller $tokens = []; foreach ($nodes as $node) { - $tokens[$node->id] = $this->keyProviderService->handle($node->servers->get(0), $request->user()); + $server = Server::where('node_id', $node->id)->first(); + if ($server == null) + continue; + + $tokens[$node->id] = $this->keyProviderService->handle($server, $request->user()); } Javascript::put([ diff --git a/public/themes/pterodactyl/js/admin/statistics.js b/public/themes/pterodactyl/js/admin/statistics.js index f2c1c13dd..12f4277bd 100644 --- a/public/themes/pterodactyl/js/admin/statistics.js +++ b/public/themes/pterodactyl/js/admin/statistics.js @@ -61,12 +61,10 @@ var servers = Pterodactyl.servers; var nodes = Pterodactyl.nodes; for (let i = 0; i < servers.length; i++) { - setTimeout(getStatus, 200 * i); + setTimeout(getStatus, 200 * i, servers[i]); } -var index = 0; -function getStatus() { - var server = servers[index]; +function getStatus(server) { var uuid = server.uuid; var node = getNodeByID(server.node_id); @@ -109,13 +107,12 @@ function getStatus() { statusChart.data.datasets[0].data[3]++; statusChart.update(); }); - - index++; } function getNodeByID(id) { for (var i = 0; i < nodes.length; i++) { - if (nodes[i].id === id) + if (nodes[i].id === id) { return nodes[i]; + } } } \ No newline at end of file From 86e70853960f89dd308aa475834deabcff44f661 Mon Sep 17 00:00:00 2001 From: stanjg Date: Sat, 26 May 2018 20:58:49 +0200 Subject: [PATCH 6/8] Cleaned up the controller and prepared for tests --- .../Repository/RepositoryInterface.php | 7 ++ .../Admin/StatisticsController.php | 65 +++++++++++++------ .../Eloquent/EloquentRepository.php | 10 +++ .../JavascriptStatisticsInjection.php | 24 +++++++ 4 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 app/Traits/Controllers/JavascriptStatisticsInjection.php diff --git a/app/Contracts/Repository/RepositoryInterface.php b/app/Contracts/Repository/RepositoryInterface.php index 4a098c34f..3da9da009 100644 --- a/app/Contracts/Repository/RepositoryInterface.php +++ b/app/Contracts/Repository/RepositoryInterface.php @@ -200,4 +200,11 @@ interface RepositoryInterface * @return bool */ public function insertIgnore(array $values): bool; + + /** + * Get the amount of entries in the database + * + * @return int + */ + public function count(): int; } diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index aedca3d6b..984b6de22 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -5,52 +5,75 @@ namespace Pterodactyl\Http\Controllers\Admin; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use JavaScript; +use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; +use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; +use Pterodactyl\Contracts\Repository\EggRepositoryInterface; +use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; +use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; +use Pterodactyl\Contracts\Repository\UserRepositoryInterface; use Pterodactyl\Http\Controllers\Controller; -use Pterodactyl\Models\Allocation; -use Pterodactyl\Models\Database; -use Pterodactyl\Models\Egg; -use Pterodactyl\Models\Node; -use Pterodactyl\Models\Server; -use Pterodactyl\Models\User; use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService; +use Pterodactyl\Traits\Controllers\JavascriptInjection; class StatisticsController extends Controller { + use JavascriptInjection; + + private $allocationRepository; + + private $databaseRepository; private $keyProviderService; - function __construct(DaemonKeyProviderService $keyProviderService) + private $eggRepository; + + private $nodeRepository; + + private $serverRepository; + + private $userRepository; + + function __construct( + AllocationRepositoryInterface $allocationRepository, + DatabaseRepositoryInterface $databaseRepository, + DaemonKeyProviderService $keyProviderService, + EggRepositoryInterface $eggRepository, + NodeRepositoryInterface $nodeRepository, + ServerRepositoryInterface $serverRepository, + UserRepositoryInterface $userRepository + ) { + $this->allocationRepository = $allocationRepository; + $this->databaseRepository = $databaseRepository; $this->keyProviderService = $keyProviderService; + $this->eggRepository = $eggRepository; + $this->nodeRepository = $nodeRepository; + $this->serverRepository = $serverRepository; + $this->userRepository = $userRepository; } public function index(Request $request) { - $servers = Server::all(); - $nodes = Node::all(); + $servers = $this->serverRepository->all(); $serversCount = count($servers); + $nodes = $this->nodeRepository->all(); $nodesCount = count($nodes); - $usersCount = User::count(); - $eggsCount = Egg::count(); - $databasesCount = Database::count(); + $usersCount = $this->userRepository->count(); + $eggsCount = $this->eggRepository->count(); + $databasesCount = $this->databaseRepository->count(); $totalServerRam = DB::table('servers')->sum('memory'); $totalNodeRam = DB::table('nodes')->sum('memory'); $totalServerDisk = DB::table('servers')->sum('disk'); $totalNodeDisk = DB::table('nodes')->sum('disk'); - $totalAllocations = Allocation::count(); - - $suspendedServersCount = Server::where('suspended', true)->count(); + $totalAllocations = $this->allocationRepository->count(); + $suspendedServersCount = $this->serverRepository->getBuilder()->where('suspended', true)->count(); $tokens = []; foreach ($nodes as $node) { - $server = Server::where('node_id', $node->id)->first(); - if ($server == null) - continue; - - $tokens[$node->id] = $this->keyProviderService->handle($server, $request->user()); + $tokens[$node->id] = $node->daemonSecret; } - Javascript::put([ + $this->injectJavascript([ 'servers' => $servers, 'serverCount' => $serversCount, 'suspendedServers' => $suspendedServersCount, diff --git a/app/Repositories/Eloquent/EloquentRepository.php b/app/Repositories/Eloquent/EloquentRepository.php index 74ec809fe..64e7cfb60 100644 --- a/app/Repositories/Eloquent/EloquentRepository.php +++ b/app/Repositories/Eloquent/EloquentRepository.php @@ -296,4 +296,14 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf return $this->getBuilder()->getConnection()->statement($statement, $bindings); } + + /** + * Get the amount of entries in the database + * + * @return int + */ + public function count(): int + { + return $this->getBuilder()->count(); + } } diff --git a/app/Traits/Controllers/JavascriptStatisticsInjection.php b/app/Traits/Controllers/JavascriptStatisticsInjection.php new file mode 100644 index 000000000..779764233 --- /dev/null +++ b/app/Traits/Controllers/JavascriptStatisticsInjection.php @@ -0,0 +1,24 @@ + Date: Sat, 26 May 2018 21:02:47 +0200 Subject: [PATCH 7/8] Wording changes and fix of major fail last commit --- app/Http/Controllers/Admin/StatisticsController.php | 5 ++--- app/Traits/Controllers/JavascriptStatisticsInjection.php | 2 +- public/themes/pterodactyl/js/admin/statistics.js | 4 ++-- resources/themes/pterodactyl/admin/statistics.blade.php | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index 984b6de22..07124e4b6 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -4,7 +4,6 @@ namespace Pterodactyl\Http\Controllers\Admin; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; -use JavaScript; use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; use Pterodactyl\Contracts\Repository\EggRepositoryInterface; @@ -13,11 +12,11 @@ use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; use Pterodactyl\Contracts\Repository\UserRepositoryInterface; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService; -use Pterodactyl\Traits\Controllers\JavascriptInjection; +use Pterodactyl\Traits\Controllers\JavascriptStatisticsInjection; class StatisticsController extends Controller { - use JavascriptInjection; + use JavascriptStatisticsInjection; private $allocationRepository; diff --git a/app/Traits/Controllers/JavascriptStatisticsInjection.php b/app/Traits/Controllers/JavascriptStatisticsInjection.php index 779764233..3b4e52d0f 100644 --- a/app/Traits/Controllers/JavascriptStatisticsInjection.php +++ b/app/Traits/Controllers/JavascriptStatisticsInjection.php @@ -10,7 +10,7 @@ namespace Pterodactyl\Traits\Controllers; use JavaScript; -class JavascriptStatisticsInjection +trait JavascriptStatisticsInjection { /** diff --git a/public/themes/pterodactyl/js/admin/statistics.js b/public/themes/pterodactyl/js/admin/statistics.js index 12f4277bd..59034a8da 100644 --- a/public/themes/pterodactyl/js/admin/statistics.js +++ b/public/themes/pterodactyl/js/admin/statistics.js @@ -5,7 +5,7 @@ let diskChart = new Chart($('#disk_chart'), { labels: ['Free Disk', 'Used Disk'], datasets: [ { - label: 'Disk in MBs', + label: 'Disk (in MB)', backgroundColor: ['#51B060', '#ff0000'], data: [freeDisk, Pterodactyl.totalServerDisk] } @@ -20,7 +20,7 @@ let ramChart = new Chart($('#ram_chart'), { labels: ['Free RAM', 'Used RAM'], datasets: [ { - label: 'RAM in MBs', + label: 'Memory (in MB)', backgroundColor: ['#51B060', '#ff0000'], data: [freeRam, Pterodactyl.totalServerRam] } diff --git a/resources/themes/pterodactyl/admin/statistics.blade.php b/resources/themes/pterodactyl/admin/statistics.blade.php index 46e112336..036ad937f 100644 --- a/resources/themes/pterodactyl/admin/statistics.blade.php +++ b/resources/themes/pterodactyl/admin/statistics.blade.php @@ -41,14 +41,14 @@
    - Total used RAM + Total used Memory (in MB) {{ $totalServerRam }}MB
    - Total used disk space + Total used Disk (in MB) {{ $totalServerDisk }}MB
    From 60e1ffa56497e5fe9bee8da8a06e74e54b328e60 Mon Sep 17 00:00:00 2001 From: stanjg Date: Sun, 27 May 2018 00:16:13 +0200 Subject: [PATCH 8/8] Added a test for the controller and cleaned up the controller --- .../Repository/NodeRepositoryInterface.php | 8 ++ .../Repository/ServerRepositoryInterface.php | 7 ++ .../Admin/StatisticsController.php | 38 +++--- app/Repositories/Eloquent/NodeRepository.php | 27 +++++ .../Eloquent/ServerRepository.php | 10 ++ ...ction.php => PlainJavascriptInjection.php} | 2 +- .../themes/pterodactyl/js/admin/statistics.js | 2 +- .../pterodactyl/admin/statistics.blade.php | 4 +- .../Admin/StatisticsControllerTest.php | 113 ++++++++++++++++++ 9 files changed, 188 insertions(+), 23 deletions(-) rename app/Traits/Controllers/{JavascriptStatisticsInjection.php => PlainJavascriptInjection.php} (88%) create mode 100644 tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php diff --git a/app/Contracts/Repository/NodeRepositoryInterface.php b/app/Contracts/Repository/NodeRepositoryInterface.php index 0ebcbe3a0..c533032c0 100644 --- a/app/Contracts/Repository/NodeRepositoryInterface.php +++ b/app/Contracts/Repository/NodeRepositoryInterface.php @@ -21,6 +21,14 @@ interface NodeRepositoryInterface extends RepositoryInterface, SearchableInterfa */ public function getUsageStats(Node $node): array; + /** + * Return the usage stats for a single node. + * + * @param \Pterodactyl\Models\Node $node + * @return array + */ + public function getUsageStatsRaw(Node $node): array; + /** * Return all available nodes with a searchable interface. * diff --git a/app/Contracts/Repository/ServerRepositoryInterface.php b/app/Contracts/Repository/ServerRepositoryInterface.php index dc677fba0..9fb712e29 100644 --- a/app/Contracts/Repository/ServerRepositoryInterface.php +++ b/app/Contracts/Repository/ServerRepositoryInterface.php @@ -145,4 +145,11 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter * @return bool */ public function isUniqueUuidCombo(string $uuid, string $short): bool; + + /** + * Get the amount of servers that are suspended + * + * @return int + */ + public function getSuspendedServersCount(): int; } diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index 07124e4b6..2327fd88d 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -11,19 +11,16 @@ use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; use Pterodactyl\Contracts\Repository\UserRepositoryInterface; use Pterodactyl\Http\Controllers\Controller; -use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService; -use Pterodactyl\Traits\Controllers\JavascriptStatisticsInjection; +use Pterodactyl\Traits\Controllers\PlainJavascriptInjection; class StatisticsController extends Controller { - use JavascriptStatisticsInjection; + use PlainJavascriptInjection; private $allocationRepository; private $databaseRepository; - private $keyProviderService; - private $eggRepository; private $nodeRepository; @@ -35,7 +32,6 @@ class StatisticsController extends Controller function __construct( AllocationRepositoryInterface $allocationRepository, DatabaseRepositoryInterface $databaseRepository, - DaemonKeyProviderService $keyProviderService, EggRepositoryInterface $eggRepository, NodeRepositoryInterface $nodeRepository, ServerRepositoryInterface $serverRepository, @@ -44,28 +40,33 @@ class StatisticsController extends Controller { $this->allocationRepository = $allocationRepository; $this->databaseRepository = $databaseRepository; - $this->keyProviderService = $keyProviderService; $this->eggRepository = $eggRepository; $this->nodeRepository = $nodeRepository; $this->serverRepository = $serverRepository; $this->userRepository = $userRepository; } - public function index(Request $request) + public function index() { $servers = $this->serverRepository->all(); - $serversCount = count($servers); $nodes = $this->nodeRepository->all(); - $nodesCount = count($nodes); $usersCount = $this->userRepository->count(); $eggsCount = $this->eggRepository->count(); $databasesCount = $this->databaseRepository->count(); - $totalServerRam = DB::table('servers')->sum('memory'); - $totalNodeRam = DB::table('nodes')->sum('memory'); - $totalServerDisk = DB::table('servers')->sum('disk'); - $totalNodeDisk = DB::table('nodes')->sum('disk'); $totalAllocations = $this->allocationRepository->count(); - $suspendedServersCount = $this->serverRepository->getBuilder()->where('suspended', true)->count(); + $suspendedServersCount = $this->serverRepository->getSuspendedServersCount(); + + $totalServerRam = 0; + $totalNodeRam = 0; + $totalServerDisk = 0; + $totalNodeDisk = 0; + foreach ($nodes as $node) { + $stats = $this->nodeRepository->getUsageStatsRaw($node); + $totalServerRam += $stats['memory']['value']; + $totalNodeRam += $stats['memory']['max']; + $totalServerDisk += $stats['disk']['value']; + $totalNodeDisk += $stats['disk']['max']; + } $tokens = []; foreach ($nodes as $node) { @@ -74,7 +75,6 @@ class StatisticsController extends Controller $this->injectJavascript([ 'servers' => $servers, - 'serverCount' => $serversCount, 'suspendedServers' => $suspendedServersCount, 'totalServerRam' => $totalServerRam, 'totalNodeRam' => $totalNodeRam, @@ -83,10 +83,10 @@ class StatisticsController extends Controller 'nodes' => $nodes, 'tokens' => $tokens, ]); - + return view('admin.statistics', [ - 'serversCount' => $serversCount, - 'nodesCount' => $nodesCount, + 'servers' => $servers, + 'nodes' => $nodes, 'usersCount' => $usersCount, 'eggsCount' => $eggsCount, 'totalServerRam' => $totalServerRam, diff --git a/app/Repositories/Eloquent/NodeRepository.php b/app/Repositories/Eloquent/NodeRepository.php index b4d6ba6b0..4f59fddce 100644 --- a/app/Repositories/Eloquent/NodeRepository.php +++ b/app/Repositories/Eloquent/NodeRepository.php @@ -56,6 +56,33 @@ class NodeRepository extends EloquentRepository implements NodeRepositoryInterfa })->toArray(); } + /** + * Return the usage stats for a single node. + * + * @param \Pterodactyl\Models\Node $node + * @return array + */ + public function getUsageStatsRaw(Node $node): array + { + $stats = $this->getBuilder()->select( + $this->getBuilder()->raw('IFNULL(SUM(servers.memory), 0) as sum_memory, IFNULL(SUM(servers.disk), 0) as sum_disk') + )->join('servers', 'servers.node_id', '=', 'nodes.id')->where('node_id', $node->id)->first(); + + return collect(['disk' => $stats->sum_disk, 'memory' => $stats->sum_memory])->mapWithKeys(function ($value, $key) use ($node) { + $maxUsage = $node->{$key}; + if ($node->{$key . '_overallocate'} > 0) { + $maxUsage = $node->{$key} * (1 + ($node->{$key . '_overallocate'} / 100)); + } + + return [ + $key => [ + 'value' => $value, + 'max' => $maxUsage, + ], + ]; + })->toArray(); + } + /** * Return all available nodes with a searchable interface. * diff --git a/app/Repositories/Eloquent/ServerRepository.php b/app/Repositories/Eloquent/ServerRepository.php index 2fc5f878b..c2c6e1e32 100644 --- a/app/Repositories/Eloquent/ServerRepository.php +++ b/app/Repositories/Eloquent/ServerRepository.php @@ -328,4 +328,14 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt $this->app->make(SubuserRepository::class)->getBuilder()->select('server_id')->where('user_id', $user) )->pluck('id')->all(); } + + /** + * Get the amount of servers that are suspended + * + * @return int + */ + public function getSuspendedServersCount(): int + { + return $this->getBuilder()->where('suspended', true)->count(); + } } diff --git a/app/Traits/Controllers/JavascriptStatisticsInjection.php b/app/Traits/Controllers/PlainJavascriptInjection.php similarity index 88% rename from app/Traits/Controllers/JavascriptStatisticsInjection.php rename to app/Traits/Controllers/PlainJavascriptInjection.php index 3b4e52d0f..eae53bfbc 100644 --- a/app/Traits/Controllers/JavascriptStatisticsInjection.php +++ b/app/Traits/Controllers/PlainJavascriptInjection.php @@ -10,7 +10,7 @@ namespace Pterodactyl\Traits\Controllers; use JavaScript; -trait JavascriptStatisticsInjection +trait PlainJavascriptInjection { /** diff --git a/public/themes/pterodactyl/js/admin/statistics.js b/public/themes/pterodactyl/js/admin/statistics.js index 59034a8da..7433f3221 100644 --- a/public/themes/pterodactyl/js/admin/statistics.js +++ b/public/themes/pterodactyl/js/admin/statistics.js @@ -28,7 +28,7 @@ let ramChart = new Chart($('#ram_chart'), { } }); -var activeServers = Pterodactyl.serverCount - Pterodactyl.suspendedServers; +var activeServers = Pterodactyl.servers.length - Pterodactyl.suspendedServers; let serversChart = new Chart($('#servers_chart'), { type: 'pie', data: { diff --git a/resources/themes/pterodactyl/admin/statistics.blade.php b/resources/themes/pterodactyl/admin/statistics.blade.php index 036ad937f..529107bb4 100644 --- a/resources/themes/pterodactyl/admin/statistics.blade.php +++ b/resources/themes/pterodactyl/admin/statistics.blade.php @@ -35,7 +35,7 @@
    Servers - {{ $serversCount }} + {{ count($servers) }}
    @@ -118,7 +118,7 @@
    Total Nodes - {{ $nodesCount }} + {{ count($nodes) }}
    diff --git a/tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php b/tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php new file mode 100644 index 000000000..f3a20f8ac --- /dev/null +++ b/tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php @@ -0,0 +1,113 @@ +allocationRepository = m::mock(AllocationRepositoryInterface::class); + $this->databaseRepository = m::mock(DatabaseRepositoryInterface::class); + $this->eggRepository = m::mock(EggRepositoryInterface::class); + $this->nodeRepository = m::mock(NodeRepositoryInterface::class); + $this->serverRepository = m::mock(ServerRepositoryInterface::class); + $this->userRepository = m::mock(UserRepositoryInterface::class); + } + + public function testIndexController() + { + $controller = $this->getController(); + + $this->serverRepository->shouldReceive('all')->withNoArgs(); + $this->nodeRepository->shouldReceive('all')->withNoArgs()->andReturn(collect([factory(Node::class)->make(), factory(Node::class)->make()])); + $this->userRepository->shouldReceive('count')->withNoArgs(); + $this->eggRepository->shouldReceive('count')->withNoArgs(); + $this->databaseRepository->shouldReceive('count')->withNoArgs(); + $this->allocationRepository->shouldReceive('count')->withNoArgs(); + $this->serverRepository->shouldReceive('getSuspendedServersCount')->withNoArgs(); + + $this->nodeRepository->shouldReceive('getUsageStatsRaw')->twice()->andReturn([ + 'memory' => [ + 'value' => 1024, + 'max' => 512, + ], + 'disk' => [ + 'value' => 1024, + 'max' => 512, + ] + ]); + + $controller->shouldReceive('injectJavascript')->once(); + + $response = $controller->index(); + + $this->assertIsViewResponse($response); + $this->assertViewNameEquals('admin.statistics', $response); + } + + private function getController() + { + return $this->buildMockedController(StatisticsController::class, [$this->allocationRepository, + $this->databaseRepository, + $this->eggRepository, + $this->nodeRepository, + $this->serverRepository, + $this->userRepository] + ); + } + +} \ No newline at end of file