feat: create GenreService to load film genres from API
This commit is contained in:
parent
75c99b28ad
commit
6bfd167122
4 changed files with 72 additions and 23 deletions
|
|
@ -3,6 +3,7 @@ from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from .serializer import VideoSerializer
|
from .serializer import VideoSerializer
|
||||||
from .models import Video
|
from .models import Video
|
||||||
|
from .class_assets import FILM_GENRES
|
||||||
from django.core.cache.backends.base import DEFAULT_TIMEOUT
|
from django.core.cache.backends.base import DEFAULT_TIMEOUT
|
||||||
from django.views.decorators.cache import cache_page
|
from django.views.decorators.cache import cache_page
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
@ -24,6 +25,15 @@ def video_list(request):
|
||||||
serializer = VideoSerializer(videos, many=True)
|
serializer = VideoSerializer(videos, many=True)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
@api_view(['GET'])
|
||||||
|
@permission_classes([IsAuthenticated])
|
||||||
|
def genre_list(request):
|
||||||
|
"""
|
||||||
|
Return a list of film genres from static choices.
|
||||||
|
"""
|
||||||
|
genres = [{'code': code, 'name': name} for code, name in FILM_GENRES]
|
||||||
|
return Response(genres)
|
||||||
|
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
@permission_classes([IsAuthenticated])
|
@permission_classes([IsAuthenticated])
|
||||||
def check_video_resolutions(request, id):
|
def check_video_resolutions(request, id):
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,9 @@ urlpatterns = [
|
||||||
# Content URLs
|
# Content URLs
|
||||||
path('videos/', video_views.video_list, name='video_list'),
|
path('videos/', video_views.video_list, name='video_list'),
|
||||||
path('video/upload/', video_views.video_upload, name='video_upload'),
|
path('video/upload/', video_views.video_upload, name='video_upload'),
|
||||||
|
path('video/genres/', video_views.genre_list, name='genre_list'),
|
||||||
path('video/<int:id>/', video_views.check_video_resolutions, name='check_video_resolutions'),
|
path('video/<int:id>/', video_views.check_video_resolutions, name='check_video_resolutions'),
|
||||||
|
|
||||||
# Users URLs
|
# Users URLs
|
||||||
path('users/', user_views.user_list, name='user_list'),
|
path('users/', user_views.user_list, name='user_list'),
|
||||||
path('users/<int:id>/', user_views.user_detail, name='user_detail'),
|
path('users/<int:id>/', user_views.user_detail, name='user_detail'),
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,13 @@ import {
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
HostListener,
|
HostListener,
|
||||||
Input,
|
Input,
|
||||||
|
OnInit,
|
||||||
Output,
|
Output,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { VideoListComponent } from './video-list/video-list.component';
|
import { VideoListComponent } from './video-list/video-list.component';
|
||||||
|
import { FilmGenre, GenreService } from '../../../services/genre.service';
|
||||||
|
import { Subject, takeUntil } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-categories',
|
selector: 'app-categories',
|
||||||
|
|
@ -17,7 +20,7 @@ import { VideoListComponent } from './video-list/video-list.component';
|
||||||
templateUrl: './categories.component.html',
|
templateUrl: './categories.component.html',
|
||||||
styleUrl: './categories.component.scss',
|
styleUrl: './categories.component.scss',
|
||||||
})
|
})
|
||||||
export class CategoriesComponent implements AfterViewInit {
|
export class CategoriesComponent implements OnInit, AfterViewInit {
|
||||||
@Input() videos: any[] = [];
|
@Input() videos: any[] = [];
|
||||||
@Input() currentVideo: number = 0;
|
@Input() currentVideo: number = 0;
|
||||||
@Input() favoriteVideos: any[] = [];
|
@Input() favoriteVideos: any[] = [];
|
||||||
|
|
@ -26,32 +29,34 @@ export class CategoriesComponent implements AfterViewInit {
|
||||||
|
|
||||||
environmentBaseUrl: string = environment.baseUrl;
|
environmentBaseUrl: string = environment.baseUrl;
|
||||||
isScrollable: boolean = false;
|
isScrollable: boolean = false;
|
||||||
|
filmGenres: FilmGenre[] = [];
|
||||||
|
|
||||||
filmGenres = [
|
private destroy$ = new Subject<void>();
|
||||||
{ code: 'action', name: 'Action' },
|
|
||||||
{ code: 'adventure', name: 'Adventure' },
|
|
||||||
{ code: 'animation', name: 'Animation' },
|
|
||||||
{ code: 'anime', name: 'Anime' },
|
|
||||||
{ code: 'comedy', name: 'Comedy' },
|
|
||||||
{ code: 'crime', name: 'Crime' },
|
|
||||||
{ code: 'documentary', name: 'Documentary' },
|
|
||||||
{ code: 'drama', name: 'Drama' },
|
|
||||||
{ code: 'fantasy', name: 'Fantasy' },
|
|
||||||
{ code: 'horror', name: 'Horror' },
|
|
||||||
{ code: 'musical', name: 'Musical' },
|
|
||||||
{ code: 'mystery', name: 'Mystery' },
|
|
||||||
{ code: 'other', name: 'Miscellaneous' },
|
|
||||||
{ code: 'romance', name: 'Romance' },
|
|
||||||
{ code: 'science_fiction', name: 'Science Fiction' },
|
|
||||||
{ code: 'thriller', name: 'Thriller' },
|
|
||||||
{ code: 'war', name: 'War' },
|
|
||||||
{ code: 'western', name: 'Western' },
|
|
||||||
];
|
|
||||||
|
|
||||||
ngAfterViewInit() {
|
constructor(private genreService: GenreService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.getFilmGenreNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
this.checkScroll();
|
this.checkScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
getFilmGenreNames(): void {
|
||||||
|
this.genreService
|
||||||
|
.getGenres()
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe((genres) => {
|
||||||
|
this.filmGenres = genres;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
openCurrentVideo(videoId: number) {
|
openCurrentVideo(videoId: number) {
|
||||||
this.currentVideo = videoId;
|
this.currentVideo = videoId;
|
||||||
this.currentVideoId.emit(videoId);
|
this.currentVideoId.emit(videoId);
|
||||||
|
|
|
||||||
33
frontend/src/app/services/genre.service.ts
Normal file
33
frontend/src/app/services/genre.service.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable, of, tap } from 'rxjs';
|
||||||
|
import { ApiService } from './api.service';
|
||||||
|
|
||||||
|
export interface FilmGenre {
|
||||||
|
code: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class GenreService {
|
||||||
|
private genres: FilmGenre[] = [];
|
||||||
|
|
||||||
|
constructor(private apiService: ApiService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the genres either from the cache or from the API endpoint.
|
||||||
|
* @returns observable of movie genres
|
||||||
|
*/
|
||||||
|
getGenres(): Observable<FilmGenre[]> {
|
||||||
|
if (this.genres.length > 0) {
|
||||||
|
return of(this.genres);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.apiService.get<FilmGenre[]>('/video/genres/', true).pipe(
|
||||||
|
tap((data) => {
|
||||||
|
this.genres = data;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue