Added & implemented notes

Added & implemented notes to servers, shared, reseller, domains, DNS and IPs

/notes is a CRUD resource
This commit is contained in:
cp6 2022-12-02 13:57:28 +11:00
parent 28e58475b1
commit 924415eb66
19 changed files with 526 additions and 2 deletions

View File

@ -0,0 +1,124 @@
<?php
namespace App\Http\Controllers;
use App\Models\DNS;
use App\Models\Domains;
use App\Models\IPs;
use App\Models\Note;
use App\Models\Reseller;
use App\Models\SeedBoxes;
use App\Models\Server;
use App\Models\Shared;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class NoteController extends Controller
{
public function index()
{
$notes = Note::allNotes();
return view('notes.index', compact('notes'));
}
public function create()
{
$servers = Server::all();
$shareds = Shared::all();
$resellers = Reseller::all();
$domains = Domains::all();
$dns = DNS::all();
$ips = IPs::all();
return view('notes.create', compact(['servers', 'shareds', 'resellers', 'domains', 'dns', 'ips']));
}
public function store(Request $request)
{
$request->validate([
'service_id' => 'required|string|size:8',
'note' => 'required|string',
]);
try {
$note_id = Str::random(8);
$a = Note::create([
'id' => $note_id,
'service_id' => $request->service_id,
'note' => $request->note
]);
} catch (\Exception $e) {
if ($e->getCode() === "23000") {
$message = "A note already exists for this service";
} else {
$message = "Error inserting note";
}
return redirect()->route('notes.create')
->withInput($request->input())->with('error', $message);
}
Cache::forget('all_notes');
return redirect()->route('notes.index')
->with('success', 'Note created successfully.');
}
public function edit(Note $note)
{
$note = Note::note($note->service_id);
$servers = Server::all();
$shareds = Shared::all();
$resellers = Reseller::all();
$domains = Domains::all();
$dns = DNS::all();
$ips = IPs::all();
return view('notes.edit', compact(['note', 'servers', 'shareds', 'resellers', 'domains', 'dns', 'ips']));
}
public function update(Request $request, Note $note)
{
$request->validate([
'service_id' => 'required|string|size:8',
'note' => 'required|string'
]);
$note->update([
'service_id' => $request->service_id,
'note' => $request->note
]);
Cache::forget('all_notes');
Cache::forget("note.$note->service_id");
return redirect()->route('notes.index')
->with('success', 'Note was updated successfully.');
}
public function show(Note $note)
{
$note = Note::note($note->service_id);
return view('notes.show', compact(['note']));
}
public function destroy(Note $note)
{
if ($note->delete()) {
Cache::forget("all_notes");
Cache::forget("note.$note->service_id");
return redirect()->route('notes.index')
->with('success', 'Note was deleted successfully.');
}
return redirect()->route('notes.index')
->with('error', 'Note was not deleted.');
}
}

View File

@ -25,4 +25,10 @@ class DNS extends Model
return DB::table('d_n_s')->count(); return DB::table('d_n_s')->count();
}); });
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View File

@ -56,4 +56,9 @@ class Domains extends Model
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id'); return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View File

@ -47,4 +47,9 @@ class IPs extends Model
}); });
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

66
app/Models/Note.php Normal file
View File

@ -0,0 +1,66 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Session;
class Note extends Model
{
use HasFactory;
public $incrementing = false;
protected $table = 'notes';
protected $keyType = 'string';
protected $fillable = ['id', 'service_id', 'note'];
public static function note(string $service_id): Note
{
return Cache::remember("note.$service_id", now()->addMonth(1), function () use ($service_id) {
return self::where('service_id', $service_id)->with(['server', 'shared', 'reseller', 'domain', 'dns', 'ip'])->first();
});
}
public static function allNotes()
{
return Cache::remember("all_notes", now()->addMonth(1), function () {
return self::with(['server', 'shared', 'reseller', 'domain', 'dns', 'ip'])->orderBy('created_at', 'desc')->get();
});
}
public function server(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Server::class, 'service_id', 'id');
}
public function shared(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Shared::class, 'service_id', 'id');
}
public function reseller(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Reseller::class, 'service_id', 'id');
}
public function domain(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Domains::class, 'service_id', 'id');
}
public function dns(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(DNS::class, 'service_id', 'id');
}
public function ip(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(IPs::class, 'service_id', 'id');
}
}

