Upgrade / Downgrade

This commit is contained in:
SahrulGnwn 2022-08-03 19:34:00 +07:00
parent 812126e120
commit 6b5986881d
5 changed files with 386 additions and 44 deletions

View file

@ -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;
@ -271,4 +272,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,
]
]);
}
}

View file

@ -204,7 +204,7 @@ class ServerController extends Controller
}
/** Remove the specified resource from storage. */
public function destroy(Server $server)
public function delete(Server $server)
{
try {
$server->delete();
@ -213,4 +213,58 @@ 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'];
$product = Product::orderBy("created_at")->get();
return view('servers.settings')->with([
'server' => $server,
'product' => $product
]);
}
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'));
}
}
}

View file

@ -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

View file

@ -0,0 +1,306 @@
@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">&times;</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($product as $product)
@if($product->eggs[0]->nest->id == $server->product->eggs[0]->id)
@if ($product->id != $server->product->id)
<option value="{{ $product->id }}">{{ $product->name }} [ {{ CREDITS_DISPLAY_NAME }} {{ $product->price }} ]</option>
@endif
@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>
</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">&times;</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>
<a href="{{ route('servers.delete', ['server' => $server->id]) }}" type="button" class="btn btn-danger">Remove</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- END CUSTOM CONTENT -->
</div>
</section>
<!-- END CONTENT -->
@endsection

View file

@ -61,6 +61,8 @@ 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::get('servers/{server}/delete', [ServerController::class,'delete'])->name('servers.delete');
Route::resource('profile', ProfileController::class);
Route::resource('store', StoreController::class);