diff --git a/app/Http/Controllers/OrganizationController.php b/app/Http/Controllers/OrganizationController.php index bd8b9647de45d538f5fd8ea1904f9eb0d0ac5500..e944749072ff7442e8db796840ef44f8eec80337 100644 --- a/app/Http/Controllers/OrganizationController.php +++ b/app/Http/Controllers/OrganizationController.php @@ -77,12 +77,6 @@ class OrganizationController extends Controller $this->authorize("show", $organization); return view("organization.show", array("organization" => $organization)); } - - public function rack(Organization $organization) - { - $this->authorize("show", $organization); - return view("organization.rack", ["organization" => $organization]); - } public function dashboard(Organization $organization) { diff --git a/app/Http/Controllers/RackController.php b/app/Http/Controllers/RackController.php new file mode 100644 index 0000000000000000000000000000000000000000..a276dbeb33f3597ab0e994dba625f07afd31d295 --- /dev/null +++ b/app/Http/Controllers/RackController.php @@ -0,0 +1,66 @@ +<?php + +namespace App\Http\Controllers; + +use App\Rack; +use App\Organization; +use Illuminate\Http\Request; + +class RackController extends Controller +{ + /** + * Display a listing of the resource. + * + */ + public function index(Organization $organization) + { + $this->authorize("show", $organization); + return view("organization.rack", ["organization" => $organization]); + } + + /** + * Show the form for creating a new resource. + * + */ + public function create(Organization $organization) + { + return view("rack.edit", [ + "rack" => new Rack(), + "organization" => $organization]); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + */ + public function store(Organization $organization, Request $request) + { + return $this->save($organization, $request, new Rack()); + } + + public function save(Organization $organization, Request $request, Rack $rack) + { + $request->validate([ + "name" => "required|string", + "height" => "required|integer|min:1|max:50" + ]); + + $rack->name = $request->name; + $rack->height = $request->height; + $rack->organization_id = $organization->id; + $rack->save(); + + return redirect(action("RackController@index", ["organization" => $organization])); + } + + /** + * Remove the specified resource from storage. + * + * @param \App\Rack $rack + */ + public function destroy(Rack $rack) + { + // + } +} diff --git a/app/Http/Controllers/ServerController.php b/app/Http/Controllers/ServerController.php index 07ad995b1c88dd00a24a88b8f94929e3dd12f44c..c03c632d94eb953997186cd3f71113fec61deeac 100644 --- a/app/Http/Controllers/ServerController.php +++ b/app/Http/Controllers/ServerController.php @@ -22,6 +22,7 @@ class ServerController extends Controller 'name' => 'required|string|regex:/^[a-zA-Z0-9\s\-\.]+$/|max:255', "organization_id" => Rule::in(Auth::user()->organizations->modelKeys()), "description" => 'nullable|string', + "rack_id" => "required|integer", "size" => "nullable|int|min:0|max:48", "position" => "nullable|int|min:0|max:48"]; } @@ -94,6 +95,12 @@ class ServerController extends Controller $server->description = $request->description; $server->size = $request->size; $server->position = $request->position; + $server->rack_id = $request->rack_id; + + if ($server->rack_id == 0) { + $server->rack_id = null; + } + $server->save(); return redirect(action("ServerController@show", ["server" => $server])); diff --git a/app/Organization.php b/app/Organization.php index fdf3c54019e10a3e86e9c9eebc917f97a924dbce..a3dfdfb11d2feea667c4c88c69ed835713bbe1a5 100644 --- a/app/Organization.php +++ b/app/Organization.php @@ -43,12 +43,18 @@ class Organization extends Model public function users() { - return $this->belongsToMany("App\User"); + return $this->belongsToMany(User::class); } public function servers() { - return $this->hasMany("App\Server"); + return $this->hasMany(Server::class); + } + + + public function racks() + { + return $this->hasMany(Rack::class); } public function url() : string diff --git a/app/Rack.php b/app/Rack.php new file mode 100644 index 0000000000000000000000000000000000000000..b6ad5f77a536b2440dc1a6a5c58cd9424501957c --- /dev/null +++ b/app/Rack.php @@ -0,0 +1,13 @@ +<?php + +namespace App; + +use Illuminate\Database\Eloquent\Model; + +class Rack extends Model +{ + public function servers() + { + return $this->hasMany(Server::class); + } +} diff --git a/app/Server.php b/app/Server.php index df4267431c5a31ebc5351abbfafd0c353d1ae354..bcac738220a873d2b6d941adeddcecb932dc6566 100644 --- a/app/Server.php +++ b/app/Server.php @@ -199,4 +199,9 @@ class Server extends Model $converter = new CommonMarkConverter(); return $converter->convertToHtml($this->description ?? ''); } + + public function rack() + { + return $this->belongsTo(Rack::class); + } } diff --git a/database/migrations/2024_04_04_110616_create_racks_table.php b/database/migrations/2024_04_04_110616_create_racks_table.php new file mode 100644 index 0000000000000000000000000000000000000000..28f1a344feba7c8acbad7606558896fabc2f6b1a --- /dev/null +++ b/database/migrations/2024_04_04_110616_create_racks_table.php @@ -0,0 +1,34 @@ +<?php + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +class CreateRacksTable extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('racks', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->timestamps(); + $table->integer("organization_id")->references("id")->on("organizations"); + $table->string("name"); + $table->integer("height"); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('racks'); + } +} diff --git a/database/migrations/2024_04_04_134753_servers_add_rack_id.php b/database/migrations/2024_04_04_134753_servers_add_rack_id.php new file mode 100644 index 0000000000000000000000000000000000000000..fa4fea8370eb9e9812a3b9151bb432fcab4ad254 --- /dev/null +++ b/database/migrations/2024_04_04_134753_servers_add_rack_id.php @@ -0,0 +1,35 @@ +<?php + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +class ServersAddRackId extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::table('servers', function (Blueprint $table) { + $table->bigInteger("rack_id") + ->nullable() + ->references("id")->on("servers") + ->onDelete('set null'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('servers', function (Blueprint $table) { + // + }); + } +} diff --git a/resources/views/organization/rack.blade.php b/resources/views/organization/rack.blade.php index a3d359e71eac5de85c1cc2db9a909f55cad8a5d1..ef11631e46f5b4501114ed7e731446dac3c9e976 100644 --- a/resources/views/organization/rack.blade.php +++ b/resources/views/organization/rack.blade.php @@ -1,20 +1,25 @@ @extends('layouts.app') @section('content') -<div class="container-fluid pb-4"> +<div class="container-fluid pb-4 text-center"> - <div class="rack size-42u"> - @for ($i = 0; $i < 42; $i++) - <div class="slot" style="bottom: {{ 2*$i }}rem"> + @foreach ($organization->racks as $rack) + <div class="rack size-{{ $rack->height + 1 }}u"> + <div class="slot" style="top: 0"> + {{ $rack->name }} + </div> + + @for ($i = 0; $i < $rack->height; $i++) + <div class="slot text-left" style="bottom: {{ 2*$i }}rem"> {{ $i + 1 }} </div> @endfor - @foreach ($organization->servers as $server) + @foreach ($rack->servers as $server) @if ($server->size == 0) @continue @endif - <div class="server size-{{ $server->size }}u" + <div class="server text-left size-{{ $server->size }}u" style="bottom: {{ 2*($server->position - 1) }}rem;"> <p> <a href="{{ $server->getUrlAttribute() }}" @@ -26,13 +31,6 @@ </div> @endforeach </div> - - <div class="rack size-12u"> - @for ($i = 0; $i < 12; $i++) - <div class="slot" style="bottom: {{ 2*$i }}rem"> - {{ $i + 1 }} - </div> - @endfor - </div> + @endforeach </div> @endsection diff --git a/resources/views/organization/show.blade.php b/resources/views/organization/show.blade.php index 12e51f90bd62c03260db35954955f5b17c3c7146..6af5ca944c6d7e9eb5f03afe23f636c62dd72527 100644 --- a/resources/views/organization/show.blade.php +++ b/resources/views/organization/show.blade.php @@ -30,7 +30,7 @@ </a> <a class="btn btn-primary btn-sm" - href="{{ action("OrganizationController@rack", ["organization" => $organization]) }}"> + href="{{ action("RackController@index", ["organization" => $organization]) }}"> <i class="fas fa-server"></i> Rack view </a> </p> diff --git a/resources/views/rack/edit.blade.php b/resources/views/rack/edit.blade.php new file mode 100644 index 0000000000000000000000000000000000000000..95d0e0475ee705204234727de76947542521cda0 --- /dev/null +++ b/resources/views/rack/edit.blade.php @@ -0,0 +1,58 @@ +@extends('layouts.app') + +@section('content') +<div class="container"> + <div class="card"> + <div class="card-header">Rack</div> + + <div class="card-body"> + @if (!$rack->exists) + <form method="POST" action="{{ action("RackController@store", ["organization" => $organization]) }}"> + @else + <form method="POST" + action="{{ action("RackController@update", ["rack" => $rack]) }}"> + {{ method_field("PUT") }} + @endif + {{ csrf_field() }} + + <div class="form-group"> + <label for="name">Name</label> + + <input id="name" type="text" + class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}" + name="name" + value="{{ old('name', $rack->name) }}" autofocus> + + @if ($errors->has('name')) + <span class="invalid-feedback"> + <strong>{{ $errors->first('name') }}</strong> + </span> + @endif + </div> + + <div class="form-group"> + <label for="height">Height</label> + + <input id="height" + type="number" min="1" max="50" step="1" + class="form-control{{ $errors->has('height') ? ' is-invalid' : '' }}" + name="height" + value="{{ old('height', $rack->height) }}" autofocus> + + @if ($errors->has('name')) + <span class="invalid-feedback"> + <strong>{{ $errors->first('name') }}</strong> + </span> + @endif + </div> + + <div class="form-group"> + <button type="submit" class="btn btn-primary btn-sm"> + <i class="fas fa-check"></i> Save + </button> + </div> + </form> + </div> + </div> +</div> +@endsection diff --git a/resources/views/server/edit.blade.php b/resources/views/server/edit.blade.php index 9781e8b0f72fef3a41b6b0f69a60d65cfd87fe0d..6b5e22a56ef3d3999dfc71874f4bc5762e1d6743 100644 --- a/resources/views/server/edit.blade.php +++ b/resources/views/server/edit.blade.php @@ -28,10 +28,9 @@ @foreach (Auth::user()->organizations as $organization) <option value="{{ $organization->id }}">{{ $organization->name }}</option> @endforeach - </select> - @if ($errors->has('name')) + @if ($errors->has('organization_id')) <span class="invalid-feedback"> <strong>{{ $errors->first('organization_id') }}</strong> </span> @@ -69,6 +68,26 @@ @endif </div> + <div class="form-group"> + <label for="rack_id">Rack</label> + + <select id="rack_id" + class="form-control{{ $errors->has('rack_id') ? ' is-invalid' : '' }}" + name="rack_id"> + + <option value="0">--</option> + @foreach ($organization->racks as $rack) + <option value="{{ $rack->id }}">{{ $rack->name }}</option> + @endforeach + </select> + + @if ($errors->has('organization_id')) + <span class="invalid-feedback"> + <strong>{{ $errors->first('organization_id') }}</strong> + </span> + @endif + </div> + <div class="form-group"> <label for="size">Form factor</label> diff --git a/resources/views/server/show.blade.php b/resources/views/server/show.blade.php index 255b1097e9a3612c4c9c3f5f8c8e5d0e79634dcf..cf6eda93307d6806ba3b33759d0778a95aff66c3 100644 --- a/resources/views/server/show.blade.php +++ b/resources/views/server/show.blade.php @@ -44,6 +44,16 @@ window.monitorServerToken = "{{ $server->read_token }}"; </p> <p>Uptime: {{ $server->info()->uptime() }}</p> + + @if (! is_null($server->rack_id)) + <p> + Rack + <b> + {{ $server->rack->name }}#{{ $server->position }} + [{{ $server->size }}u] + </b> + </p> + @endif </div> </div> diff --git a/routes/web.php b/routes/web.php index 3282999c41d29b5e802dacaa7d2b7172b31ce6ad..2a3e64e965bb0841b97cdec648b7e30f4fd4815f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -51,8 +51,10 @@ Route::get( 'app/organizations/{organization}/{token}/dashboard.json', 'OrganizationDashboardController@json' ); -Route::get('app/organizations/{organization}/rack', 'OrganizationController@rack'); + Route::resource('app/organizations', 'OrganizationController'); Route::resource("app/organizations.user", "OrganizationUserController")->only(["create", "store", "destroy"]); +Route::resource("app/organizations.rack", 'RackController')->only(["index", "create", "store", "destroy"]); Route::resource('app/servers', 'ServerController')->except(["index"]); + Route::get("app/records/{record}", "RecordController@show");