View File

@ -78,4 +78,9 @@ class Reseller extends Model
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id'); return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View File

@ -234,4 +234,9 @@ class Server extends Model
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id'); return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View File

@ -78,4 +78,9 @@ class Shared extends Model
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id'); return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View File

@ -88,6 +88,12 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-12 col-lg-6">
@if(isset($dns->note))
<p class="font-bold text-muted mt-3 mb-1 pb-0">Note:</p>
<p class="pt-0">{{$dns->note->note}}</p>
@endif
</div>
</div> </div>
<a href="{{ route('dns.index') }}" <a href="{{ route('dns.index') }}"
class="btn btn-success btn-sm mx-2"> class="btn btn-success btn-sm mx-2">

View File

@ -85,6 +85,12 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-12 col-lg-6">
@if(isset($domain_info->note))
<p class="font-bold text-muted mt-3 mb-1 pb-0">Note:</p>
<p class="pt-0">{{$domain_info->note->note}}</p>
@endif
</div>
</div> </div>
<x-back-btn> <x-back-btn>
<x-slot name="route">{{ route('domains.index') }}</x-slot> <x-slot name="route">{{ route('domains.index') }}</x-slot>

View File

@ -38,6 +38,7 @@
<li><a class="dropdown-item" href="{{route('providers.index')}}">Providers</a></li> <li><a class="dropdown-item" href="{{route('providers.index')}}">Providers</a></li>
<li><a class="dropdown-item" href="{{route('seedboxes.index')}}">Seedboxes</a></li> <li><a class="dropdown-item" href="{{route('seedboxes.index')}}">Seedboxes</a></li>
<li><a class="dropdown-item" href="{{route('yabs.index')}}">YABS</a></li> <li><a class="dropdown-item" href="{{route('yabs.index')}}">YABS</a></li>
<li><a class="dropdown-item" href="{{route('notes.index')}}">Notes</a></li>
<li><a class="dropdown-item" href="{{route('settings.index')}}">Settings</a></li> <li><a class="dropdown-item" href="{{route('settings.index')}}">Settings</a></li>
<li><a class="dropdown-item" href="{{route('account.index')}}">Account</a></li> <li><a class="dropdown-item" href="{{route('account.index')}}">Account</a></li>
</ul> </ul>

View File

@ -0,0 +1,67 @@
@section("title", "Add a note")
<x-app-layout>
<x-slot name="header">
{{ __('Create a note') }}
</x-slot>
<div class="container">
<x-card class="shadow mt-3">
<x-back-button>
<x-slot name="href">{{ route('notes.index') }}</x-slot>
Go back
</x-back-button>
<x-response-alerts></x-response-alerts>
<form action="{{ route('notes.store') }}" method="POST">
@csrf
<div class="row">
<div class="col-12 mb-4">
<textarea class="form-control" id="note" name="note" rows="6">{{ old('note') }}</textarea>
</div>
</div>
<div class="row">
<p>This note is for:</p>
<div class="col-12 col-md-6 mb-3">
<div class="input-group">
<div class="input-group-prepend"><span class="input-group-text">Service</span></div>
<select class="form-control" name="service_id">
@foreach ($servers as $server)
<option value="{{ $server['id'] }}">
{{ $server['hostname'] }} (Server)
</option>
@endforeach
@foreach ($shareds as $shared)
<option value="{{ $shared['id'] }}">
{{ $shared['main_domain'] }} (Shared)
</option>
@endforeach
@foreach ($resellers as $reseller)
<option value="{{ $reseller['id'] }}">
{{ $reseller['main_domain'] }} (Reseller)
</option>
@endforeach
@foreach ($domains as $seed_box)
<option value="{{ $seed_box['id'] }}">
{{ $seed_box['domain'] }}.{{ $seed_box['extension'] }} (Domain)
</option>
@endforeach
@foreach ($dns as $dn)
<option value="{{ $dn['id'] }}">
{{ $dn['dns_type'] }} {{ $dn['hostname'] }} {{ $dn['address'] }} (DNS)
</option>
@endforeach
@foreach ($ips as $ip)
<option value="{{ $ip['id'] }}">
{{ $ip['address'] }} (IP)
</option>
@endforeach
</select></div>
</div>
</div>
<div class="row">
<div class="col-12 col-lg-4">
<x-submit-button>Create note</x-submit-button>
</div>
</div>
</form>
</x-card>
</div>
</x-app-layout>

