fine tuning :)
This commit is contained in:
parent
24e6d48496
commit
8c7c938c6a
|
@ -67,7 +67,6 @@ class Pterodactyl
|
||||||
{
|
{
|
||||||
$response = self::client()->get('/application/nodes');
|
$response = self::client()->get('/application/nodes');
|
||||||
if ($response->failed()) throw self::getException();
|
if ($response->failed()) throw self::getException();
|
||||||
dd($response->json());
|
|
||||||
return $response->json()['data'];
|
return $response->json()['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Egg;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\Nest;
|
||||||
|
use App\Models\Node;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -30,11 +34,32 @@ class OverViewController extends Controller
|
||||||
return Server::query()->count();
|
return Server::query()->count();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$lastEgg = Egg::query()->latest('updated_at')->first();
|
||||||
|
$syncLastUpdate = $lastEgg ? $lastEgg->updated_at->isoFormat('LLL') : __('unknown');
|
||||||
|
|
||||||
return view('admin.overview.index', [
|
return view('admin.overview.index', [
|
||||||
'serverCount' => $serverCount,
|
'serverCount' => $serverCount,
|
||||||
'userCount' => $userCount,
|
'userCount' => $userCount,
|
||||||
'paymentCount' => $paymentCount,
|
'paymentCount' => $paymentCount,
|
||||||
'creditCount' => number_format($creditCount, 2, '.', ''),
|
'creditCount' => number_format($creditCount, 2, '.', ''),
|
||||||
|
|
||||||
|
'locationCount' => Location::query()->count(),
|
||||||
|
'nodeCount' => Node::query()->count(),
|
||||||
|
'nestCount' => Nest::query()->count(),
|
||||||
|
'eggCount' => Egg::query()->count(),
|
||||||
|
'syncLastUpdate' => $syncLastUpdate
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Sync locations,nodes,nests,eggs with the linked pterodactyl panel
|
||||||
|
*/
|
||||||
|
public function syncPterodactyl()
|
||||||
|
{
|
||||||
|
Node::syncNodes();
|
||||||
|
Egg::syncEggs();
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', __('Pterodactyl synced'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use App\Models\Product;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Notifications\ServerCreationError;
|
use App\Notifications\ServerCreationError;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Http\Client\Response;
|
use Illuminate\Http\Client\Response;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
@ -32,12 +33,22 @@ class ServerController extends Controller
|
||||||
{
|
{
|
||||||
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
||||||
|
|
||||||
|
$productCount = Product::query()->where('disabled', '=', false)->count();
|
||||||
|
|
||||||
|
$nodeCount = Node::query()->has('products')->count();
|
||||||
|
|
||||||
|
$eggs = Egg::query()->has('products')->get();
|
||||||
|
|
||||||
|
$nests = Nest::query()->whereHas('eggs', function (Builder $builder) {
|
||||||
|
$builder->has('products');
|
||||||
|
})->get();
|
||||||
|
|
||||||
return view('servers.create')->with([
|
return view('servers.create')->with([
|
||||||
'productCount' => Product::query()->where('disabled', '=', false)->count(),
|
'productCount' => $productCount,
|
||||||
'nodeCount' => Node::query()->where('disabled', '=', false)->count(),
|
'nodeCount' => $nodeCount,
|
||||||
'nests' => Nest::query()->where('disabled', '=', false)->get(),
|
'nests' => $nests,
|
||||||
'eggs' => Egg::query()->where('disabled', '=', false)->get(),
|
'eggs' => $eggs,
|
||||||
'minimum_credits' => Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)
|
'user' => Auth::user(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +91,10 @@ class ServerController extends Controller
|
||||||
/** Store a newly created resource in storage. */
|
/** Store a newly created resource in storage. */
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
/** @var Node $node */
|
||||||
|
/** @var Egg $egg */
|
||||||
|
/** @var Product $product */
|
||||||
|
|
||||||
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
||||||
|
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
@ -90,8 +105,9 @@ class ServerController extends Controller
|
||||||
]);
|
]);
|
||||||
|
|
||||||
//get required resources
|
//get required resources
|
||||||
$egg = Egg::findOrFail($request->input('egg'));
|
$product = Product::query()->findOrFail($request->input('product'));
|
||||||
$node = Node::findOrFail($request->input('node'));
|
$egg = $product->eggs()->findOrFail($request->input('egg'));
|
||||||
|
$node = $product->nodes()->findOrFail($request->input('node'));
|
||||||
|
|
||||||
$server = $request->user()->servers()->create([
|
$server = $request->user()->servers()->create([
|
||||||
'name' => $request->input('name'),
|
'name' => $request->input('name'),
|
||||||
|
|
|
@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
|
||||||
|
|
||||||
class Egg extends Model
|
class Egg extends Model
|
||||||
{
|
{
|
||||||
|
@ -23,8 +22,70 @@ class Egg extends Model
|
||||||
'docker_image',
|
'docker_image',
|
||||||
'startup',
|
'startup',
|
||||||
'environment',
|
'environment',
|
||||||
|
'updated_at',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public static function boot()
|
||||||
|
{
|
||||||
|
parent::boot(); // TODO: Change the autogenerated stub
|
||||||
|
|
||||||
|
static::deleting(function (Egg $egg) {
|
||||||
|
$egg->products()->detach();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function syncEggs()
|
||||||
|
{
|
||||||
|
Nest::syncNests();
|
||||||
|
|
||||||
|
Nest::all()->each(function (Nest $nest) {
|
||||||
|
$eggs = Pterodactyl::getEggs($nest);
|
||||||
|
|
||||||
|
foreach ($eggs as $egg) {
|
||||||
|
$array = [];
|
||||||
|
$environment = [];
|
||||||
|
|
||||||
|
$array['id'] = $egg['attributes']['id'];
|
||||||
|
$array['nest_id'] = $egg['attributes']['nest'];
|
||||||
|
$array['name'] = $egg['attributes']['name'];
|
||||||
|
$array['description'] = $egg['attributes']['description'];
|
||||||
|
$array['docker_image'] = $egg['attributes']['docker_image'];
|
||||||
|
$array['startup'] = $egg['attributes']['startup'];
|
||||||
|
$array['updated_at'] = now();
|
||||||
|
|
||||||
|
//get environment variables
|
||||||
|
foreach ($egg['attributes']['relationships']['variables']['data'] as $variable) {
|
||||||
|
$environment[$variable['attributes']['env_variable']] = $variable['attributes']['default_value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$array['environment'] = json_encode([$environment]);
|
||||||
|
|
||||||
|
self::query()->updateOrCreate([
|
||||||
|
'id' => $array['id']
|
||||||
|
], array_diff_key($array, array_flip(["id"]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::removeDeletedEggs($nest, $eggs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description remove eggs that have been deleted on pterodactyl
|
||||||
|
* @param Nest $nest
|
||||||
|
* @param array $eggs
|
||||||
|
*/
|
||||||
|
private static function removeDeletedEggs(Nest $nest, array $eggs): void
|
||||||
|
{
|
||||||
|
$ids = array_map(function ($data) {
|
||||||
|
return $data['attributes']['id'];
|
||||||
|
}, $eggs);
|
||||||
|
|
||||||
|
$nest->eggs()->each(function (Egg $egg) use ($ids) {
|
||||||
|
if (!in_array($egg->id, $ids)) $egg->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -41,42 +102,12 @@ class Egg extends Model
|
||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function syncEggs()
|
|
||||||
{
|
|
||||||
|
|
||||||
Nest::all()->each(function (Nest $nest) {
|
|
||||||
$eggs = Pterodactyl::getEggs($nest);
|
|
||||||
|
|
||||||
foreach ($eggs as $egg) {
|
|
||||||
$array = [];
|
|
||||||
$environment = [];
|
|
||||||
|
|
||||||
$array['id'] = $egg['attributes']['id'];
|
|
||||||
$array['nest_id'] = $egg['attributes']['nest'];
|
|
||||||
$array['name'] = $egg['attributes']['name'];
|
|
||||||
$array['description'] = $egg['attributes']['description'];
|
|
||||||
$array['docker_image'] = $egg['attributes']['docker_image'];
|
|
||||||
$array['startup'] = $egg['attributes']['startup'];
|
|
||||||
|
|
||||||
//get environment variables
|
|
||||||
foreach ($egg['attributes']['relationships']['variables']['data'] as $variable) {
|
|
||||||
$environment[$variable['attributes']['env_variable']] = $variable['attributes']['default_value'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$array['environment'] = json_encode([$environment]);
|
|
||||||
|
|
||||||
self::firstOrCreate(['id' => $array['id']], $array);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsTo
|
* @return BelongsTo
|
||||||
*/
|
*/
|
||||||
public function nest()
|
public function nest()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Nest::class, 'id', 'nest_id');
|
return $this->belongsTo(Nest::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,18 +15,27 @@ class Location extends Model
|
||||||
|
|
||||||
public $guarded = [];
|
public $guarded = [];
|
||||||
|
|
||||||
public function nodes(){
|
public static function boot()
|
||||||
return $this->hasMany(Node::class , 'location_id' , 'id');
|
{
|
||||||
|
parent::boot(); // TODO: Change the autogenerated stub
|
||||||
|
|
||||||
|
static::deleting(function (Location $location) {
|
||||||
|
$location->nodes()->each(function (Node $node) {
|
||||||
|
$node->delete();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sync locations with pterodactyl panel
|
* Sync locations with pterodactyl panel
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static function syncLocations(){
|
public static function syncLocations()
|
||||||
|
{
|
||||||
$locations = Pterodactyl::getLocations();
|
$locations = Pterodactyl::getLocations();
|
||||||
|
|
||||||
$locations = array_map(function($val) {
|
//map response
|
||||||
|
$locations = array_map(function ($val) {
|
||||||
return array(
|
return array(
|
||||||
'id' => $val['attributes']['id'],
|
'id' => $val['attributes']['id'],
|
||||||
'name' => $val['attributes']['short'],
|
'name' => $val['attributes']['short'],
|
||||||
|
@ -34,9 +43,40 @@ class Location extends Model
|
||||||
);
|
);
|
||||||
}, $locations);
|
}, $locations);
|
||||||
|
|
||||||
|
//update or create
|
||||||
foreach ($locations as $location) {
|
foreach ($locations as $location) {
|
||||||
self::firstOrCreate(['id' => $location['id']] , $location);
|
self::query()->updateOrCreate(
|
||||||
|
[
|
||||||
|
'id' => $location['id']
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => $location['name'],
|
||||||
|
'description' => $location['name'],
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::removeDeletedLocation($locations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description remove locations that have been deleted on pterodactyl
|
||||||
|
* @param array $locations
|
||||||
|
*/
|
||||||
|
private static function removeDeletedLocation(array $locations): void
|
||||||
|
{
|
||||||
|
$ids = array_map(function ($data) {
|
||||||
|
return $data['id'];
|
||||||
|
}, $locations);
|
||||||
|
|
||||||
|
self::all()->each(function (Location $location) use ($ids) {
|
||||||
|
if (!in_array($location->id, $ids)) $location->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function nodes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Node::class, 'location_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,60 @@ class Nest extends Model
|
||||||
'disabled',
|
'disabled',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public static function boot()
|
||||||
|
{
|
||||||
|
parent::boot(); // TODO: Change the autogenerated stub
|
||||||
|
|
||||||
public function eggs(){
|
static::deleting(function (Nest $nest) {
|
||||||
return $this->hasMany(Egg::class);
|
$nest->eggs()->each(function (Egg $egg) {
|
||||||
|
$egg->delete();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function syncNests(){
|
public static function syncNests()
|
||||||
self::query()->delete();
|
{
|
||||||
$nests = Pterodactyl::getNests();
|
$nests = Pterodactyl::getNests();
|
||||||
|
|
||||||
|
//map response
|
||||||
|
$nests = array_map(function ($nest) {
|
||||||
|
return array(
|
||||||
|
'id' => $nest['attributes']['id'],
|
||||||
|
'name' => $nest['attributes']['name'],
|
||||||
|
'description' => $nest['attributes']['description'],
|
||||||
|
);
|
||||||
|
}, $nests);
|
||||||
|
|
||||||
foreach ($nests as $nest) {
|
foreach ($nests as $nest) {
|
||||||
self::firstOrCreate(['id' => $nest['attributes']['id']] , array_merge($nest['attributes'] , ['disabled' => '1']));
|
self::query()->updateOrCreate([
|
||||||
|
'id' => $nest['id']
|
||||||
|
], [
|
||||||
|
'name' => $nest['name'],
|
||||||
|
'description' => $nest['description'],
|
||||||
|
'disabled' => false
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::removeDeletedNests($nests);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description remove nests that have been deleted on pterodactyl
|
||||||
|
* @param array $nests
|
||||||
|
*/
|
||||||
|
private static function removeDeletedNests(array $nests): void
|
||||||
|
{
|
||||||
|
$ids = array_map(function ($data) {
|
||||||
|
return $data['id'];
|
||||||
|
}, $nests);
|
||||||
|
|
||||||
|
self::all()->each(function (Nest $nest) use ($ids) {
|
||||||
|
if (!in_array($nest->id, $ids)) $nest->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function eggs()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Egg::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,65 @@ class Node extends Model
|
||||||
|
|
||||||
public $guarded = [];
|
public $guarded = [];
|
||||||
|
|
||||||
|
public static function boot()
|
||||||
|
{
|
||||||
|
parent::boot(); // TODO: Change the autogenerated stub
|
||||||
|
|
||||||
|
static::deleting(function (Node $node) {
|
||||||
|
$node->products()->detach();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function syncNodes()
|
||||||
|
{
|
||||||
|
Location::syncLocations();
|
||||||
|
$nodes = Pterodactyl::getNodes();
|
||||||
|
|
||||||
|
//map response
|
||||||
|
$nodes = array_map(function ($node) {
|
||||||
|
return array(
|
||||||
|
'id' => $node['attributes']['id'],
|
||||||
|
'location_id' => $node['attributes']['location_id'],
|
||||||
|
'name' => $node['attributes']['name'],
|
||||||
|
'description' => $node['attributes']['description'],
|
||||||
|
);
|
||||||
|
}, $nodes);
|
||||||
|
|
||||||
|
//update or create
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
self::query()->updateOrCreate(
|
||||||
|
[
|
||||||
|
'id' => $node['id']
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => $node['name'],
|
||||||
|
'description' => $node['description'],
|
||||||
|
'location_id' => $node['location_id'],
|
||||||
|
'disabled' => false
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::removeDeletedNodes($nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description remove nodes that have been deleted on pterodactyl
|
||||||
|
* @param array $nodes
|
||||||
|
*/
|
||||||
|
private static function removeDeletedNodes(array $nodes): void
|
||||||
|
{
|
||||||
|
$ids = array_map(function ($data) {
|
||||||
|
return $data['id'];
|
||||||
|
}, $nodes);
|
||||||
|
|
||||||
|
self::all()->each(function (Node $node) use ($ids) {
|
||||||
|
if (!in_array($node->id, $ids)) $node->delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsTo
|
* @return BelongsTo
|
||||||
|
@ -26,29 +85,6 @@ class Node extends Model
|
||||||
return $this->belongsTo(Location::class);
|
return $this->belongsTo(Location::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static function syncNodes(){
|
|
||||||
Location::syncLocations();
|
|
||||||
$nodes = Pterodactyl::getNodes();
|
|
||||||
|
|
||||||
$nodes = array_map(function($node) {
|
|
||||||
return array(
|
|
||||||
'id' => $node['attributes']['id'],
|
|
||||||
'location_id' => $node['attributes']['location_id'],
|
|
||||||
'name' => $node['attributes']['name'],
|
|
||||||
'description' => $node['attributes']['description'],
|
|
||||||
'disabled' => '1'
|
|
||||||
);
|
|
||||||
}, $nodes);
|
|
||||||
|
|
||||||
foreach ($nodes as $node) {
|
|
||||||
self::firstOrCreate(['id' => $node['id']] , $node);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsToMany
|
* @return BelongsToMany
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -26,16 +26,20 @@
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<a href="https://discord.gg/4Y6HjD2uyU" class="btn btn-dark btn-block px-3"><i class="fab fa-discord mr-2"></i> {{__('Support server')}}</a>
|
<a href="https://discord.gg/4Y6HjD2uyU" class="btn btn-dark btn-block px-3"><i
|
||||||
|
class="fab fa-discord mr-2"></i> {{__('Support server')}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<a href="https://controlpanel.gg/docs/intro" class="btn btn-dark btn-block px-3"><i class="fas fa-link mr-2"></i> {{__('Documentation')}}</a>
|
<a href="https://controlpanel.gg/docs/intro" class="btn btn-dark btn-block px-3"><i
|
||||||
|
class="fas fa-link mr-2"></i> {{__('Documentation')}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<a href="https://github.com/ControlPanel-gg/dashboard" class="btn btn-dark btn-block px-3"><i class="fab fa-github mr-2"></i> {{__('Github')}}</a>
|
<a href="https://github.com/ControlPanel-gg/dashboard" class="btn btn-dark btn-block px-3"><i
|
||||||
|
class="fab fa-github mr-2"></i> {{__('Github')}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<a href="https://controlpanel.gg/docs/Contributing/donating" class="btn btn-dark btn-block px-3"><i class="fas fa-money-bill mr-2"></i> {{__('Support ControlPanel')}}</a>
|
<a href="https://controlpanel.gg/docs/Contributing/donating" class="btn btn-dark btn-block px-3"><i
|
||||||
|
class="fas fa-money-bill mr-2"></i> {{__('Support ControlPanel')}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -68,7 +72,8 @@
|
||||||
|
|
||||||
<div class="col-12 col-sm-6 col-md-3">
|
<div class="col-12 col-sm-6 col-md-3">
|
||||||
<div class="info-box">
|
<div class="info-box">
|
||||||
<span class="info-box-icon bg-warning elevation-1"><i class="fas fa-coins text-white"></i></span>
|
<span class="info-box-icon bg-warning elevation-1"><i
|
||||||
|
class="fas fa-coins text-white"></i></span>
|
||||||
|
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
<span class="info-box-text">{{__('Total')}} {{CREDITS_DISPLAY_NAME}}</span>
|
<span class="info-box-text">{{__('Total')}} {{CREDITS_DISPLAY_NAME}}</span>
|
||||||
|
@ -101,7 +106,8 @@
|
||||||
<div class="card-title ">
|
<div class="card-title ">
|
||||||
<span><i class="fas fa-kiwi-bird mr-2"></i>{{__('Pterodactyl')}}</span>
|
<span><i class="fas fa-kiwi-bird mr-2"></i>{{__('Pterodactyl')}}</span>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary"><i class="fas fa-sync mr-2"></i>{{__('Sync')}}</button>
|
<a href="{{route('admin.overview.sync')}}" class="btn btn-primary btn-sm"><i
|
||||||
|
class="fas fa-sync mr-2"></i>{{__('Sync')}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body py-1">
|
<div class="card-body py-1">
|
||||||
|
@ -115,25 +121,25 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{__('Locations')}}</td>
|
<td>{{__('Locations')}}</td>
|
||||||
<td>1</td>
|
<td>{{$locationCount}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{__('Nodes')}}</td>
|
<td>{{__('Nodes')}}</td>
|
||||||
<td>1</td>
|
<td>{{$nodeCount}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{__('Nests')}}</td>
|
<td>{{__('Nests')}}</td>
|
||||||
<td>1</td>
|
<td>{{$nestCount}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{__('Eggs')}}</td>
|
<td>{{__('Eggs')}}</td>
|
||||||
<td>1</td>
|
<td>{{$eggCount}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<span><i class="fas fa-sync mr-2"></i>{{__('Last updated :date', ['date' => now()])}}</span>
|
<span><i class="fas fa-sync mr-2"></i>{{__('Last updated :date', ['date' => $syncLastUpdate])}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -78,11 +78,33 @@
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link" href="#" id="userDropdown" role="button" data-toggle="dropdown"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false">
|
||||||
|
<span class="mr-1 d-lg-inline text-gray-600">
|
||||||
|
<small><i class="fas fa-coins mr-2"></i></small>{{Auth::user()->credits()}}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
|
||||||
|
<a class="dropdown-item" href="{{route('store.index')}}">
|
||||||
|
<i class="fas fa-coins fa-sm fa-fw mr-2 text-gray-400"></i>
|
||||||
|
{{__('Store')}}
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" data-toggle="modal" data-target="#redeemVoucherModal"
|
||||||
|
href="javascript:void(0)">
|
||||||
|
<i class="fas fa-money-check-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
||||||
|
{{__('Redeem code')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
<li class="nav-item dropdown no-arrow">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown"
|
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="false">
|
aria-expanded="false">
|
||||||
<span class="mr-1 d-none d-lg-inline text-gray-600 small">
|
<span class="mr-1 d-lg-inline text-gray-600 small">
|
||||||
{{Auth::user()->name}}
|
{{Auth::user()->name}}
|
||||||
<img width="28px" height="28px" class="rounded-circle ml-1" src="{{Auth::user()->getAvatar()}}">
|
<img width="28px" height="28px" class="rounded-circle ml-1" src="{{Auth::user()->getAvatar()}}">
|
||||||
</span>
|
</span>
|
||||||
|
@ -104,11 +126,6 @@
|
||||||
Log back in
|
Log back in
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
<a class="dropdown-item" data-toggle="modal" data-target="#redeemVoucherModal"
|
|
||||||
href="javascript:void(0)">
|
|
||||||
<i class="fas fa-money-check-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Redeem code
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<form method="post" action="{{route('logout')}}">
|
<form method="post" action="{{route('logout')}}">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
|
@ -37,14 +37,18 @@
|
||||||
|
|
||||||
@if($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0 )
|
@if($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0 )
|
||||||
<div class="alert alert-danger p-2 m-2">
|
<div class="alert alert-danger p-2 m-2">
|
||||||
<h5><i class="icon fas fa-exclamation-circle"></i>Error!</h5>
|
<h5><i class="icon fas fa-exclamation-circle"></i>{{__('Error!')}}</h5>
|
||||||
|
<p class="pl-4">
|
||||||
|
{{__('Make sure to link your products to nodes and eggs.')}} <br>
|
||||||
|
{{__('There has to be at least 1 valid product for server creation')}}
|
||||||
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
@if($productCount === 0 )
|
@if($productCount === 0 )
|
||||||
<li> {{__('No products available!')}}</li>
|
<li> {{__('No products available!')}}</li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if($nodeCount === 0 )
|
@if($nodeCount === 0 )
|
||||||
<li>{{__('No nodes available!')}}</li>
|
<li>{{__('No nodes have been linked!')}}</li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if(count($nests) === 0 )
|
@if(count($nests) === 0 )
|
||||||
|
@ -52,7 +56,7 @@
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if(count($eggs) === 0 )
|
@if(count($eggs) === 0 )
|
||||||
<li>{{__('No eggs available!')}}</li>
|
<li>{{__('No eggs have been linked!')}}</li>
|
||||||
@endif
|
@endif
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,7 +100,7 @@
|
||||||
id="nest"
|
id="nest"
|
||||||
x-model="selectedNest"
|
x-model="selectedNest"
|
||||||
@change="setNests();">
|
@change="setNests();">
|
||||||
<option selected disabled
|
<option selected disabled hidden
|
||||||
value="null">{{count($nests) > 0 ? __('Please select software..') : __('---')}}</option>
|
value="null">{{count($nests) > 0 ? __('Please select software..') : __('---')}}</option>
|
||||||
@foreach ($nests as $nest)
|
@foreach ($nests as $nest)
|
||||||
<option value="{{ $nest->id }}">{{ $nest->name }}</option>
|
<option value="{{ $nest->id }}">{{ $nest->name }}</option>
|
||||||
|
@ -140,7 +144,7 @@
|
||||||
class="custom-select">
|
class="custom-select">
|
||||||
<option
|
<option
|
||||||
x-text="getNodeInputText()"
|
x-text="getNodeInputText()"
|
||||||
disabled selected value="null"></option>
|
disabled selected hidden value="null"></option>
|
||||||
<template x-for="node in nodes" :key="node.id">
|
<template x-for="node in nodes" :key="node.id">
|
||||||
<option x-text="node.name" :value="node.id"></option>
|
<option x-text="node.name" :value="node.id"></option>
|
||||||
</template>
|
</template>
|
||||||
|
@ -159,10 +163,12 @@
|
||||||
class="custom-select">
|
class="custom-select">
|
||||||
<option
|
<option
|
||||||
x-text="getProductInputText()"
|
x-text="getProductInputText()"
|
||||||
disabled selected value="null"></option>
|
disabled selected hidden value="null"></option>
|
||||||
<template x-for="product in products" :key="product.id">
|
<template x-for="product in products" :key="product.id">
|
||||||
<option x-text="product.name + ' (' + product.description + ')'"
|
<option :disabled="product.minimum_credits > user.credits"
|
||||||
:value="product.id"></option>
|
x-text="getProductOptionText(product)"
|
||||||
|
:value="product.id">
|
||||||
|
</option>
|
||||||
</template>
|
</template>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -222,7 +228,8 @@
|
||||||
</strong>
|
</strong>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button :disabled="!isFormValid()" :class="isFormValid() ? '' : 'disabled'" class="btn btn-primary btn-block">
|
<button :disabled="!isFormValid()" :class="isFormValid() ? '' : 'disabled'"
|
||||||
|
class="btn btn-primary btn-block">
|
||||||
{{__('Create server')}}
|
{{__('Create server')}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -258,6 +265,7 @@
|
||||||
selectedProductObject: {},
|
selectedProductObject: {},
|
||||||
|
|
||||||
//values
|
//values
|
||||||
|
user: {!! $user !!},
|
||||||
nests: {!! $nests !!},
|
nests: {!! $nests !!},
|
||||||
eggsSave:{!! $eggs !!}, //store back-end eggs
|
eggsSave:{!! $eggs !!}, //store back-end eggs
|
||||||
eggs: [],
|
eggs: [],
|
||||||
|
@ -374,6 +382,16 @@
|
||||||
return '{{__('Please select a configuration...')}}';
|
return '{{__('Please select a configuration...')}}';
|
||||||
}
|
}
|
||||||
return '{{__('---')}}';
|
return '{{__('---')}}';
|
||||||
|
},
|
||||||
|
|
||||||
|
getProductOptionText(product){
|
||||||
|
let text = product.name + ' (' + product.description + ')';
|
||||||
|
|
||||||
|
if (product.minimum_credits > this.user.credits){
|
||||||
|
return '{{__('Not enough credits!')}} | ' + text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
use App\Http\Controllers\Admin\ActivityLogController;
|
use App\Http\Controllers\Admin\ActivityLogController;
|
||||||
use App\Http\Controllers\Admin\ApplicationApiController;
|
use App\Http\Controllers\Admin\ApplicationApiController;
|
||||||
use App\Http\Controllers\Admin\ConfigurationController;
|
use App\Http\Controllers\Admin\ConfigurationController;
|
||||||
use App\Http\Controllers\Admin\NestsController;
|
|
||||||
use App\Http\Controllers\Admin\NodeController;
|
|
||||||
use App\Http\Controllers\Admin\OverViewController;
|
use App\Http\Controllers\Admin\OverViewController;
|
||||||
use App\Http\Controllers\Admin\PaymentController;
|
use App\Http\Controllers\Admin\PaymentController;
|
||||||
use App\Http\Controllers\Admin\PaypalProductController;
|
use App\Http\Controllers\Admin\PaypalProductController;
|
||||||
|
@ -58,8 +56,8 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
||||||
|
|
||||||
#server create utility routes (product)
|
#server create utility routes (product)
|
||||||
#routes made for server create page to fetch product info
|
#routes made for server create page to fetch product info
|
||||||
Route::get('/products/nodes/egg/{egg?}' , [FrontProductController::class , 'getNodesBasedOnEgg'])->name('products.nodes.egg');
|
Route::get('/products/nodes/egg/{egg?}', [FrontProductController::class, 'getNodesBasedOnEgg'])->name('products.nodes.egg');
|
||||||
Route::get('/products/products/node/{node?}' , [FrontProductController::class , 'getProductsBasedOnNode'])->name('products.products.node');
|
Route::get('/products/products/node/{node?}', [FrontProductController::class, 'getProductsBasedOnNode'])->name('products.products.node');
|
||||||
|
|
||||||
#payments
|
#payments
|
||||||
Route::get('checkout/{paypalProduct}', [PaymentController::class, 'checkOut'])->name('checkout');
|
Route::get('checkout/{paypalProduct}', [PaymentController::class, 'checkOut'])->name('checkout');
|
||||||
|
@ -79,7 +77,8 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
||||||
#admin
|
#admin
|
||||||
Route::prefix('admin')->name('admin.')->middleware('admin')->group(function () {
|
Route::prefix('admin')->name('admin.')->middleware('admin')->group(function () {
|
||||||
|
|
||||||
Route::get('overview', [OverViewController::class , 'index'])->name('overview.index');
|
Route::get('overview', [OverViewController::class, 'index'])->name('overview.index');
|
||||||
|
Route::get('overview/sync', [OverViewController::class, 'syncPterodactyl'])->name('overview.sync');
|
||||||
|
|
||||||
Route::resource('activitylogs', ActivityLogController::class);
|
Route::resource('activitylogs', ActivityLogController::class);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue