mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig-portal.git
synced 2025-12-11 06:46:47 +00:00
new forms added for courses
This commit is contained in:
74
app/Http/Controllers/Api/CourseController.php
Normal file
74
app/Http/Controllers/Api/CourseController.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Course;
|
||||
use App\Models\Lecturer;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CourseController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return Course::query()
|
||||
->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)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
];
|
||||
|
||||
@@ -47,7 +47,6 @@ class ContentCreatorForm extends Component
|
||||
$this->lecturer = new Lecturer([
|
||||
'intro' => '',
|
||||
'active' => true,
|
||||
'team_id' => true,
|
||||
]);
|
||||
}
|
||||
if (!$this->fromUrl) {
|
||||
|
||||
@@ -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',
|
||||
|
||||
67
app/Http/Livewire/School/Form/CourseEventForm.php
Normal file
67
app/Http/Livewire/School/Form/CourseEventForm.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School\Form;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseEvent;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class CourseEventForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
use Actions;
|
||||
|
||||
public ?CourseEvent $courseEvent = null;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
public $image;
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => [
|
||||
'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');
|
||||
}
|
||||
}
|
||||
103
app/Http/Livewire/School/Form/CourseForm.php
Normal file
103
app/Http/Livewire/School/Form/CourseForm.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\School\Form;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use WireUi\Traits\Actions;
|
||||
|
||||
class CourseForm extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
use Actions;
|
||||
|
||||
public ?Course $course = null;
|
||||
|
||||
public ?string $fromUrl = '';
|
||||
|
||||
public $image;
|
||||
|
||||
public array $selectedTags = [];
|
||||
|
||||
protected $queryString = [
|
||||
'fromUrl' => [
|
||||
'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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
@@ -29,6 +29,7 @@ class EventTable extends DataTableComponent
|
||||
->setDefaultSort('from', 'asc')
|
||||
->setAdditionalSelects([
|
||||
'course_events.id',
|
||||
'course_events.created_by',
|
||||
'course_id',
|
||||
'venue_id',
|
||||
])
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
|
||||
@@ -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__);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user