View File

@ -0,0 +1,74 @@
@section("title", "Edit note")
<x-app-layout>
<x-slot name="header">
{{ __('Edit note') }}
</x-slot>
<div class="container">
<x-card class="shadow mt-3">
<x-back-button>
<x-slot name="href">{{ route('notes.index') }}</x-slot>
Go back
</x-back-button>
<x-response-alerts></x-response-alerts>
<form action="{{ route('notes.update', $note->id) }}" method="POST">
@csrf
@method('PUT')
<div class="row">
<div class="col-12 mb-4">
<textarea class="form-control" id="note" name="note" rows="6">{{ $note->note }}</textarea>
</div>
</div>
<div class="row">
<p>This note is for:</p>
<div class="col-12 col-md-6 mb-3">
<div class="input-group">
<div class="input-group-prepend"><span class="input-group-text">Service</span></div>
<select class="form-control" name="service_id">
@foreach ($servers as $server)
<option value="{{ $server['id'] }}"
@if ($server['id'] === $note->service_id) selected @endif>
{{ $server['hostname'] }} (Server)
</option>
@endforeach
@foreach ($shareds as $shared)
<option value="{{ $shared['id'] }}"
@if ($shared['id'] === $note->service_id) selected @endif>
{{ $shared['main_domain'] }} (Shared)
</option>
@endforeach
@foreach ($resellers as $reseller)
<option value="{{ $reseller['id'] }}"
@if ($reseller['id'] === $note->service_id) selected @endif>
{{ $reseller['main_domain'] }} (Reseller)
</option>
@endforeach
@foreach ($domains as $seed_box)
<option value="{{ $seed_box['id'] }}"
@if ($seed_box['id'] === $note->service_id) selected @endif>
{{ $seed_box['domain'] }}.{{ $seed_box['extension'] }} (Domain)
</option>
@endforeach
@foreach ($dns as $dn)
<option value="{{ $dn['id'] }}"
@if ($dn['id'] === $note->service_id) selected @endif>
{{ $dn['dns_type'] }}.{{ $dn['hostname'] }} (DNS)
</option>
@endforeach
@foreach ($ips as $ip)
<option value="{{ $ip['id'] }}"
@if ($ip['id'] === $note->service_id) selected @endif>
{{ $ip['address'] }} (IP)
</option>
@endforeach
</select></div>
</div>
</div>
<div class="row">
<div class="col-12 col-lg-4">
<x-submit-button>Update note</x-submit-button>
</div>
</div>
</form>
</x-card>
</div>
</x-app-layout>

View File

