Skip to content

Commit 6f2fcab

Browse files
committed
Add very basic server search and dynamic rendering functionality
1 parent f337a89 commit 6f2fcab

File tree

7 files changed

+169
-46
lines changed

7 files changed

+169
-46
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Controllers\Base;
4+
5+
use Illuminate\Http\Request;
6+
use Pterodactyl\Models\User;
7+
use Pterodactyl\Http\Controllers\Controller;
8+
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
9+
10+
class DashboardController extends Controller
11+
{
12+
/**
13+
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
14+
*/
15+
private $repository;
16+
17+
/**
18+
* DashboardController constructor.
19+
*
20+
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
21+
*/
22+
public function __construct(ServerRepositoryInterface $repository)
23+
{
24+
$this->repository = $repository;
25+
}
26+
27+
public function servers(Request $request)
28+
{
29+
$servers = $this->repository->setSearchTerm($request->input('query'))->filterUserAccessServers(
30+
$request->user(), User::FILTER_LEVEL_ALL
31+
);
32+
33+
$data = [];
34+
foreach ($servers->items() as $server) {
35+
$cleaned = collect($server)->only([
36+
'uuidShort',
37+
'uuid',
38+
'name',
39+
'cpu',
40+
'memory',
41+
]);
42+
43+
$data[] = array_merge($cleaned->toArray(), [
44+
'allocation' => [
45+
'ip' => $server->allocation->ip,
46+
'port' => $server->allocation->port,
47+
],
48+
'node_name' => $server->node->name,
49+
]);
50+
}
51+
52+
return response()->json($data);
53+
}
54+
}

resources/assets/scripts/app.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import { flash } from './mixins/flash';
1010

1111
// Base Vuejs Templates
1212
import Login from './components/auth/Login';
13-
import Base from './components/base/Base';
13+
import Dashboard from './components/dashboard/Dashboard';
14+
import Account from './components/dashboard/Account';
1415
import ResetPassword from './components/auth/ResetPassword';
1516

1617
window.events = new Vue;
@@ -45,10 +46,10 @@ const router = new VueRouter({
4546
return { token: route.params.token, email: route.query.email || '' };
4647
}
4748
},
48-
{ name : 'index', path: '/', component: Base },
49-
{ name : 'account', path: '/account', component: Base },
50-
{ name : 'account-api', path: '/account/api', component: Base },
51-
{ name : 'account-security', path: '/account/security', component: Base },
49+
{ name : 'index', path: '/', component: Dashboard },
50+
{ name : 'account', path: '/account', component: Account },
51+
{ name : 'account-api', path: '/account/api', component: Account },
52+
{ name : 'account-security', path: '/account/security', component: Account },
5253
]
5354
});
5455

resources/assets/scripts/components/base/Base.vue

