fix: 🐛 Merge issues
This commit is contained in:
parent
fda40fe8bc
commit
255671e20d
5 changed files with 280 additions and 446 deletions
|
@ -33,7 +33,7 @@ class ServerController extends Controller
|
|||
|
||||
//Get server infos from ptero
|
||||
$serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id, true);
|
||||
if (! $serverAttributes) {
|
||||
if (!$serverAttributes) {
|
||||
continue;
|
||||
}
|
||||
$serverRelationships = $serverAttributes['relationships'];
|
||||
|
@ -70,7 +70,7 @@ class ServerController extends Controller
|
|||
/** Show the form for creating a new resource. */
|
||||
public function create()
|
||||
{
|
||||
if (! is_null($this->validateConfigurationRules())) {
|
||||
if (!is_null($this->validateConfigurationRules())) {
|
||||
return $this->validateConfigurationRules();
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ class ServerController extends Controller
|
|||
// Check if node has enough memory and disk space
|
||||
$checkResponse = Pterodactyl::checkNodeResources($node, $product->memory, $product->disk);
|
||||
if ($checkResponse == false) {
|
||||
return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to allocate this product."));
|
||||
return redirect()->route('servers.index')->with('error', __("The node '" . $nodeName . "' doesn't have the required memory or disk left to allocate this product."));
|
||||
}
|
||||
|
||||
// Min. Credits
|
||||
|
@ -133,23 +133,23 @@ class ServerController extends Controller
|
|||
Auth::user()->credits < $product->minimum_credits ||
|
||||
Auth::user()->credits < $product->price
|
||||
) {
|
||||
return redirect()->route('servers.index')->with('error', 'You do not have the required amount of '.CREDITS_DISPLAY_NAME.' to use this product!');
|
||||
return redirect()->route('servers.index')->with('error', 'You do not have the required amount of ' . CREDITS_DISPLAY_NAME . ' to use this product!');
|
||||
}
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', 'false') === 'true' && ! Auth::user()->hasVerifiedEmail()) {
|
||||
if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', 'false') === 'true' && !Auth::user()->hasVerifiedEmail()) {
|
||||
return redirect()->route('profile.index')->with('error', __('You are required to verify your email address before you can create a server.'));
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
|
||||
if (! config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', 'true') && Auth::user()->role != 'admin') {
|
||||
if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', 'true') && Auth::user()->role != 'admin') {
|
||||
return redirect()->route('servers.index')->with('error', __('The system administrator has blocked the creation of new servers.'));
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', 'false') === 'true' && ! Auth::user()->discordUser) {
|
||||
if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', 'false') === 'true' && !Auth::user()->discordUser) {
|
||||
return redirect()->route('profile.index')->with('error', __('You are required to link your discord account before you can create a server.'));
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ class ServerController extends Controller
|
|||
/** @var Node $node */
|
||||
/** @var Egg $egg */
|
||||
/** @var Product $product */
|
||||
if (! is_null($this->validateConfigurationRules())) {
|
||||
if (!is_null($this->validateConfigurationRules())) {
|
||||
return $this->validateConfigurationRules();
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ class ServerController extends Controller
|
|||
|
||||
//get free allocation ID
|
||||
$allocationId = Pterodactyl::getFreeAllocationId($node);
|
||||
if (! $allocationId) {
|
||||
if (!$allocationId) {
|
||||
return $this->noAllocationsError($server);
|
||||
}
|
||||
|
||||
|
@ -249,13 +249,9 @@ class ServerController extends Controller
|
|||
}
|
||||
|
||||
/** Cancel Server */
|
||||
public function cancel (Server $server)
|
||||
public function cancel(Server $server)
|
||||
{
|
||||
try {
|
||||
error_log($server->update([
|
||||
'cancelled' => now(),
|
||||
]));
|
||||
|
||||
return redirect()->route('servers.index')->with('success', __('Server cancelled'));
|
||||
} catch (Exception $e) {
|
||||
return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to cancel the server"') . $e->getMessage() . '"');
|
||||
|
@ -267,7 +263,9 @@ class ServerController extends Controller
|
|||
{
|
||||
|
||||
|
||||
if($server->user_id != Auth::user()->id){ return back()->with('error', __('This is not your Server!'));}
|
||||
if ($server->user_id != Auth::user()->id) {
|
||||
return back()->with('error', __('This is not your Server!'));
|
||||
}
|
||||
$serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id);
|
||||
$serverRelationships = $serverAttributes['relationships'];
|
||||
$serverLocationAttributes = $serverRelationships['location']['attributes'];
|
||||
|
@ -287,10 +285,10 @@ class ServerController extends Controller
|
|||
$pteroNode = Pterodactyl::getNode($serverRelationships['node']['attributes']['id']);
|
||||
|
||||
$products = Product::orderBy('created_at')
|
||||
->whereHas('nodes', function (Builder $builder) use ($serverRelationships) { //Only show products for that node
|
||||
$builder->where('id', '=', $serverRelationships['node']['attributes']['id']);
|
||||
})
|
||||
->get();
|
||||
->whereHas('nodes', function (Builder $builder) use ($serverRelationships) { //Only show products for that node
|
||||
$builder->where('id', '=', $serverRelationships['node']['attributes']['id']);
|
||||
})
|
||||
->get();
|
||||
|
||||
// Set the each product eggs array to just contain the eggs name
|
||||
foreach ($products as $product) {
|
||||
|
@ -308,9 +306,8 @@ class ServerController extends Controller
|
|||
|
||||
public function upgrade(Server $server, Request $request)
|
||||
{
|
||||
if($server->user_id != Auth::user()->id || $server->suspended) return redirect()->route('servers.index');
|
||||
if(!isset($request->product_upgrade))
|
||||
{
|
||||
if ($server->user_id != Auth::user()->id || $server->suspended) return redirect()->route('servers.index');
|
||||
if (!isset($request->product_upgrade)) {
|
||||
return redirect()->route('servers.show', ['server' => $server->id])->with('error', __('this product is the only one'));
|
||||
}
|
||||
$user = Auth::user();
|
||||
|
@ -329,7 +326,7 @@ class ServerController extends Controller
|
|||
$requiredisk = $newProduct->disk - $oldProduct->disk;
|
||||
$checkResponse = Pterodactyl::checkNodeResources($node, $requireMemory, $requiredisk);
|
||||
if ($checkResponse == false) {
|
||||
return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to upgrade the server."));
|
||||
return redirect()->route('servers.index')->with('error', __("The node '" . $nodeName . "' doesn't have the required memory or disk left to upgrade the server."));
|
||||
}
|
||||
|
||||
// calculate the amount of credits that the user overpayed for the old product when canceling the server right now
|
||||
|
@ -353,8 +350,7 @@ class ServerController extends Controller
|
|||
$overpayedCredits = $oldProduct->price - $oldProduct->price * ($timeDifference / $billingPeriodMultiplier);
|
||||
|
||||
|
||||
if ($user->credits >= $newProduct->price && $user->credits >= $newProduct->minimum_credits)
|
||||
{
|
||||
if ($user->credits >= $newProduct->price && $user->credits >= $newProduct->minimum_credits) {
|
||||
$server->allocation = $serverAttributes['allocation'];
|
||||
// Update the server on the panel
|
||||
$response = Pterodactyl::updateServer($server, $newProduct);
|
||||
|
@ -374,11 +370,11 @@ class ServerController extends Controller
|
|||
if ($overpayedCredits > 0) $user->increment('credits', $overpayedCredits);
|
||||
|
||||
// Withdraw the credits for the new product
|
||||
$user->decrement('credits', $newProduct->price);
|
||||
$user->decrement('credits', $newProduct->price);
|
||||
|
||||
//restart the server
|
||||
$response = Pterodactyl::powerAction($server, "restart");
|
||||
if ($response->failed()) return redirect()->route('servers.index')->with('error', 'Server upgraded successfully! Could not restart the server: '.$response->json()['errors'][0]['detail']);
|
||||
if ($response->failed()) return redirect()->route('servers.index')->with('error', 'Server upgraded successfully! Could not restart the server: ' . $response->json()['errors'][0]['detail']);
|
||||
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'));
|
||||
|
|
|
@ -185,7 +185,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function suspend()
|
||||
{
|
||||
|
@ -201,7 +201,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function unSuspend()
|
||||
{
|
||||
|
@ -218,12 +218,6 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return $this;
|
||||
}
|
||||
|
||||
private function getServersWithProduct()
|
||||
{
|
||||
return $this->servers()
|
||||
->with('product')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
|
@ -257,7 +251,8 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return number_format($usage, 2, '.', '');
|
||||
}
|
||||
|
||||
private function getServersWithProduct() {
|
||||
private function getServersWithProduct()
|
||||
{
|
||||
return $this->servers()
|
||||
->whereNull('suspended')
|
||||
->whereNull('cancelled')
|
||||
|
|
|
@ -1,295 +0,0 @@
|
|||
@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>{{ __('Servers') }}</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('servers.index') }}">{{ __('Servers') }}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- CUSTOM CONTENT -->
|
||||
<div class="d-flex justify-content-md-start justify-content-center mb-3 ">
|
||||
<a @if (Auth::user()->Servers->count() >= Auth::user()->server_limit)
|
||||
disabled="disabled" title="Server limit reached!"
|
||||
@endif href="{{ route('servers.create') }}"
|
||||
class="btn
|
||||
@if (Auth::user()->Servers->count() >= Auth::user()->server_limit) disabled
|
||||
@endif btn-primary"><i
|
||||
class="fa fa-plus mr-2"></i>
|
||||
{{ __('Create Server') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row d-flex flex-row justify-content-center justify-content-md-start">
|
||||
@foreach ($servers as $server)
|
||||
<div class="col-xl-3 col-lg-5 col-md-6 col-sm-6 col-xs-12 card pr-0 pl-0 ml-sm-2 mr-sm-3"
|
||||
style="max-width: 350px">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mt-1">{{ $server->name }}
|
||||
</h5>
|
||||
<div class="card-tools mt-1">
|
||||
<div class="dropdown no-arrow">
|
||||
<a href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-ellipsis-v fa-sm fa-fw text-white-50"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
||||
aria-labelledby="dropdownMenuLink">
|
||||
@if (!empty(config('SETTINGS::MISC:PHPMYADMIN:URL')))
|
||||
<a href="{{ config('SETTINGS::MISC:PHPMYADMIN:URL') }}"
|
||||
class="dropdown-item text-info" target="__blank"><i title="manage"
|
||||
class="fas fa-database mr-2"></i><span>{{ __('Database') }}</span></a>
|
||||
@endif
|
||||
<div class="dropdown-divider"></div>
|
||||
<span class="dropdown-item"><i title="Created at"
|
||||
class="fas fa-sync-alt mr-2"></i><span>{{ $server->created_at->isoFormat('LL') }}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="container mt-1">
|
||||
<div class="row mb-3">
|
||||
<div class="col my-auto">{{ __('Status') }}:</div>
|
||||
<div class="col-7 my-auto">
|
||||
@if($server->suspended)
|
||||
<span class="badge badge-danger">{{ __('Suspended') }}</span>
|
||||
@elseif($server->cancelled)
|
||||
<span class="badge badge-warning">{{ __('Cancelled') }}</span>
|
||||
@else
|
||||
<span class="badge badge-success">{{ __('Active') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5">
|
||||
{{ __('Location') }}:
|
||||
</div>
|
||||
<div class="col-7 d-flex justify-content-between align-items-center">
|
||||
<span class="">{{ $server->location }}</span>
|
||||
<i data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{ __('Node') }}: {{ $server->node }}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Software') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap">
|
||||
<span>{{ $server->nest }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Specification') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap">
|
||||
<span>{{ $server->egg }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Resource plan') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap d-flex justify-content-between align-items-center">
|
||||
<span>{{ $server->product->name }}
|
||||
</span>
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('CPU') }}: {{ $server->product->cpu / 100 }} {{ __('vCores') }} <br/>{{ __('RAM') }}: {{ $server->product->memory }} MB <br/>{{ __('Disk') }}: {{ $server->product->disk }} MB <br/>{{ __('Backups') }}: {{ $server->product->backups }} <br/> {{ __('MySQL Databases') }}: {{ $server->product->databases }} <br/> {{ __('Allocations') }}: {{ $server->product->allocations }} <br/> {{ __('Billing Period') }}: {{$server->product->billing_period}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4 ">
|
||||
<div class="col-5 word-break" style="hyphens: auto">
|
||||
{{ __('Next Billing Cycle') }}:
|
||||
</div>
|
||||
<div class="col-7 d-flex text-wrap align-items-center">
|
||||
<span>
|
||||
@if ($server->suspended)
|
||||
-
|
||||
@else
|
||||
@switch($server->product->billing_period)
|
||||
@case('monthly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addMonth()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('weekly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addWeek()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('daily')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addDay()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('hourly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addHour()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('quarterly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addMonths(3)->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('half-annually')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addMonths(6)->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('annually')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addYear()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@default
|
||||
{{ __('Unknown') }}
|
||||
@endswitch
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-2">
|
||||
<div class="col-4">
|
||||
{{ __('Price') }}:
|
||||
<span class="text-muted">
|
||||
({{ CREDITS_DISPLAY_NAME }})
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-8 text-center">
|
||||
<div class="text-muted">
|
||||
@if($server->product->billing_period == 'monthly')
|
||||
{{ __('per Month') }}
|
||||
@elseif($server->product->billing_period == 'half-annually')
|
||||
{{ __('per 6 Months') }}
|
||||
@elseif($server->product->billing_period == 'quarterly')
|
||||
{{ __('per 3 Months') }}
|
||||
@elseif($server->product->billing_period == 'annually')
|
||||
{{ __('per Year') }}
|
||||
@elseif($server->product->billing_period == 'weekly')
|
||||
{{ __('per Week') }}
|
||||
@elseif($server->product->billing_period == 'daily')
|
||||
{{ __('per Day') }}
|
||||
@elseif($server->product->billing_period == 'hourly')
|
||||
{{ __('per Hour') }}
|
||||
@endif
|
||||
</div>
|
||||
<span>
|
||||
{{ $server->product->price == round($server->product->price) ? round($server->product->price) : $server->product->price }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer text-center">
|
||||
<a href="{{ config('SETTINGS::SYSTEM:PTERODACTYL:URL') }}/server/{{ $server->identifier }}"
|
||||
target="__blank"
|
||||
class="btn btn-info text-center float-left ml-2"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Manage Server') }}">
|
||||
<i class="fas fa-tools mx-2"></i>
|
||||
</a>
|
||||
@if(config("SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN"))
|
||||
<a href="{{ route('servers.show', ['server' => $server->id])}}"
|
||||
class="btn btn-info text-center mr-3"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Server Settings') }}">
|
||||
<i class="fas fa-cog mx-2"></i>
|
||||
</a>
|
||||
@endif
|
||||
<button onclick="handleServerCancel('{{ $server->id }}');" target="__blank"
|
||||
class="btn btn-warning text-center"
|
||||
{{ $server->suspended || $server->cancelled ? "disabled" : "" }}
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Cancel Server') }}">
|
||||
<i class="fas fa-ban mx-2"></i>
|
||||
</button>
|
||||
<button onclick="handleServerDelete('{{ $server->id }}');" target="__blank"
|
||||
class="btn btn-danger text-center float-right mr-2"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Delete Server') }}">
|
||||
<i class="fas fa-trash mx-2"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
const handleServerCancel = (serverId) => {
|
||||
// Handle server cancel with sweetalert
|
||||
Swal.fire({
|
||||
title: "{{ __('Cancel Server?') }}",
|
||||
text: "{{ __('This will cancel your current server to the next billing period. It will get suspended when the current period runs out.') }}",
|
||||
icon: 'warning',
|
||||
confirmButtonColor: '#d9534f',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "{{ __('Yes, cancel it!') }}",
|
||||
cancelButtonText: "{{ __('No, abort!') }}",
|
||||
reverseButtons: true
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
// Delete server
|
||||
fetch("{{ route('servers.cancel', '') }}" + '/' + serverId, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
}
|
||||
}).then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleServerDelete = (serverId) => {
|
||||
Swal.fire({
|
||||
title: "{{ __('Delete Server?') }}",
|
||||
html: "{{!! __('This is an irreversible action, all files of this server will be removed. <strong>No funds will get refunded</strong>. We recommend deleting the server when server is suspended.') !!}}",
|
||||
icon: 'warning',
|
||||
confirmButtonColor: '#d9534f',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "{{ __('Yes, delete it!') }}",
|
||||
cancelButtonText: "{{ __('No, abort!') }}",
|
||||
reverseButtons: true
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
// Delete server
|
||||
fetch("{{ route('servers.destroy', '') }}" + '/' + serverId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
}
|
||||
}).then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
return
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
})
|
||||
</script>
|
||||
@endsection
|
|
@ -213,11 +213,11 @@
|
|||
|
||||
<span class="d-inline-block" x-text="product.billing_period"></span>
|
||||
</li>
|
||||
<li>
|
||||
<li class="d-flex justify-content-between">
|
||||
<span class="d-inline-block"><i class="fa fa-coins"></i>
|
||||
{{ __('Minimum') }} {{ CREDITS_DISPLAY_NAME }}</span>
|
||||
<span class="d-inline-block"
|
||||
x-text="product.minimum_credits == -1 ? {{ config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER') }} : product.minimum_credits"></span>
|
||||
x-text="product.minimum_credits == -1 ? {{ config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER') }} : Math.round(product.minimum_credits)"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -240,14 +240,16 @@
|
|||
<input type="hidden" name="product" x-model="selectedProduct">
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" x-model="selectedProduct" name="product"
|
||||
:disabled="product.minimum_credits > user.credits || product.price > user.credits || product.doesNotFit == true ||
|
||||
submitClicked"
|
||||
:class="product.minimum_credits > user.credits || product.price > user.credits || product.doesNotFit == true ||
|
||||
submitClicked ? 'disabled' : ''"
|
||||
class="btn btn-primary btn-block mt-2" @click="setProduct(product.id);"
|
||||
x-text="product.doesNotFit == true ? '{{ __('Server cant fit on this Node') }}' : (product.minimum_credits > user.credits || product.price > user.credits ? '{{ __('Not enough') }} {{ CREDITS_DISPLAY_NAME }}!' : '{{ __('Create server') }}')">
|
||||
</button>
|
||||
<button type="submit" x-model="selectedProduct" name="product"
|
||||
:disabled="product.minimum_credits > user.credits || product.price > user.credits ||
|
||||
product.doesNotFit == true ||
|
||||
submitClicked"
|
||||
:class="product.minimum_credits > user.credits || product.price > user.credits ||
|
||||
product.doesNotFit == true ||
|
||||
submitClicked ? 'disabled' : ''"
|
||||
class="btn btn-primary btn-block mt-2" @click="setProduct(product.id);"
|
||||
x-text="product.doesNotFit == true ? '{{ __('Server cant fit on this Node') }}' : (product.minimum_credits > user.credits || product.price > user.credits ? '{{ __('Not enough') }} {{ CREDITS_DISPLAY_NAME }}!' : '{{ __('Create server') }}')">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -36,124 +36,260 @@
|
|||
class="fa fa-plus mr-2"></i>
|
||||
{{ __('Create Server') }}
|
||||
</a>
|
||||
@if (Auth::user()->Servers->count() > 0&&!empty(config('SETTINGS::MISC:PHPMYADMIN:URL')))
|
||||
<a
|
||||
href="{{ config('SETTINGS::MISC:PHPMYADMIN:URL') }}" target="_blank"
|
||||
class="btn btn-secondary ml-2"><i title="manage"
|
||||
class="fas fa-database mr-2"></i><span>{{ __('Database') }}</span>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="row d-flex flex-row justify-content-center justify-content-md-start">
|
||||
@foreach ($servers as $server)
|
||||
@if($server->location&&$server->node&&$server->nest&&$server->egg)
|
||||
<div class="col-xl-3 col-lg-5 col-md-6 col-sm-6 col-xs-12 card pr-0 pl-0 ml-sm-2 mr-sm-3"
|
||||
style="max-width: 350px">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mt-1">{{ $server->name }}
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="container mt-1">
|
||||
<div class="row mb-3">
|
||||
<div class="col my-auto">{{ __('Status') }}:</div>
|
||||
<div class="col-7 my-auto">
|
||||
<i
|
||||
class="fas {{ $server->isSuspended() ? 'text-danger' : 'text-success' }} fa-circle mr-2"></i>
|
||||
{{ $server->isSuspended() ? 'Suspended' : 'Active' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5">
|
||||
{{ __('Location') }}:
|
||||
</div>
|
||||
<div class="col-7 d-flex justify-content-between align-items-center">
|
||||
<span class="">{{ $server->location }}</span>
|
||||
<i data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{ __('Node') }}: {{ $server->node }}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Software') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap">
|
||||
<span>{{ $server->nest }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Specification') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap">
|
||||
<span>{{ $server->egg }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="col-5 ">
|
||||
{{ __('Resource plan') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap d-flex justify-content-between align-items-center">
|
||||
<span>{{ $server->product->name }}
|
||||
</span>
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('CPU') }}: {{ $server->product->cpu / 100 }} {{ __('vCores') }} <br/>{{ __('RAM') }}: {{ $server->product->memory }} MB <br/>{{ __('Disk') }}: {{ $server->product->disk }} MB <br/>{{ __('Backups') }}: {{ $server->product->backups }} <br/> {{ __('MySQL Databases') }}: {{ $server->product->databases }} <br/> {{ __('Allocations') }}: {{ $server->product->allocations }} <br/>"
|
||||
class="fas fa-info-circle"></i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-4">
|
||||
{{ __('Price') }}:
|
||||
<span class="text-muted">
|
||||
({{ CREDITS_DISPLAY_NAME }})
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="row">
|
||||
<div class="col-6 text-center">
|
||||
<div class="text-muted">{{ __('per Hour') }}</div>
|
||||
<span>
|
||||
{{ number_format($server->product->getHourlyPrice(), 2, '.', '') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-6 text-center">
|
||||
<div class="text-muted">{{ __('per Month') }}
|
||||
</div>
|
||||
<span>
|
||||
{{ $server->product->getHourlyPrice() * 24 * 30 }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-lg-5 col-md-6 col-sm-6 col-xs-12 card pr-0 pl-0 ml-sm-2 mr-sm-3"
|
||||
style="max-width: 350px">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mt-1">{{ $server->name }}
|
||||
</h5>
|
||||
<div class="card-tools mt-1">
|
||||
<div class="dropdown no-arrow">
|
||||
<a href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-ellipsis-v fa-sm fa-fw text-white-50"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
||||
aria-labelledby="dropdownMenuLink">
|
||||
@if (!empty(config('SETTINGS::MISC:PHPMYADMIN:URL')))
|
||||
<a href="{{ config('SETTINGS::MISC:PHPMYADMIN:URL') }}"
|
||||
class="dropdown-item text-info" target="__blank"><i title="manage"
|
||||
class="fas fa-database mr-2"></i><span>{{ __('Database') }}</span></a>
|
||||
@endif
|
||||
<div class="dropdown-divider"></div>
|
||||
<span class="dropdown-item"><i title="Created at"
|
||||
class="fas fa-sync-alt mr-2"></i><span>{{ $server->created_at->isoFormat('LL') }}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer d-flex align-items-center justify-content-between">
|
||||
<a href="{{ config('SETTINGS::SYSTEM:PTERODACTYL:URL') }}/server/{{ $server->identifier }}"
|
||||
target="__blank"
|
||||
class="btn btn-info mx-3 w-100 align-items-center justify-content-center d-flex">
|
||||
<i class="fas fa-tools mr-2"></i>
|
||||
<span>{{ __('Manage') }}</span>
|
||||
</a>
|
||||
<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>
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<div class="container mt-1">
|
||||
<div class="row mb-3">
|
||||
<div class="col my-auto">{{ __('Status') }}:</div>
|
||||
<div class="col-7 my-auto">
|
||||
@if($server->suspended)
|
||||
<span class="badge badge-danger">{{ __('Suspended') }}</span>
|
||||
@elseif($server->cancelled)
|
||||
<span class="badge badge-warning">{{ __('Cancelled') }}</span>
|
||||
@else
|
||||
<span class="badge badge-success">{{ __('Active') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5">
|
||||
{{ __('Location') }}:
|
||||
</div>
|
||||
<div class="col-7 d-flex justify-content-between align-items-center">
|
||||
<span class="">{{ $server->location }}</span>
|
||||
<i data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{ __('Node') }}: {{ $server->node }}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Software') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap">
|
||||
<span>{{ $server->nest }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Specification') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap">
|
||||
<span>{{ $server->egg }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-5 ">
|
||||
{{ __('Resource plan') }}:
|
||||
</div>
|
||||
<div class="col-7 text-wrap d-flex justify-content-between align-items-center">
|
||||
<span>{{ $server->product->name }}
|
||||
</span>
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('CPU') }}: {{ $server->product->cpu / 100 }} {{ __('vCores') }} <br/>{{ __('RAM') }}: {{ $server->product->memory }} MB <br/>{{ __('Disk') }}: {{ $server->product->disk }} MB <br/>{{ __('Backups') }}: {{ $server->product->backups }} <br/> {{ __('MySQL Databases') }}: {{ $server->product->databases }} <br/> {{ __('Allocations') }}: {{ $server->product->allocations }} <br/> {{ __('Billing Period') }}: {{$server->product->billing_period}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4 ">
|
||||
<div class="col-5 word-break" style="hyphens: auto">
|
||||
{{ __('Next Billing Cycle') }}:
|
||||
</div>
|
||||
<div class="col-7 d-flex text-wrap align-items-center">
|
||||
<span>
|
||||
@if ($server->suspended)
|
||||
-
|
||||
@else
|
||||
@switch($server->product->billing_period)
|
||||
@case('monthly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addMonth()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('weekly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addWeek()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('daily')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addDay()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('hourly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addHour()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('quarterly')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addMonths(3)->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('half-annually')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addMonths(6)->toDayDateTimeString(); }}
|
||||
@break
|
||||
@case('annually')
|
||||
{{ \Carbon\Carbon::parse($server->last_billed)->addYear()->toDayDateTimeString(); }}
|
||||
@break
|
||||
@default
|
||||
{{ __('Unknown') }}
|
||||
@endswitch
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-2">
|
||||
<div class="col-4">
|
||||
{{ __('Price') }}:
|
||||
<span class="text-muted">
|
||||
({{ CREDITS_DISPLAY_NAME }})
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-8 text-center">
|
||||
<div class="text-muted">
|
||||
@if($server->product->billing_period == 'monthly')
|
||||
{{ __('per Month') }}
|
||||
@elseif($server->product->billing_period == 'half-annually')
|
||||
{{ __('per 6 Months') }}
|
||||
@elseif($server->product->billing_period == 'quarterly')
|
||||
{{ __('per 3 Months') }}
|
||||
@elseif($server->product->billing_period == 'annually')
|
||||
{{ __('per Year') }}
|
||||
@elseif($server->product->billing_period == 'weekly')
|
||||
{{ __('per Week') }}
|
||||
@elseif($server->product->billing_period == 'daily')
|
||||
{{ __('per Day') }}
|
||||
@elseif($server->product->billing_period == 'hourly')
|
||||
{{ __('per Hour') }}
|
||||
@endif
|
||||
</div>
|
||||
<span>
|
||||
{{ $server->product->price == round($server->product->price) ? round($server->product->price) : $server->product->price }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer text-center">
|
||||
<a href="{{ config('SETTINGS::SYSTEM:PTERODACTYL:URL') }}/server/{{ $server->identifier }}"
|
||||
target="__blank"
|
||||
class="btn btn-info text-center float-left ml-2"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Manage Server') }}">
|
||||
<i class="fas fa-tools mx-2"></i>
|
||||
</a>
|
||||
@if(config("SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN"))
|
||||
<a href="{{ route('servers.show', ['server' => $server->id])}}"
|
||||
class="btn btn-info text-center mr-3"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Server Settings') }}">
|
||||
<i class="fas fa-cog mx-2"></i>
|
||||
</a>
|
||||
@endif
|
||||
<button onclick="handleServerCancel('{{ $server->id }}');" target="__blank"
|
||||
class="btn btn-warning text-center"
|
||||
{{ $server->suspended || $server->cancelled ? "disabled" : "" }}
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Cancel Server') }}">
|
||||
<i class="fas fa-ban mx-2"></i>
|
||||
</button>
|
||||
<button onclick="handleServerDelete('{{ $server->id }}');" target="__blank"
|
||||
class="btn btn-danger text-center float-right mr-2"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ __('Delete Server') }}">
|
||||
<i class="fas fa-trash mx-2"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
const handleServerCancel = (serverId) => {
|
||||
// Handle server cancel with sweetalert
|
||||
Swal.fire({
|
||||
title: "{{ __('Cancel Server?') }}",
|
||||
text: "{{ __('This will cancel your current server to the next billing period. It will get suspended when the current period runs out.') }}",
|
||||
icon: 'warning',
|
||||
confirmButtonColor: '#d9534f',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "{{ __('Yes, cancel it!') }}",
|
||||
cancelButtonText: "{{ __('No, abort!') }}",
|
||||
reverseButtons: true
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
// Delete server
|
||||
fetch("{{ route('servers.cancel', '') }}" + '/' + serverId, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
}
|
||||
}).then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleServerDelete = (serverId) => {
|
||||
Swal.fire({
|
||||
title: "{{ __('Delete Server?') }}",
|
||||
html: "{{!! __('This is an irreversible action, all files of this server will be removed. <strong>No funds will get refunded</strong>. We recommend deleting the server when server is suspended.') !!}}",
|
||||
icon: 'warning',
|
||||
confirmButtonColor: '#d9534f',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "{{ __('Yes, delete it!') }}",
|
||||
cancelButtonText: "{{ __('No, abort!') }}",
|
||||
reverseButtons: true
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
// Delete server
|
||||
fetch("{{ route('servers.destroy', '') }}" + '/' + serverId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
}
|
||||
}).then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
return
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
})
|
||||
</script>
|
||||
@endsection
|
||||
|
|
Loading…
Reference in a new issue