commit
93fdab5e76
|
@ -112,7 +112,7 @@ class ConfigurationController extends Controller
|
|||
|
||||
return datatables($query)
|
||||
->addColumn('actions', function (Configuration $configuration) {
|
||||
return '<button data-content="Edit" data-toggle="popover" data-trigger="hover" data-placement="top" onclick="configuration.parse(\'' . $configuration->key . '\',\'' . $configuration->value . '\')" data-content="Edit" data-trigger="hover" data-toggle="tooltip" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></button> ';
|
||||
return '<button data-content="Edit" data-toggle="popover" data-trigger="hover" data-placement="top" onclick="configuration.parse(\'' . $configuration->key . '\',\'' . $configuration->value . '\',\'' . $configuration->type . '\')" data-content="Edit" data-trigger="hover" data-toggle="tooltip" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></button> ';
|
||||
})
|
||||
->editColumn('created_at', function (Configuration $configuration) {
|
||||
return $configuration->created_at ? $configuration->created_at->diffForHumans() : '';
|
||||
|
|
|
@ -141,12 +141,12 @@ class PaymentController extends Controller
|
|||
$user->increment('credits', $paypalProduct->quantity);
|
||||
|
||||
//update server limit
|
||||
if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE', 10) !== 0) {
|
||||
if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE', 10)) {
|
||||
$user->update(['server_limit' => 10]);
|
||||
if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
|
||||
if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
|
||||
$user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//update role
|
||||
if ($user->role == 'member') {
|
||||
$user->update(['role' => 'client']);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\Product;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
|
@ -51,6 +52,7 @@ class ProductController extends Controller
|
|||
"swap" => "required|numeric|max:1000000|min:0",
|
||||
"description" => "required|string|max:191",
|
||||
"disk" => "required|numeric|max:1000000|min:5",
|
||||
"minimum_credits" => "required|numeric|max:1000000|min:-1",
|
||||
"io" => "required|numeric|max:1000000|min:0",
|
||||
"databases" => "required|numeric|max:1000000|min:0",
|
||||
"backups" => "required|numeric|max:1000000|min:0",
|
||||
|
@ -73,7 +75,8 @@ class ProductController extends Controller
|
|||
public function show(Product $product)
|
||||
{
|
||||
return view('admin.products.show', [
|
||||
'product' => $product
|
||||
'product' => $product,
|
||||
'minimum_credits' => Configuration::getValueByKey("MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER"),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -108,6 +111,7 @@ class ProductController extends Controller
|
|||
"description" => "required|string|max:191",
|
||||
"disk" => "required|numeric|max:1000000|min:5",
|
||||
"io" => "required|numeric|max:1000000|min:0",
|
||||
"minimum_credits" => "required|numeric|max:1000000|min:-1",
|
||||
"databases" => "required|numeric|max:1000000|min:0",
|
||||
"backups" => "required|numeric|max:1000000|min:0",
|
||||
"allocations" => "required|numeric|max:1000000|min:0",
|
||||
|
@ -125,7 +129,8 @@ class ProductController extends Controller
|
|||
* @param Product $product
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function disable(Request $request, Product $product) {
|
||||
public function disable(Request $request, Product $product)
|
||||
{
|
||||
$product->update(['disabled' => !$product->disabled]);
|
||||
|
||||
return redirect()->route('admin.products.index')->with('success', 'product has been updated!');
|
||||
|
@ -181,12 +186,11 @@ class ProductController extends Controller
|
|||
' . csrf_field() . '
|
||||
' . method_field("PATCH") . '
|
||||
<div class="custom-control custom-switch">
|
||||
<input '.$checked.' name="disabled" onchange="this.form.submit()" type="checkbox" class="custom-control-input" id="switch'.$product->id.'">
|
||||
<label class="custom-control-label" for="switch'.$product->id.'"></label>
|
||||
<input ' . $checked . ' name="disabled" onchange="this.form.submit()" type="checkbox" class="custom-control-input" id="switch' . $product->id . '">
|
||||
<label class="custom-control-label" for="switch' . $product->id . '"></label>
|
||||
</div>
|
||||
</form>
|
||||
';
|
||||
|
||||
})
|
||||
->editColumn('created_at', function (Product $product) {
|
||||
return $product->created_at ? $product->created_at->diffForHumans() : '';
|
||||
|
|
|
@ -221,6 +221,20 @@ class UserController extends Controller
|
|||
return redirect()->route('admin.users.notifications')->with('success', 'Notification sent!');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function toggleSuspended(User $user){
|
||||
try {
|
||||
!$user->isSuspended() ? $user->suspend() : $user->unSuspend();
|
||||
} catch (Exception $exception) {
|
||||
return redirect()->back()->with('error', $exception->getMessage());
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', 'User has been updated!');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
|
@ -252,10 +266,17 @@ class UserController extends Controller
|
|||
return $user->last_seen ? $user->last_seen->diffForHumans() : '';
|
||||
})
|
||||
->addColumn('actions', function (User $user) {
|
||||
$suspendColor = $user->isSuspended() ? "btn-success" : "btn-warning";
|
||||
$suspendIcon = $user->isSuspended() ? "fa-play-circle" : "fa-pause-circle";
|
||||
$suspendText = $user->isSuspended() ? "Unsuspend" : "Suspend";
|
||||
return '
|
||||
<a data-content="Login as user" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.loginas', $user->id) . '" class="btn btn-sm btn-primary mr-1"><i class="fas fa-sign-in-alt"></i></a>
|
||||
<a data-content="Show" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.show', $user->id) . '" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-eye"></i></a>
|
||||
<a data-content="Edit" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.edit', $user->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" method="post" action="' . route('admin.users.togglesuspend', $user->id) . '">
|
||||
' . csrf_field() . '
|
||||
<button data-content="'.$suspendText.'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm '.$suspendColor.' text-white mr-1"><i class="far '.$suspendIcon.'"></i></button>
|
||||
</form>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.users.destroy', $user->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin;
|
|||
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Models\Voucher;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
@ -115,6 +116,13 @@ class VoucherController extends Controller
|
|||
return redirect()->back()->with('success', 'voucher has been removed!');
|
||||
}
|
||||
|
||||
public function users(Voucher $voucher)
|
||||
{
|
||||
return view('admin.vouchers.users', [
|
||||
'voucher' => $voucher
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
|
@ -144,7 +152,7 @@ class VoucherController extends Controller
|
|||
]);
|
||||
|
||||
if ($request->user()->credits + $voucher->credits >= 99999999) throw ValidationException::withMessages([
|
||||
'code' => "You can't redeem this voucher because you would exceed the ".CREDITS_DISPLAY_NAME." limit"
|
||||
'code' => "You can't redeem this voucher because you would exceed the " . CREDITS_DISPLAY_NAME . " limit"
|
||||
]);
|
||||
|
||||
#redeem voucher
|
||||
|
@ -153,10 +161,27 @@ class VoucherController extends Controller
|
|||
event(new UserUpdateCreditsEvent($request->user()));
|
||||
|
||||
return response()->json([
|
||||
'success' => "{$voucher->credits} ".CREDITS_DISPLAY_NAME." have been added to your balance!"
|
||||
'success' => "{$voucher->credits} " . CREDITS_DISPLAY_NAME . " have been added to your balance!"
|
||||
]);
|
||||
}
|
||||
|
||||
public function usersDataTable(Voucher $voucher)
|
||||
{
|
||||
$users = $voucher->users();
|
||||
|
||||
return datatables($users)
|
||||
->editColumn('name', function (User $user) {
|
||||
return '<a class="text-info" target="_blank" href="' . route('admin.users.show', $user->id) . '">' . $user->name . '</a>';
|
||||
})
|
||||
->addColumn('credits', function (User $user) {
|
||||
return '<i class="fas fa-coins mr-2"></i> ' . $user->credits();
|
||||
})
|
||||
->addColumn('last_seen', function (User $user) {
|
||||
return $user->last_seen ? $user->last_seen->diffForHumans() : '';
|
||||
})
|
||||
->rawColumns(['name', 'credits', 'last_seen'])
|
||||
->make();
|
||||
}
|
||||
public function dataTable()
|
||||
{
|
||||
$query = Voucher::query();
|
||||
|
@ -164,6 +189,7 @@ class VoucherController extends Controller
|
|||
return datatables($query)
|
||||
->addColumn('actions', function (Voucher $voucher) {
|
||||
return '
|
||||
<a data-content="Users" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.vouchers.users', $voucher->id) . '" class="btn btn-sm btn-primary mr-1"><i class="fas fa-users"></i></a>
|
||||
<a data-content="Edit" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.vouchers.edit', $voucher->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.vouchers.destroy', $voucher->id) . '">
|
||||
|
|
|
@ -6,11 +6,13 @@ use App\Http\Controllers\Controller;
|
|||
use App\Models\DiscordUser;
|
||||
use App\Models\User;
|
||||
use App\Notifications\DynamicNotification;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\ValidationRules\Rules\Delimited;
|
||||
|
||||
class NotificationController extends Controller
|
||||
|
@ -55,19 +57,21 @@ class NotificationController extends Controller
|
|||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function send(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
"via" => ["required", new Delimited("in:mail,database")],
|
||||
"all" => "required_without:users|boolean",
|
||||
"users" => ["required_without:all", new Delimited("exists:users,id")],
|
||||
"users" => ["required_without:all"],
|
||||
"title" => "required|string|min:1",
|
||||
"content" => "required|string|min:1"
|
||||
]);
|
||||
$via = explode(",", $data["via"]);
|
||||
$mail = null;
|
||||
$database = null;
|
||||
|
||||
if (in_array("database", $via)) {
|
||||
$database = [
|
||||
"title" => $data["title"],
|
||||
|
@ -79,10 +83,28 @@ class NotificationController extends Controller
|
|||
->subject($data["title"])
|
||||
->line(new HtmlString($data["content"]));
|
||||
}
|
||||
|
||||
$all = $data["all"] ?? false;
|
||||
$users = $all ? User::all() : User::whereIn("id", explode(",", $data["users"]))->get();
|
||||
if ($all) {
|
||||
$users = User::all();
|
||||
} else {
|
||||
$userIds = explode(",", $data["users"]);
|
||||
$users = User::query()
|
||||
->whereIn("id", $userIds)
|
||||
->orWhereHas('discordUser', function (Builder $builder) use ($userIds) {
|
||||
$builder->whereIn('id', $userIds);
|
||||
})
|
||||
->get();
|
||||
}
|
||||
|
||||
if ($users->count() == 0) {
|
||||
throw ValidationException::withMessages([
|
||||
'users' => ['No users found!'],
|
||||
]);
|
||||
}
|
||||
|
||||
Notification::send($users, new DynamicNotification($via, $database, $mail));
|
||||
return response()->json(["message" => "Notification successfully sent."]);
|
||||
return response()->json(["message" => "Notification successfully sent.", 'user_count' => $users->count()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,11 +6,17 @@ use App\Http\Controllers\Controller;
|
|||
use App\Models\Server;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
|
||||
class ServerController extends Controller
|
||||
{
|
||||
public const ALLOWED_INCLUDES = ['product', 'user'];
|
||||
public const ALLOWED_FILTERS = ['name', 'suspended', 'identifier', 'pterodactyl_id', 'user_id', 'product_id'];
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
|
@ -19,21 +25,28 @@ class ServerController extends Controller
|
|||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return Server::with('product')->paginate($request->query('per_page') ?? 50);
|
||||
}
|
||||
$query = QueryBuilder::for(Server::class)
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES)
|
||||
->allowedFilters(self::ALLOWED_FILTERS);
|
||||
|
||||
return $query->paginate($request->input('per_page') ?? 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Server $server
|
||||
* @return Server
|
||||
*
|
||||
* @return Server|Collection|Model
|
||||
*/
|
||||
public function show(Server $server)
|
||||
{
|
||||
return $server->load('product');
|
||||
}
|
||||
$query = QueryBuilder::for(Server::class)
|
||||
->where('id', '=', $server->id)
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES);
|
||||
|
||||
return $query->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
|
|
|
@ -2,28 +2,45 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\DiscordUser;
|
||||
use App\Models\User;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'discordUser'];
|
||||
const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended'];
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return User::paginate($request->query('per_page') ?? 50);
|
||||
$query = QueryBuilder::for(User::class)
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES)
|
||||
->allowedFilters(self::ALLOWED_FILTERS);
|
||||
|
||||
return $query->paginate($request->input('per_page') ?? 50);
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,12 +48,23 @@ class UserController extends Controller
|
|||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return User
|
||||
*
|
||||
* @return User|Builder|Collection|Model
|
||||
*/
|
||||
public function show(int $id)
|
||||
{
|
||||
$discordUser = DiscordUser::find($id);
|
||||
return $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$query = QueryBuilder::for($user)
|
||||
->with('discordUser')
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES)
|
||||
->where('users.id', '=', $id)
|
||||
->orWhereHas('discordUser', function (Builder $builder) use ($id) {
|
||||
$builder->where('id', '=', $id);
|
||||
});
|
||||
|
||||
return $query->firstOrFail();
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,11 +81,11 @@ class UserController extends Controller
|
|||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
"name" => "sometimes|string|min:4|max:30",
|
||||
"email" => "sometimes|string|email",
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"name" => "sometimes|string|min:4|max:30",
|
||||
"email" => "sometimes|string|email",
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"server_limit" => "sometimes|numeric|min:0|max:1000000",
|
||||
"role" => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])],
|
||||
"role" => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])],
|
||||
]);
|
||||
|
||||
$user->update($request->all());
|
||||
|
@ -81,23 +109,23 @@ class UserController extends Controller
|
|||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"server_limit" => "sometimes|numeric|min:0|max:1000000",
|
||||
]);
|
||||
|
||||
if($request->credits){
|
||||
if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([
|
||||
if ($request->credits) {
|
||||
if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([
|
||||
'credits' => "You can't add this amount of credits because you would exceed the credit limit"
|
||||
]);
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
$user->increment('credits', $request->credits);
|
||||
}
|
||||
}
|
||||
|
||||
if($request->server_limit){
|
||||
if ($request->server_limit) {
|
||||
if ($user->server_limit + $request->server_limit >= 2147483647) throw ValidationException::withMessages([
|
||||
'server_limit' => "You cannot add this amount of servers because it would exceed the server limit."
|
||||
]);
|
||||
$user->increment('server_limit', $request->server_limit);
|
||||
$user->increment('server_limit', $request->server_limit);
|
||||
}
|
||||
|
||||
return $user;
|
||||
|
@ -117,27 +145,72 @@ class UserController extends Controller
|
|||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"server_limit" => "sometimes|numeric|min:0|max:1000000",
|
||||
]);
|
||||
|
||||
if($request->credits){
|
||||
if($user->credits - $request->credits < 0) throw ValidationException::withMessages([
|
||||
if ($request->credits) {
|
||||
if ($user->credits - $request->credits < 0) throw ValidationException::withMessages([
|
||||
'credits' => "You can't remove this amount of credits because you would exceed the minimum credit limit"
|
||||
]);
|
||||
$user->decrement('credits', $request->credits);
|
||||
}
|
||||
}
|
||||
|
||||
if($request->server_limit){
|
||||
if($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([
|
||||
if ($request->server_limit) {
|
||||
if ($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([
|
||||
'server_limit' => "You cannot remove this amount of servers because it would exceed the minimum server."
|
||||
]);
|
||||
$user->decrement('server_limit', $request->server_limit);
|
||||
$user->decrement('server_limit', $request->server_limit);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
|
||||
'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'max:191'],
|
||||
]);
|
||||
|
||||
$user = User::create([
|
||||
'name' => $request->input('name'),
|
||||
'email' => $request->input('email'),
|
||||
'credits' => Configuration::getValueByKey('INITIAL_CREDITS', 150),
|
||||
'server_limit' => Configuration::getValueByKey('INITIAL_SERVER_LIMIT', 1),
|
||||
'password' => Hash::make($request->input('password')),
|
||||
]);
|
||||
|
||||
$response = Pterodactyl::client()->post('/application/users', [
|
||||
"external_id" => App::environment('local') ? Str::random(16) : (string)$user->id,
|
||||
"username" => $user->name,
|
||||
"email" => $user->email,
|
||||
"first_name" => $user->name,
|
||||
"last_name" => $user->name,
|
||||
"password" => $request->input('password'),
|
||||
"root_admin" => false,
|
||||
"language" => "en"
|
||||
]);
|
||||
|
||||
if ($response->failed()) {
|
||||
$user->delete();
|
||||
throw ValidationException::withMessages([
|
||||
'pterodactyl_error_message' => $response->toException()->getMessage(),
|
||||
'pterodactyl_error_status' => $response->toException()->getCode()
|
||||
]);
|
||||
}
|
||||
|
||||
$user->update([
|
||||
'pterodactyl_id' => $response->json()['attributes']['id']
|
||||
]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
|
|
|
@ -5,20 +5,30 @@ namespace App\Http\Controllers\Api;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Voucher;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
|
||||
class VoucherController extends Controller
|
||||
{
|
||||
const ALLOWED_INCLUDES = ['users'];
|
||||
const ALLOWED_FILTERS = ['code', 'memo', 'credits', 'uses'];
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return Voucher::paginate($request->query('per_page') ?? 50);
|
||||
$query = QueryBuilder::for(Voucher::class)
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES)
|
||||
->allowedFilters(self::ALLOWED_FILTERS);
|
||||
|
||||
return $query->paginate($request->input('per_page') ?? 50);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,10 +50,10 @@ class VoucherController extends Controller
|
|||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers',
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers',
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
|
||||
]);
|
||||
|
||||
|
@ -54,11 +64,16 @@ class VoucherController extends Controller
|
|||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*
|
||||
* @return Voucher|Collection|Model
|
||||
*/
|
||||
public function show(int $id)
|
||||
{
|
||||
return Voucher::findOrFail($id);
|
||||
$query = QueryBuilder::for(Voucher::class)
|
||||
->where('id', '=', $id)
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES);
|
||||
|
||||
return $query->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,10 +99,10 @@ class VoucherController extends Controller
|
|||
$voucher = Voucher::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}",
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}",
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
|
||||
]);
|
||||
|
||||
|
|
|
@ -1,30 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\UsefulLink;
|
||||
use App\Models\Configuration;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
const TIME_LEFT_BG_SUCCESS = "bg-success";
|
||||
const TIME_LEFT_BG_WARNING = "bg-warning";
|
||||
const TIME_LEFT_BG_DANGER = "bg-danger";
|
||||
const TIME_LEFT_OUT_OF_CREDITS_TEXT = "You ran out of Credits";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get the Background Color for the Days-Left-Box in HomeView
|
||||
*
|
||||
* @param float $days
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeLeftBoxBackground(float $days)
|
||||
{
|
||||
switch ($days)
|
||||
{
|
||||
case ($days >= 15):
|
||||
return $this::TIME_LEFT_BG_SUCCESS;
|
||||
break;
|
||||
|
||||
case ($days >= 8 && $days <= 14):
|
||||
return $this::TIME_LEFT_BG_WARNING;
|
||||
break;
|
||||
|
||||
case ($days <= 7):
|
||||
return $this::TIME_LEFT_BG_DANGER;
|
||||
break;
|
||||
|
||||
default:
|
||||
return $this::TIME_LEFT_BG_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get the Text for the Days-Left-Box in HomeView
|
||||
*
|
||||
* @param float $days
|
||||
* @param float $hours
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeLeftBoxText(float $days, float $hours)
|
||||
{
|
||||
if ($days < 1)
|
||||
{
|
||||
if ($hours < 1)
|
||||
{
|
||||
return $this::TIME_LEFT_OUT_OF_CREDITS_TEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return strval($hours);
|
||||
}
|
||||
}
|
||||
return strval(number_format($days, 0));
|
||||
}
|
||||
|
||||
/** Show the application dashboard. */
|
||||
public function index(Request $request)
|
||||
{
|
||||
$usage = 0;
|
||||
$usage = Auth::user()->creditUsage();
|
||||
$credits = Auth::user()->Credits();
|
||||
$bg = "";
|
||||
$boxText = "";
|
||||
$unit = "";
|
||||
|
||||
/** Build our Time-Left-Box */
|
||||
if ($credits > 0.01 and $usage > 0)
|
||||
{
|
||||
$days = number_format(($credits * 30) / $usage, 2, '.', '');
|
||||
$hours = number_format($credits / ($usage / 30 / 24) , 2, '.', '');
|
||||
|
||||
$bg = $this->getTimeLeftBoxBackground($days);
|
||||
$boxText = $this->getTimeLeftBoxText($days, $hours);
|
||||
$unit = $days < 1 ? 'hours' : 'days';
|
||||
|
||||
foreach (Auth::user()->servers as $server){
|
||||
$usage += $server->product->price;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// RETURN ALL VALUES
|
||||
return view('home')->with([
|
||||
'useage' => $usage,
|
||||
'useful_links' => UsefulLink::all()->sortBy('id')
|
||||
'credits' => $credits,
|
||||
'useful_links' => UsefulLink::all()->sortBy('id'),
|
||||
'bg' => $bg,
|
||||
'boxText' => $boxText,
|
||||
'unit' => $unit
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ use Illuminate\Http\Client\Response;
|
|||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Request as FacadesRequest;
|
||||
|
||||
class ServerController extends Controller
|
||||
{
|
||||
|
@ -39,6 +40,7 @@ class ServerController extends Controller
|
|||
$query->where('disabled', '=', false);
|
||||
})->get(),
|
||||
'nests' => Nest::where('disabled', '=', false)->get(),
|
||||
'minimum_credits' => Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -52,7 +54,7 @@ class ServerController extends Controller
|
|||
"description" => "nullable|max:191",
|
||||
"node_id" => "required|exists:nodes,id",
|
||||
"egg_id" => "required|exists:eggs,id",
|
||||
"product_id" => "required|exists:products,id",
|
||||
"product_id" => "required|exists:products,id"
|
||||
]);
|
||||
|
||||
//get required resources
|
||||
|
@ -74,8 +76,8 @@ class ServerController extends Controller
|
|||
'identifier' => $response->json()['attributes']['identifier']
|
||||
]);
|
||||
|
||||
if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR' , 'true') == 'true'){
|
||||
if (Auth::user()->credits >= $server->product->getHourlyPrice()){
|
||||
if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
|
||||
if (Auth::user()->credits >= $server->product->getHourlyPrice()) {
|
||||
Auth::user()->decrement('credits', $server->product->getHourlyPrice());
|
||||
}
|
||||
}
|
||||
|
@ -86,15 +88,24 @@ class ServerController extends Controller
|
|||
/**
|
||||
* @return null|RedirectResponse
|
||||
*/
|
||||
private function validateConfigurationRules(){
|
||||
private function validateConfigurationRules()
|
||||
{
|
||||
//limit validation
|
||||
if (Auth::user()->servers()->count() >= Auth::user()->server_limit) {
|
||||
return redirect()->route('servers.index')->with('error', 'Server limit reached!');
|
||||
}
|
||||
|
||||
//minimum credits
|
||||
if (Auth::user()->credits <= Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)) {
|
||||
return redirect()->route('servers.index')->with('error', "You do not have the required amount of ".CREDITS_DISPLAY_NAME." to create a new server!");
|
||||
// minimum credits
|
||||
if (FacadesRequest::has("product_id")) {
|
||||
$product = Product::findOrFail(FacadesRequest::input("product_id"));
|
||||
if (
|
||||
Auth::user()->credits <
|
||||
($product->minimum_credits == -1
|
||||
? Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)
|
||||
: $product->minimum_credits)
|
||||
) {
|
||||
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
|
||||
|
@ -141,7 +152,7 @@ class ServerController extends Controller
|
|||
* @param Server $server
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
private function serverCreationFailed(Response $response , Server $server)
|
||||
private function serverCreationFailed(Response $response, Server $server)
|
||||
{
|
||||
$server->delete();
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http;
|
||||
|
||||
use App\Http\Middleware\ApiAuthToken;
|
||||
use App\Http\Middleware\CheckSuspended;
|
||||
use App\Http\Middleware\CreditsDisplayName;
|
||||
use App\Http\Middleware\isAdmin;
|
||||
use App\Http\Middleware\LastSeen;
|
||||
|
@ -42,7 +43,7 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
LastSeen::class,
|
||||
CreditsDisplayName::class
|
||||
CreditsDisplayName::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
|
@ -70,6 +71,7 @@ class Kernel extends HttpKernel
|
|||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'admin' => isAdmin::class,
|
||||
'api.token' => ApiAuthToken::class
|
||||
'api.token' => ApiAuthToken::class,
|
||||
'checkSuspended' => CheckSuspended::class
|
||||
];
|
||||
}
|
||||
|
|
28
app/Http/Middleware/CheckSuspended.php
Normal file
28
app/Http/Middleware/CheckSuspended.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CheckSuspended
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (auth()->check() && auth()->user()->isSuspended()) {
|
||||
auth()->logout();
|
||||
|
||||
$message = 'Your account has been suspended. Please contact our support team!';
|
||||
|
||||
return redirect()->route('login')->withMessage($message);
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ use Hidehalo\Nanoid\Client;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
class Product extends Model
|
||||
|
@ -17,10 +16,11 @@ class Product extends Model
|
|||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
public static function boot() {
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function(Product $product) {
|
||||
static::creating(function (Product $product) {
|
||||
$client = new Client();
|
||||
|
||||
$product->{$product->getKeyName()} = $client->generateId($size = 21);
|
||||
|
@ -47,6 +47,6 @@ class Product extends Model
|
|||
*/
|
||||
public function servers(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class , 'id' , 'product_id');
|
||||
return $this->belongsTo(Server::class, 'id', 'product_id');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
'password',
|
||||
'pterodactyl_id',
|
||||
'discord_verified_at',
|
||||
'avatar'
|
||||
'avatar',
|
||||
'suspended'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -79,7 +80,9 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
*/
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'last_seen' => 'datetime',
|
||||
'last_seen' => 'datetime',
|
||||
'credits' => 'float',
|
||||
'server_limit' => 'float',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -94,13 +97,13 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
});
|
||||
|
||||
static::deleting(function (User $user) {
|
||||
$user->servers()->chunk(10 , function ($servers) {
|
||||
$user->servers()->chunk(10, function ($servers) {
|
||||
foreach ($servers as $server) {
|
||||
$server->delete();
|
||||
}
|
||||
});
|
||||
|
||||
$user->payments()->chunk(10 , function ($payments) {
|
||||
$user->payments()->chunk(10, function ($payments) {
|
||||
foreach ($payments as $payment) {
|
||||
$payment->delete();
|
||||
}
|
||||
|
@ -114,6 +117,38 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function servers()
|
||||
{
|
||||
return $this->hasMany(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function payments()
|
||||
{
|
||||
return $this->hasMany(Payment::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function vouchers()
|
||||
{
|
||||
return $this->belongsToMany(Voucher::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne
|
||||
*/
|
||||
public function discordUser()
|
||||
{
|
||||
return $this->hasOne(DiscordUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -130,11 +165,67 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return number_format($this->credits, 2, '.', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuspended()
|
||||
{
|
||||
return $this->suspended;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function suspend()
|
||||
{
|
||||
foreach ($this->servers as $server) {
|
||||
$server->suspend();
|
||||
}
|
||||
|
||||
$this->update([
|
||||
'suspended' => true
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function unSuspend()
|
||||
{
|
||||
foreach ($this->servers as $server) {
|
||||
if ($this->credits >= $server->product->getHourlyPrice()) {
|
||||
$server->unSuspend();
|
||||
}
|
||||
}
|
||||
|
||||
$this->update([
|
||||
'suspended' => false
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAvatar(){
|
||||
public function getAvatar()
|
||||
{
|
||||
//TODO loading the images to confirm they exist is causing to much load time. alternative has to be found :) maybe onerror tag on the <img tags>
|
||||
// if ($this->discordUser()->exists()) {
|
||||
// if(@getimagesize($this->discordUser->getAvatar())) {
|
||||
// $avatar = $this->discordUser->getAvatar();
|
||||
// } else {
|
||||
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
// }
|
||||
// } else {
|
||||
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
// }
|
||||
|
||||
return "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,7 +235,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
{
|
||||
$usage = 0;
|
||||
|
||||
foreach ($this->Servers as $server){
|
||||
foreach ($this->Servers as $server) {
|
||||
$usage += $server->product->price;
|
||||
}
|
||||
|
||||
|
@ -154,42 +245,12 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
/**
|
||||
* @return array|string|string[]
|
||||
*/
|
||||
public function getVerifiedStatus(){
|
||||
public function getVerifiedStatus()
|
||||
{
|
||||
$status = '';
|
||||
if ($this->hasVerifiedEmail()) $status .= 'email ';
|
||||
if ($this->discordUser()->exists()) $status .= 'discord';
|
||||
$status = str_replace(' ' , '/' , $status);
|
||||
$status = str_replace(' ', '/', $status);
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function vouchers(){
|
||||
return $this->belongsToMany(Voucher::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne
|
||||
*/
|
||||
public function discordUser(){
|
||||
return $this->hasOne(DiscordUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function servers()
|
||||
{
|
||||
return $this->hasMany(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany
|
||||
*/
|
||||
public function payments()
|
||||
{
|
||||
return $this->hasMany(Payment::class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,17 @@ class Voucher extends Model
|
|||
'expires_at'
|
||||
];
|
||||
|
||||
protected $appends = ['used' , 'status'];
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'credits' => 'float',
|
||||
'uses' => 'integer'
|
||||
];
|
||||
|
||||
protected $appends = ['used', 'status'];
|
||||
|
||||
/**
|
||||
* @return int
|
||||
|
@ -44,7 +54,8 @@ class Voucher extends Model
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getStatusAttribute(){
|
||||
public function getStatusAttribute()
|
||||
{
|
||||
return $this->getStatus();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,26 @@ class WelcomeMessage extends Notification implements ShouldQueue
|
|||
{
|
||||
return ['database'];
|
||||
}
|
||||
public function AdditionalLines()
|
||||
{
|
||||
|
||||
$AdditionalLine = "";
|
||||
if(Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL') != 0) {
|
||||
$AdditionalLine .= "Verifying your e-mail address will grant you ".Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL')." additional " . Configuration::getValueByKey('CREDITS_DISPLAY_NAME') . ". <br />";
|
||||
}
|
||||
if(Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') != 0) {
|
||||
$AdditionalLine .= "Verifying your e-mail will also increase your Server Limit by " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') . ". <br />";
|
||||
}
|
||||
$AdditionalLine .="<br />";
|
||||
if(Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') != 0) {
|
||||
$AdditionalLine .= "You can also verify your discord account to get another " . Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') . " " . Configuration::getValueByKey('CREDITS_DISPLAY_NAME') . ". <br />";
|
||||
}
|
||||
if(Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') != 0) {
|
||||
$AdditionalLine .= "Verifying your Discord account will also increase your Server Limit by " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') . ". <br />";
|
||||
}
|
||||
|
||||
return $AdditionalLine;
|
||||
}
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
|
@ -51,7 +70,10 @@ class WelcomeMessage extends Notification implements ShouldQueue
|
|||
'content' => "
|
||||
<p>Hello <strong>{$this->user->name}</strong>, Welcome to our dashboard!</p>
|
||||
<h5>Verification</h5>
|
||||
<p>Please verify your email address to get " . Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL') . " extra credits and increase your server limit to " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') . "<br />You can also verify your discord account to get another " . Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') . " credits and to increase your server limit again with " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') . "</p>
|
||||
<p>You can verify your e-mail address and link/verify your Discord account.</p>
|
||||
<p>
|
||||
".$this->AdditionalLines()."
|
||||
</p>
|
||||
<h5>Information</h5>
|
||||
<p>This dashboard can be used to create and delete servers.<br /> These servers can be used and managed on our pterodactyl panel.<br /> If you have any questions, please join our Discord server and #create-a-ticket.</p>
|
||||
<p>We hope you can enjoy this hosting experience and if you have any suggestions please let us know!</p>
|
||||
|
|
|
@ -29,7 +29,6 @@ class AppServiceProvider extends ServiceProvider
|
|||
{
|
||||
Paginator::useBootstrap();
|
||||
Schema::defaultStringLength(191);
|
||||
QueryBuilderRequest::setArrayValueDelimiter('|');
|
||||
|
||||
Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) {
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"paypal/rest-api-sdk-php": "^1.14",
|
||||
"socialiteproviders/discord": "^4.1",
|
||||
"spatie/laravel-activitylog": "^3.16",
|
||||
"spatie/laravel-query-builder": "^3.5",
|
||||
"spatie/laravel-query-builder": "^3.6",
|
||||
"spatie/laravel-validation-rules": "^3.0",
|
||||
"yajra/laravel-datatables-oracle": "~9.0"
|
||||
},
|
||||
|
|
14
composer.lock
generated
14
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "b3b61a46d5d4d6560d052cfda863d12c",
|
||||
"content-hash": "f7ba581ff6641d3ab79d558070e99f3c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
|
@ -3462,16 +3462,16 @@
|
|||
},
|
||||
{
|
||||
"name": "spatie/laravel-query-builder",
|
||||
"version": "3.5.0",
|
||||
"version": "3.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/laravel-query-builder.git",
|
||||
"reference": "4e5257be24139836dc092f618d7c73bcb1c00302"
|
||||
"reference": "03d8e1307dcb58b16fcc9c4947633fc60ae74802"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/4e5257be24139836dc092f618d7c73bcb1c00302",
|
||||
"reference": "4e5257be24139836dc092f618d7c73bcb1c00302",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/03d8e1307dcb58b16fcc9c4947633fc60ae74802",
|
||||
"reference": "03d8e1307dcb58b16fcc9c4947633fc60ae74802",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3528,7 +3528,7 @@
|
|||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2021-07-05T14:17:44+00:00"
|
||||
"time": "2021-09-06T08:03:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-validation-rules",
|
||||
|
@ -8713,5 +8713,5 @@
|
|||
"ext-intl": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
return [
|
||||
|
||||
'version' => '0.5',
|
||||
'version' => '0.6',
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|
|
46
config/query-builder.php
Normal file
46
config/query-builder.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/**
|
||||
* @see https://github.com/spatie/laravel-query-builder
|
||||
*/
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
* By default the package will use the `include`, `filter`, `sort`
|
||||
* and `fields` query parameters as described in the readme.
|
||||
*
|
||||
* You can customize these query string parameters here.
|
||||
*/
|
||||
'parameters' => [
|
||||
'include' => 'include',
|
||||
|
||||
'filter' => 'filter',
|
||||
|
||||
'sort' => 'sort',
|
||||
|
||||
'fields' => 'fields',
|
||||
|
||||
'append' => 'append',
|
||||
],
|
||||
|
||||
/*
|
||||
* Related model counts are included using the relationship name suffixed with this string.
|
||||
* For example: GET /users?include=postsCount
|
||||
*/
|
||||
'count_suffix' => 'Count',
|
||||
|
||||
/*
|
||||
* By default the package will throw an `InvalidFilterQuery` exception when a filter in the
|
||||
* URL is not allowed in the `allowedFilters()` method.
|
||||
*/
|
||||
'disable_invalid_filter_query_exception' => false,
|
||||
|
||||
/*
|
||||
* By default the package inspects query string of request using $request->query().
|
||||
* You can change this behavior to inspect the request body using $request->input()
|
||||
* by setting this value to `body`.
|
||||
*
|
||||
* Possible values: `query_string`, `body`
|
||||
*/
|
||||
'request_data_source' => 'query_string',
|
||||
];
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddSuspendedToUsersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->boolean('suspended')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('suspended');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddProductMinimumCredits extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->float('minimum_credits')->default(-1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->dropColumn('minimum_credits');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -71,7 +71,10 @@
|
|||
<tbody>
|
||||
@foreach($logs as $log)
|
||||
<tr>
|
||||
<td>{{$log->causer ? json_decode($log->causer)->name : 'system'}}</td>
|
||||
<td> @if($log->causer) <a href='/admin/users/{{$log->causer_id}}'> {{json_decode($log->causer)->name}}
|
||||
@else
|
||||
System
|
||||
@endif</td>
|
||||
<td>
|
||||
<span>
|
||||
@switch($log->description)
|
||||
|
@ -90,6 +93,18 @@
|
|||
@endswitch
|
||||
{{ucfirst($log->description)}}
|
||||
{{ explode("\\" , $log->subject_type)[2]}}
|
||||
@php $first=true @endphp
|
||||
@foreach(json_decode($log->properties, true) as $properties)
|
||||
@if($first)
|
||||
@if(isset($properties['name']))
|
||||
" {{$properties['name']}} "
|
||||
@endif
|
||||
@if(isset($properties['email']))
|
||||
< {{$properties['email']}} >
|
||||
@endif
|
||||
@php $first=false @endphp
|
||||
@endif
|
||||
@endforeach
|
||||
</span>
|
||||
</td>
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
<i class="fa fa-cog"></i>
|
||||
</div>
|
||||
</div>
|
||||
<input id="value" name="value" type="text" class="form-control" required="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -37,16 +36,26 @@
|
|||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.configuration = {
|
||||
parse(key, value){
|
||||
parse(key, value, type) {
|
||||
$('#keyLabel').html(key)
|
||||
$('#key').val(key)
|
||||
$('#value').remove();
|
||||
if (type === 'integer') {
|
||||
$('.input-group').append('<input id="value" name="value" type="number" class="form-control" required="required">')
|
||||
} else if (type === 'boolean') {
|
||||
$('.input-group').append('<select id="value" name="value" class="form-control" required=required>' +
|
||||
'<option value="true">true</option>' +
|
||||
'<option value="false">false</option>' +
|
||||
'</select>')
|
||||
} else if (type === 'string') {
|
||||
$('.input-group').append('<input id="value" name="value" type="text" class="form-control" required="required">')
|
||||
}
|
||||
$('#value').val(value)
|
||||
$('#editConfigurationModel').modal('show')
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
</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('admin.products.index')}}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.products.create')}}">Create</a>
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.products.index') }}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{ route('admin.products.create') }}">Create</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
@ -29,12 +30,16 @@
|
|||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="{{route('admin.products.store')}}" method="POST">
|
||||
<form action="{{ route('admin.products.store') }}" method="POST">
|
||||
@csrf
|
||||
<div class="d-flex flex-row-reverse">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" name="disabled" class="custom-control-input custom-control-input-danger" id="switch1">
|
||||
<label class="custom-control-label" for="switch1">Disabled <i data-toggle="popover" data-trigger="hover" data-content="Will hide this option from being selected" class="fas fa-info-circle"></i></label>
|
||||
<input type="checkbox" name="disabled"
|
||||
class="custom-control-input custom-control-input-danger" id="switch1">
|
||||
<label class="custom-control-label" for="switch1">Disabled <i data-toggle="popover"
|
||||
data-trigger="hover"
|
||||
data-content="Will hide this option from being selected"
|
||||
class="fas fa-info-circle"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -42,78 +47,75 @@
|
|||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input value="{{old('name')}}" id="name" name="name" type="text"
|
||||
class="form-control @error('name') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('name') }}" id="name" name="name" type="text"
|
||||
class="form-control @error('name') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('name')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="price">Price in {{CREDITS_DISPLAY_NAME}}</label>
|
||||
<input value="{{old('price')}}" id="price" name="price"
|
||||
type="number"
|
||||
class="form-control @error('price') is-invalid @enderror"
|
||||
required="required">
|
||||
<label for="price">Price in {{ CREDITS_DISPLAY_NAME }}</label>
|
||||
<input value="{{ old('price') }}" id="price" name="price" type="number"
|
||||
class="form-control @error('price') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('price')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="memory">Memory</label>
|
||||
<input value="{{old('memory')}}" id="memory" name="memory"
|
||||
type="number"
|
||||
class="form-control @error('memory') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('memory') }}" id="memory" name="memory" type="number"
|
||||
class="form-control @error('memory') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('memory')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cpu">Cpu</label>
|
||||
<input value="{{old('cpu')}}" id="cpu" name="cpu"
|
||||
type="number"
|
||||
class="form-control @error('cpu') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('cpu') }}" id="cpu" name="cpu" type="number"
|
||||
class="form-control @error('cpu') is-invalid @enderror" required="required">
|
||||
@error('cpu')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="swap">Swap</label>
|
||||
<input value="{{old('swap')}}" id="swap" name="swap"
|
||||
type="number"
|
||||
class="form-control @error('swap') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('swap') }}" id="swap" name="swap" type="number"
|
||||
class="form-control @error('swap') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('swap')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description <i data-toggle="popover" data-trigger="hover" data-content="This is what the users sees" class="fas fa-info-circle"></i></label>
|
||||
<textarea id="description" name="description"
|
||||
type="text"
|
||||
class="form-control @error('description') is-invalid @enderror"
|
||||
required="required">{{old('description')}}</textarea>
|
||||
<label for="description">Description <i data-toggle="popover"
|
||||
data-trigger="hover" data-content="This is what the users sees"
|
||||
class="fas fa-info-circle"></i></label>
|
||||
<textarea id="description" name="description" type="text"
|
||||
class="form-control @error('description') is-invalid @enderror"
|
||||
required="required">{{ old('description') }}</textarea>
|
||||
@error('description')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
|
@ -121,65 +123,74 @@
|
|||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label for="disk">Disk</label>
|
||||
<input value="{{old('disk') ?? 1000}}" id="disk" name="disk"
|
||||
type="number"
|
||||
class="form-control @error('disk') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('disk') ?? 1000 }}" id="disk" name="disk" type="number"
|
||||
class="form-control @error('disk') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('disk')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="minimum_credits">Minimum {{ CREDITS_DISPLAY_NAME }} <i
|
||||
data-toggle="popover" data-trigger="hover"
|
||||
data-content="Setting to -1 will use the value from configuration."
|
||||
class="fas fa-info-circle"></i></label>
|
||||
<input value="{{ old('minimum_credits') ?? -1 }}" id="minimum_credits"
|
||||
name="minimum_credits" type="number"
|
||||
class="form-control @error('minimum_credits') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('minimum_credits')
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="io">IO</label>
|
||||
<input value="{{old('io') ?? 500}}" id="io" name="io"
|
||||
type="number"
|
||||
class="form-control @error('io') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('io') ?? 500 }}" id="io" name="io" type="number"
|
||||
class="form-control @error('io') is-invalid @enderror" required="required">
|
||||
@error('io')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="databases">Databases</label>
|
||||
<input value="{{old('databases') ?? 1}}" id="databases"
|
||||
name="databases"
|
||||
type="number"
|
||||
class="form-control @error('databases') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('databases') ?? 1 }}" id="databases" name="databases"
|
||||
type="number" class="form-control @error('databases') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('databases')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="backups">Backups</label>
|
||||
<input value="{{old('backups') ?? 1}}" id="backups"
|
||||
name="backups"
|
||||
type="number"
|
||||
class="form-control @error('backups') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('backups') ?? 1 }}" id="backups" name="backups"
|
||||
type="number" class="form-control @error('backups') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('backups')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="allocations">Allocations</label>
|
||||
<input value="{{old('allocations') ?? 0}}"
|
||||
id="allocations" name="allocations"
|
||||
type="number"
|
||||
class="form-control @error('allocations') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ old('allocations') ?? 0 }}" id="allocations"
|
||||
name="allocations" type="number"
|
||||
class="form-control @error('allocations') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('allocations')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
@ -200,6 +211,11 @@
|
|||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
</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('admin.products.index')}}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.products.edit' , $product->id)}}">Edit</a>
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.products.index') }}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{ route('admin.products.edit', $product->id) }}">Edit</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
@ -29,22 +30,28 @@
|
|||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
||||
@if($product->servers()->count() > 0)
|
||||
@if ($product->servers()->count() > 0)
|
||||
<div class="callout callout-danger">
|
||||
<h4>Editing the resource options will not automatically update the servers on pterodactyl's side!</h4>
|
||||
<p class="text-muted">Automatically updating resource options on pterodactyl side is on my todo list :)</p>
|
||||
<h4>Editing the resource options will not automatically update the servers on pterodactyl's
|
||||
side!</h4>
|
||||
<p class="text-muted">Automatically updating resource options on pterodactyl side is on my
|
||||
todo list :)</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="{{route('admin.products.update' , $product->id)}}" method="POST">
|
||||
<form action="{{ route('admin.products.update', $product->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
<div class="d-flex flex-row-reverse">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" @if($product->disabled) checked @endif name="disabled" class="custom-control-input custom-control-input-danger" id="switch1">
|
||||
<label class="custom-control-label" for="switch1">Disabled <i data-toggle="popover" data-trigger="hover" data-content="Will hide this option from being selected" class="fas fa-info-circle"></i></label>
|
||||
<input type="checkbox" @if ($product->disabled) checked @endif name="disabled"
|
||||
class="custom-control-input custom-control-input-danger" id="switch1">
|
||||
<label class="custom-control-label" for="switch1">Disabled <i data-toggle="popover"
|
||||
data-trigger="hover"
|
||||
data-content="Will hide this option from being selected"
|
||||
class="fas fa-info-circle"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -52,78 +59,74 @@
|
|||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input value="{{$product->name}}" id="name" name="name" type="text"
|
||||
class="form-control @error('name') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->name }}" id="name" name="name" type="text"
|
||||
class="form-control @error('name') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('name')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="price">Price in {{CREDITS_DISPLAY_NAME}}</label>
|
||||
<input value="{{$product->price}}" id="price" name="price"
|
||||
type="number"
|
||||
class="form-control @error('price') is-invalid @enderror"
|
||||
required="required">
|
||||
<label for="price">Price in {{ CREDITS_DISPLAY_NAME }}</label>
|
||||
<input value="{{ $product->price }}" id="price" name="price" type="number"
|
||||
class="form-control @error('price') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('price')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="memory">Memory</label>
|
||||
<input value="{{$product->memory}}" id="memory" name="memory"
|
||||
type="number"
|
||||
class="form-control @error('memory') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->memory }}" id="memory" name="memory" type="number"
|
||||
class="form-control @error('memory') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('memory')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cpu">Cpu</label>
|
||||
<input value="{{$product->cpu}}" id="cpu" name="cpu"
|
||||
type="number"
|
||||
class="form-control @error('cpu') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->cpu }}" id="cpu" name="cpu" type="number"
|
||||
class="form-control @error('cpu') is-invalid @enderror" required="required">
|
||||
@error('cpu')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="swap">Swap</label>
|
||||
<input value="{{$product->swap}}" id="swap" name="swap"
|
||||
type="number"
|
||||
class="form-control @error('swap') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->swap }}" id="swap" name="swap" type="number"
|
||||
class="form-control @error('swap') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('swap')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description <i data-toggle="popover" data-trigger="hover" data-content="This is what the users sees" class="fas fa-info-circle"></i></label>
|
||||
<textarea id="description" name="description"
|
||||
type="text"
|
||||
class="form-control @error('description') is-invalid @enderror"
|
||||
required="required">{{$product->description}}</textarea>
|
||||
<label for="description">Description <i data-toggle="popover"
|
||||
data-trigger="hover" data-content="This is what the users sees"
|
||||
class="fas fa-info-circle"></i></label>
|
||||
<textarea id="description" name="description" type="text"
|
||||
class="form-control @error('description') is-invalid @enderror"
|
||||
required="required">{{ $product->description }}</textarea>
|
||||
@error('description')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
|
@ -131,65 +134,72 @@
|
|||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label for="disk">Disk</label>
|
||||
<input value="{{$product->disk}}" id="disk" name="disk"
|
||||
type="number"
|
||||
class="form-control @error('disk') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->disk }}" id="disk" name="disk" type="number"
|
||||
class="form-control @error('disk') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('disk')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="minimum_credits">Minimum {{ CREDITS_DISPLAY_NAME }} <i
|
||||
data-toggle="popover" data-trigger="hover"
|
||||
data-content="Setting to -1 will use the value from configuration."
|
||||
class="fas fa-info-circle"></i></label>
|
||||
<input value="{{ $product->minimum_credits }}" id="minimum_credits"
|
||||
name="minimum_credits" type="number"
|
||||
class="form-control @error('minimum_credits') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('minimum_credits')
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="io">IO</label>
|
||||
<input value="{{$product->io}}" id="io" name="io"
|
||||
type="number"
|
||||
class="form-control @error('io') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->io }}" id="io" name="io" type="number"
|
||||
class="form-control @error('io') is-invalid @enderror" required="required">
|
||||
@error('io')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="databases">Databases</label>
|
||||
<input value="{{$product->databases}}" id="databases"
|
||||
name="databases"
|
||||
type="number"
|
||||
class="form-control @error('databases') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->databases }}" id="databases" name="databases"
|
||||
type="number" class="form-control @error('databases') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('databases')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="backups">Backups</label>
|
||||
<input value="{{$product->backups}}" id="backups"
|
||||
name="backups"
|
||||
type="number"
|
||||
class="form-control @error('backups') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->backups }}" id="backups" name="backups"
|
||||
type="number" class="form-control @error('backups') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('backups')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="allocations">Allocations</label>
|
||||
<input value="{{$product->allocations}}"
|
||||
id="allocations" name="allocations"
|
||||
type="number"
|
||||
class="form-control @error('allocations') is-invalid @enderror"
|
||||
required="required">
|
||||
<input value="{{ $product->allocations }}" id="allocations"
|
||||
name="allocations" type="number"
|
||||
class="form-control @error('allocations') is-invalid @enderror"
|
||||
required="required">
|
||||
@error('allocations')
|
||||
<div class="invalid-feedback">
|
||||
{{$message}}
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
{{ $message }}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
@ -210,6 +220,11 @@
|
|||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
</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('admin.users.index')}}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.users.index') }}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.products.show' , $product->id)}}">Show</a>
|
||||
href="{{ route('admin.products.show', $product->id) }}">Show</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
@ -30,11 +30,15 @@
|
|||
<div class="card-header d-flex justify-content-between">
|
||||
<h5 class="card-title"><i class="fas fa-sliders-h mr-2"></i>Product</h5>
|
||||
<div class="ml-auto">
|
||||
<a data-content="Edit" data-trigger="hover" data-toggle="tooltip" href="{{ route('admin.products.edit', $product->id) }}" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="{{ route('admin.products.destroy', $product->id) }}">
|
||||
<a data-content="Edit" data-trigger="hover" data-toggle="tooltip"
|
||||
href="{{ route('admin.products.edit', $product->id) }}" class="btn btn-sm btn-info mr-1"><i
|
||||
class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post"
|
||||
action="{{ route('admin.products.destroy', $product->id) }}">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field("DELETE") }}
|
||||
<button data-content="Delete" data-trigger="hover" data-toggle="tooltip" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
{{ method_field('DELETE') }}
|
||||
<button data-content="Delete" data-trigger="hover" data-toggle="tooltip"
|
||||
class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -47,9 +51,9 @@
|
|||
<label>ID</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->id}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->id }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -60,9 +64,9 @@
|
|||
<label>Name</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->name}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->name }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -73,9 +77,26 @@
|
|||
<label>Price</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
<i class="fas fa-coins mr-1"></i>{{$product->price}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
<i class="fas fa-coins mr-1"></i>{{ $product->price }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Minimum {{ CREDITS_DISPLAY_NAME }}</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
@if ($product->minimum_credits == -1)
|
||||
<i class="fas fa-coins mr-1"></i>{{ $minimum_credits }}
|
||||
@else
|
||||
<i class="fas fa-coins mr-1"></i>{{ $product->minimum_credits }}
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -87,9 +108,9 @@
|
|||
<label>Memory</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->memory}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->memory }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -100,9 +121,9 @@
|
|||
<label>CPU</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->cpu}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->cpu }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -113,9 +134,9 @@
|
|||
<label>Swap</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->swap}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->swap }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -126,9 +147,9 @@
|
|||
<label>Disk</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->disk}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->disk }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -139,9 +160,9 @@
|
|||
<label>IO</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->io}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->io }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -152,9 +173,9 @@
|
|||
<label>Databases</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->databases}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->databases }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -165,9 +186,9 @@
|
|||
<label>Allocations</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->allocations}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->allocations }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -178,9 +199,9 @@
|
|||
<label>Created At</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->created_at ? $product->created_at->diffForHumans() : ''}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->created_at ? $product->created_at->diffForHumans() : '' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -192,9 +213,9 @@
|
|||
<label>Description</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span class="d-inline-block text-truncate">
|
||||
{{$product->description}}
|
||||
</span>
|
||||
<span class="d-inline-block text-truncate">
|
||||
{{ $product->description }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -206,9 +227,9 @@
|
|||
<label>Updated At</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->updated_at ? $product->updated_at->diffForHumans() : ''}}
|
||||
</span>
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{ $product->updated_at ? $product->updated_at->diffForHumans() : '' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,240 +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>Products</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('admin.users.index')}}">Products</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.products.show' , $product->id)}}">Show</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<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>Product</h5>
|
||||
<div class="ml-auto">
|
||||
<a data-content="Edit" data-trigger="hover" data-toggle="tooltip" href="{{ route('admin.products.edit', $product->id) }}" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="{{ route('admin.products.destroy', $product->id) }}">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field("DELETE") }}
|
||||
<button data-content="Delete" data-trigger="hover" data-toggle="tooltip" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>ID</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->id}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Name</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->name}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Price</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
<i class="fas fa-coins mr-1"></i>{{$product->price}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Memory</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->memory}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>CPU</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->cpu}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Swap</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->swap}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Disk</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->disk}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>IO</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->io}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Databases</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->databases}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Allocations</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->allocations}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Created At</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->created_at ? $product->created_at->diffForHumans() : ''}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Description</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span class="d-inline-block text-truncate">
|
||||
{{$product->description}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<label>Updated At</label>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<span style="max-width: 250px;" class="d-inline-block text-truncate">
|
||||
{{$product->updated_at ? $product->updated_at->diffForHumans() : ''}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title"><i class="fas fa-server mr-2"></i>Servers</h5>
|
||||
</div>
|
||||
<div class="card-body table-responsive">
|
||||
|
||||
@include('admin.servers.table' , ['filter' => '?product=' . $product->id])
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
|
||||
|
||||
@endsection
|
93
resources/views/admin/vouchers/users.blade.php
Normal file
93
resources/views/admin/vouchers/users.blade.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
@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>Vouchers</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('admin.vouchers.index') }}">Vouchers</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{ route('admin.vouchers.users', $voucher->id) }}">Users</a>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="card">
|
||||
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h5 class="card-title"><i class="fas fa-users mr-2"></i>Users</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body table-responsive">
|
||||
|
||||
<table id="datatable" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>{{ CREDITS_DISPLAY_NAME }}</th>
|
||||
<th>Last Seen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
$('#datatable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
stateSave: true,
|
||||
ajax: "{{ route('admin.vouchers.usersdatatable', $voucher->id) }}",
|
||||
columns: [{
|
||||
data: 'id'
|
||||
}, {
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
data: 'email'
|
||||
},
|
||||
{
|
||||
data: 'credits'
|
||||
},
|
||||
{
|
||||
data: 'last_seen'
|
||||
},
|
||||
],
|
||||
fnDrawCallback: function(oSettings) {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@endsection
|
|
@ -11,6 +11,10 @@
|
|||
<div class="card-body">
|
||||
<p class="login-box-msg">Sign in to start your session</p>
|
||||
|
||||
@if (session('message'))
|
||||
<div class="alert alert-danger">{{ session('message') }}</div>
|
||||
@endif
|
||||
|
||||
<form action="{{route('login')}}" method="post">
|
||||
@csrf
|
||||
@if(Session::has('error'))
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<!-- /.col -->
|
||||
<div class="col-12 col-sm-6 col-md-3">
|
||||
<div class="info-box mb-3">
|
||||
<span class="info-box-icon bg-danger elevation-1"><i class="fas fa-coins"></i></span>
|
||||
<span class="info-box-icon bg-secondary elevation-1"><i class="fas fa-coins"></i></span>
|
||||
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">{{CREDITS_DISPLAY_NAME}}</span>
|
||||
|
@ -65,11 +65,28 @@
|
|||
</div>
|
||||
<!-- /.info-box -->
|
||||
</div>
|
||||
|
||||
<!-- /.col -->
|
||||
@if($credits > 0.01 and $useage > 0)
|
||||
<div class="col-12 col-sm-6 col-md-3">
|
||||
<div class="info-box mb-3">
|
||||
<span class="info-box-icon {{$bg}} elevation-1">
|
||||
<i class="fas fa-hourglass-half"></i></span>
|
||||
<div class="info-box-content">
|
||||
<span class="info-box-text">Out of {{CREDITS_DISPLAY_NAME}} in </span>
|
||||
<span class="info-box-number">{{$boxText}}<sup>{{$unit}}</sup></span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.info-box -->
|
||||
@endif
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card card-default">
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
@component('mail::message')
|
||||
# Thank you for your purchase!
|
||||
Your payment has been confirmed; Your credit balance has been updated.
|
||||
Your payment has been confirmed; Your credit balance has been updated.<br>
|
||||
|
||||
# Details
|
||||
___
|
||||
### Payment ID: **{{$payment->id}}**
|
||||
### Status: **{{$payment->status}}**
|
||||
### Price: **{{$payment->formatCurrency()}}**
|
||||
### Type: **{{$payment->type}}**
|
||||
### Amount: **{{$payment->amount}}**
|
||||
### Balance: **{{$payment->user->credits}}**
|
||||
### User ID: **{{$payment->user_id}}**
|
||||
### Payment ID: **{{$payment->id}}**<br>
|
||||
### Status: **{{$payment->status}}**<br>
|
||||
### Price: **{{$payment->formatCurrency()}}**<br>
|
||||
### Type: **{{$payment->type}}**<br>
|
||||
### Amount: **{{$payment->amount}}**<br>
|
||||
### Balance: **{{$payment->user->credits}}**<br>
|
||||
### User ID: **{{$payment->user_id}}**<br>
|
||||
|
||||
<br>
|
||||
Thanks,<br>
|
||||
|
|
|
@ -213,6 +213,23 @@
|
|||
<p>You are verified!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="small-box bg-dark">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="p-3">
|
||||
<h3>{{$user->discordUser->username}} <sup>{{$user->discordUser->locale}}</sup> </h3>
|
||||
<p>{{$user->discordUser->id}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="p-3"><img width="100px" height="100px" class="rounded-circle" src="{{$user->discordUser->getAvatar()}}" alt="avatar"></div>
|
||||
</div>
|
||||
<div class="small-box-footer">
|
||||
<a href="{{route('auth.redirect')}}">
|
||||
<i class="fab fa-discord mr-1"></i>Re-Sync Discord
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
</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')}}">Servers</a>
|
||||
<li class="breadcrumb-item"><a class="text-muted" href="{{route('servers.create')}}">Create</a>
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('servers.index') }}">Servers</a>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{ route('servers.create') }}">Create</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
@ -32,29 +33,29 @@
|
|||
<h5 class="card-title"><i class="fa fa-server mr-2"></i>Create Server</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" action="{{route('servers.store')}}">
|
||||
<form method="post" action="{{ route('servers.store') }}">
|
||||
@csrf
|
||||
<div class="form-group">
|
||||
<label for="name">* Name</label>
|
||||
<input id="name" name="name" type="text" required="required"
|
||||
class="form-control @error('name') is-invalid @enderror">
|
||||
class="form-control @error('name') is-invalid @enderror">
|
||||
|
||||
@error('name')
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
@enderror
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<input id="description" name="description" type="text"
|
||||
class="form-control @error('description') is-invalid @enderror">
|
||||
class="form-control @error('description') is-invalid @enderror">
|
||||
|
||||
@error('description')
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
@enderror
|
||||
|
||||
</div>
|
||||
|
@ -63,13 +64,13 @@
|
|||
<div>
|
||||
|
||||
<select id="node_id" name="node_id" required="required"
|
||||
class="custom-select @error('node_id') is-invalid @enderror">
|
||||
|
||||
@foreach($locations as $location)
|
||||
<optgroup label="{{$location->name}}">
|
||||
@foreach($location->nodes as $node)
|
||||
@if(!$node->disabled)
|
||||
<option value="{{$node->id}}">{{$node->name}}</option>
|
||||
class="custom-select @error('node_id') is-invalid @enderror">
|
||||
<option selected disabled hidden value="">Please Select ...</option>
|
||||
@foreach ($locations as $location)
|
||||
<optgroup label="{{ $location->name }}">
|
||||
@foreach ($location->nodes as $node)
|
||||
@if (!$node->disabled)
|
||||
<option value="{{ $node->id }}">{{ $node->name }}</option>
|
||||
@endif
|
||||
@endforeach
|
||||
</optgroup>
|
||||
|
@ -79,20 +80,21 @@
|
|||
</div>
|
||||
|
||||
@error('node_id')
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="egg_id">* Server configuration</label>
|
||||
<div>
|
||||
<select id="egg_id" name="egg_id" required="required"
|
||||
class="custom-select @error('egg_id') is-invalid @enderror">
|
||||
@foreach($nests as $nest)
|
||||
<optgroup label="{{$nest->name}}">
|
||||
@foreach($nest->eggs as $egg)
|
||||
<option value="{{$egg->id}}">{{$egg->name}}</option>
|
||||
class="custom-select @error('egg_id') is-invalid @enderror">
|
||||
<option selected disabled hidden value="">Please Select ...</option>
|
||||
@foreach ($nests as $nest)
|
||||
<optgroup label="{{ $nest->name }}">
|
||||
@foreach ($nest->eggs as $egg)
|
||||
<option value="{{ $egg->id }}">{{ $egg->name }}</option>
|
||||
@endforeach
|
||||
</optgroup>
|
||||
@endforeach
|
||||
|
@ -100,32 +102,40 @@
|
|||
</div>
|
||||
|
||||
@error('egg_id')
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="product_id">* Resource Configuration</label>
|
||||
<div>
|
||||
<select id="product_id" name="product_id" required="required"
|
||||
class="custom-select @error('product_id') is-invalid @enderror">
|
||||
@foreach($products as $product)
|
||||
<option value="{{$product->id}}">{{$product->name}}
|
||||
({{$product->description}})
|
||||
</option>
|
||||
class="custom-select @error('product_id') is-invalid @enderror">
|
||||
<option selected disabled hidden value="">Please Select...</option>
|
||||
@foreach ($products as $product)
|
||||
<option value="{{ $product->id }}" @if ($product->minimum_credits == -1 && Auth::user()->credits >= $minimum_credits)
|
||||
@elseif ($product->minimum_credits != -1 && Auth::user()->credits >=
|
||||
$product->minimum_credits)
|
||||
@else
|
||||
disabled
|
||||
@endif
|
||||
>{{ $product->name }}
|
||||
({{ $product->description }})
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@error('product_id')
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
Please fill out this field.
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group text-right">
|
||||
<button type="submit" class="btn btn-primary mt-3">Submit</button>
|
||||
<input type="submit" class="btn btn-primary mt-3" value="Submit"
|
||||
onclick="this.disabled=true;this.value='Creating, please wait...';this.form.submit();">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
|
@ -83,6 +83,14 @@
|
|||
<td>Backups</td>
|
||||
<td>{{$server->product->backups}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price per Hour</td>
|
||||
<td>{{number_format($server->product->getHourlyPrice(),2,".", "")}} {{CREDITS_DISPLAY_NAME}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price per Month</td>
|
||||
<td>{{$server->product->getHourlyPrice()*24*30}} {{CREDITS_DISPLAY_NAME}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<!-- info row -->
|
||||
<div class="row invoice-info">
|
||||
<div class="col-sm-4 invoice-col">
|
||||
From
|
||||
To
|
||||
<address>
|
||||
<strong>{{config('app.name' , 'Laravel')}}</strong><br>
|
||||
Email: {{env('PAYPAL_EMAIL' , env('MAIL_FROM_NAME'))}}
|
||||
|
@ -50,7 +50,7 @@
|
|||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-sm-4 invoice-col">
|
||||
To
|
||||
From
|
||||
<address>
|
||||
<strong>{{Auth::user()->name}}</strong><br>
|
||||
Email: {{Auth::user()->email}}
|
||||
|
|
|
@ -20,7 +20,7 @@ use Illuminate\Support\Facades\Route;
|
|||
Route::middleware('api.token')->group(function () {
|
||||
Route::patch('/users/{user}/increment', [UserController::class, 'increment']);
|
||||
Route::patch('/users/{user}/decrement', [UserController::class, 'decrement']);
|
||||
Route::resource('users', UserController::class)->except(['store', 'create']);
|
||||
Route::resource('users', UserController::class)->except(['create']);
|
||||
|
||||
Route::patch('/servers/{server}/suspend', [ServerController::class, 'suspend']);
|
||||
Route::patch('/servers/{server}/unsuspend', [ServerController::class, 'unSuspend']);
|
||||
|
|
|
@ -40,7 +40,7 @@ Route::middleware('guest')->get('/', function () {
|
|||
|
||||
Auth::routes(['verify' => true]);
|
||||
|
||||
Route::middleware('auth')->group(function () {
|
||||
Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
||||
#resend verification email
|
||||
Route::get('/email/verification-notification', function (Request $request) {
|
||||
$request->user()->sendEmailVerificationNotification();
|
||||
|
@ -79,6 +79,7 @@ Route::middleware('auth')->group(function () {
|
|||
Route::get('users/datatable', [UserController::class, 'datatable'])->name('users.datatable');
|
||||
Route::get('users/notifications', [UserController::class, 'notifications'])->name('users.notifications');
|
||||
Route::post('users/notifications', [UserController::class, 'notify'])->name('users.notifications');
|
||||
Route::post('users/togglesuspend/{user}', [UserController::class, 'toggleSuspended'])->name('users.togglesuspend');
|
||||
Route::resource('users', UserController::class);
|
||||
|
||||
Route::get('servers/datatable', [AdminServerController::class, 'datatable'])->name('servers.datatable');
|
||||
|
@ -118,6 +119,8 @@ Route::middleware('auth')->group(function () {
|
|||
Route::resource('usefullinks', UsefulLinkController::class);
|
||||
|
||||
Route::get('vouchers/datatable', [VoucherController::class, 'datatable'])->name('vouchers.datatable');
|
||||
Route::get('vouchers/{voucher}/usersdatatable', [VoucherController::class, 'usersdatatable'])->name('vouchers.usersdatatable');
|
||||
Route::get('vouchers/{voucher}/users', [VoucherController::class, 'users'])->name('vouchers.users');
|
||||
Route::resource('vouchers', VoucherController::class);
|
||||
|
||||
Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
|
||||
|
|
Loading…
Reference in a new issue