Whitespace-only changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<template>
2+
3+
</template>
4+
5+
<script>
6+
export default {
7+
name: 'account'
8+
};
9+
</script>
10+
11+
<style scoped>
12+
13+
</style>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<template>
2+
<div>
3+
<div class="server-search animate fadein">
4+
<input type="text" placeholder="search for servers..."
5+
@input="onChange"
6+
v-model="search"
7+
ref="search"
8+
/>
9+
</div>
10+
<transition-group class="w-full m-auto mt-4 animate fadein sm:flex flex-wrap content-start">
11+
<div class="server-box" :key="index" v-for="(server, index) in servers">
12+
<div class="content">
13+
<div class="float-right">
14+
<div class="indicator online"></div>
15+
</div>
16+
<div class="mb-4">
17+
<div class="text-black font-bold text-xl">{{ server.name }}</div>
18+
</div>
19+
<div class="mb-0 flex">
20+
<div class="usage">
21+
<div class="indicator-title">CPU</div>
22+
</div>
23+
<div class="usage">
24+
<div class="indicator-title">Memory</div>
25+
</div>
26+
</div>
27+
<div class="mb-4 flex text-center">
28+
<div class="inline-block border border-grey-lighter border-l-0 p-4 flex-1">
29+
<span class="font-bold text-xl">---</span>
30+
<span class="font-light text-sm">%</span>
31+
</div>
32+
<div class="inline-block border border-grey-lighter border-l-0 border-r-0 p-4 flex-1">
33+
<span class="font-bold text-xl">---</span>
34+
<span class="font-light text-sm">Mb</span>
35+
</div>
36+
</div>
37+
<div class="flex items-center">
38+
<div class="text-sm">
39+
<p class="text-grey">{{ server.node_name }}</p>
40+
<p class="text-grey-dark">{{ server.allocation.ip }}:{{ server.allocation.port }}</p>
41+
</div>
42+
</div>
43+
</div>
44+
</div>
45+
</transition-group>
46+
</div>
47+
</template>
48+
49+
<script>
50+
import _ from 'lodash';
51+
52+
export default {
53+
name: 'dashboard',
54+
data: function () {
55+
return {
56+
search: '',
57+
servers: [],
58+
}
59+
},
60+
61+
mounted: function () {
62+
this.loadServers();
63+
},
64+
65+
methods: {
66+
/**
67+
* Load the user's servers and render them onto the dashboard.
68+
*
69+
* @param {string} query
70+
*/
71+
loadServers: function (query = '') {
72+
const self = this;
73+
74+
window.axios.get(this.route('dashboard.servers'), {
75+
params: { query },
76+
})
77+
.then(function (response) {
78+
self.servers = response.data;
79+
})
80+
.catch(function (error) {
81+
console.error(error);
82+
});
83+
},
84+
85+
/**
86+
* Handle a search for servers but only call the search function every 500ms
87+
* at the fastest.
88+
*/
89+
onChange: _.debounce(function () {
90+
this.loadServers(this.$data.search);
91+
}, 500),
92+
}
93+
};
94+
</script>

resources/themes/pterodactyl/templates/base/core.blade.php

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,47 +33,7 @@
3333
@endsection
3434

3535
@section('container')
36-
<div class="server-search animate fadein">
37-
<input type="text" placeholder="search for servers..."/>
38-
</div>
39-
<div class="w-full m-auto mt-4 animate fadein sm:flex flex-wrap content-start">
40-
@foreach($servers as $server)
41-
<div class="server-box">
42-
<div class="content">
43-
<div class="float-right">
44-
<div class="indicator {{ ['online', 'offline'][rand(0, 1)] }}"></div>
45-
</div>
46-
<div class="mb-4">
47-
<div class="text-black font-bold text-xl">{{ $server->name }}</div>
48-
</div>
49-
<div class="mb-0 flex">
50-
<div class="usage">
51-
<div class="indicator-title">CPU</div>
52-
</div>
53-
<div class="usage">
54-
<div class="indicator-title">Memory</div>
55-
</div>
56-
</div>
57-
<div class="mb-4 flex text-center">
58-
<div class="inline-block border border-grey-lighter border-l-0 p-4 flex-1">
59-
<span class="font-bold text-xl">{{ rand(1, 200) }}</span>
60-
<span class="font-light text-sm">%</span>
61-
</div>
62-
<div class="inline-block border border-grey-lighter border-l-0 border-r-0 p-4 flex-1">
63-
<span class="font-bold text-xl">{{ rand(128, 2048) }}</span>
64-
<span class="font-light text-sm">Mb</span>
65-
</div>
66-
</div>
67-
<div class="flex items-center">
68-
<div class="text-sm">
69-
<p class="text-grey">{{ $server->node->name }}</p>
70-
<p class="text-grey-dark">{{ $server->allocation->ip }}:{{ $server->allocation->port }}</p>
71-
</div>
72-
</div>
73-
</div>
74-
</div>
75-
@endforeach
76-
</div>
36+
<router-view></router-view>
7737
<div class="w-full m-auto mt-0">
7838
<p class="text-right text-grey-dark text-xs">
7939
{!! trans('strings.copyright', ['year' => date('Y')]) !!}

routes/base.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* https://opensource.org/licenses/MIT
88
*/
99
Route::get('/', 'IndexController@index')->name('index');
10+
Route::get('/dashboard/servers', 'DashboardController@servers')->name('dashboard.servers');
1011
Route::get('/status/{server}', 'IndexController@status')->name('index.status');
1112

1213
/*

0 commit comments

Comments
 (0)