From ce972e66c60fc48f9ebdadfab7d99d1575efd16c Mon Sep 17 00:00:00 2001 From: HolgerHatGarKeineNode Date: Mon, 27 Feb 2023 18:37:23 +0100 Subject: [PATCH] new forms added for courses --- app/Http/Controllers/Api/CourseController.php | 74 ++++++++++ app/Http/Livewire/City/Form/CityForm.php | 7 +- .../Form/ContentCreatorForm.php | 1 - app/Http/Livewire/Meetup/Form/MeetupForm.php | 6 +- .../Livewire/School/Form/CourseEventForm.php | 67 +++++++++ app/Http/Livewire/School/Form/CourseForm.php | 103 ++++++++++++++ app/Http/Livewire/Tables/CourseTable.php | 4 +- app/Http/Livewire/Tables/EventTable.php | 1 + app/Models/Lecturer.php | 12 +- app/Nova/Course.php | 9 +- app/Nova/CourseEvent.php | 6 + app/Nova/Episode.php | 1 - app/Policies/CoursePolicy.php | 2 +- ...73229_change_team_id_on_lecturer_table.php | 26 ++++ database/seeders/DatabaseSeeder.php | 4 - .../areas/toolbar-left-end.blade.php | 2 +- .../views/columns/courses/action.blade.php | 26 +++- .../courses/areas/toolbar-left-end.blade.php | 2 +- .../views/columns/events/action.blade.php | 16 ++- .../views/columns/meetups/action.blade.php | 18 +-- .../frontend/navigation/courses.blade.php | 4 +- .../meetup/form/meetup-event-form.blade.php | 2 +- .../meetup/form/meetup-form.blade.php | 2 +- .../news/form/news-article-form.blade.php | 16 +-- .../school/form/course-event-form.blade.php | 127 ++++++++++++++++++ .../school/form/course-form.blade.php | 107 +++++++++++++++ routes/api.php | 1 + routes/web.php | 15 +++ 28 files changed, 612 insertions(+), 49 deletions(-) create mode 100644 app/Http/Controllers/Api/CourseController.php create mode 100644 app/Http/Livewire/School/Form/CourseEventForm.php create mode 100644 app/Http/Livewire/School/Form/CourseForm.php create mode 100644 database/migrations/2023_02_27_173229_change_team_id_on_lecturer_table.php create mode 100644 resources/views/livewire/school/form/course-event-form.blade.php create mode 100644 resources/views/livewire/school/form/course-form.blade.php diff --git a/app/Http/Controllers/Api/CourseController.php b/app/Http/Controllers/Api/CourseController.php new file mode 100644 index 00000000..3e0e0813 --- /dev/null +++ b/app/Http/Controllers/Api/CourseController.php @@ -0,0 +1,74 @@ +select('id', 'name', ) + ->orderBy('name') + ->when($request->has('user_id'), + fn(Builder $query) => $query->where('created_by', $request->user_id)) + ->when( + $request->search, + fn (Builder $query) => $query + ->where('name', 'ilike', "%{$request->search}%") + ) + ->when( + $request->exists('selected'), + fn (Builder $query) => $query->whereIn('id', + $request->input('selected', [])), + fn (Builder $query) => $query->limit(10) + ) + ->get() + ->map(function (Course $course) { + $course->image = $course->getFirstMediaUrl('logo', + 'thumb'); + + return $course; + }); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + */ + public function show(Course $course) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, Course $course) + { + // + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Course $course) + { + // + } +} diff --git a/app/Http/Livewire/City/Form/CityForm.php b/app/Http/Livewire/City/Form/CityForm.php index 733ac3f4..7be7187f 100644 --- a/app/Http/Livewire/City/Form/CityForm.php +++ b/app/Http/Livewire/City/Form/CityForm.php @@ -3,6 +3,7 @@ namespace App\Http\Livewire\City\Form; use App\Models\City; +use Illuminate\Validation\Rule; use Livewire\Component; class CityForm extends Component @@ -21,7 +22,11 @@ class CityForm extends Component { return [ 'city.country_id' => 'required', - 'city.name' => 'required|string', + 'city.name' => [ + 'required', + Rule::unique('cities', 'name') + ->ignore($this->city), + ], 'city.longitude' => 'required', 'city.latitude' => 'required', ]; diff --git a/app/Http/Livewire/ContentCreator/Form/ContentCreatorForm.php b/app/Http/Livewire/ContentCreator/Form/ContentCreatorForm.php index 8040426a..2ad42ea8 100644 --- a/app/Http/Livewire/ContentCreator/Form/ContentCreatorForm.php +++ b/app/Http/Livewire/ContentCreator/Form/ContentCreatorForm.php @@ -47,7 +47,6 @@ class ContentCreatorForm extends Component $this->lecturer = new Lecturer([ 'intro' => '', 'active' => true, - 'team_id' => true, ]); } if (!$this->fromUrl) { diff --git a/app/Http/Livewire/Meetup/Form/MeetupForm.php b/app/Http/Livewire/Meetup/Form/MeetupForm.php index 888ddd33..04207ac0 100644 --- a/app/Http/Livewire/Meetup/Form/MeetupForm.php +++ b/app/Http/Livewire/Meetup/Form/MeetupForm.php @@ -33,7 +33,11 @@ class MeetupForm extends Component 'image' => [Rule::requiredIf(!$this->meetup->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'], 'meetup.city_id' => 'required', - 'meetup.name' => 'required', + 'meetup.name' => [ + 'required', + Rule::unique('meetups', 'name') + ->ignore($this->meetup), + ], 'meetup.community' => 'required', 'meetup.telegram_link' => 'string|nullable|required_without_all:meetup.webpage,meetup.nostr,meetup.twitter_username,meetup.matrix_group', 'meetup.intro' => 'string|nullable', diff --git a/app/Http/Livewire/School/Form/CourseEventForm.php b/app/Http/Livewire/School/Form/CourseEventForm.php new file mode 100644 index 00000000..57c5ac98 --- /dev/null +++ b/app/Http/Livewire/School/Form/CourseEventForm.php @@ -0,0 +1,67 @@ + [ + 'except' => null, + ], + ]; + + public function rules() + { + return [ + 'courseEvent.course_id' => 'required', + 'courseEvent.venue_id' => 'required', + 'courseEvent.from' => 'required', + 'courseEvent.to' => 'required', + 'courseEvent.link' => 'required', + ]; + } + + public function mount() + { + if (!$this->courseEvent) { + $this->courseEvent = new CourseEvent([]); + } elseif ( + !auth() + ->user() + ->can('update', $this->courseEvent) + ) { + abort(403); + } + if (!$this->fromUrl) { + $this->fromUrl = url()->previous(); + } + } + + public function submit() + { + $this->validate(); + $this->courseEvent->save(); + + return redirect($this->fromUrl); + } + + public function render() + { + return view('livewire.school.form.course-event-form'); + } +} diff --git a/app/Http/Livewire/School/Form/CourseForm.php b/app/Http/Livewire/School/Form/CourseForm.php new file mode 100644 index 00000000..84f2fbad --- /dev/null +++ b/app/Http/Livewire/School/Form/CourseForm.php @@ -0,0 +1,103 @@ + [ + 'except' => null, + ], + ]; + + public function rules() + { + return [ + 'image' => [Rule::requiredIf(!$this->course->id), 'nullable', 'mimes:jpeg,png,jpg,gif', 'max:10240'], + + 'course.lecturer_id' => 'required', + 'course.name' => [ + 'required', + Rule::unique('courses', 'name') + ->ignore($this->course), + ], + 'course.description' => 'string|nullable', + ]; + } + + public function mount() + { + if (!$this->course) { + $this->course = new Course([ + 'description' => '', + ]); + } elseif ( + !auth() + ->user() + ->can('update', $this->course) + ) { + abort(403); + } + if (!$this->fromUrl) { + $this->fromUrl = url()->previous(); + } + } + + public function submit() + { + $this->validate(); + $this->course->save(); + + $this->course->syncTagsWithType( + $this->selectedTags, + 'course' + ); + + if ($this->image) { + $this->course->addMedia($this->image) + ->usingFileName(md5($this->image->getClientOriginalName()).'.'.$this->image->getClientOriginalExtension()) + ->toMediaCollection('logo'); + } + + return redirect($this->fromUrl); + } + + public function selectTag($name) + { + $selectedTags = collect($this->selectedTags); + if ($selectedTags->contains($name)) { + $selectedTags = $selectedTags->filter(fn($tag) => $tag !== $name); + } else { + $selectedTags->push($name); + } + $this->selectedTags = $selectedTags->values() + ->toArray(); + } + + public function render() + { + return view('livewire.school.form.course-form', [ + 'tags' => Tag::query() + ->where('type', 'course') + ->get(), + ]); + } +} diff --git a/app/Http/Livewire/Tables/CourseTable.php b/app/Http/Livewire/Tables/CourseTable.php index 70b2c3a4..ea044c5d 100644 --- a/app/Http/Livewire/Tables/CourseTable.php +++ b/app/Http/Livewire/Tables/CourseTable.php @@ -18,7 +18,7 @@ class CourseTable extends DataTableComponent public function configure(): void { $this->setPrimaryKey('id') - ->setAdditionalSelects(['id']) + ->setAdditionalSelects(['courses.id', 'courses.created_by']) ->setThAttributes(function (Column $column) { return [ 'class' => 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider dark:bg-gray-800 dark:text-gray-400', @@ -101,7 +101,7 @@ class CourseTable extends DataTableComponent 'tags', ]) ->withCount([ - 'courseEvents', + 'courseEvents' => fn($query) => $query->where('course_events.from', '>', now()), ]) ->whereHas('courseEvents.venue.city.country', fn ($query) => $query->where('countries.code', $this->country)) diff --git a/app/Http/Livewire/Tables/EventTable.php b/app/Http/Livewire/Tables/EventTable.php index 854a62ea..f5a3c9ad 100644 --- a/app/Http/Livewire/Tables/EventTable.php +++ b/app/Http/Livewire/Tables/EventTable.php @@ -29,6 +29,7 @@ class EventTable extends DataTableComponent ->setDefaultSort('from', 'asc') ->setAdditionalSelects([ 'course_events.id', + 'course_events.created_by', 'course_id', 'venue_id', ]) diff --git a/app/Models/Lecturer.php b/app/Models/Lecturer.php index 99633ea4..aeed16f1 100644 --- a/app/Models/Lecturer.php +++ b/app/Models/Lecturer.php @@ -23,31 +23,25 @@ class Lecturer extends Model implements HasMedia /** * 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', - 'team_id' => 'integer', - 'active' => 'boolean', + 'id' => 'integer', + 'active' => 'boolean', ]; protected static function booted() { static::creating(function ($model) { - if (! $model->created_by) { + if (!$model->created_by) { $model->created_by = auth()->id(); } - if (! $model->team_id) { - $model->team_id = auth()->user()->current_team_id; - } }); } diff --git a/app/Nova/Course.php b/app/Nova/Course.php index 1e9e918b..0cb456ae 100644 --- a/app/Nova/Course.php +++ b/app/Nova/Course.php @@ -42,6 +42,13 @@ class Course extends Resource 'name', ]; + public static $with = [ + 'lecturer.team', + 'categories', + 'tags', + 'createdBy', + ]; + public static function label() { return __('Course'); @@ -55,7 +62,7 @@ class Course extends Resource public static function relatableLecturers(NovaRequest $request, $query, Field $field) { if ($field instanceof BelongsTo) { - $query->where('team_id', $request->user()->current_team_id); + $query->where('created_by', $request->user()->id); } return $query; diff --git a/app/Nova/CourseEvent.php b/app/Nova/CourseEvent.php index 21b27b68..e4b0ad60 100644 --- a/app/Nova/CourseEvent.php +++ b/app/Nova/CourseEvent.php @@ -31,6 +31,12 @@ class CourseEvent extends Resource 'course.name', ]; + public static $with = [ + 'course.lecturer.team', + 'venue', + 'createdBy', + ]; + public function title() { return $this->from.' - '.$this->venue->name.' - '.$this->course->name; diff --git a/app/Nova/Episode.php b/app/Nova/Episode.php index f44a6356..a6199726 100644 --- a/app/Nova/Episode.php +++ b/app/Nova/Episode.php @@ -39,7 +39,6 @@ class Episode extends Resource if ($request->tags) { if ($model->data['link']) { $lecturer = \App\Models\Lecturer::updateOrCreate(['name' => $model->podcast->title], [ - 'team_id' => 1, 'active' => true, 'website' => $model->podcast->link, ]); diff --git a/app/Policies/CoursePolicy.php b/app/Policies/CoursePolicy.php index b6ac1fcf..f4d1fb89 100644 --- a/app/Policies/CoursePolicy.php +++ b/app/Policies/CoursePolicy.php @@ -47,7 +47,7 @@ class CoursePolicy extends BasePolicy */ public function update(User $user, Course $course): bool { - return $user->belongsToTeam($course->lecturer->team) || $user->can((new \ReflectionClass($this))->getShortName().'.'.__FUNCTION__); + return $course->created_by === $user->id || $user->can((new \ReflectionClass($this))->getShortName().'.'.__FUNCTION__); } /** diff --git a/database/migrations/2023_02_27_173229_change_team_id_on_lecturer_table.php b/database/migrations/2023_02_27_173229_change_team_id_on_lecturer_table.php new file mode 100644 index 00000000..c82532cc --- /dev/null +++ b/database/migrations/2023_02_27_173229_change_team_id_on_lecturer_table.php @@ -0,0 +1,26 @@ +dropForeign('lecturers_team_id_foreign'); + $table->dropColumn('team_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 48b77d28..28e757d3 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -161,25 +161,21 @@ class DatabaseSeeder extends Seeder 'created_by' => 1, ]); Lecturer::create([ - 'team_id' => 1, 'name' => 'Markus Turm', 'active' => true, 'created_by' => 1, ]); Lecturer::create([ - 'team_id' => 1, 'name' => 'Beppo', 'active' => true, 'created_by' => 1, ]); Lecturer::create([ - 'team_id' => 1, 'name' => 'Helper', 'active' => true, 'created_by' => 1, ]); Lecturer::create([ - 'team_id' => 1, 'name' => 'Gigi', 'active' => true, 'created_by' => 1, diff --git a/resources/views/columns/course-events/areas/toolbar-left-end.blade.php b/resources/views/columns/course-events/areas/toolbar-left-end.blade.php index f43cf186..ded63854 100644 --- a/resources/views/columns/course-events/areas/toolbar-left-end.blade.php +++ b/resources/views/columns/course-events/areas/toolbar-left-end.blade.php @@ -1,5 +1,5 @@
- + {{ __('Register course date') }} diff --git a/resources/views/columns/courses/action.blade.php b/resources/views/columns/courses/action.blade.php index 87854c56..4960d92f 100644 --- a/resources/views/columns/courses/action.blade.php +++ b/resources/views/columns/courses/action.blade.php @@ -1,5 +1,23 @@ -
- - {{ __('Show dates') }} - +
+ @if($row->course_events_count > 0) +
+ + {{ __('Show dates') }} [{{ $row->course_events_count }}] + +
+ @else +
+ + {{ __('Show dates') }} + +
+ @endif + @can('update', $row) +
+ + + {{ __('Edit') }} + +
+ @endcan
diff --git a/resources/views/columns/courses/areas/toolbar-left-end.blade.php b/resources/views/columns/courses/areas/toolbar-left-end.blade.php index 3cf97901..0fcc2518 100644 --- a/resources/views/columns/courses/areas/toolbar-left-end.blade.php +++ b/resources/views/columns/courses/areas/toolbar-left-end.blade.php @@ -1,5 +1,5 @@
- + {{ __('Register course') }} diff --git a/resources/views/columns/events/action.blade.php b/resources/views/columns/events/action.blade.php index d436bf39..8a440b96 100644 --- a/resources/views/columns/events/action.blade.php +++ b/resources/views/columns/events/action.blade.php @@ -1,3 +1,15 @@ -
- {{ __('Register') }} +
+
+ {{ __('Register') }} +
+ @can('update', $row) +
+ + + {{ __('Edit') }} + +
+ @endcan
diff --git a/resources/views/columns/meetups/action.blade.php b/resources/views/columns/meetups/action.blade.php index 34db19ad..521f8090 100644 --- a/resources/views/columns/meetups/action.blade.php +++ b/resources/views/columns/meetups/action.blade.php @@ -98,13 +98,15 @@
@endif @if(auth()->check() && auth()->user()->meetups->contains($row)) - - - {{ __('Edit') }} - +
+ + + {{ __('Edit') }} + +
@endif
diff --git a/resources/views/livewire/frontend/navigation/courses.blade.php b/resources/views/livewire/frontend/navigation/courses.blade.php index 545bd5ad..4cab7ee5 100644 --- a/resources/views/livewire/frontend/navigation/courses.blade.php +++ b/resources/views/livewire/frontend/navigation/courses.blade.php @@ -77,13 +77,13 @@ {{ __('Create venue') }} - {{ __('Register course') }} - {{ __('Register course date') }} diff --git a/resources/views/livewire/meetup/form/meetup-event-form.blade.php b/resources/views/livewire/meetup/form/meetup-event-form.blade.php index 784ab6ca..e982ab7a 100644 --- a/resources/views/livewire/meetup/form/meetup-event-form.blade.php +++ b/resources/views/livewire/meetup/form/meetup-event-form.blade.php @@ -16,7 +16,7 @@ @endif
- + {{ __('Back') }} diff --git a/resources/views/livewire/meetup/form/meetup-form.blade.php b/resources/views/livewire/meetup/form/meetup-form.blade.php index 2a1dc962..5d9685b4 100644 --- a/resources/views/livewire/meetup/form/meetup-form.blade.php +++ b/resources/views/livewire/meetup/form/meetup-form.blade.php @@ -9,7 +9,7 @@
- + {{ __('Back') }} diff --git a/resources/views/livewire/news/form/news-article-form.blade.php b/resources/views/livewire/news/form/news-article-form.blade.php index 23cfc625..227f95cd 100644 --- a/resources/views/livewire/news/form/news-article-form.blade.php +++ b/resources/views/livewire/news/form/news-article-form.blade.php @@ -24,7 +24,7 @@ @endif
- + {{ __('Back') }} @@ -53,14 +53,14 @@ wire:model="libraryItem.lecturer_id" :searchable="true" :async-data="[ - 'api' => route('api.lecturers.index'), - 'method' => 'GET', // default is GET - 'params' => ['user_id' => auth()->id()], // default is [] - ]" + 'api' => route('api.lecturers.index'), + 'method' => 'GET', // default is GET + 'params' => ['user_id' => auth()->id()], // default is [] + ]" :template="[ - 'name' => 'user-option', - 'config' => ['src' => 'image'] - ]" + 'name' => 'user-option', + 'config' => ['src' => 'image'] + ]" option-label="name" option-value="id" /> diff --git a/resources/views/livewire/school/form/course-event-form.blade.php b/resources/views/livewire/school/form/course-event-form.blade.php new file mode 100644 index 00000000..e838dd9a --- /dev/null +++ b/resources/views/livewire/school/form/course-event-form.blade.php @@ -0,0 +1,127 @@ +
+ {{-- HEADER --}} + + +
+ +
+

{{ __('Course Event') }}

+
+ +
+ + + {{ __('Back') }} + +
+
+
+ +
+
+
+ + + +
+
+ {{ __('Course') }} +
+ + + {{ __('Register course') }} + +
+
+ +
+ + + +
+
+ {{ __('Venue') }} +
+ + + {{ __('Create venue') }} + +
+
+ +
+ + + + + + + + + + + + + + + + + {{ __('Save') }} + + + +
+
+
+
+ +
diff --git a/resources/views/livewire/school/form/course-form.blade.php b/resources/views/livewire/school/form/course-form.blade.php new file mode 100644 index 00000000..68933ed9 --- /dev/null +++ b/resources/views/livewire/school/form/course-form.blade.php @@ -0,0 +1,107 @@ +
+ {{-- HEADER --}} + + +
+ +
+

{{ __('Course') }}

+
+ +
+ + + {{ __('Back') }} + +
+
+
+ +
+
+
+ + +
+ @if ($image) +
{{ __('Preview') }}:
+ + @endif + @if ($course->getFirstMediaUrl('logo')) +
{{ __('Current picture') }}:
+ + @endif +
+ + @error('image') {{ $message }} @enderror +
+ + + + + + + + + + +
+ @foreach($tags as $tag) +
+ @if(collect($selectedTags)->contains($tag->name)) + + {{ $tag->name }} + + @else + + {{ $tag->name }} + + @endif +
+ @endforeach +
+
+ + +
{{ __('For images in Markdown, please use eg. Imgur or another provider.') }}
+ + @error('course.description') {{ $message }} @enderror +
+ + + + + {{ __('Save') }} + + + +
+
+
+
+ + +
diff --git a/routes/api.php b/routes/api.php index 577734f7..5408c6c8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -29,6 +29,7 @@ Route::middleware([]) Route::resource('countries', \App\Http\Controllers\Api\CountryController::class); Route::resource('meetup', \App\Http\Controllers\Api\MeetupController::class); Route::resource('lecturers', \App\Http\Controllers\Api\LecturerController::class); + Route::resource('courses', \App\Http\Controllers\Api\CourseController::class); Route::resource('cities', \App\Http\Controllers\Api\CityController::class); Route::resource('venues', \App\Http\Controllers\Api\VenueController::class); Route::resource('languages', \App\Http\Controllers\Api\LanguageController::class); diff --git a/routes/web.php b/routes/web.php index 03c0eb6a..cb450ccc 100644 --- a/routes/web.php +++ b/routes/web.php @@ -65,6 +65,21 @@ Route::middleware([ ->name('form'); }); +/* + * Course + * */ +Route::middleware([ + 'auth', +]) + ->as('course.') + ->prefix('/course') + ->group(function () { + Route::get('/form/course/{course?}', \App\Http\Livewire\School\Form\CourseForm::class) + ->name('form.course'); + Route::get('/form/course-event/{courseEvent?}', \App\Http\Livewire\School\Form\CourseEventForm::class) + ->name('form.courseEvent'); + }); + /* * Venue * */