From 5d958dd177bde79dbc3ee3f99ccf6796e5d61b1c Mon Sep 17 00:00:00 2001 From: Benjamin Takats Date: Thu, 1 Dec 2022 17:03:52 +0100 Subject: [PATCH] nova updates --- app/Models/City.php | 2 +- app/Models/Lecturer.php | 20 ++++++++-- app/Models/Venue.php | 18 +++++++-- app/Nova/City.php | 6 +-- app/Nova/Country.php | 3 +- app/Nova/Course.php | 31 +++++++++++---- app/Nova/Lecturer.php | 38 ++++++++++++------ app/Nova/Venue.php | 21 +++++----- app/Policies/CityPolicy.php | 4 +- app/Policies/CoursePolicy.php | 6 +-- app/Policies/LecturerPolicy.php | 13 ++++-- app/Policies/VenuePolicy.php | 4 +- app/Providers/NovaServiceProvider.php | 2 +- composer.json | 5 ++- composer.lock | 57 ++++++++++++++++++++++++++- database/seeders/DatabaseSeeder.php | 6 +-- 16 files changed, 178 insertions(+), 58 deletions(-) diff --git a/app/Models/City.php b/app/Models/City.php index dc146327..a2497f1e 100644 --- a/app/Models/City.php +++ b/app/Models/City.php @@ -33,7 +33,7 @@ class City extends Model public function getSlugOptions(): SlugOptions { return SlugOptions::create() - ->generateSlugsFrom('name') + ->generateSlugsFrom(['country.code', 'name']) ->saveSlugsTo('slug') ->usingLanguage('de'); } diff --git a/app/Models/Lecturer.php b/app/Models/Lecturer.php index 97ba95f3..d56ea5e4 100644 --- a/app/Models/Lecturer.php +++ b/app/Models/Lecturer.php @@ -4,29 +4,41 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Spatie\Sluggable\HasSlug; +use Spatie\Sluggable\SlugOptions; class Lecturer extends Model { use HasFactory; + use HasSlug; /** * The attributes that aren't mass assignable. - * * @var array */ protected $guarded = []; /** * The attributes that should be cast to native types. - * * @var array */ protected $casts = [ - 'id' => 'integer', + 'id' => 'integer', 'team_id' => 'integer', - 'active' => 'boolean', + 'active' => 'boolean', ]; + /** + * Get the options for generating the slug. + */ + public function getSlugOptions(): SlugOptions + { + return SlugOptions::create() + ->generateSlugsFrom(['name']) + ->saveSlugsTo('slug') + ->usingLanguage('de'); + } + public function team(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Team::class); diff --git a/app/Models/Venue.php b/app/Models/Venue.php index c7ffbfd2..9a7defc3 100644 --- a/app/Models/Venue.php +++ b/app/Models/Venue.php @@ -4,28 +4,40 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Spatie\Sluggable\HasSlug; +use Spatie\Sluggable\SlugOptions; class Venue extends Model { use HasFactory; + use HasSlug; /** * The attributes that aren't mass assignable. - * * @var array */ protected $guarded = []; /** * The attributes that should be cast to native types. - * * @var array */ protected $casts = [ - 'id' => 'integer', + 'id' => 'integer', 'city_id' => 'integer', ]; + /** + * Get the options for generating the slug. + */ + public function getSlugOptions(): SlugOptions + { + return SlugOptions::create() + ->generateSlugsFrom(['city.slug', 'name',]) + ->saveSlugsTo('slug') + ->usingLanguage('de'); + } + public function city(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(City::class); diff --git a/app/Nova/City.php b/app/Nova/City.php index 4b611ff4..848f9f8f 100644 --- a/app/Nova/City.php +++ b/app/Nova/City.php @@ -21,7 +21,7 @@ class City extends Resource * * @var string */ - public static $title = 'id'; + public static $title = 'name'; /** * The columns that should be searched. @@ -30,6 +30,7 @@ class City extends Resource */ public static $search = [ 'id', + 'name', ]; /** @@ -47,11 +48,10 @@ class City extends Resource ->rules('required', 'string'), Text::make('Slug') - ->rules('required', 'string', 'unique:cities,slug'), + ->exceptOnForms(), BelongsTo::make('Country'), - ]; } diff --git a/app/Nova/Country.php b/app/Nova/Country.php index fd9457fd..3e5a9796 100644 --- a/app/Nova/Country.php +++ b/app/Nova/Country.php @@ -21,7 +21,7 @@ class Country extends Resource * * @var string */ - public static $title = 'id'; + public static $title = 'name'; /** * The columns that should be searched. @@ -30,6 +30,7 @@ class Country extends Resource */ public static $search = [ 'id', + 'name', ]; /** diff --git a/app/Nova/Course.php b/app/Nova/Course.php index c98a6ebd..27ed267c 100644 --- a/app/Nova/Course.php +++ b/app/Nova/Course.php @@ -2,55 +2,68 @@ namespace App\Nova; -use Laravel\Nova\Fields\ID; use Illuminate\Http\Request; -use Laravel\Nova\Fields\Text; use Laravel\Nova\Fields\BelongsTo; use Laravel\Nova\Fields\BelongsToMany; +use Laravel\Nova\Fields\Field; +use Laravel\Nova\Fields\ID; +use Laravel\Nova\Fields\Text; +use Laravel\Nova\Http\Requests\NovaRequest; +use ZiffMedia\NovaSelectPlus\SelectPlus; class Course extends Resource { /** * The model the resource corresponds to. - * * @var string */ public static $model = \App\Models\Course::class; /** * The single value that should be used to represent the resource when being displayed. - * * @var string */ public static $title = 'id'; /** * The columns that should be searched. - * * @var array */ public static $search = [ 'id', ]; + public static function relatableLecturers(NovaRequest $request, $query, Field $field) + { + if ($field instanceof BelongsTo) { + $query->where('team_id', $request->user()->current_team_id); + } + + return $query; + } + /** * Get the fields displayed by the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function fields(Request $request) { return [ - ID::make()->sortable(), + ID::make() + ->sortable(), Text::make('Name') ->rules('required', 'string'), BelongsTo::make('Lecturer'), - BelongsToMany::make('Categories'), + SelectPlus::make('Categories', 'categories', Category::class) + ->usingIndexLabel('name'), + BelongsToMany::make('Categories')->onlyOnDetail(), ]; } @@ -59,6 +72,7 @@ class Course extends Resource * Get the cards available for the request. * * @param \Illuminate\Http\Request $request + * * @return array */ public function cards(Request $request) @@ -70,6 +84,7 @@ class Course extends Resource * Get the filters available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function filters(Request $request) @@ -81,6 +96,7 @@ class Course extends Resource * Get the lenses available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function lenses(Request $request) @@ -92,6 +108,7 @@ class Course extends Resource * Get the actions available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function actions(Request $request) diff --git a/app/Nova/Lecturer.php b/app/Nova/Lecturer.php index dc6bbc9a..de209eee 100644 --- a/app/Nova/Lecturer.php +++ b/app/Nova/Lecturer.php @@ -2,60 +2,72 @@ namespace App\Nova; -use Laravel\Nova\Fields\ID; use Illuminate\Http\Request; -use Laravel\Nova\Fields\Text; -use Laravel\Nova\Fields\Boolean; use Laravel\Nova\Fields\BelongsTo; +use Laravel\Nova\Fields\Boolean; +use Laravel\Nova\Fields\Field; +use Laravel\Nova\Fields\ID; +use Laravel\Nova\Fields\Text; +use Laravel\Nova\Http\Requests\NovaRequest; class Lecturer extends Resource { /** * The model the resource corresponds to. - * * @var string */ public static $model = \App\Models\Lecturer::class; /** * The single value that should be used to represent the resource when being displayed. - * * @var string */ - public static $title = 'id'; + public static $title = 'name'; /** * The columns that should be searched. - * * @var array */ public static $search = [ 'id', + 'name', ]; + public static function relatableTeams(NovaRequest $request, $query, Field $field) + { + if ($field instanceof BelongsTo) { + $query->where('id', $request->user()->current_team_id); + } + + return $query; + } + /** * Get the fields displayed by the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function fields(Request $request) { return [ - ID::make()->sortable(), + ID::make() + ->sortable(), Text::make('Name') ->rules('required', 'string'), Text::make('Slug') - ->rules('required', 'string', 'unique:lecturers,slug'), + ->rules('required', 'string', 'unique:lecturers,slug') + ->exceptOnForms(), Boolean::make('Active') - ->rules('required'), + ->rules('required') + ->default(true), BelongsTo::make('Team'), - ]; } @@ -63,6 +75,7 @@ class Lecturer extends Resource * Get the cards available for the request. * * @param \Illuminate\Http\Request $request + * * @return array */ public function cards(Request $request) @@ -74,6 +87,7 @@ class Lecturer extends Resource * Get the filters available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function filters(Request $request) @@ -85,6 +99,7 @@ class Lecturer extends Resource * Get the lenses available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function lenses(Request $request) @@ -96,6 +111,7 @@ class Lecturer extends Resource * Get the actions available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function actions(Request $request) diff --git a/app/Nova/Venue.php b/app/Nova/Venue.php index 07f88ac7..acf17216 100644 --- a/app/Nova/Venue.php +++ b/app/Nova/Venue.php @@ -2,59 +2,58 @@ namespace App\Nova; -use Laravel\Nova\Fields\ID; use Illuminate\Http\Request; -use Laravel\Nova\Fields\Text; use Laravel\Nova\Fields\BelongsTo; +use Laravel\Nova\Fields\ID; +use Laravel\Nova\Fields\Text; class Venue extends Resource { /** * The model the resource corresponds to. - * * @var string */ public static $model = \App\Models\Venue::class; /** * The single value that should be used to represent the resource when being displayed. - * * @var string */ - public static $title = 'id'; + public static $title = 'name'; /** * The columns that should be searched. - * * @var array */ public static $search = [ 'id', + 'name', ]; /** * Get the fields displayed by the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function fields(Request $request) { return [ - ID::make()->sortable(), + ID::make() + ->sortable(), Text::make('Name') ->rules('required', 'string'), Text::make('Slug') - ->rules('required', 'string', 'unique:venues,slug'), + ->exceptOnForms(), Text::make('Street') ->rules('required', 'string'), BelongsTo::make('City'), - ]; } @@ -62,6 +61,7 @@ class Venue extends Resource * Get the cards available for the request. * * @param \Illuminate\Http\Request $request + * * @return array */ public function cards(Request $request) @@ -73,6 +73,7 @@ class Venue extends Resource * Get the filters available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function filters(Request $request) @@ -84,6 +85,7 @@ class Venue extends Resource * Get the lenses available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function lenses(Request $request) @@ -95,6 +97,7 @@ class Venue extends Resource * Get the actions available for the resource. * * @param \Illuminate\Http\Request $request + * * @return array */ public function actions(Request $request) diff --git a/app/Policies/CityPolicy.php b/app/Policies/CityPolicy.php index 2f8cc748..790d254b 100644 --- a/app/Policies/CityPolicy.php +++ b/app/Policies/CityPolicy.php @@ -30,7 +30,7 @@ class CityPolicy */ public function view(User $user, City $city) { - // + return $user->is_lecturer; } /** @@ -41,7 +41,7 @@ class CityPolicy */ public function create(User $user) { - // + return $user->is_lecturer; } /** diff --git a/app/Policies/CoursePolicy.php b/app/Policies/CoursePolicy.php index 2eaebe33..e3c83b5a 100644 --- a/app/Policies/CoursePolicy.php +++ b/app/Policies/CoursePolicy.php @@ -30,7 +30,7 @@ class CoursePolicy */ public function view(User $user, Course $course) { - // + return $user->is_lecturer; } /** @@ -41,7 +41,7 @@ class CoursePolicy */ public function create(User $user) { - // + return $user->is_lecturer; } /** @@ -53,7 +53,7 @@ class CoursePolicy */ public function update(User $user, Course $course) { - // + return $user->belongsToTeam($course->lecturer->team); } /** diff --git a/app/Policies/LecturerPolicy.php b/app/Policies/LecturerPolicy.php index a5d7178d..7077c33d 100644 --- a/app/Policies/LecturerPolicy.php +++ b/app/Policies/LecturerPolicy.php @@ -14,6 +14,7 @@ class LecturerPolicy * Determine whether the user can view any models. * * @param \App\Models\User $user + * * @return \Illuminate\Auth\Access\Response|bool */ public function viewAny(User $user) @@ -26,22 +27,24 @@ class LecturerPolicy * * @param \App\Models\User $user * @param \App\Models\Lecturer $lecturer + * * @return \Illuminate\Auth\Access\Response|bool */ public function view(User $user, Lecturer $lecturer) { - return false; + return $user->is_lecturer; } /** * Determine whether the user can create models. * * @param \App\Models\User $user + * * @return \Illuminate\Auth\Access\Response|bool */ public function create(User $user) { - // + return $user->is_lecturer; } /** @@ -49,11 +52,12 @@ class LecturerPolicy * * @param \App\Models\User $user * @param \App\Models\Lecturer $lecturer + * * @return \Illuminate\Auth\Access\Response|bool */ public function update(User $user, Lecturer $lecturer) { - // + return $user->belongsToTeam($lecturer->team); } /** @@ -61,6 +65,7 @@ class LecturerPolicy * * @param \App\Models\User $user * @param \App\Models\Lecturer $lecturer + * * @return \Illuminate\Auth\Access\Response|bool */ public function delete(User $user, Lecturer $lecturer) @@ -73,6 +78,7 @@ class LecturerPolicy * * @param \App\Models\User $user * @param \App\Models\Lecturer $lecturer + * * @return \Illuminate\Auth\Access\Response|bool */ public function restore(User $user, Lecturer $lecturer) @@ -85,6 +91,7 @@ class LecturerPolicy * * @param \App\Models\User $user * @param \App\Models\Lecturer $lecturer + * * @return \Illuminate\Auth\Access\Response|bool */ public function forceDelete(User $user, Lecturer $lecturer) diff --git a/app/Policies/VenuePolicy.php b/app/Policies/VenuePolicy.php index 24718f91..213f7e94 100644 --- a/app/Policies/VenuePolicy.php +++ b/app/Policies/VenuePolicy.php @@ -30,7 +30,7 @@ class VenuePolicy */ public function view(User $user, Venue $venue) { - // + return $user->is_lecturer; } /** @@ -41,7 +41,7 @@ class VenuePolicy */ public function create(User $user) { - // + return $user->is_lecturer; } /** diff --git a/app/Providers/NovaServiceProvider.php b/app/Providers/NovaServiceProvider.php index 4f9baf95..38226de6 100644 --- a/app/Providers/NovaServiceProvider.php +++ b/app/Providers/NovaServiceProvider.php @@ -39,8 +39,8 @@ class NovaServiceProvider extends NovaApplicationServiceProvider MenuSection::make('Schule', [ MenuItem::resource(City::class), - MenuItem::resource(Lecturer::class), MenuItem::resource(Venue::class), + MenuItem::resource(Lecturer::class), MenuItem::resource(Course::class), MenuItem::resource(Event::class), MenuItem::resource(Participant::class), diff --git a/composer.json b/composer.json index 837124b2..639b36fa 100644 --- a/composer.json +++ b/composer.json @@ -17,12 +17,13 @@ "laravel/sanctum": "^3.0", "laravel/tinker": "^2.7", "livewire/livewire": "^2.5", + "nova/start": "*", "rappasoft/laravel-livewire-tables": "^2.8", "spatie/laravel-google-fonts": "^1.2", "spatie/laravel-sluggable": "^3.4", "stijnvanouplines/blade-country-flags": "^1.0", "wireui/wireui": "^1.17", - "nova/start": "*" + "ziffmedia/nova-select-plus": "^2.0" }, "require-dev": { "fakerphp/faker": "^1.9.1", @@ -99,4 +100,4 @@ "url": "./nova-components/Start" } ] -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 53582072..e098c4d7 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "fe688c8ea9a0c69b1cff7d3876e83e4f", + "content-hash": "0946bfc7eeb16ba3f6719a28461cd673", "packages": [ { "name": "bacon/bacon-qr-code", @@ -7634,6 +7634,61 @@ } ], "time": "2022-11-28T17:38:50+00:00" + }, + { + "name": "ziffmedia/nova-select-plus", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/ziffmedia/nova-select-plus.git", + "reference": "99d3edca015ee9dcd79fb4855b7deacb98f31771" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ziffmedia/nova-select-plus/zipball/99d3edca015ee9dcd79fb4855b7deacb98f31771", + "reference": "99d3edca015ee9dcd79fb4855b7deacb98f31771", + "shasum": "" + }, + "require": { + "laravel/nova": "^4.0", + "php": "^7.3|^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "ZiffMedia\\NovaSelectPlus\\FieldServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "ZiffMedia\\NovaSelectPlus\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Schindler", + "email": "ralph.schindler@ziffmedia.com" + } + ], + "description": "A Nova select field for simple and complex select inputs", + "keywords": [ + "ajax", + "laravel", + "nova", + "select", + "vue-select" + ], + "support": { + "issues": "https://github.com/ziffmedia/nova-select-plus/issues", + "source": "https://github.com/ziffmedia/nova-select-plus/tree/v2.0.0" + }, + "time": "2022-08-29T18:16:54+00:00" } ], "packages-dev": [ diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 4296384f..907b65a9 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -36,6 +36,7 @@ class DatabaseSeeder extends Seeder 'email_verified_at' => now(), 'password' => bcrypt('1234'), 'remember_token' => Str::random(10), + 'is_lecturer' => true, ]); $team = Team::create([ 'name' => 'Admin Team', @@ -59,28 +60,23 @@ class DatabaseSeeder extends Seeder City::create([ 'country_id' => 1, 'name' => 'Füssen', - 'slug' => str('Füssen')->slug('-', 'de'), ]); City::create([ 'country_id' => 2, 'name' => 'Wien', - 'slug' => str('Wien')->slug('-', 'de'), ]); City::create([ 'country_id' => 3, 'name' => 'Zürich', - 'slug' => str('Zürich')->slug('-', 'de'), ]); Venue::create([ 'city_id' => 1, 'name' => 'The Blue Studio Coworking', - 'slug' => str('The Blue Studio Coworking')->slug('-', 'de'), 'street' => 'Teststraße 12', ]); Lecturer::create([ 'team_id' => 1, 'name' => 'Markus Turm', - 'slug' => str('Markus Turm')->slug('-', 'de'), 'active' => true, ]); $category = Category::create([