@ -0,0 +1,90 @@
@section('title', 'Notes')
<x-app-layout>
<x-slot name="header">
{{ __('Notes') }}
</x-slot>
<div class="container" id="app">
<x-delete-confirm-modal></x-delete-confirm-modal>
<x-card class="shadow mt-3">
<a href="{{ route('notes.create') }}" class="btn btn-primary mb-3">Add a note</a>
<x-response-alerts></x-response-alerts>
<div class="table-responsive">
<table class="table table-bordered">
<thead class="table-light">
<tr>
<th class="text-nowrap">Service</th>
<th class="text-nowrap">Type</th>
<th class="text-nowrap">Note Preview</th>
<th class="text-nowrap">Actions</th>
</tr>
</thead>
<tbody>
@if(!empty($notes[0]))
@foreach($notes as $n)
<tr>
<td class="text-nowrap">
@if(!is_null($n->server))
{{$n->server->hostname}}
@elseif(!is_null($n->shared))
{{$n->shared->main_domain}}
@elseif(!is_null($n->reseller))
{{$n->reseller->main_domain}}
@elseif(!is_null($n->domain))
{{$n->domain->domain}}.{{$n->domain->extension}}
@elseif(!is_null($n->dns))
{{$n->dns->dns_type}} {{$n->dns->hostname}}
@elseif(!is_null($n->ip))
{{$n->ip->address}}
@endif
</td>
<td class="text-nowrap">
@if(!is_null($n->server))
SERVER
@elseif(!is_null($n->shared))
SHARED
@elseif(!is_null($n->reseller))
RESELLER
@elseif(!is_null($n->domain))
DOMAIN
@elseif(!is_null($n->dns))
DNS
@elseif(!is_null($n->ip))
IP
@endif
</td>
<td class="text-nowrap">{{strlen($n->note) > 80 ? substr($n->note,0,80)."" : $n->note}}</td>
<td class="text-nowrap">
<form action="{{ route('notes.destroy', $n->id) }}" method="POST">
<a href="{{ route('notes.edit', $n->id) }}"
class="text-body mx-1">
<i class="fas fa-pen" title="edit"></i></a>
<a href="{{ route('notes.show', $n->id) }}"
class="text-body mx-1">
<i class="fas fa-eye" title="view"></i></a>
@csrf
@method('DELETE')
<i class="fas fa-trash text-danger ms-3" @click="confirmDeleteModal"
id="{{$n->id}}"
title="{{strlen($n->note) > 24 ? substr($n->note,0,24)."" : $n->note}}"></i>
</form>
</td>
</tr>
@endforeach
@else
<tr>
<td class="border text-red-500">No notes found.</td>
<td></td>
<td></td>
<td></td>
</tr>
@endif
</tbody>
</table>
</div>
</x-card>
<x-details-footer></x-details-footer>
</div>
<x-modal-delete-script>
<x-slot name="uri">notes</x-slot>
</x-modal-delete-script>
</x-app-layout>

View File

@ -0,0 +1,40 @@
@section("title", "Note $note->id")
<x-app-layout>
<x-slot name="header">
{{ __('Note') }}
</x-slot>
<div class="container">
<x-card class="shadow mt-3">
<div class="row">
<div class="col-12 mb-2">
<h2>
@if(!is_null($note->server))
{{$note->server->hostname}} (server)
@elseif(!is_null($note->shared))
{{$note->shared->main_domain}} (shared)
@elseif(!is_null($note->reseller))
{{$note->reseller->main_domain}} (reseller)
@elseif(!is_null($note->domain))
{{$note->domain->domain}}.{{$note->domain->extension}} (domain)
@elseif(!is_null($note->dns))
{{$note->dns->dns_type}} {{$note->dns->hostname}} (DNS)
@elseif(!is_null($note->ip))
{{$note->ip->address}} (IP)
@endif
</h2>
</div>
</div>
<div class="row mb-4">
<div class="col-12 px-lg-4">
<code>{{$note->note}}</code>
</div>
</div>
<x-back-btn>
<x-slot name="route">{{ route('notes.index') }}</x-slot>
</x-back-btn>
<x-edit-btn>
<x-slot name="route">{{ route('notes.edit', $note->id) }}</x-slot>
</x-edit-btn>
</x-card>
</div>
</x-app-layout>

View File

