diff --git a/backend/requirements.txt b/backend/requirements.txt index 68e03a3..c5d43db 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -3,7 +3,7 @@ certifi==2024.7.4 charset-normalizer==3.3.2 click==8.1.7 diff-match-patch==20230430 -Django==5.0.10 +Django==5.2 django-cors-headers==4.4.0 django-environ==0.12.0 django-grip==3.5.0 @@ -30,7 +30,7 @@ rq==1.16.2 sentry-sdk==2.14.0 setuptools==72.1.0 six==1.16.0 -sqlparse==0.5.1 +sqlparse==0.5.3 tablib==3.5.0 urllib3==2.2.2 Werkzeug==3.0.6 diff --git a/backend/video_app/admin.py b/backend/video_app/admin.py index 31702ee..5774075 100644 --- a/backend/video_app/admin.py +++ b/backend/video_app/admin.py @@ -10,5 +10,5 @@ class VideoResource(resources.ModelResource): @admin.register(Video) class VideoAdmin(ImportExportModelAdmin): resource_class = VideoResource - readonly_fields = ('file_name',) - list_display = ('title', 'file_name', 'created_at') \ No newline at end of file + readonly_fields = ('file_path',) + list_display = ('title', 'file_path', 'created_at') \ No newline at end of file diff --git a/backend/video_app/class_assets.py b/backend/video_app/class_assets.py index e2a9a88..edc7714 100644 --- a/backend/video_app/class_assets.py +++ b/backend/video_app/class_assets.py @@ -1,4 +1,4 @@ -FILM_GENRES = [ +VIDEO_GENRES = [ ('action', 'Action'), ('adventure', 'Adventure'), ('animation', 'Animation'), diff --git a/backend/video_app/models.py b/backend/video_app/models.py index 51aab66..e378463 100644 --- a/backend/video_app/models.py +++ b/backend/video_app/models.py @@ -1,7 +1,7 @@ from django.db import models from django.conf import settings from datetime import date -from .class_assets import FILM_GENRES +from .class_assets import VIDEO_GENRES import os class Video(models.Model): @@ -9,17 +9,17 @@ class Video(models.Model): created_at = models.DateField(default=date.today) title = models.CharField(max_length=80) description = models.CharField(max_length=500) - film_genre = models.CharField(max_length=20, choices=FILM_GENRES, blank=True, null=True) - video_file = models.FileField(upload_to='videos/', blank=True, null=True) + genre = models.CharField(max_length=20, choices=VIDEO_GENRES, blank=True, null=True) + file_path = models.FileField(upload_to='videos/', blank=True, null=True) file_name = models.CharField(max_length=50, blank=True, null=True) def __str__(self): return f'({self.id}) {self.title}' def save(self, *args, **kwargs): - if self.video_file and not self.file_name: - video_file_path = self.video_file.path - base_filename, _ = os.path.splitext(os.path.basename(video_file_path)) + if self.file_path and not self.file_name: + file_path = self.file_path.path + base_filename, _ = os.path.splitext(os.path.basename(file_path)) self.file_name = base_filename super().save(*args, **kwargs) \ No newline at end of file diff --git a/backend/video_app/signals.py b/backend/video_app/signals.py index 5e2f8ef..899dcfe 100644 --- a/backend/video_app/signals.py +++ b/backend/video_app/signals.py @@ -19,10 +19,10 @@ def video_post_save(sender, instance, created, **kwargs): #Convert video for resolution in ["1280x720", "640x360", "1920x1080"]: - queue.enqueue(convert_video_to_hls, instance.video_file.path, resolution, instance.id) + queue.enqueue(convert_video_to_hls, instance.file_path.path, resolution, instance.id) #Delete the original video file - queue.enqueue(delete_original_video, instance.video_file.path) + queue.enqueue(delete_original_video, instance.file_path.path) @receiver(post_delete, sender=Video) def auto_delete_file_on_delete(sender, instance, **kwargs): @@ -30,7 +30,7 @@ def auto_delete_file_on_delete(sender, instance, **kwargs): Deletes the video and all converted files from the file system, when the corresponding `Video` object is deleted. """ - main_directory = os.path.dirname(instance.video_file.path) + main_directory = os.path.dirname(instance.file_path.path) parent_directory = os.path.dirname(main_directory) model_directory = os.path.join(main_directory, str(instance.id)) thumbnail_directory = os.path.join(parent_directory, 'thumbnails', str(instance.id)) diff --git a/backend/video_app/tasks.py b/backend/video_app/tasks.py index eb250d8..a5b1f2b 100644 --- a/backend/video_app/tasks.py +++ b/backend/video_app/tasks.py @@ -46,7 +46,7 @@ def create_thumbnails(instance, model_id): """ Creates high-resolution and low-resolution thumbnails from a video file. """ - video_file_path = instance.video_file.path + video_file_path = instance.file_path.path thumbnail_dir = os.path.join(settings.THUMBNAIL_DIR, str(model_id)) base_filename = os.path.splitext(os.path.basename(video_file_path))[0] diff --git a/backend/video_app/views.py b/backend/video_app/views.py index 142b1c3..7b0b1fb 100644 --- a/backend/video_app/views.py +++ b/backend/video_app/views.py @@ -3,7 +3,7 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from .serializer import VideoSerializer from .models import Video -from .class_assets import FILM_GENRES +from .class_assets import VIDEO_GENRES from django.core.cache.backends.base import DEFAULT_TIMEOUT from django.views.decorators.cache import cache_page from django.conf import settings @@ -29,9 +29,9 @@ def video_list(request): @permission_classes([IsAuthenticated]) def genre_list(request): """ - Return a list of film genres from static choices. + Return a list of video genres from static choices. """ - genres = [{'code': code, 'name': name} for code, name in FILM_GENRES] + genres = [{'code': code, 'name': name} for code, name in VIDEO_GENRES] return Response(genres) @api_view(['GET']) diff --git a/frontend/src/app/components/home/categories/categories.component.html b/frontend/src/app/components/home/categories/categories.component.html index e06fc12..3eda400 100644 --- a/frontend/src/app/components/home/categories/categories.component.html +++ b/frontend/src/app/components/home/categories/categories.component.html @@ -30,14 +30,14 @@ @if (genres$ | async; as genres) { - @for (filmGenre of genres; track filmGenre) { + @for (genre of genres; track genre) { - @if (getAllVideos(filmGenre.code).length > 0) { + @if (getAllVideos(genre.code).length > 0) {
-

{{ filmGenre.name }}

+

{{ genre.name }}

video.film_genre === filmGenre); + getAllVideos(genre: string) { + return this.videos.filter((video) => video.genre === genre); } getFavoriteVideos() { diff --git a/frontend/src/app/components/home/upload-video/upload-video.component.html b/frontend/src/app/components/home/upload-video/upload-video.component.html index 87d08a4..7a8a87d 100644 --- a/frontend/src/app/components/home/upload-video/upload-video.component.html +++ b/frontend/src/app/components/home/upload-video/upload-video.component.html @@ -39,11 +39,11 @@ }
- @if (!filmGenre.valid && filmGenre.touched) { -

Please enter a movie genre

+ @if (!genre.valid && genre.touched) { +

Please enter a genre

}
diff --git a/frontend/src/app/components/home/upload-video/upload-video.component.ts b/frontend/src/app/components/home/upload-video/upload-video.component.ts index 87ec95f..edfef78 100644 --- a/frontend/src/app/components/home/upload-video/upload-video.component.ts +++ b/frontend/src/app/components/home/upload-video/upload-video.component.ts @@ -28,8 +28,8 @@ export class UploadVideoComponent { videoData = { title: '', description: '', - filmGenre: '', - videoFile: null as File | null, + genre: '', + file: null as File | null, send: false, }; @@ -54,7 +54,7 @@ export class UploadVideoComponent { isOneFile(event: any) { const file = event.target.files[0]; if (file) { - this.videoData.videoFile = file; + this.videoData.file = file; } } isFileSize(event: any) { @@ -93,9 +93,9 @@ export class UploadVideoComponent { const formData = new FormData(); formData.append('title', this.videoData.title); formData.append('description', this.videoData.description); - formData.append('film_genre', this.videoData.filmGenre); - if (this.videoData.videoFile) { - formData.append('video_file', this.videoData.videoFile); + formData.append('genre', this.videoData.genre); + if (this.videoData.file) { + formData.append('file_path', this.videoData.file); } return formData; } diff --git a/frontend/src/app/interfaces/film-genre.interface.ts b/frontend/src/app/interfaces/genre.interface.ts similarity index 53% rename from frontend/src/app/interfaces/film-genre.interface.ts rename to frontend/src/app/interfaces/genre.interface.ts index 822116c..c9e74ee 100644 --- a/frontend/src/app/interfaces/film-genre.interface.ts +++ b/frontend/src/app/interfaces/genre.interface.ts @@ -1,4 +1,4 @@ -export interface FilmGenre { +export interface Genre { code: string; name: string; } diff --git a/frontend/src/app/interfaces/video.interface.ts b/frontend/src/app/interfaces/video.interface.ts index 138b64d..20739e0 100644 --- a/frontend/src/app/interfaces/video.interface.ts +++ b/frontend/src/app/interfaces/video.interface.ts @@ -4,7 +4,7 @@ export interface Video { created_at: string; title: string; description: string; - film_genre: string; - video_file: string; + genre: string; + file_path: string; file_name: string; } diff --git a/frontend/src/app/services/film-genre.service.ts b/frontend/src/app/services/genre.service.ts similarity index 66% rename from frontend/src/app/services/film-genre.service.ts rename to frontend/src/app/services/genre.service.ts index 87d5e46..8a6ae43 100644 --- a/frontend/src/app/services/film-genre.service.ts +++ b/frontend/src/app/services/genre.service.ts @@ -1,13 +1,13 @@ import { Injectable } from '@angular/core'; import { Observable, of, tap } from 'rxjs'; import { ApiService } from './api.service'; -import { FilmGenre } from '../interfaces/film-genre.interface'; +import { Genre } from '../interfaces/genre.interface'; @Injectable({ providedIn: 'root', }) -export class FilmGenreService { - private genres: FilmGenre[] = []; +export class GenreService { + private genres: Genre[] = []; constructor(private apiService: ApiService) {} @@ -15,12 +15,12 @@ export class FilmGenreService { * Returns the genres either from the cache or from the API endpoint. * @returns observable of movie genres */ - getGenres(): Observable { + getGenres(): Observable { if (this.genres.length > 0) { return of(this.genres); } - return this.apiService.get('/video/genres/', true).pipe( + return this.apiService.get('/video/genres/', true).pipe( tap((data) => { this.genres = data; })