responsive design & bugfixes
This commit is contained in:
parent
fd7cb3a8dc
commit
55b63966cf
6 changed files with 178 additions and 30 deletions
|
|
@ -30,8 +30,7 @@ def video_list(request):
|
||||||
@permission_classes([IsAuthenticated])
|
@permission_classes([IsAuthenticated])
|
||||||
def check_video(request, id):
|
def check_video(request, id):
|
||||||
"""
|
"""
|
||||||
Check if a specific video exists in 480p, 720p, and 1080p resolutions
|
Check if a specific video exists in different resolutions (480p, 720p, 1080p).
|
||||||
URL: /content/movie/<video_id>/
|
|
||||||
"""
|
"""
|
||||||
resolutions = ['480', '720', '1080']
|
resolutions = ['480', '720', '1080']
|
||||||
result = {}
|
result = {}
|
||||||
|
|
@ -49,9 +48,13 @@ def check_video(request, id):
|
||||||
result[res] = os.path.exists(video_file_path)
|
result[res] = os.path.exists(video_file_path)
|
||||||
|
|
||||||
return JsonResponse(result)
|
return JsonResponse(result)
|
||||||
|
|
||||||
@api_view(['POST'])
|
@api_view(['POST'])
|
||||||
@permission_classes([IsAuthenticated])
|
@permission_classes([IsAuthenticated])
|
||||||
def video_upload(request):
|
def video_upload(request):
|
||||||
|
"""
|
||||||
|
Handle the upload of a video file.
|
||||||
|
"""
|
||||||
parser_classes = (MultiPartParser, FormParser)
|
parser_classes = (MultiPartParser, FormParser)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
serializer = VideoSerializer(data=request.data)
|
serializer = VideoSerializer(data=request.data)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<div *ngIf="recentMovies().length > 0" class="category">
|
<div *ngIf="recentMovies().length > 0" class="category">
|
||||||
<p>Added in the last 7 days</p>
|
<p>Added in the last 7 days</p>
|
||||||
<div class="movies">
|
<div class="movies">
|
||||||
|
<!-- Filme hier einfügen -->
|
||||||
@for (movie of recentMovies(); track movie) {
|
@for (movie of recentMovies(); track movie) {
|
||||||
<div class="movie" (click)="openCurrentMovie(movie.id)">
|
<div class="movie" (click)="openCurrentMovie(movie.id)">
|
||||||
<img
|
<img
|
||||||
|
|
@ -19,16 +20,22 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<!-- Buttons for scrolling -->
|
||||||
|
<div class="scroll-buttons">
|
||||||
|
<button class="scroll-left" (click)="scrollLeft($event)"></button>
|
||||||
|
<button class="scroll-right" (click)="scrollRight($event)"></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Genre columns -->
|
<!-- Genre columns -->
|
||||||
@for (filmGenre of filmGenres; track filmGenre) {
|
@for (filmGenre of filmGenres; track filmGenre) {
|
||||||
<!-- Movie available in genre -->
|
<!-- Movie available in genre -->
|
||||||
@if (allMovies(filmGenre).length > 0) {
|
@if (allMovies(filmGenre.code).length > 0) {
|
||||||
<div class="category">
|
<div class="category">
|
||||||
<p>{{ filmGenre }}</p>
|
<p>{{ filmGenre.name }}</p>
|
||||||
<div class="movies">
|
<div class="movies">
|
||||||
@for (movie of allMovies(filmGenre); track movie) {
|
@for (movie of allMovies(filmGenre.code); track movie) {
|
||||||
<div class="movie" (click)="openCurrentMovie(movie.id)">
|
<div class="movie" (click)="openCurrentMovie(movie.id)">
|
||||||
<img
|
<img
|
||||||
[ngClass]="{ selected: movie.id === currentMovie }"
|
[ngClass]="{ selected: movie.id === currentMovie }"
|
||||||
|
|
@ -44,6 +51,11 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<!-- Buttons for scrolling -->
|
||||||
|
<div class="scroll-buttons">
|
||||||
|
<button class="scroll-left" (click)="scrollLeft($event)"></button>
|
||||||
|
<button class="scroll-right" (click)="scrollRight($event)"></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
@import "./../../../../../assets/style/colors.scss";
|
@import "./../../../../../assets/style/colors.scss";
|
||||||
|
|
||||||
section {
|
section {
|
||||||
padding: 0 48px;
|
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
|
padding: 0 24px;
|
||||||
|
margin: 0 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category {
|
.category {
|
||||||
|
position: relative;
|
||||||
height: 165px;
|
height: 165px;
|
||||||
|
padding-top: 12px;
|
||||||
p {
|
p {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.movies {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.movie {
|
.movie {
|
||||||
width: 213px;
|
width: 213px;
|
||||||
height: 120px;
|
height: 120px;
|
||||||
|
|
@ -38,11 +37,71 @@ section {
|
||||||
border: 2px solid $blue !important;
|
border: 2px solid $blue !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Movies
|
||||||
|
|
||||||
|
.movies {
|
||||||
|
display: flex;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
padding: 0 24x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.movies::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-buttons {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
opacity: 0;
|
||||||
|
justify-content: space-between;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-buttons.show {
|
||||||
|
opacity: 1; /* Sichtbar machen, wenn Klasse 'show' hinzugefügt wird */
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-left,
|
||||||
|
.scroll-right {
|
||||||
|
background: url("./../../../../../assets/img/arrow_forward.svg") no-repeat
|
||||||
|
center;
|
||||||
|
background-size: 20px 30px;
|
||||||
|
border: none;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
pointer-events: auto;
|
||||||
|
&:hover {
|
||||||
|
transition: 125ms ease-in-out;
|
||||||
|
filter: brightness(0) saturate(100%) invert(26%) sepia(77%) saturate(2342%)
|
||||||
|
hue-rotate(228deg) brightness(83%) contrast(115%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-left {
|
||||||
|
position: absolute;
|
||||||
|
left: -32px;
|
||||||
|
background-image: url("./../../../../../assets/img/arrow_back.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-right {
|
||||||
|
position: absolute;
|
||||||
|
right: -38px;
|
||||||
|
background-image: url("./../../../../../assets/img/arrow_forward.svg");
|
||||||
|
}
|
||||||
|
|
||||||
// Hide scrollbar
|
// Hide scrollbar
|
||||||
|
|
||||||
.hide-scrollbar {
|
.hide-scrollbar {
|
||||||
overflow: scroll;
|
overflow-y: auto;
|
||||||
height: 60%;
|
overflow-x: hidden;
|
||||||
|
height: 50%;
|
||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
}
|
}
|
||||||
|
|
@ -50,3 +109,14 @@ section {
|
||||||
.hide-scrollbar::-webkit-scrollbar {
|
.hide-scrollbar::-webkit-scrollbar {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*------------- RESPONSIVE -------------*/
|
||||||
|
|
||||||
|
@media screen and (max-width: 400px) {
|
||||||
|
.category {
|
||||||
|
p {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
EventEmitter,
|
||||||
|
HostListener,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
Renderer2,
|
||||||
|
ViewChild,
|
||||||
|
} from '@angular/core';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -15,26 +25,32 @@ export class CategoriesComponent {
|
||||||
@Output() currentMovieId = new EventEmitter<number>();
|
@Output() currentMovieId = new EventEmitter<number>();
|
||||||
|
|
||||||
environmentBaseUrl: string = environment.baseUrl;
|
environmentBaseUrl: string = environment.baseUrl;
|
||||||
|
isScrollable: boolean = false;
|
||||||
|
|
||||||
filmGenres = [
|
filmGenres = [
|
||||||
'action',
|
{ code: 'action', name: 'Action' },
|
||||||
'adventure',
|
{ code: 'adventure', name: 'Adventure' },
|
||||||
'comedy',
|
{ code: 'comedy', name: 'Comedy' },
|
||||||
'drama',
|
{ code: 'drama', name: 'Drama' },
|
||||||
'horror',
|
{ code: 'horror', name: 'Horror' },
|
||||||
'science_fiction',
|
{ code: 'science_fiction', name: 'Science Fiction' },
|
||||||
'fantasy',
|
{ code: 'fantasy', name: 'Fantasy' },
|
||||||
'romance',
|
{ code: 'romance', name: 'Romance' },
|
||||||
'thriller',
|
{ code: 'thriller', name: 'Thriller' },
|
||||||
'mystery',
|
{ code: 'mystery', name: 'Mystery' },
|
||||||
'crime',
|
{ code: 'crime', name: 'Crime' },
|
||||||
'animation',
|
{ code: 'animation', name: 'Animation' },
|
||||||
'documentary',
|
{ code: 'documentary', name: 'Documentary' },
|
||||||
'musical',
|
{ code: 'musical', name: 'Musical' },
|
||||||
'war',
|
{ code: 'war', name: 'War' },
|
||||||
'western',
|
{ code: 'western', name: 'Western' },
|
||||||
|
{ code: 'other', name: 'Miscellaneous' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.checkScroll();
|
||||||
|
}
|
||||||
|
|
||||||
openCurrentMovie(movieId: number) {
|
openCurrentMovie(movieId: number) {
|
||||||
this.currentMovie = movieId;
|
this.currentMovie = movieId;
|
||||||
this.currentMovieId.emit(movieId);
|
this.currentMovieId.emit(movieId);
|
||||||
|
|
@ -50,8 +66,53 @@ export class CategoriesComponent {
|
||||||
sevenDaysAgo.setDate(today.getDate() - 7);
|
sevenDaysAgo.setDate(today.getDate() - 7);
|
||||||
|
|
||||||
return this.movies.filter((movie) => {
|
return this.movies.filter((movie) => {
|
||||||
const movieDate = new Date(movie.create);
|
const movieDate = new Date(movie.created_at);
|
||||||
return movieDate >= sevenDaysAgo;
|
return movieDate >= sevenDaysAgo;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Category scroll
|
||||||
|
|
||||||
|
@HostListener('window:resize')
|
||||||
|
onResize() {
|
||||||
|
this.checkScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
checkScroll() {
|
||||||
|
const containers = document.querySelectorAll(
|
||||||
|
'.movies'
|
||||||
|
) as NodeListOf<HTMLElement>;
|
||||||
|
containers.forEach((container) => {
|
||||||
|
const scrollButtons = container.parentElement?.querySelector(
|
||||||
|
'.scroll-buttons'
|
||||||
|
) as HTMLElement;
|
||||||
|
if (container && scrollButtons) {
|
||||||
|
if (container.scrollWidth > container.clientWidth) {
|
||||||
|
scrollButtons.classList.add('show');
|
||||||
|
} else {
|
||||||
|
scrollButtons.classList.remove('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollLeft(event: MouseEvent) {
|
||||||
|
const button = event.target as HTMLElement;
|
||||||
|
const container = button
|
||||||
|
.closest('.category')
|
||||||
|
?.querySelector('.movies') as HTMLElement;
|
||||||
|
if (container) {
|
||||||
|
container.scrollLeft -= 217;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollRight(event: MouseEvent) {
|
||||||
|
const button = event.target as HTMLElement;
|
||||||
|
const container = button
|
||||||
|
.closest('.category')
|
||||||
|
?.querySelector('.movies') as HTMLElement;
|
||||||
|
if (container) {
|
||||||
|
container.scrollLeft += 217;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
frontend/src/assets/img/arrow_back.svg
Normal file
1
frontend/src/assets/img/arrow_back.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M400-80 0-480l400-400 71 71-329 329 329 329-71 71Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 175 B |
1
frontend/src/assets/img/arrow_forward.svg
Normal file
1
frontend/src/assets/img/arrow_forward.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="m321-80-71-71 329-329-329-329 71-71 400 400L321-80Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 176 B |
Loading…
Reference in a new issue