@ -133,6 +133,12 @@
<td class="px-2 py-2 font-bold text-muted">FTP Limit</td> <td class="px-2 py-2 font-bold text-muted">FTP Limit</td>
<td>{{$reseller->ftp_limit}}</td> <td>{{$reseller->ftp_limit}}</td>
</tr> </tr>
@if(isset($reseller->note))
<tr>
<td class="px-2 py-2 font-bold text-muted">Note:</td>
<td>{{$reseller->note->note}}</td>
</tr>
@endif
</tbody> </tbody>
</table> </table>

View File

@ -210,6 +210,10 @@
@endif @endif
</div> </div>
<p id="yabs_code" class="d-none pt-3"><code>curl -sL yabs.sh | bash -s -- -s "{{route('api.store-yabs', [$server_data->id, \Illuminate\Support\Facades\Auth::user()->api_token])}}"</code></p> <p id="yabs_code" class="d-none pt-3"><code>curl -sL yabs.sh | bash -s -- -s "{{route('api.store-yabs', [$server_data->id, \Illuminate\Support\Facades\Auth::user()->api_token])}}"</code></p>
@if(isset($server_data->note))
<p class="font-bold text-muted mt-3 mb-1 pb-0">Note:</p>
<p class="pt-0">{{$server_data->note->note}}</p>
@endif
</div> </div>
</x-card> </x-card>
<x-details-footer></x-details-footer> <x-details-footer></x-details-footer>

View File

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="'col-12 col-lg-6"> <div class="col-12 col-lg-6">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-borderless text-nowrap"> <table class="table table-borderless text-nowrap">
<tbody> <tbody>
@ -97,7 +97,7 @@
</table> </table>
</div> </div>
</div> </div>
<div class="'col-12 col-lg-6"> <div class="col-12 col-lg-6">
<table class="table table-borderless"> <table class="table table-borderless">
<tbody> <tbody>
<tr> <tr>
@ -128,6 +128,12 @@
<td class="px-2 py-2 font-bold text-muted">FTP Limit</td> <td class="px-2 py-2 font-bold text-muted">FTP Limit</td>
<td>{{$shared->ftp_limit}}</td> <td>{{$shared->ftp_limit}}</td>
</tr> </tr>
@if(isset($shared->note))
<tr>
<td class="px-2 py-2 font-bold text-muted">Note:</td>
<td>{{$shared->note->note}}</td>
</tr>
@endif
</tbody> </tbody>
</table> </table>

View File

@ -7,6 +7,7 @@ use App\Http\Controllers\IPsController;
use App\Http\Controllers\LabelsController; use App\Http\Controllers\LabelsController;
use App\Http\Controllers\LocationsController; use App\Http\Controllers\LocationsController;
use App\Http\Controllers\MiscController; use App\Http\Controllers\MiscController;
use App\Http\Controllers\NoteController;
use App\Http\Controllers\OsController; use App\Http\Controllers\OsController;
use App\Http\Controllers\ProvidersController; use App\Http\Controllers\ProvidersController;
use App\Http\Controllers\ResellerController; use App\Http\Controllers\ResellerController;
@ -64,6 +65,8 @@ Route::resource('shared', SharedController::class)->middleware(['auth']);
Route::resource('yabs', YabsController::class)->middleware(['auth']); Route::resource('yabs', YabsController::class)->middleware(['auth']);
Route::resource('notes', NoteController::class)->middleware(['auth']);
Route::get('yabs/{yab}/json', 'App\Http\Controllers\YabsController@yabsToJson')->middleware(['auth'])->name('yabs.json'); Route::get('yabs/{yab}/json', 'App\Http\Controllers\YabsController@yabsToJson')->middleware(['auth'])->name('yabs.json');
Route::get('yabs-compare-choose', 'App\Http\Controllers\YabsController@chooseYabsCompare')->middleware(['auth'])->name('yabs.compare-choose'); Route::get('yabs-compare-choose', 'App\Http\Controllers\YabsController@chooseYabsCompare')->middleware(['auth'])->name('yabs.compare-choose');