feat: 💄 Added basic resource cards

This commit is contained in:
IceToast 2021-11-20 23:38:44 +01:00
parent bd6cec92ea
commit 679e4d4670

View file

@ -13,7 +13,7 @@
<li class="breadcrumb-item"><a href="{{ route('home') }}">Dashboard</a></li> <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 href="{{ route('servers.index') }}">Servers</a>
<li class="breadcrumb-item"><a class="text-muted" <li class="breadcrumb-item"><a class="text-muted"
href="{{ route('servers.create') }}">Create</a> href="{{ route('servers.create') }}">Create</a>
</li> </li>
</ol> </ol>
</div> </div>
@ -27,38 +27,39 @@
<div class="container"> <div class="container">
<!-- FORM --> <!-- FORM -->
<form action="{{route('servers.store')}}" method="post" class="row"> <form action="{{ route('servers.store') }}" method="post" class="row">
@csrf @csrf
<div class="col-md-8"> <div class="col-md-8">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<div class="card-title"><i class="fas fa-cogs mr-2"></i>{{__('Server configuration')}}</div> <div class="card-title"><i class="fas fa-cogs mr-2"></i>{{ __('Server configuration') }}
</div>
</div> </div>
@if($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0 ) @if ($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0)
<div class="alert alert-danger p-2 m-2"> <div class="alert alert-danger p-2 m-2">
<h5><i class="icon fas fa-exclamation-circle"></i>{{__('Error!')}}</h5> <h5><i class="icon fas fa-exclamation-circle"></i>{{ __('Error!') }}</h5>
<p class="pl-4"> <p class="pl-4">
@if(Auth::user()->role == 'admin') @if (Auth::user()->role == 'admin')
{{__('Make sure to link your products to nodes and eggs.')}} <br> {{ __('Make sure to link your products to nodes and eggs.') }} <br>
{{__('There has to be at least 1 valid product for server creation')}} {{ __('There has to be at least 1 valid product for server creation') }}
@endif @endif
</p> </p>
<ul> <ul>
@if($productCount === 0 ) @if ($productCount === 0)
<li> {{__('No products available!')}}</li> <li> {{ __('No products available!') }}</li>
@endif @endif
@if($nodeCount === 0 ) @if ($nodeCount === 0)
<li>{{__('No nodes have been linked!')}}</li> <li>{{ __('No nodes have been linked!') }}</li>
@endif @endif
@if(count($nests) === 0 ) @if (count($nests) === 0)
<li>{{__('No nests available!')}}</li> <li>{{ __('No nests available!') }}</li>
@endif @endif
@if(count($eggs) === 0 ) @if (count($eggs) === 0)
<li>{{__('No eggs have been linked!')}}</li> <li>{{ __('No eggs have been linked!') }}</li>
@endif @endif
</ul> </ul>
</div> </div>
@ -68,8 +69,8 @@
<div x-show="loading" class="overlay dark"> <div x-show="loading" class="overlay dark">
<i class="fas fa-2x fa-sync-alt"></i> <i class="fas fa-2x fa-sync-alt"></i>
</div> </div>
<div class="card-body">
<div class="card-body">
@if ($errors->any()) @if ($errors->any())
<div class="alert alert-danger"> <div class="alert alert-danger">
<ul class="list-group pl-3"> <ul class="list-group pl-3">
@ -81,29 +82,25 @@
@endif @endif
<div class="form-group"> <div class="form-group">
<label for="name">{{__('Name')}}</label> <label for="name">{{ __('Name') }}</label>
<input x-model="name" id="name" name="name" type="text" required="required" <input x-model="name" id="name" name="name" type="text" required="required"
class="form-control @error('name') is-invalid @enderror"> class="form-control @error('name') is-invalid @enderror">
@error('name') @error('name')
<div class="invalid-feedback"> <div class="invalid-feedback">
{{ $message }} {{ $message }}
</div> </div>
@enderror @enderror
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="nest">{{__('Software / Games')}}</label> <label for="nest">{{ __('Software / Games') }}</label>
<select class="custom-select" <select class="custom-select" required name="nest" id="nest" x-model="selectedNest"
required @change="setEggs();">
name="nest" <option selected disabled hidden value="null">
id="nest" {{ count($nests) > 0 ? __('Please select software ...') : __('---') }}
x-model="selectedNest" </option>
@change="setEggs();">
<option selected disabled hidden
value="null">{{count($nests) > 0 ? __('Please select software ...') : __('---')}}</option>
@foreach ($nests as $nest) @foreach ($nests as $nest)
<option value="{{ $nest->id }}">{{ $nest->name }}</option> <option value="{{ $nest->id }}">{{ $nest->name }}</option>
@endforeach @endforeach
@ -111,21 +108,15 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="egg">{{__('Specification ')}}</label> <label for="egg">{{ __('Specification ') }}</label>
<div> <div>
<select id="egg" <select id="egg" required name="egg" :disabled="eggs.length == 0"
required x-model="selectedEgg" @change="fetchLocations();" required="required"
name="egg" class="custom-select">
:disabled="eggs.length == 0" <option x-text="getEggInputText()" selected disabled hidden value="null">
x-model="selectedEgg" </option>
@change="fetchLocations();"
required="required"
class="custom-select">
<option x-text="getEggInputText()"
selected disabled hidden value="null"></option>
<template x-for="egg in eggs" :key="egg.id"> <template x-for="egg in eggs" :key="egg.id">
<option x-text="egg.name" :value="egg.id"></option> <option x-text="egg.name" :value="egg.id"></option>
</template> </template>
@ -136,25 +127,17 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="node">{{__('Node')}}</label> <label for="node">{{ __('Node') }}</label>
<select name="node" <select name="node" required id="node" x-model="selectedNode" :disabled="!fetchedLocations"
required @change="fetchProducts();" class="custom-select">
id="node" <option x-text="getNodeInputText()" disabled selected hidden value="null">
x-model="selectedNode"
:disabled="!fetchedLocations"
@change="fetchProducts();"
class="custom-select">
<option
x-text="getNodeInputText()"
disabled selected hidden value="null">
</option> </option>
<template x-for="location in locations" :key="location.id"> <template x-for="location in locations" :key="location.id">
<optgroup :label="location.name"> <optgroup :label="location.name">
<template x-for="node in location.nodes" :key="node.id"> <template x-for="node in location.nodes" :key="node.id">
<option x-text="node.name" <option x-text="node.name" :value="node.id">
:value="node.id">
</option> </option>
</template> </template>
@ -166,27 +149,51 @@
<div class="form-group"> <div class="form-group">
<label for="product">{{__('Resources')}}</label> <label for="product">{{ __('Resources') }}</label>
<select name="product" <select name="product" required id="product" :disabled="!fetchedProducts"
required x-model="selectedProduct" @change="updateSelectedObjects()" class="custom-select">
id="product" <option x-text="getProductInputText()" disabled selected hidden value="null"></option>
:disabled="!fetchedProducts"
x-model="selectedProduct"
@change="updateSelectedObjects()"
class="custom-select">
<option
x-text="getProductInputText()"
disabled selected hidden value="null"></option>
<template x-for="product in products" :key="product.id"> <template x-for="product in products" :key="product.id">
<option :disabled="product.minimum_credits > user.credits" <option :disabled="product.minimum_credits > user.credits"
x-text="getProductOptionText(product)" x-text="getProductOptionText(product)" :value="product.id">
:value="product.id">
</option> </option>
</template> </template>
</select> </select>
</div> </div>
</div>
</div>
<div class="form-group">
<label for="product">{{ __('Resources') }}</label>
<div class="container">
<div class="row justify-content-around">
<template x-for="product in products" :key="product.id">
<div class="card col-4">
<div class="card-body">
<h4 class="card-title" x-text="product.name"></h4>
<div class="mt-6">
<div>
<p class="card-text text-muted">Resource Data:</p>
<div class="col">
<div class="row">
<div class="col">
<span>{{ __('CPU') }}</span>
</div>
<div class="col">
<p x-text="product.cpu + ' %'""></p>
</div>
</div>
</div>
</div>
<div class=" mt-4">
<span class="card-text text-muted">Description</span>
<p class="card-text" x-text="product.description"></p>
</div>
</div>
</div>
</div>
</template>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -194,73 +201,73 @@
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<div class="card-title"> <div class="card-title">
<i class="fas fa-list mr-2"></i>{{__('Server details')}} <i class="fas fa-list mr-2"></i>{{ __('Server details') }}
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul class="list-group mb-3"> <ul class="list-group mb-3">
<li x-show="selectedNestObject.name" <li x-show="selectedNestObject.name"
class="list-group-item d-flex justify-content-between lh-condensed"> class="list-group-item d-flex justify-content-between lh-condensed">
<div> <div>
<h6 class="my-0">{{__('Software / Games')}}</h6> <h6 class="my-0">{{ __('Software / Games') }}</h6>
<small x-text="selectedNestObject?.name ?? '{{__('No selection')}}'" <small x-text="selectedNestObject?.name ?? '{{ __('No selection') }}'"
class="text-muted"></small> class="text-muted"></small>
</div> </div>
</li> </li>
<li class="list-group-item d-flex justify-content-between lh-condensed"> <li class="list-group-item d-flex justify-content-between lh-condensed">
<div> <div>
<h6 class="my-0">{{__('Specification')}}</h6> <h6 class="my-0">{{ __('Specification') }}</h6>
<small x-text="selectedEggObject?.name ?? '{{__('No selection')}}'" <small x-text="selectedEggObject?.name ?? '{{ __('No selection') }}'"
class="text-muted"></small> class="text-muted"></small>
</div> </div>
</li> </li>
<li <li class="list-group-item d-flex justify-content-between lh-condensed">
class="list-group-item d-flex justify-content-between lh-condensed">
<div> <div>
<h6 class="my-0">{{__('Node')}}</h6> <h6 class="my-0">{{ __('Node') }}</h6>
<small x-text="selectedNodeObject?.name ?? '{{__('No selection')}}'" <small x-text="selectedNodeObject?.name ?? '{{ __('No selection') }}'"
class="text-muted"></small> class="text-muted"></small>
</div> </div>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<div> <div>
<h6 class="my-0">{{__('Resources')}}</h6> <h6 class="my-0">{{ __('Resources') }}</h6>
<small x-text="selectedProductObject?.name ?? '{{__('No selection')}}'" <small x-text="selectedProductObject?.name ?? '{{ __('No selection') }}'"
class="text-muted"></small> class="text-muted"></small>
</div> </div>
<template x-if="selectedProductObject?.name"> <template x-if="selectedProductObject?.name">
<ul class="pl-0"> <ul class="pl-0">
<li class="d-flex justify-content-between"> <li class="d-flex justify-content-between">
<small class="text-muted d-inline-block">{{__('CPU')}}</small> <small class="text-muted d-inline-block">{{ __('CPU') }}</small>
<small class="text-muted d-inline-block" <small class="text-muted d-inline-block"
x-text="selectedProductObject.cpu + ' %'"></small> x-text="selectedProductObject.cpu + ' %'"></small>
</li> </li>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<small class="text-muted d-inline-block">{{__('Memory')}}</small> <small class="text-muted d-inline-block">{{ __('Memory') }}</small>
<small class="text-muted d-inline-block" <small class="text-muted d-inline-block"
x-text="selectedProductObject.memory + ' {{__('MB')}}'"></small> x-text="selectedProductObject.memory + ' {{ __('MB') }}'"></small>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<small class="text-muted d-inline-block">{{__('Disk')}}</small> <small class="text-muted d-inline-block">{{ __('Disk') }}</small>
<small class="text-muted d-inline-block" <small class="text-muted d-inline-block"
x-text="selectedProductObject.disk + ' {{__('MB')}}'"></small> x-text="selectedProductObject.disk + ' {{ __('MB') }}'"></small>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<small class="text-muted d-inline-block">{{__('Databases')}}</small> <small class="text-muted d-inline-block">{{ __('Databases') }}</small>
<small class="text-muted d-inline-block" <small class="text-muted d-inline-block"
x-text="selectedProductObject.databases + ' {{__('MySQL')}}'"></small> x-text="selectedProductObject.databases + ' {{ __('MySQL') }}'"></small>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<small class="text-muted d-inline-block">{{__('Backups')}}</small> <small class="text-muted d-inline-block">{{ __('Backups') }}</small>
<small class="text-muted d-inline-block" <small class="text-muted d-inline-block"
x-text="selectedProductObject.backups"></small> x-text="selectedProductObject.backups"></small>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<small class="text-muted d-inline-block">{{__('Allocations')}} ({{__('ports')}})</small> <small class="text-muted d-inline-block">{{ __('Allocations') }}
<small class="text-muted d-inline-block" x-text="selectedProductObject.allocations"></small> ({{ __('ports') }})</small>
</div> <small class="text-muted d-inline-block"
x-text="selectedProductObject.allocations"></small>
</div>
</ul> </ul>
</template> </template>
@ -268,7 +275,7 @@
</ul> </ul>
<ul class="list-group mb-3"> <ul class="list-group mb-3">
<li class="list-group-item d-flex justify-content-between"> <li class="list-group-item d-flex justify-content-between">
<span>{{CREDITS_DISPLAY_NAME}} {{__('per month')}}</span> <span>{{ CREDITS_DISPLAY_NAME }} {{ __('per month') }}</span>
<strong> <strong>
<i x-show="selectedProductObject?.price" class="fas fa-coins"></i> <i x-show="selectedProductObject?.price" class="fas fa-coins"></i>
<span x-text="selectedProductObject?.price ?? ''"></span> <span x-text="selectedProductObject?.price ?? ''"></span>
@ -276,8 +283,8 @@
</li> </li>
</ul> </ul>
<button :disabled="!isFormValid()" :class="isFormValid() ? '' : 'disabled'" <button :disabled="!isFormValid()" :class="isFormValid() ? '' : 'disabled'"
class="btn btn-primary btn-block"> class="btn btn-primary btn-block">
{{__('Create server')}} {{ __('Create server') }}
</button> </button>
</div> </div>
</div> </div>
@ -314,7 +321,7 @@
//values //values
user: {!! $user !!}, user: {!! $user !!},
nests: {!! $nests !!}, nests: {!! $nests !!},
eggsSave:{!! $eggs !!}, //store back-end eggs eggsSave: {!! $eggs !!}, //store back-end eggs
eggs: [], eggs: [],
locations: [], locations: [],
products: [], products: [],
@ -360,7 +367,7 @@
this.selectedNode = 'null'; this.selectedNode = 'null';
this.selectedProduct = 'null'; this.selectedProduct = 'null';
let response = await axios.get(`{{route('products.locations.egg')}}/${this.selectedEgg}`) let response = await axios.get(`{{ route('products.locations.egg') }}/${this.selectedEgg}`)
.catch(console.error) .catch(console.error)
this.fetchedLocations = true; this.fetchedLocations = true;
@ -388,7 +395,8 @@
this.products = []; this.products = [];
this.selectedProduct = 'null'; this.selectedProduct = 'null';
let response = await axios.get(`{{route('products.products.node')}}/${this.selectedEgg}/${this.selectedNode}`) let response = await axios.get(
`{{ route('products.products.node') }}/${this.selectedEgg}/${this.selectedNode}`)
.catch(console.error) .catch(console.error)
this.fetchedProducts = true; this.fetchedProducts = true;
@ -414,7 +422,8 @@
this.selectedNodeObject = {}; this.selectedNodeObject = {};
this.locations.forEach(location => { this.locations.forEach(location => {
if (!this.selectedNodeObject?.id) { if (!this.selectedNodeObject?.id) {
this.selectedNodeObject = location.nodes.find(node => node.id == this.selectedNode) ?? {}; this.selectedNodeObject = location.nodes.find(node => node.id == this.selectedNode) ??
{};
} }
}) })
@ -436,35 +445,35 @@
getNodeInputText() { getNodeInputText() {
if (this.fetchedLocations) { if (this.fetchedLocations) {
if (this.locations.length > 0) { if (this.locations.length > 0) {
return '{{__('Please select a node ...')}}'; return '{{ __('Please select a node ...') }}';
} }
return '{{__('No nodes found matching current configuration')}}' return '{{ __('No nodes found matching current configuration') }}'
} }
return '{{__('---')}}'; return '{{ __('---') }}';
}, },
getProductInputText() { getProductInputText() {
if (this.fetchedProducts) { if (this.fetchedProducts) {
if (this.products.length > 0) { if (this.products.length > 0) {
return '{{__('Please select a resource ...')}}'; return '{{ __('Please select a resource ...') }}';
} }
return '{{__('No resources found matching current configuration')}}' return '{{ __('No resources found matching current configuration') }}'
} }
return '{{__('---')}}'; return '{{ __('---') }}';
}, },
getEggInputText() { getEggInputText() {
if (this.selectedNest) { if (this.selectedNest) {
return '{{__('Please select a configuration ...')}}'; return '{{ __('Please select a configuration ...') }}';
} }
return '{{__('---')}}'; return '{{ __('---') }}';
}, },
getProductOptionText(product) { getProductOptionText(product) {
let text = product.name + ' (' + product.description + ')'; let text = product.name + ' (' + product.description + ')';
if (product.minimum_credits > this.user.credits) { if (product.minimum_credits > this.user.credits) {
return '{{__('Not enough credits!')}} | ' + text; return '{{ __('Not enough credits!') }} | ' + text;
} }
return text; return text;