removed pterodactyl pages, added overview page, made server create work
This commit is contained in:
parent
16a7d174e9
commit
24e6d48496
15 changed files with 681 additions and 174 deletions
|
@ -11,10 +11,22 @@ use Exception;
|
||||||
use Illuminate\Http\Client\PendingRequest;
|
use Illuminate\Http\Client\PendingRequest;
|
||||||
use Illuminate\Http\Client\Response;
|
use Illuminate\Http\Client\Response;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Validation\Validator;
|
|
||||||
|
|
||||||
class Pterodactyl
|
class Pterodactyl
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return null
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getNests()
|
||||||
|
{
|
||||||
|
$response = self::client()->get('/application/nests');
|
||||||
|
if ($response->failed()) throw self::getException();
|
||||||
|
return $response->json()['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Extend error handling (maybe logger for more errors when debugging)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return PendingRequest
|
* @return PendingRequest
|
||||||
*/
|
*/
|
||||||
|
@ -27,18 +39,57 @@ class Pterodactyl
|
||||||
])->baseUrl(env('PTERODACTYL_URL') . '/api');
|
])->baseUrl(env('PTERODACTYL_URL') . '/api');
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Extend error handling (maybe logger for more errors when debugging)
|
|
||||||
/**
|
/**
|
||||||
* Get user by pterodactyl id
|
* @return Exception
|
||||||
* @param int $pterodactylId
|
*/
|
||||||
|
private static function getException(): Exception
|
||||||
|
{
|
||||||
|
return new Exception('Request Failed, is pterodactyl set-up correctly?');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Nest $nest
|
||||||
|
* @return mixed
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getEggs(Nest $nest)
|
||||||
|
{
|
||||||
|
$response = self::client()->get("/application/nests/{$nest->id}/eggs?include=nest,variables");
|
||||||
|
if ($response->failed()) throw self::getException();
|
||||||
|
return $response->json()['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getNodes()
|
||||||
|
{
|
||||||
|
$response = self::client()->get('/application/nodes');
|
||||||
|
if ($response->failed()) throw self::getException();
|
||||||
|
dd($response->json());
|
||||||
|
return $response->json()['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getLocations()
|
||||||
|
{
|
||||||
|
$response = self::client()->get('/application/locations');
|
||||||
|
if ($response->failed()) throw self::getException();
|
||||||
|
return $response->json()['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Node $node
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getUser(int $pterodactylId)
|
public static function getFreeAllocationId(Node $node)
|
||||||
{
|
{
|
||||||
$response = self::client()->get("/application/users/{$pterodactylId}");
|
|
||||||
|
|
||||||
if ($response->failed()) return $response->json();
|
return self::getFreeAllocations($node)[0]['attributes']['id'] ?? null;
|
||||||
return $response->json()['attributes'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,64 +113,6 @@ class Pterodactyl
|
||||||
return $freeAllocations;
|
return $freeAllocations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return null
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static function getNests()
|
|
||||||
{
|
|
||||||
$response = self::client()->get('/application/nests');
|
|
||||||
if ($response->failed()) throw self::getException();
|
|
||||||
return $response->json()['data'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Nest $nest
|
|
||||||
* @return mixed
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static function getEggs(Nest $nest)
|
|
||||||
{
|
|
||||||
$response = self::client()->get("/application/nests/{$nest->id}/eggs?include=nest,variables");
|
|
||||||
if ($response->failed()) throw self::getException();
|
|
||||||
return $response->json()['data'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static function getNodes()
|
|
||||||
{
|
|
||||||
$response = self::client()->get('/application/nodes');
|
|
||||||
if ($response->failed()) throw self::getException();
|
|
||||||
return $response->json()['data'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static function getLocations()
|
|
||||||
{
|
|
||||||
$response = self::client()->get('/application/locations');
|
|
||||||
if ($response->failed()) throw self::getException();
|
|
||||||
return $response->json()['data'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Node $node
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public static function getFreeAllocationId(Node $node)
|
|
||||||
{
|
|
||||||
|
|
||||||
return self::getFreeAllocations($node)[0]['attributes']['id'] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Node $node
|
* @param Node $node
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
|
@ -132,7 +125,6 @@ class Pterodactyl
|
||||||
return $response->json();
|
return $response->json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param String $route
|
* @param String $route
|
||||||
* @return string
|
* @return string
|
||||||
|
@ -151,21 +143,21 @@ class Pterodactyl
|
||||||
public static function createServer(Server $server, Egg $egg, int $allocationId)
|
public static function createServer(Server $server, Egg $egg, int $allocationId)
|
||||||
{
|
{
|
||||||
return self::client()->post("/application/servers", [
|
return self::client()->post("/application/servers", [
|
||||||
"name" => $server->name,
|
"name" => $server->name,
|
||||||
"external_id" => $server->id,
|
"external_id" => $server->id,
|
||||||
"user" => $server->user->pterodactyl_id,
|
"user" => $server->user->pterodactyl_id,
|
||||||
"egg" => $egg->id,
|
"egg" => $egg->id,
|
||||||
"docker_image" => $egg->docker_image,
|
"docker_image" => $egg->docker_image,
|
||||||
"startup" => $egg->startup,
|
"startup" => $egg->startup,
|
||||||
"environment" => $egg->getEnvironmentVariables(),
|
"environment" => $egg->getEnvironmentVariables(),
|
||||||
"limits" => [
|
"limits" => [
|
||||||
"memory" => $server->product->memory,
|
"memory" => $server->product->memory,
|
||||||
"swap" => $server->product->swap,
|
"swap" => $server->product->swap,
|
||||||
"disk" => $server->product->disk,
|
"disk" => $server->product->disk,
|
||||||
"io" => $server->product->io,
|
"io" => $server->product->io,
|
||||||
"cpu" => $server->product->cpu
|
"cpu" => $server->product->cpu
|
||||||
],
|
],
|
||||||
"feature_limits" => [
|
"feature_limits" => [
|
||||||
"databases" => $server->product->databases,
|
"databases" => $server->product->databases,
|
||||||
"backups" => $server->product->backups,
|
"backups" => $server->product->backups,
|
||||||
"allocations" => $server->product->allocations,
|
"allocations" => $server->product->allocations,
|
||||||
|
@ -174,6 +166,7 @@ class Pterodactyl
|
||||||
"default" => $allocationId
|
"default" => $allocationId
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function suspendServer(Server $server)
|
public static function suspendServer(Server $server)
|
||||||
|
@ -191,10 +184,15 @@ class Pterodactyl
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Exception
|
* Get user by pterodactyl id
|
||||||
|
* @param int $pterodactylId
|
||||||
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
private static function getException(): Exception
|
public function getUser(int $pterodactylId)
|
||||||
{
|
{
|
||||||
return new Exception('Request Failed, is pterodactyl set-up correctly?');
|
$response = self::client()->get("/application/users/{$pterodactylId}");
|
||||||
|
|
||||||
|
if ($response->failed()) return $response->json();
|
||||||
|
return $response->json()['attributes'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,11 @@ use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Class NestsController
|
||||||
|
* @package App\Http\Controllers\Admin
|
||||||
|
*/
|
||||||
class NestsController extends Controller
|
class NestsController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,6 +14,11 @@ use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Class NodeController
|
||||||
|
* @package App\Http\Controllers\Admin
|
||||||
|
*/
|
||||||
class NodeController extends Controller
|
class NodeController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
40
app/Http/Controllers/Admin/OverViewController.php
Normal file
40
app/Http/Controllers/Admin/OverViewController.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
|
class OverViewController extends Controller
|
||||||
|
{
|
||||||
|
public const TTL = 86400;
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$userCount = Cache::remember('user:count', self::TTL, function () {
|
||||||
|
return User::query()->count();
|
||||||
|
});
|
||||||
|
|
||||||
|
$creditCount = Cache::remember('credit:count', self::TTL, function () {
|
||||||
|
return User::query()->sum('credits');
|
||||||
|
});
|
||||||
|
|
||||||
|
$paymentCount = Cache::remember('payment:count', self::TTL, function () {
|
||||||
|
return Payment::query()->count();
|
||||||
|
});
|
||||||
|
|
||||||
|
$serverCount = Cache::remember('server:count', self::TTL, function () {
|
||||||
|
return Server::query()->count();
|
||||||
|
});
|
||||||
|
|
||||||
|
return view('admin.overview.index', [
|
||||||
|
'serverCount' => $serverCount,
|
||||||
|
'userCount' => $userCount,
|
||||||
|
'paymentCount' => $paymentCount,
|
||||||
|
'creditCount' => number_format($creditCount, 2, '.', ''),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,8 +52,8 @@ class ServerController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// minimum credits
|
// minimum credits
|
||||||
if (FacadesRequest::has("product_id")) {
|
if (FacadesRequest::has("product")) {
|
||||||
$product = Product::findOrFail(FacadesRequest::input("product_id"));
|
$product = Product::findOrFail(FacadesRequest::input("product"));
|
||||||
if (
|
if (
|
||||||
Auth::user()->credits <
|
Auth::user()->credits <
|
||||||
($product->minimum_credits == -1
|
($product->minimum_credits == -1
|
||||||
|
@ -83,17 +83,20 @@ class ServerController extends Controller
|
||||||
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
||||||
|
|
||||||
$request->validate([
|
$request->validate([
|
||||||
"name" => "required|max:191",
|
"name" => "required|max:191",
|
||||||
"description" => "nullable|max:191",
|
"node" => "required|exists:nodes,id",
|
||||||
"node_id" => "required|exists:nodes,id",
|
"egg" => "required|exists:eggs,id",
|
||||||
"egg_id" => "required|exists:eggs,id",
|
"product" => "required|exists:products,id"
|
||||||
"product_id" => "required|exists:products,id"
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
//get required resources
|
//get required resources
|
||||||
$egg = Egg::findOrFail($request->input('egg_id'));
|
$egg = Egg::findOrFail($request->input('egg'));
|
||||||
$node = Node::findOrFail($request->input('node_id'));
|
$node = Node::findOrFail($request->input('node'));
|
||||||
$server = Auth::user()->servers()->create($request->all());
|
|
||||||
|
$server = $request->user()->servers()->create([
|
||||||
|
'name' => $request->input('name'),
|
||||||
|
'product_id' => $request->input('product'),
|
||||||
|
]);
|
||||||
|
|
||||||
//get free allocation ID
|
//get free allocation ID
|
||||||
$allocationId = Pterodactyl::getFreeAllocationId($node);
|
$allocationId = Pterodactyl::getFreeAllocationId($node);
|
||||||
|
@ -110,8 +113,8 @@ class ServerController extends Controller
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
|
if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
|
||||||
if (Auth::user()->credits >= $server->product->getHourlyPrice()) {
|
if ($request->user()->credits >= $server->product->getHourlyPrice()) {
|
||||||
Auth::user()->decrement('credits', $server->product->getHourlyPrice());
|
$request->user()->decrement('credits', $server->product->getHourlyPrice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ class Node extends Model
|
||||||
Location::syncLocations();
|
Location::syncLocations();
|
||||||
$nodes = Pterodactyl::getNodes();
|
$nodes = Pterodactyl::getNodes();
|
||||||
|
|
||||||
|
|
||||||
$nodes = array_map(function($node) {
|
$nodes = array_map(function($node) {
|
||||||
return array(
|
return array(
|
||||||
'id' => $node['attributes']['id'],
|
'id' => $node['attributes']['id'],
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"yajra/laravel-datatables-oracle": "~9.0"
|
"yajra/laravel-datatables-oracle": "~9.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"barryvdh/laravel-debugbar": "^3.6",
|
||||||
"facade/ignition": "^2.5",
|
"facade/ignition": "^2.5",
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"laravel/sail": "^1.0.1",
|
"laravel/sail": "^1.0.1",
|
||||||
|
|
222
composer.lock
generated
222
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "f7ba581ff6641d3ab79d558070e99f3c",
|
"content-hash": "500346cc4a4a83b162e07bb0071d1602",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asm89/stack-cors",
|
"name": "asm89/stack-cors",
|
||||||
|
@ -6202,6 +6202,91 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "barryvdh/laravel-debugbar",
|
||||||
|
"version": "v3.6.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/barryvdh/laravel-debugbar.git",
|
||||||
|
"reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/3c2d678269ba60e178bcd93e36f6a91c36b727f1",
|
||||||
|
"reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/routing": "^6|^7|^8",
|
||||||
|
"illuminate/session": "^6|^7|^8",
|
||||||
|
"illuminate/support": "^6|^7|^8",
|
||||||
|
"maximebf/debugbar": "^1.17.2",
|
||||||
|
"php": ">=7.2",
|
||||||
|
"symfony/debug": "^4.3|^5",
|
||||||
|
"symfony/finder": "^4.3|^5"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.3.3",
|
||||||
|
"orchestra/testbench-dusk": "^4|^5|^6",
|
||||||
|
"phpunit/phpunit": "^8.5|^9.0",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.6-dev"
|
||||||
|
},
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Barryvdh\\Debugbar\\ServiceProvider"
|
||||||
|
],
|
||||||
|
"aliases": {
|
||||||
|
"Debugbar": "Barryvdh\\Debugbar\\Facade"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Barryvdh\\Debugbar\\": "src/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/helpers.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP Debugbar integration for Laravel",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"debugbar",
|
||||||
|
"laravel",
|
||||||
|
"profiler",
|
||||||
|
"webprofiler"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
|
||||||
|
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.4"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://fruitcake.nl",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/barryvdh",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-10-21T10:57:31+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
|
@ -6713,6 +6798,71 @@
|
||||||
},
|
},
|
||||||
"time": "2021-05-25T16:41:13+00:00"
|
"time": "2021-05-25T16:41:13+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "maximebf/debugbar",
|
||||||
|
"version": "v1.17.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/maximebf/php-debugbar.git",
|
||||||
|
"reference": "e8ac3499af0ea5b440908e06cc0abe5898008b3c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/e8ac3499af0ea5b440908e06cc0abe5898008b3c",
|
||||||
|
"reference": "e8ac3499af0ea5b440908e06cc0abe5898008b3c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.1|^8",
|
||||||
|
"psr/log": "^1|^2|^3",
|
||||||
|
"symfony/var-dumper": "^2.6|^3|^4|^5"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7.5.20 || ^9.4.2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"kriswallsmith/assetic": "The best way to manage assets",
|
||||||
|
"monolog/monolog": "Log using Monolog",
|
||||||
|
"predis/predis": "Redis storage"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.17-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DebugBar\\": "src/DebugBar/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Maxime Bouroumeau-Fuseau",
|
||||||
|
"email": "maxime.bouroumeau@gmail.com",
|
||||||
|
"homepage": "http://maximebf.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Debug bar in the browser for php application",
|
||||||
|
"homepage": "https://github.com/maximebf/php-debugbar",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"debugbar"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/maximebf/php-debugbar/issues",
|
||||||
|
"source": "https://github.com/maximebf/php-debugbar/tree/v1.17.3"
|
||||||
|
},
|
||||||
|
"time": "2021-10-19T12:33:27+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "mockery/mockery",
|
"name": "mockery/mockery",
|
||||||
"version": "1.4.3",
|
"version": "1.4.3",
|
||||||
|
@ -8652,6 +8802,74 @@
|
||||||
],
|
],
|
||||||
"time": "2020-09-28T06:39:44+00:00"
|
"time": "2020-09-28T06:39:44+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/debug",
|
||||||
|
"version": "v4.4.31",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/debug.git",
|
||||||
|
"reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/debug/zipball/43ede438d4cb52cd589ae5dc070e9323866ba8e0",
|
||||||
|
"reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1.3",
|
||||||
|
"psr/log": "^1|^2|^3"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/http-kernel": "<3.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/http-kernel": "^3.4|^4.0|^5.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Debug\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides tools to ease debugging PHP code",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/debug/tree/v4.4.31"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-09-24T13:30:14+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
|
@ -8713,5 +8931,5 @@
|
||||||
"ext-intl": "*"
|
"ext-intl": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.1.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
147
resources/views/admin/overview/index.blade.php
Normal file
147
resources/views/admin/overview/index.blade.php
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
@extends('layouts.main')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<!-- CONTENT HEADER -->
|
||||||
|
<section class="content-header">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h1>Admin Overview</h1>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<ol class="breadcrumb float-sm-right">
|
||||||
|
<li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
|
||||||
|
<li class="breadcrumb-item"><a class="text-muted"
|
||||||
|
href="{{route('admin.overview.index')}}">Admin Overview</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- END CONTENT HEADER -->
|
||||||
|
|
||||||
|
<!-- MAIN CONTENT -->
|
||||||
|
<section class="content">
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<div class="row mb-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>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-sm-6 col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-info elevation-1"><i class="fas fa-server"></i></span>
|
||||||
|
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">{{__('Servers')}}</span>
|
||||||
|
<span class="info-box-number">{{$serverCount}}</span>
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box-content -->
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-sm-6 col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-primary elevation-1"><i class="fas fa-users"></i></span>
|
||||||
|
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">{{__('Users')}}</span>
|
||||||
|
<span class="info-box-number">{{$userCount}}</span>
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box-content -->
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-sm-6 col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-warning elevation-1"><i class="fas fa-coins text-white"></i></span>
|
||||||
|
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">{{__('Total')}} {{CREDITS_DISPLAY_NAME}}</span>
|
||||||
|
<span class="info-box-number">{{$creditCount}}</span>
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box-content -->
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-sm-6 col-md-3">
|
||||||
|
<div class="info-box">
|
||||||
|
<span class="info-box-icon bg-success elevation-1"><i class="fas fa-money-bill"></i></span>
|
||||||
|
|
||||||
|
<div class="info-box-content">
|
||||||
|
<span class="info-box-text">{{__('Payments')}}</span>
|
||||||
|
<span class="info-box-number">{{$paymentCount}}</span>
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box-content -->
|
||||||
|
</div>
|
||||||
|
<!-- /.info-box -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="card-title ">
|
||||||
|
<span><i class="fas fa-kiwi-bird mr-2"></i>{{__('Pterodactyl')}}</span>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary"><i class="fas fa-sync mr-2"></i>{{__('Sync')}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body py-1">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{__('Resources')}}</th>
|
||||||
|
<th>{{__('Count')}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{__('Locations')}}</td>
|
||||||
|
<td>1</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{__('Nodes')}}</td>
|
||||||
|
<td>1</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{__('Nests')}}</td>
|
||||||
|
<td>1</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{__('Eggs')}}</td>
|
||||||
|
<td>1</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<span><i class="fas fa-sync mr-2"></i>{{__('Last updated :date', ['date' => now()])}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- END CUSTOM CONTENT -->
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- END CONTENT -->
|
||||||
|
@endsection
|
|
@ -50,7 +50,8 @@
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name">Name</label>
|
<label for="name">Name</label>
|
||||||
<input value="{{$product->name ?? old('name')}}" id="name" name="name" type="text"
|
<input value="{{$product->name ?? old('name')}}" id="name" name="name"
|
||||||
|
type="text"
|
||||||
class="form-control @error('name') is-invalid @enderror"
|
class="form-control @error('name') is-invalid @enderror"
|
||||||
required="required">
|
required="required">
|
||||||
@error('name')
|
@error('name')
|
||||||
|
@ -76,7 +77,8 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="memory">Memory</label>
|
<label for="memory">Memory</label>
|
||||||
<input value="{{$product->memory ?? old('memory')}}" id="memory" name="memory"
|
<input value="{{$product->memory ?? old('memory')}}" id="memory"
|
||||||
|
name="memory"
|
||||||
type="number"
|
type="number"
|
||||||
class="form-control @error('memory') is-invalid @enderror"
|
class="form-control @error('memory') is-invalid @enderror"
|
||||||
required="required">
|
required="required">
|
||||||
|
@ -133,7 +135,8 @@
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="disk">Disk</label>
|
<label for="disk">Disk</label>
|
||||||
<input value="{{$product->disk ?? old('disk') ?? 1000}}" id="disk" name="disk"
|
<input value="{{$product->disk ?? old('disk') ?? 1000}}" id="disk"
|
||||||
|
name="disk"
|
||||||
type="number"
|
type="number"
|
||||||
class="form-control @error('disk') is-invalid @enderror"
|
class="form-control @error('disk') is-invalid @enderror"
|
||||||
required="required">
|
required="required">
|
||||||
|
@ -174,7 +177,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="databases">Databases</label>
|
<label for="databases">Databases</label>
|
||||||
<input value="{{$product->databases ?? old('databases') ?? 1}}" id="databases"
|
<input value="{{$product->databases ?? old('databases') ?? 1}}"
|
||||||
|
id="databases"
|
||||||
name="databases"
|
name="databases"
|
||||||
type="number"
|
type="number"
|
||||||
class="form-control @error('databases') is-invalid @enderror"
|
class="form-control @error('databases') is-invalid @enderror"
|
||||||
|
@ -227,21 +231,25 @@
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h5 class="card-title">Product Linking <i data-toggle="popover" data-trigger="hover"
|
<h5 class="card-title">Product Linking
|
||||||
data-content="Linked products will only be available when the user has selected the linked node and/or egg"
|
<i data-toggle="popover"
|
||||||
class="fas fa-info-circle"></i></h5>
|
data-trigger="hover"
|
||||||
|
data-content="Link your products to nodes and eggs to create dynamic pricing for each option"
|
||||||
|
class="fas fa-info-circle"></i></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="nodes">Nodes</label>
|
<label for="nodes">Nodes</label>
|
||||||
<select id="nodes" style="width:100%" class="custom-select @error('nodes') is-invalid @enderror"
|
<select id="nodes" style="width:100%"
|
||||||
|
class="custom-select @error('nodes') is-invalid @enderror"
|
||||||
name="nodes[]" multiple="multiple" autocomplete="off">
|
name="nodes[]" multiple="multiple" autocomplete="off">
|
||||||
@foreach($locations as $location)
|
@foreach($locations as $location)
|
||||||
<optgroup label="{{$location->name}}">
|
<optgroup label="{{$location->name}}">
|
||||||
@foreach($location->nodes as $node)
|
@foreach($location->nodes as $node)
|
||||||
<option @if(isset($product)) @if($product->nodes->contains('id' , $node->id)) selected
|
<option
|
||||||
@endif @endif value="{{$node->id}}">{{$node->name}}</option>
|
@if(isset($product)) @if($product->nodes->contains('id' , $node->id)) selected
|
||||||
|
@endif @endif value="{{$node->id}}">{{$node->name}}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</optgroup>
|
</optgroup>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@ -259,13 +267,15 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="eggs">Eggs</label>
|
<label for="eggs">Eggs</label>
|
||||||
<select id="eggs" style="width:100%" class="custom-select @error('eggs') is-invalid @enderror"
|
<select id="eggs" style="width:100%"
|
||||||
|
class="custom-select @error('eggs') is-invalid @enderror"
|
||||||
name="eggs[]" multiple="multiple" autocomplete="off">
|
name="eggs[]" multiple="multiple" autocomplete="off">
|
||||||
@foreach($nests as $nest)
|
@foreach($nests as $nest)
|
||||||
<optgroup label="{{$nest->name}}">
|
<optgroup label="{{$nest->name}}">
|
||||||
@foreach($nest->eggs as $egg)
|
@foreach($nest->eggs as $egg)
|
||||||
<option @if(isset($product)) @if($product->eggs->contains('id' , $egg->id)) selected
|
<option
|
||||||
@endif @endif value="{{$egg->id}}">{{$egg->name}}</option>
|
@if(isset($product)) @if($product->eggs->contains('id' , $egg->id)) selected
|
||||||
|
@endif @endif value="{{$egg->id}}">{{$egg->name}}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</optgroup>
|
</optgroup>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
|
@ -224,9 +224,11 @@
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h5 class="card-title">Product Linking <i data-toggle="popover" data-trigger="hover"
|
<h5 class="card-title">Product Linking
|
||||||
data-content="Linked products will only be available when the user has selected the linked node and/or egg"
|
<i data-toggle="popover"
|
||||||
class="fas fa-info-circle"></i></h5>
|
data-trigger="hover"
|
||||||
|
data-content="Link your products to nodes and eggs to create dynamic pricing for each option"
|
||||||
|
class="fas fa-info-circle"></i></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
|
|
|
@ -212,47 +212,34 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-header">Pterodactyl</li>
|
{{-- <li class="nav-header">Pterodactyl</li>--}}
|
||||||
|
|
||||||
<li class="nav-item">
|
{{-- <li class="nav-item">--}}
|
||||||
<a href="{{route('admin.nodes.index')}}"
|
{{-- <a href="{{route('admin.nodes.index')}}"--}}
|
||||||
class="nav-link @if(Request::routeIs('admin.nodes.*')) active @endif">
|
{{-- class="nav-link @if(Request::routeIs('admin.nodes.*')) active @endif">--}}
|
||||||
<i class="nav-icon fas fa-sitemap"></i>
|
{{-- <i class="nav-icon fas fa-sitemap"></i>--}}
|
||||||
<p>Nodes</p>
|
{{-- <p>Nodes</p>--}}
|
||||||
</a>
|
{{-- </a>--}}
|
||||||
</li>
|
{{-- </li>--}}
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{route('admin.nests.index')}}"
|
|
||||||
class="nav-link @if(Request::routeIs('admin.nests.*')) active @endif">
|
|
||||||
<i class="nav-icon fas fa-th-large"></i>
|
|
||||||
<p>Nests</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-header">Logs</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{route('admin.payments.index')}}"
|
|
||||||
class="nav-link @if(Request::routeIs('admin.payments.*')) active @endif">
|
|
||||||
<i class="nav-icon fas fa-money-bill-wave"></i>
|
|
||||||
<p>Payments
|
|
||||||
<span class="badge badge-success right">{{\App\Models\Payment::count()}}</span>
|
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="{{route('admin.activitylogs.index')}}"
|
|
||||||
class="nav-link @if(Request::routeIs('admin.activitylogs.*')) active @endif">
|
|
||||||
<i class="nav-icon fas fa-clipboard-list"></i>
|
|
||||||
<p>Activity Logs</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
{{-- <li class="nav-item">--}}
|
||||||
|
{{-- <a href="{{route('admin.nests.index')}}"--}}
|
||||||
|
{{-- class="nav-link @if(Request::routeIs('admin.nests.*')) active @endif">--}}
|
||||||
|
{{-- <i class="nav-icon fas fa-th-large"></i>--}}
|
||||||
|
{{-- <p>Nests</p>--}}
|
||||||
|
{{-- </a>--}}
|
||||||
|
{{-- </li>--}}
|
||||||
|
|
||||||
<li class="nav-header">Dashboard</li>
|
<li class="nav-header">Dashboard</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{route('admin.overview.index')}}"
|
||||||
|
class="nav-link @if(Request::routeIs('admin.overview.*')) active @endif">
|
||||||
|
<i class="nav-icon fa fa-gamepad"></i>
|
||||||
|
<p>Overview</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{{route('admin.api.index')}}"
|
<a href="{{route('admin.api.index')}}"
|
||||||
class="nav-link @if(Request::routeIs('admin.api.*')) active @endif">
|
class="nav-link @if(Request::routeIs('admin.api.*')) active @endif">
|
||||||
|
@ -287,6 +274,26 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-header">Logs</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{route('admin.payments.index')}}"
|
||||||
|
class="nav-link @if(Request::routeIs('admin.payments.*')) active @endif">
|
||||||
|
<i class="nav-icon fas fa-money-bill-wave"></i>
|
||||||
|
<p>Payments
|
||||||
|
<span class="badge badge-success right">{{\App\Models\Payment::count()}}</span>
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{route('admin.activitylogs.index')}}"
|
||||||
|
class="nav-link @if(Request::routeIs('admin.activitylogs.*')) active @endif">
|
||||||
|
<i class="nav-icon fas fa-clipboard-list"></i>
|
||||||
|
<p>Activity Logs</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -27,11 +27,12 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<!-- FORM -->
|
<!-- FORM -->
|
||||||
<div class="row">
|
<form action="{{route('servers.store')}}" method="post" class="row">
|
||||||
|
@csrf
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-title">{{__('Server configuration')}}</div>
|
<div class="card-title"><i class="fas fa-cogs mr-2"></i>{{__('Server configuration')}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0 )
|
@if($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0 )
|
||||||
|
@ -62,7 +63,17 @@
|
||||||
<i class="fas fa-2x fa-sync-alt"></i>
|
<i class="fas fa-2x fa-sync-alt"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@csrf
|
|
||||||
|
@if ($errors->any())
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<ul class="list-group pl-3">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name">{{__('Name')}}</label>
|
<label for="name">{{__('Name')}}</label>
|
||||||
<input x-model="name" id="name" name="name" type="text" required="required"
|
<input x-model="name" id="name" name="name" type="text" required="required"
|
||||||
|
@ -70,7 +81,7 @@
|
||||||
|
|
||||||
@error('name')
|
@error('name')
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
Please fill out this field.
|
{{ $message }}
|
||||||
</div>
|
</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,10 +91,11 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="nest">{{__('Software')}}</label>
|
<label for="nest">{{__('Software')}}</label>
|
||||||
<select class="custom-select"
|
<select class="custom-select"
|
||||||
|
required
|
||||||
name="nest"
|
name="nest"
|
||||||
id="nest"
|
id="nest"
|
||||||
x-model="selectedNest"
|
x-model="selectedNest"
|
||||||
@change="setNests(); $refs.egg.selectedIndex = '0'">
|
@change="setNests();">
|
||||||
<option selected disabled
|
<option selected disabled
|
||||||
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)
|
||||||
|
@ -99,11 +111,11 @@
|
||||||
<label for="egg">{{__('Configuration')}}</label>
|
<label for="egg">{{__('Configuration')}}</label>
|
||||||
<div>
|
<div>
|
||||||
<select id="egg"
|
<select id="egg"
|
||||||
|
required
|
||||||
name="egg"
|
name="egg"
|
||||||
x-ref="egg"
|
|
||||||
:disabled="eggs.length == 0"
|
:disabled="eggs.length == 0"
|
||||||
x-model="selectedEgg"
|
x-model="selectedEgg"
|
||||||
@change="fetchNodes(); $refs.node.selectedIndex = '0'"
|
@change="fetchNodes();"
|
||||||
required="required"
|
required="required"
|
||||||
class="custom-select">
|
class="custom-select">
|
||||||
<option x-text="getEggInputText()"
|
<option x-text="getEggInputText()"
|
||||||
|
@ -120,8 +132,8 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="node">{{__('Node')}}</label>
|
<label for="node">{{__('Node')}}</label>
|
||||||
<select name="node"
|
<select name="node"
|
||||||
|
required
|
||||||
id="node"
|
id="node"
|
||||||
x-ref="node"
|
|
||||||
x-model="selectedNode"
|
x-model="selectedNode"
|
||||||
:disabled="!fetchedNodes"
|
:disabled="!fetchedNodes"
|
||||||
@change="fetchProducts();"
|
@change="fetchProducts();"
|
||||||
|
@ -139,10 +151,11 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="product">{{__('Resources')}}</label>
|
<label for="product">{{__('Resources')}}</label>
|
||||||
<select name="product"
|
<select name="product"
|
||||||
|
required
|
||||||
id="product"
|
id="product"
|
||||||
x-ref="product"
|
|
||||||
:disabled="!fetchedProducts"
|
:disabled="!fetchedProducts"
|
||||||
x-model="selectedProduct"
|
x-model="selectedProduct"
|
||||||
|
@change="updateSelectedObjects()"
|
||||||
class="custom-select">
|
class="custom-select">
|
||||||
<option
|
<option
|
||||||
x-text="getProductInputText()"
|
x-text="getProductInputText()"
|
||||||
|
@ -160,48 +173,62 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 mb-4">
|
<div class="col-md-4 mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="card-title">
|
||||||
|
<i class="fas fa-list mr-2"></i>{{__('Server details')}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h4 class="d-flex justify-content-between align-items-center mb-3">
|
|
||||||
<span class="text-muted">{{__('Server details')}}</span>
|
|
||||||
</h4>
|
|
||||||
<ul class="list-group mb-3">
|
<ul class="list-group mb-3">
|
||||||
<li class="list-group-item d-flex justify-content-between lh-condensed">
|
<li x-show="selectedNestObject.name"
|
||||||
|
class="list-group-item d-flex justify-content-between lh-condensed">
|
||||||
<div>
|
<div>
|
||||||
<h6 class="my-0">{{__('Software')}}</h6>
|
<h6 class="my-0">{{__('Software')}}</h6>
|
||||||
<small class="text-muted">Brief description</small>
|
<small x-text="selectedNestObject?.name ?? '{{__('No selection')}}'"
|
||||||
|
class="text-muted"></small>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item d-flex justify-content-between lh-condensed">
|
<li class="list-group-item d-flex justify-content-between lh-condensed">
|
||||||
<div>
|
<div>
|
||||||
<h6 class="my-0">{{__('Configuration')}}</h6>
|
<h6 class="my-0">{{__('Configuration')}}</h6>
|
||||||
<small class="text-muted">Brief description</small>
|
<small x-text="selectedEggObject?.name ?? '{{__('No selection')}}'"
|
||||||
|
class="text-muted"></small>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
class="list-group-item d-flex justify-content-between lh-condensed">
|
class="list-group-item d-flex justify-content-between lh-condensed">
|
||||||
<div>
|
<div>
|
||||||
<h6 class="my-0">{{__('Node')}}</h6>
|
<h6 class="my-0">{{__('Node')}}</h6>
|
||||||
<small class="text-muted">Brief description</small>
|
<small x-text="selectedNodeObject?.name ?? '{{__('No selection')}}'"
|
||||||
|
class="text-muted"></small>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
class="list-group-item d-flex justify-content-between lh-condensed">
|
class="list-group-item d-flex justify-content-between lh-condensed">
|
||||||
<div>
|
<div>
|
||||||
<h6 class="my-0">{{__('Resources')}}</h6>
|
<h6 class="my-0">{{__('Resources')}}</h6>
|
||||||
<small class="text-muted">Brief description</small>
|
<small x-text="selectedProductObject?.name ?? '{{__('No selection')}}'"
|
||||||
|
class="text-muted"></small>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul x-show="selectedProduct" class="list-group">
|
<ul class="list-group mb-3">
|
||||||
<li class="list-group-item d-flex justify-content-between">
|
<li class="list-group-item d-flex justify-content-between">
|
||||||
<span>{{CREDITS_DISPLAY_NAME}} {{__('per month')}}</span>
|
<span>{{CREDITS_DISPLAY_NAME}} {{__('per month')}}</span>
|
||||||
<strong x-text="selectedProduct"></strong>
|
<strong>
|
||||||
|
<i x-show="selectedProductObject?.price" class="fas fa-coins"></i>
|
||||||
|
<span x-text="selectedProductObject?.price ?? ''"></span>
|
||||||
|
</strong>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<button :disabled="!isFormValid()" :class="isFormValid() ? '' : 'disabled'" class="btn btn-primary btn-block">
|
||||||
|
{{__('Create server')}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
<!-- END FORM -->
|
<!-- END FORM -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -212,16 +239,25 @@
|
||||||
<script>
|
<script>
|
||||||
function serverApp() {
|
function serverApp() {
|
||||||
return {
|
return {
|
||||||
|
//loading
|
||||||
loading: false,
|
loading: false,
|
||||||
fetchedNodes: false,
|
fetchedNodes: false,
|
||||||
fetchedProducts: false,
|
fetchedProducts: false,
|
||||||
|
|
||||||
|
//input fields
|
||||||
name: null,
|
name: null,
|
||||||
selectedNest: null,
|
selectedNest: null,
|
||||||
selectedEgg: null,
|
selectedEgg: null,
|
||||||
selectedNode: null,
|
selectedNode: null,
|
||||||
selectedProduct: null,
|
selectedProduct: null,
|
||||||
|
|
||||||
|
//selected objects based on input
|
||||||
|
selectedNestObject: {},
|
||||||
|
selectedEggObject: {},
|
||||||
|
selectedNodeObject: {},
|
||||||
|
selectedProductObject: {},
|
||||||
|
|
||||||
|
//values
|
||||||
nests: {!! $nests !!},
|
nests: {!! $nests !!},
|
||||||
eggsSave:{!! $eggs !!}, //store back-end eggs
|
eggsSave:{!! $eggs !!}, //store back-end eggs
|
||||||
eggs: [],
|
eggs: [],
|
||||||
|
@ -239,8 +275,12 @@
|
||||||
this.fetchedProducts = false;
|
this.fetchedProducts = false;
|
||||||
this.nodes = [];
|
this.nodes = [];
|
||||||
this.products = [];
|
this.products = [];
|
||||||
|
this.selectedEgg = 'null';
|
||||||
|
this.selectedNode = 'null';
|
||||||
|
this.selectedProduct = 'null';
|
||||||
|
|
||||||
this.eggs = this.eggsSave.filter(egg => egg.nest_id == this.selectedNest)
|
this.eggs = this.eggsSave.filter(egg => egg.nest_id == this.selectedNest)
|
||||||
|
this.updateSelectedObjects()
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,6 +294,8 @@
|
||||||
this.fetchedProducts = false;
|
this.fetchedProducts = false;
|
||||||
this.nodes = [];
|
this.nodes = [];
|
||||||
this.products = [];
|
this.products = [];
|
||||||
|
this.selectedNode = 'null';
|
||||||
|
this.selectedProduct = 'null';
|
||||||
|
|
||||||
let response = await axios.get(`{{route('products.nodes.egg')}}/${this.selectedEgg}`)
|
let response = await axios.get(`{{route('products.nodes.egg')}}/${this.selectedEgg}`)
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
@ -261,6 +303,7 @@
|
||||||
this.fetchedNodes = true;
|
this.fetchedNodes = true;
|
||||||
this.nodes = response.data
|
this.nodes = response.data
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
this.updateSelectedObjects()
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,6 +315,7 @@
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.fetchedProducts = false;
|
this.fetchedProducts = false;
|
||||||
this.products = [];
|
this.products = [];
|
||||||
|
this.selectedProduct = 'null';
|
||||||
|
|
||||||
let response = await axios.get(`{{route('products.products.node')}}/${this.selectedNode}`)
|
let response = await axios.get(`{{route('products.products.node')}}/${this.selectedNode}`)
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
@ -279,6 +323,30 @@
|
||||||
this.fetchedProducts = true;
|
this.fetchedProducts = true;
|
||||||
this.products = response.data
|
this.products = response.data
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
this.updateSelectedObjects()
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description map selected id's to selected objects
|
||||||
|
* @note being used in the server info box
|
||||||
|
*/
|
||||||
|
updateSelectedObjects() {
|
||||||
|
this.selectedNestObject = this.nests.find(nest => nest.id == this.selectedNest) ?? {}
|
||||||
|
this.selectedEggObject = this.eggs.find(egg => egg.id == this.selectedEgg) ?? {}
|
||||||
|
this.selectedNodeObject = this.nodes.find(node => node.id == this.selectedNode) ?? {}
|
||||||
|
this.selectedProductObject = this.products.find(product => product.id == this.selectedProduct) ?? {}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description check if all options are selected
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
isFormValid() {
|
||||||
|
if (Object.keys(this.selectedNestObject).length === 0) return false;
|
||||||
|
if (Object.keys(this.selectedEggObject).length === 0) return false;
|
||||||
|
if (Object.keys(this.selectedNodeObject).length === 0) return false;
|
||||||
|
if (Object.keys(this.selectedProductObject).length === 0) return false;
|
||||||
|
return !!this.name;
|
||||||
},
|
},
|
||||||
|
|
||||||
getNodeInputText() {
|
getNodeInputText() {
|
||||||
|
|
|
@ -5,6 +5,7 @@ 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\NestsController;
|
||||||
use App\Http\Controllers\Admin\NodeController;
|
use App\Http\Controllers\Admin\NodeController;
|
||||||
|
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;
|
||||||
use App\Http\Controllers\Admin\ProductController;
|
use App\Http\Controllers\Admin\ProductController;
|
||||||
|
@ -60,7 +61,6 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
||||||
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');
|
||||||
Route::get('payment/success', [PaymentController::class, 'success'])->name('payment.success');
|
Route::get('payment/success', [PaymentController::class, 'success'])->name('payment.success');
|
||||||
|
@ -79,6 +79,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::resource('activitylogs', ActivityLogController::class);
|
Route::resource('activitylogs', ActivityLogController::class);
|
||||||
|
|
||||||
Route::get("users.json", [UserController::class, "json"])->name('users.json');
|
Route::get("users.json", [UserController::class, "json"])->name('users.json');
|
||||||
|
@ -107,13 +109,13 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
||||||
Route::get('payments/datatable', [PaymentController::class, 'datatable'])->name('payments.datatable');
|
Route::get('payments/datatable', [PaymentController::class, 'datatable'])->name('payments.datatable');
|
||||||
Route::get('payments', [PaymentController::class, 'index'])->name('payments.index');
|
Route::get('payments', [PaymentController::class, 'index'])->name('payments.index');
|
||||||
|
|
||||||
Route::get('nodes/datatable', [NodeController::class, 'datatable'])->name('nodes.datatable');
|
// Route::get('nodes/datatable', [NodeController::class, 'datatable'])->name('nodes.datatable');
|
||||||
Route::get('nodes/sync', [NodeController::class, 'sync'])->name('nodes.sync');
|
// Route::get('nodes/sync', [NodeController::class, 'sync'])->name('nodes.sync');
|
||||||
Route::resource('nodes', NodeController::class);
|
// Route::resource('nodes', NodeController::class);
|
||||||
|
//
|
||||||
Route::get('nests/datatable', [NestsController::class, 'datatable'])->name('nests.datatable');
|
// Route::get('nests/datatable', [NestsController::class, 'datatable'])->name('nests.datatable');
|
||||||
Route::get('nests/sync', [NestsController::class, 'sync'])->name('nests.sync');
|
// Route::get('nests/sync', [NestsController::class, 'sync'])->name('nests.sync');
|
||||||
Route::resource('nests', NestsController::class);
|
// Route::resource('nests', NestsController::class);
|
||||||
|
|
||||||
Route::get('configurations/datatable', [ConfigurationController::class, 'datatable'])->name('configurations.datatable');
|
Route::get('configurations/datatable', [ConfigurationController::class, 'datatable'])->name('configurations.datatable');
|
||||||
Route::patch('configurations/updatevalue', [ConfigurationController::class, 'updatevalue'])->name('configurations.updatevalue');
|
Route::patch('configurations/updatevalue', [ConfigurationController::class, 'updatevalue'])->name('configurations.updatevalue');
|
||||||
|
|
2
storage/debugbar/.gitignore
vendored
Normal file
2
storage/debugbar/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
Loading…
Reference in a new issue