Merge pull request #520 from ControlPanel-gg/dev---upgradesystem
Dev upgradesystem
This commit is contained in:
commit
1f9301ef0e
|
@ -6,6 +6,7 @@ use App\Models\Egg;
|
|||
use App\Models\Nest;
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use App\Models\Product;
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Http\Client\Response;
|
||||
|
@ -298,4 +299,22 @@ class Pterodactyl
|
|||
if ($response->failed()) throw self::getException("Failed to get server attributes from pterodactyl - ", $response->status());
|
||||
return $response->json()['attributes'];
|
||||
}
|
||||
|
||||
public static function updateServer(Server $server, Product $product)
|
||||
{
|
||||
return self::client()->patch("/application/servers/{$server->pterodactyl_id}/build", [
|
||||
"allocation" => $server->allocation,
|
||||
"memory" => $product->memory,
|
||||
"swap" => $product->swap,
|
||||
"disk" => $product->disk,
|
||||
"io" => $product->io,
|
||||
"cpu" => $product->cpu,
|
||||
"threads" => null,
|
||||
"feature_limits" => [
|
||||
"databases" => $product->databases,
|
||||
"backups" => $product->backups,
|
||||
"allocations" => $product->allocations,
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -235,4 +235,65 @@ class ServerController extends Controller
|
|||
return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to remove a resource "') . $e->getMessage() . '"');
|
||||
}
|
||||
}
|
||||
|
||||
/** Show Server Settings */
|
||||
public function show(Server $server)
|
||||
{
|
||||
$serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id);
|
||||
$serverRelationships = $serverAttributes['relationships'];
|
||||
$serverLocationAttributes = $serverRelationships['location']['attributes'];
|
||||
|
||||
//Set server infos
|
||||
$server->location = $serverLocationAttributes['long'] ?
|
||||
$serverLocationAttributes['long'] :
|
||||
$serverLocationAttributes['short'];
|
||||
|
||||
$server->node = $serverRelationships['node']['attributes']['name'];
|
||||
$server->name = $serverAttributes['name'];
|
||||
$server->egg = $serverRelationships['egg']['attributes']['name'];
|
||||
$products = Product::orderBy("created_at")->get();
|
||||
|
||||
// Set the each product eggs array to just contain the eggs name
|
||||
foreach ($products as $product) {
|
||||
$product->eggs = $product->eggs->pluck('name')->toArray();
|
||||
}
|
||||
|
||||
return view('servers.settings')->with([
|
||||
'server' => $server,
|
||||
'products' => $products
|
||||
]);
|
||||
}
|
||||
|
||||
public function upgrade(Server $server, Request $request)
|
||||
{
|
||||
if(!isset($request->product_upgrade))
|
||||
{
|
||||
return redirect()->route('servers.show', ['server' => $server->id])->with('error', __('this product is the only one'));
|
||||
}
|
||||
$user = Auth::user();
|
||||
$oldProduct = Product::where('id', $server->product->id)->first();
|
||||
$newProduct = Product::where('id', $request->product_upgrade)->first();
|
||||
$serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id);
|
||||
$priceupgrade = $newProduct->getHourlyPrice();
|
||||
|
||||
if ($priceupgrade < $oldProduct->getHourlyPrice()) {
|
||||
$priceupgrade = 0;
|
||||
}
|
||||
if ($user->credits >= $priceupgrade)
|
||||
{
|
||||
|
||||
$server->product_id = $request->product_upgrade;
|
||||
$server->update();
|
||||
$server->allocation = $serverAttributes['allocation'];
|
||||
$response = Pterodactyl::updateServer($server, $newProduct);
|
||||
if ($response->failed()) return $this->serverCreationFailed($response, $server);
|
||||
//update user balance
|
||||
$user->decrement('credits', $priceupgrade);
|
||||
return redirect()->route('servers.show', ['server' => $server->id])->with('success', __('Server Successfully Upgraded'));
|
||||
}
|
||||
else
|
||||
{
|
||||
return redirect()->route('servers.show', ['server' => $server->id])->with('error', __('Not Enough Balance for Upgrade'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,11 +155,10 @@
|
|||
<i class="fas fa-tools mr-2"></i>
|
||||
<span>{{ __('Manage') }}</span>
|
||||
</a>
|
||||
<button onclick="confirmSubmit('{{ $server->id }}', handleServerDelete);" target="__blank"
|
||||
class="btn btn-danger mx-3 w-100 align-items-center justify-content-center d-flex">
|
||||
<i class="fas fa-trash mr-2"></i>
|
||||
<span>{{ __('Delete') }}</span>
|
||||
</button>
|
||||
<a href="{{ route('servers.show', ['server' => $server->id])}}" class="btn btn-warning mx-3 w-100 align-items-center justify-content-center d-flex">
|
||||
<i class="fas fa-cog mr-2"></i>
|
||||
<span>{{ __('Settings') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
@ -168,42 +167,4 @@
|
|||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
const confirmSubmit = (serverId, handleServerDelete) => {
|
||||
// Confirm delete submit with sweetalert
|
||||
Swal.fire({
|
||||
title: "{{ __('Are you sure?') }}",
|
||||
text: "{{ __('This is an irreversible action, all files of this server will be removed.') }}",
|
||||
icon: 'warning',
|
||||
confirmButtonColor: '#d9534f',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "{{ __('Yes, delete it!') }}",
|
||||
cancelButtonText: "{{ __('No, cancel!') }}",
|
||||
reverseButtons: true
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
handleServerDelete(serverId);
|
||||
return
|
||||
}
|
||||
Swal.fire("{{ __('Canceled ...') }}", `{{ __('Deletion has been canceled.') }}`, 'info');
|
||||
});
|
||||
}
|
||||
|
||||
const handleServerDelete = (serverId) => {
|
||||
// Delete server
|
||||
fetch("{{ route('servers.destroy', '') }}" + '/' + serverId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
}
|
||||
}).then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
308
resources/views/servers/settings.blade.php
Normal file
308
resources/views/servers/settings.blade.php
Normal file
|
@ -0,0 +1,308 @@
|
|||
@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>{{__('Server Settings')}}</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 href="{{ route('servers.index') }}">{{__('Server')}}</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{ route('servers.show', $server->id) }}">{{__('Settings')}}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="row pt-3">
|
||||
<div class="col-xl-3 col-sm-6 mb-xl-0 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-body p-3">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="numbers">
|
||||
<p class="text-sm mb-0 text-uppercase font-weight-bold">SERVER NAME</p>
|
||||
<h5 class="font-weight-bolder" id="domain_text">
|
||||
<span class="text-success text-sm font-weight-bolder">{{ $server->name }}</span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 text-end">
|
||||
<div class="icon icon-shape bg-gradient-primary shadow-primary text-center rounded-circle">
|
||||
<i class='bx bx-fingerprint' style="color: white;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-sm-6 mb-xl-0 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-body p-3">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="numbers">
|
||||
<p class="text-sm mb-0 text-uppercase font-weight-bold">CPU</p>
|
||||
<h5 class="font-weight-bolder">
|
||||
<span class="text-success text-sm font-weight-bolder">@if($server->product->cpu == 0)Unlimited @else {{$server->product->cpu}} % @endif</span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 text-end">
|
||||
<div class="icon icon-shape bg-gradient-danger shadow-danger text-center rounded-circle">
|
||||
<i class='bx bxs-chip' style="color: white;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-sm-6 mb-xl-0 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-body p-3">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="numbers">
|
||||
<p class="text-sm mb-0 text-uppercase font-weight-bold">Memory</p>
|
||||
<h5 class="font-weight-bolder">
|
||||
<span class="text-success text-sm font-weight-bolder">@if($server->product->memory == 0)Unlimited @else {{$server->product->memory}}MB @endif</span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 text-end">
|
||||
<div class="icon icon-shape bg-gradient-success shadow-success text-center rounded-circle">
|
||||
<i class='bx bxs-memory-card' style="color: white;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-sm-6">
|
||||
<div class="card">
|
||||
<div class="card-body p-3">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="numbers">
|
||||
<p class="text-sm mb-0 text-uppercase font-weight-bold">STORAGE</p>
|
||||
<h5 class="font-weight-bolder">
|
||||
<span class="text-success text-sm font-weight-bolder">@if($server->product->disk == 0)Unlimited @else {{$server->product->disk}}MB @endif</span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4 text-end">
|
||||
<div class="icon icon-shape bg-gradient-warning shadow-warning text-center rounded-circle">
|
||||
<i class='bx bxs-hdd' style="color: white;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<h5 class="card-title"><i class="fas fa-sliders-h mr-2"></i>{{__('Server Information')}}</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('Server ID')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $server->id }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('Pterodactyl ID')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $server->identifier }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('Hourly Price')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ number_format($server->product->getHourlyPrice(), 2, '.', '') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('Monthly Price')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $server->product->getHourlyPrice() * 24 * 30 }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('Location')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $server->location }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('Node')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $server->node }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('Backups')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $server->product->backups }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>{{__('MySQL Database')}}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $server->product->databases }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="col-md-12 text-center">
|
||||
<!-- Upgrade Button trigger modal -->
|
||||
<button type="button" data-toggle="modal" data-target="#UpgradeModal{{ $server->id }}" target="__blank"
|
||||
class="btn btn-info btn-md">
|
||||
<i class="fas fa-upload mr-2"></i>
|
||||
<span>{{ __('Upgrade') }}</span>
|
||||
</button>
|
||||
<!-- Upgrade Modal -->
|
||||
<div style="width: 100%; margin-block-start: 100px;" class="modal fade" id="UpgradeModal{{ $server->id }}" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header card-header">
|
||||
<h5 class="modal-title">UPGRADE SERVER</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body card-body">
|
||||
<strong>FOR DOWNGRADE PLEASE CHOOSE A PLAN BELOW YOUR PLAN</strong>
|
||||
<br>
|
||||
<br>
|
||||
<strong>YOUR PRODUCT : </strong> {{ $server->product->name }}
|
||||
<br>
|
||||
<br>
|
||||
<form action="{{ route('servers.upgrade', ['server' => $server->id]) }}" method="POST">
|
||||
@csrf
|
||||
<select name="product_upgrade" id="product_upgrade" class="form-input2 form-control">
|
||||
<option value="">Select the product</option>
|
||||
@foreach($products as $product)
|
||||
@if(in_array($server->egg, $product->eggs) && $product->id != $server->product->id)
|
||||
<option value="{{ $product->id }}">{{ $product->name }} [ {{ CREDITS_DISPLAY_NAME }} {{ $product->price }} ]</option>
|
||||
@endif
|
||||
@endforeach
|
||||
</select>
|
||||
<br> Once the Upgrade button is pressed, we will automatically deduct the amount for the first hour according to the new product from your credits. <br>
|
||||
</div>
|
||||
<div class="modal-footer card-body">
|
||||
<button type="submit" class="btn btn-primary" style="width: 100%"><strong>Upgrade</strong></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Delete Button trigger modal -->
|
||||
<button type="button" data-toggle="modal" data-target="#DeleteModal" target="__blank"
|
||||
class="btn btn-danger btn-md">
|
||||
<i class="fas fa-trash mr-2"></i>
|
||||
<span>{{ __('Delete') }}</span>
|
||||
</button>
|
||||
<!-- Delete Modal -->
|
||||
<div class="modal fade" id="DeleteModal" tabindex="-1" role="dialog" aria-labelledby="DeleteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="DeleteModalLabel">Delete Server</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
This is an irreversible action, all files of this server will be removed.!!!
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
|
||||
<form class="d-inline" method="post" action="{{ route('servers.destroy', ['server' => $server->id]) }}">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-danger mr-1">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
|
||||
@endsection
|
|
@ -63,6 +63,7 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
|||
Route::get('notifications/readAll',[NotificationController::class,'readAll'])->name('notifications.readAll');
|
||||
Route::resource('notifications', NotificationController::class);
|
||||
Route::resource('servers', ServerController::class);
|
||||
Route::post('servers/{server}/upgrade', [ServerController::class,'upgrade'])->name('servers.upgrade');
|
||||
Route::resource('profile', ProfileController::class);
|
||||
Route::resource('store', StoreController::class);
|
||||
|
||||
|
|
Loading…
Reference in a new issue