From a306fd236605c5fa0eb6bc155e149b58b906e5f1 Mon Sep 17 00:00:00 2001 From: Stefanos Georgopoulos Date: Tue, 26 Nov 2024 15:06:21 +0100 Subject: [PATCH] Fetch only current semester series in dashboard - Also import livewire view to dashboard Signed-off-by: Stefanos Georgopoulos --- .../Backend/DashboardController.php | 18 +- app/Livewire/IndexPagesDatatable.php | 248 ++++++++---------- app/Models/Clip.php | 10 +- app/Models/Series.php | 20 +- app/Models/User.php | 2 +- .../views/backend/dashboard/index.blade.php | 37 ++- .../livewire/index-pages-datatable.blade.php | 2 +- .../Backend/DashboardControllerTest.php | 9 +- 8 files changed, 162 insertions(+), 184 deletions(-) diff --git a/app/Http/Controllers/Backend/DashboardController.php b/app/Http/Controllers/Backend/DashboardController.php index 309209a0..813c0e32 100644 --- a/app/Http/Controllers/Backend/DashboardController.php +++ b/app/Http/Controllers/Backend/DashboardController.php @@ -86,18 +86,12 @@ public function __invoke(OpencastService $opencastService): Application|Factory| $livestreams = Livestream::active()->orderBy('clip_id'); return view('backend.dashboard.index', [ - 'userSeries' => auth()->user() - ->getAllSeries() - ->with('owner') - ->withLastPublicClip() - ->CurrentSemester() - ->orderBy('title') - ->paginate(12), - 'userClips' => auth()->user()->clips() - ->whereNull('series_id') - ->orderByDesc('updated_at') - ->limit(12) - ->get(), + 'userSeriesCounter' => auth()->user() + ->getAllSeries()->currentSemester()->count(), + 'userClipsCounter' => auth()->user()->clips() + ->single() + ->currentSemester() + ->count(), 'files' => fetchDropZoneFiles(false), 'opencastEvents' => $opencastEvents, 'opencastSettings' => $opencastSettings->data, diff --git a/app/Livewire/IndexPagesDatatable.php b/app/Livewire/IndexPagesDatatable.php index 491db61d..ccb8f534 100644 --- a/app/Livewire/IndexPagesDatatable.php +++ b/app/Livewire/IndexPagesDatatable.php @@ -31,8 +31,7 @@ class IndexPagesDatatable extends Component public function sortBy($field): void { - $this->sortAsc = ! ($this->sortField === $field) || ! $this->sortAsc; - + $this->sortAsc = ($this->sortField !== $field) || ! $this->sortAsc; $this->sortField = $field; } @@ -44,7 +43,7 @@ public function updatingSearch(): void public function render() { $search = trim(Str::lower($this->search)); - $objects = $this->determineClipQuery($search)->paginate(20); + $objects = $this->determineQuery($search)->paginate(20); return view('livewire.index-pages-datatable', [ 'type' => $this->type, @@ -54,148 +53,109 @@ public function render() ]); } - protected function determineClipQuery($search) + protected function determineQuery($search) + { + switch ($this->type) { + case 'series': + return $this->querySeries($search); + case 'clips': + return $this->queryClips($search); + case 'organization': + return $this->queryOrganization($search); + default: + return collect(); // Return empty collection as fallback + } + } + + protected function querySeries($search) + { + $query = Series::query()->with(['presenters'])->withLastPublicClip(); + + if ($this->actionButton === 'dashboard') { + $query = $this->userSeriesQuery(query: $query, currentSemester: true); + } elseif ($this->actionButton === 'assignClip' && ! $this->isAdmin()) { + $query = $this->userSeriesQuery($query); + } else { + $query->isPublic()->whereHas('clips.assets'); + } + + return $this->applySearchFilter($query, $search)->orderBy('id', 'desc'); + } + + protected function queryClips($search) + { + $query = Clip::query()->with(['presenters'])->Public(); + + if ($this->actionButton === 'dashboard') { + return auth()->user() + ->clips() + ->single() + ->with(['presenters']) + ->currentSemester(); + } + if ($this->singleClips) { + $query->Single(); + } + + return $this->applySearchFilter($query, $search)->orderBy('updated_at', 'desc'); + } + + protected function queryOrganization($search) + { + $string = Str::substr($this->organization->orgno, 0, 2); + + $query = Series::whereHas('organization', function ($q) use ($string) { + $q->whereRaw('orgno like ?', ["{$string}%"]); + })->with(['presenters']) + ->withLastPublicClip() + ->isPublic() + ->whereHas('clips.assets'); + + return $this->applySearchFilter($query, $search)->orderBy('id', 'desc'); + } + + protected function userSeriesQuery($query, $currentSemester = false) { - if ($this->type === 'series') { - //if it is a lecturer fetch all user series to assign them to a clip - if ($this->actionButton === 'assignClip' && ! auth()->user()->isAdmin()) { - if (auth()->user()->isAdmin()) { - return Series::query() - ->with(['presenters']) - ->withLastPublicClip() - ->where(function ($q) use ($search) { - $search = strtolower($search); - $q->where('id', (int) $search) - ->orWhereRaw('lower(title) like ?', ["%{$search}%"]) - ->orWhereHas('presenters', function ($q) use ($search) { - if (DB::getDriverName() === 'pgsql' || DB::getDriverName() === 'sqlite') { - // PostgresSQL concatenation using "||" - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(first_name || \' \' || last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name || \' \' || first_name) like ?', ["%{$search}%"]); - } else { - // MySQL or others using CONCAT() - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(first_name, " ", last_name)) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(last_name, " ", first_name)) like ?', ["%{$search}%"]); - } - }); - }) - ->orderBy('id', 'desc'); - } else { - return auth()->user()->accessableSeries()->with(['presenters']) - ->withLastPublicClip() - ->where(function ($q) use ($search) { - $search = strtolower($search); - $q->where('id', (int) $search) - ->orWhereRaw('lower(title) like ?', ["%{$search}%"]) - ->orWhereHas('presenters', function ($q) use ($search) { - if (DB::getDriverName() === 'pgsql' || DB::getDriverName() === 'sqlite') { - // PostgresSQL concatenation using "||" - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(first_name || \' \' || last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name || \' \' || first_name) like ?', ["%{$search}%"]); - } else { - // MySQL or others using CONCAT() - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(first_name, " ", last_name)) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(last_name, " ", first_name)) like ?', ["%{$search}%"]); - } - }); - }) - ->orderBy('id', 'desc'); - } - } else { - return Series::query() - ->with(['presenters']) - ->withLastPublicClip() - ->isPublic() - ->whereHas('clips.assets') - ->where(function ($q) use ($search) { - $search = strtolower($search); - $q->where('id', (int) $search) - ->orWhereRaw('lower(title) like ?', ["%{$search}%"]) - ->orWhereHas('presenters', function ($q) use ($search) { - if (DB::getDriverName() === 'pgsql' || DB::getDriverName() === 'sqlite') { - // PostgresSQL concatenation using "||" - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(first_name || \' \' || last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name || \' \' || first_name) like ?', ["%{$search}%"]); - } else { - // MySQL or others using CONCAT() - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(first_name, " ", last_name)) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(last_name, " ", first_name)) like ?', ["%{$search}%"]); - } - }); - }) - ->orderBy('id', 'desc'); - } - - } elseif ($this->type === 'clips') { - $query = Clip::query(); - if ($this->singleClips) { - $query->Single(); - } - - return $query->with(['presenters']) - ->Public() - ->where(function ($q) use ($search) { - $search = strtolower($search); - $q->where('id', (int) $search) - ->orWhereRaw('lower(title) like ?', ["%{$search}%"]) - ->orWhereHas('presenters', function ($q) use ($search) { - if (DB::getDriverName() === 'pgsql' || DB::getDriverName() === 'sqlite') { - // PostgresSQL concatenation using "||" - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(first_name || \' \' || last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name || \' \' || first_name) like ?', ["%{$search}%"]); - } else { - // MySQL or others using CONCAT() - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(first_name, " ", last_name)) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(last_name, " ", first_name)) like ?', ["%{$search}%"]); - } - }); - }) - ->orderBy('updated_at', 'desc'); - } elseif ($this->type === 'organization') { - return Series::whereHas('organization', function ($q) { - $string = Str::substr($this->organization->orgno, 0, 2); - $q->whereRaw('orgno like (?)', ["{$string}%"]); - })->with(['presenters']) - ->withLastPublicClip() - ->isPublic() - ->whereHas('clips.assets') - ->where(function ($q) use ($search) { - $search = strtolower($search); - $q->where('id', (int) $search) - ->orWhereRaw('lower(title) like ?', ["%{$search}%"]) - ->orWhereHas('presenters', function ($q) use ($search) { - if (DB::getDriverName() === 'pgsql' || DB::getDriverName() === 'sqlite') { - // PostgresSQL concatenation using "||" - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(first_name || \' \' || last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name || \' \' || first_name) like ?', ["%{$search}%"]); - } else { - // MySQL or others using CONCAT() - $q->whereRaw('lower(first_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(first_name, " ", last_name)) like ?', ["%{$search}%"]) - ->orWhereRaw('lower(CONCAT(last_name, " ", first_name)) like ?', ["%{$search}%"]); - } - }); - }) - ->orderBy('id', 'desc'); + if ($currentSemester) { + return auth()->user()->getAllSeries()->with(['presenters']) + ->withLastPublicClip()->currentSemester(); } + + if ($this->isAdmin()) { + return $query; + } + + return auth()->user()->getAllSeries()->with(['presenters'])->withLastPublicClip(); + } + + protected function applySearchFilter($query, $search) + { + return $query->where(function ($q) use ($search) { + $q->where('id', (int) $search) + ->orWhereRaw('lower(title) like ?', ["%{$search}%"]) + ->orWhereHas('presenters', function ($q) use ($search) { + $this->applyPresenterSearchFilter($q, $search); + }); + }); + } + + protected function applyPresenterSearchFilter($query, $search) + { + if (DB::getDriverName() === 'pgsql' || DB::getDriverName() === 'sqlite') { + $query->whereRaw('lower(first_name) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(first_name || \' \' || last_name) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(last_name || \' \' || first_name) like ?', ["%{$search}%"]); + } else { + $query->whereRaw('lower(first_name) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(last_name) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(CONCAT(first_name, " ", last_name)) like ?', ["%{$search}%"]) + ->orWhereRaw('lower(CONCAT(last_name, " ", first_name)) like ?', ["%{$search}%"]); + } + } + + protected function isAdmin() + { + return auth()->user()->isAdmin(); } } diff --git a/app/Models/Clip.php b/app/Models/Clip.php index 7cb363ec..042c558c 100644 --- a/app/Models/Clip.php +++ b/app/Models/Clip.php @@ -394,9 +394,6 @@ public function scopeSingle($query): mixed return $query->whereNull('series_id'); } - /** - * Scope a query to only include the semester name of the clip - */ public function scopeWithSemester($query) { return $query->addSelect( @@ -408,6 +405,13 @@ public function scopeWithSemester($query) ); } + public function scopeCurrentSemester($query) + { + return $query->whereHas('semester', function ($q) { + $q->current(); + }); + } + protected function title(): Attribute { return Attribute::make( diff --git a/app/Models/Series.php b/app/Models/Series.php index f2c904e6..4a87667d 100644 --- a/app/Models/Series.php +++ b/app/Models/Series.php @@ -308,11 +308,21 @@ public function scopeHasClipsWithAssets($query): mixed public function scopeCurrentSemester($query): mixed { - return $query->whereHas('clips', function ($q) { - $q->whereHas('semester', function ($q) { - $q->current(); - }); - })->orWhere('owner_id', auth()->user()?->id); + return $query->where(function ($query) { + // Include VideoSeries that have clips within the current semester + $query->whereHas('clips', function ($q) { + $q->whereHas('semester', function ($q) { + $q->current(); + }); + }) + // OR include VideoSeries without clips but created during the current semester + ->orWhere(function ($q) { + $currentSemester = Semester::current()->first(); // Get the current semester + if ($currentSemester) { + $q->whereBetween('created_at', [$currentSemester->start_date, $currentSemester->stop_date]); + } + }); + }); } public function scopeHasOpencastSeriesID($query): mixed diff --git a/app/Models/User.php b/app/Models/User.php index 64c33a2c..9b260112 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -231,7 +231,7 @@ public function memberships(): BelongsToMany public function getAllSeries(): Builder|Series { - return Series::select('id', 'slug', 'title', 'updated_at', 'owner_id', 'organization_id') + return Series::select('id', 'slug', 'title', 'updated_at', 'owner_id', 'organization_id', 'created_at') ->whereHas('clips', function ($q) { $q->where('supervisor_id', $this->id); }) diff --git a/resources/views/backend/dashboard/index.blade.php b/resources/views/backend/dashboard/index.blade.php index c90cf54b..a7b627e5 100644 --- a/resources/views/backend/dashboard/index.blade.php +++ b/resources/views/backend/dashboard/index.blade.php @@ -6,7 +6,7 @@ {{ __('dashboard.welcome to personal dashboard', ['fullName' => auth()->user()->getFullNameAttribute() ]) }} ! - @if($userSeries->count() == 0) + @if($userSeriesCounter == 0)

@@ -33,7 +33,7 @@

@php $dropBoxFilesCheck = count($files) > 0 && Setting::portal()->data['show_dropbox_files_in_dashboard']; @endphp
- @if($activeLivestreams->count()>0) + @if($activeLivestreams->count()>0 && auth()->user()->can('administrate-assistant-pages')) @include('backend.dashboard._active-livestreams',['activeLivestreams' => $activeLivestreams]) @endif @if($opencastEvents->isNotEmpty()) @@ -49,14 +49,29 @@ @endif @endcan
-
-
- @include('backend.users.series._layout',[ - 'layoutHeader' => __('dashboard.your last series'), - 'series'=> $userSeries]) - @include('backend.users.clips._layout',[ - 'layoutHeader' => __('dashboard.your last clips'), - 'clips'=> $userClips]) + @if($userSeriesCounter > 0) +
+
+
+ {{ __('dashboard.your last series') }} +
+
+
+ +
+
-
+ @endif + @if($userClipsCounter > 0) +
+
+
+ {{ __('dashboard.your last series') }} +
+
+
+ +
+
+ @endif @endsection diff --git a/resources/views/livewire/index-pages-datatable.blade.php b/resources/views/livewire/index-pages-datatable.blade.php index e63bad0f..5a49a0e3 100644 --- a/resources/views/livewire/index-pages-datatable.blade.php +++ b/resources/views/livewire/index-pages-datatable.blade.php @@ -59,7 +59,7 @@ class=" text-gray-700 dark:text-white" @else

- {!! __('search.frontend.no clips results found for search term', ['searchTerm' => $search]) !!} + {!! __('search.frontend.no series results found for search term', ['searchTerm' => $search]) !!}

@endif diff --git a/tests/Feature/Http/Controllers/Backend/DashboardControllerTest.php b/tests/Feature/Http/Controllers/Backend/DashboardControllerTest.php index bd79ef88..64c7bb5d 100644 --- a/tests/Feature/Http/Controllers/Backend/DashboardControllerTest.php +++ b/tests/Feature/Http/Controllers/Backend/DashboardControllerTest.php @@ -64,16 +64,11 @@ ->assertSee(__('dashboard.new clip')); }); -it('should display an info text if no series existing for user', function () { - get(route('dashboard'))->assertSee(__('homepage.series.no series found')); -}); - it('display\'s user series', function () { SeriesFactory::create(); - get(route('dashboard'))->assertSee(__('homepage.series.no series found')); + $series = SeriesFactory::ownedBy(auth()->user())->create(); - $userSeries = SeriesFactory::ownedBy(auth()->user())->create(); - get(route('dashboard'))->assertSee($userSeries->title); + get(route('dashboard'))->assertSee($series->title); }); it('display\'s user supervised series', function () {