From 4870349e23c6a0dea15a1f30436c4e9bec63ce4a Mon Sep 17 00:00:00 2001
From: Chneemann
Date: Thu, 8 Aug 2024 00:28:58 +0200
Subject: [PATCH] show error overlay for a backend error
---
backend/videoflix/auth/views.py | 12 ++---
frontend/src/app/app.component.html | 3 +-
frontend/src/app/app.component.ts | 2 +-
.../app/components/auth/auth.component.html | 4 +-
.../src/app/components/auth/auth.component.ts | 3 +-
.../forgot-password.component.html | 8 ++--
.../forgot-password.component.ts | 8 +++-
.../auth/login/login.component.html | 8 ++--
.../components/auth/login/login.component.ts | 4 +-
.../auth/register/register.component.html | 4 +-
.../auth/register/register.component.ts | 4 +-
.../verify-email/verify-email.component.html | 4 +-
.../verify-email/verify-email.component.ts | 17 ++-----
.../app/components/home/home.component.html | 1 +
.../app/components/home/home.component.scss | 8 ----
.../src/app/components/home/home.component.ts | 9 +++-
frontend/src/app/services/error.service.ts | 48 ++++++-------------
.../error-toast/error-toast.component.html | 39 +++++++--------
.../error-toast/error-toast.component.scss | 27 +++++++++++
.../error-toast/error-toast.component.ts | 19 ++++++--
20 files changed, 126 insertions(+), 106 deletions(-)
diff --git a/backend/videoflix/auth/views.py b/backend/videoflix/auth/views.py
index c112b1b..f8f531a 100644
--- a/backend/videoflix/auth/views.py
+++ b/backend/videoflix/auth/views.py
@@ -25,9 +25,9 @@ class LoginView(APIView):
if user:
if not user.is_active:
- return Response({'password': 'Account is inactive, please check your mails'}, status=status.HTTP_403_FORBIDDEN)
+ return Response({'error': 'Account is inactive, please check your mails'}, status=status.HTTP_403_FORBIDDEN)
return self._create_token_response(user)
- return Response({'mail': 'Unable to login with provided credentials.'}, status=status.HTTP_401_UNAUTHORIZED)
+ return Response({'error': 'Unable to login with provided credentials.'}, status=status.HTTP_401_UNAUTHORIZED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@@ -40,7 +40,7 @@ class RegisterView(APIView):
email = request.data.get('email')
password = request.data.get('password')
if CustomUser.objects.filter(email=email).exists():
- return Response({'mail': 'A user with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)
+ return Response({'error': 'A user with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)
serialized = UserSerializer(data=request.data)
if serialized.is_valid():
@@ -93,7 +93,7 @@ class ForgotPasswordView(APIView):
def post(self, request):
email = request.data.get('email')
if not email:
- return Response({"mail": "Email required."}, status=status.HTTP_400_BAD_REQUEST)
+ return Response({"error": "Email required."}, status=status.HTTP_400_BAD_REQUEST)
try:
user = CustomUser.objects.get(email=email)
@@ -101,7 +101,7 @@ class ForgotPasswordView(APIView):
user.save()
self.send_email(user)
except CustomUser.DoesNotExist:
- return Response({"mail": "This email does not exist."}, status=status.HTTP_400_BAD_REQUEST)
+ return Response({"error": "This email does not exist."}, status=status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_200_OK)
def send_email(self, user):
@@ -149,5 +149,5 @@ class AuthView(ObtainAuthToken):
def post(self, request):
email = request.data.get('email')
if CustomUser.objects.filter(email=email).exists():
- return Response({'mail': 'A user with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)
+ return Response({'error': 'A user with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_200_OK)
\ No newline at end of file
diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html
index 3c7c33b..67e7bd4 100644
--- a/frontend/src/app/app.component.html
+++ b/frontend/src/app/app.component.html
@@ -1,2 +1 @@
-
-
+
diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts
index 8cb1fac..4b631b0 100644
--- a/frontend/src/app/app.component.ts
+++ b/frontend/src/app/app.component.ts
@@ -5,7 +5,7 @@ import { ErrorToastComponent } from './shared/components/error-toast/error-toast
@Component({
selector: 'app-root',
standalone: true,
- imports: [RouterOutlet, ErrorToastComponent],
+ imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
diff --git a/frontend/src/app/components/auth/auth.component.html b/frontend/src/app/components/auth/auth.component.html
index 5a77ea9..741d4ff 100644
--- a/frontend/src/app/components/auth/auth.component.html
+++ b/frontend/src/app/components/auth/auth.component.html
@@ -33,11 +33,11 @@
!isUserEmailValid(authData.mail.toLowerCase())) {
This is not a valid email format
}}
-
+
This is not a valid email format
}}
-
+
The passwords do not match
}
-
+
This is not a valid email format
}}
-
+
Password is too short, min 6 characters
} }
-
+
-
+
diff --git a/frontend/src/app/components/auth/verify-email/verify-email.component.ts b/frontend/src/app/components/auth/verify-email/verify-email.component.ts
index 460edcc..6ce68ad 100644
--- a/frontend/src/app/components/auth/verify-email/verify-email.component.ts
+++ b/frontend/src/app/components/auth/verify-email/verify-email.component.ts
@@ -45,20 +45,9 @@ export class VerifyEmailComponent {
this.errorService.clearError();
} catch (error) {
this.verified = false;
- this.errorMsg(error);
- }
- }
-
- errorMsg(error: any) {
- if (error instanceof HttpErrorResponse) {
- const errorTypes = ['error'];
- for (const type of errorTypes) {
- if (error.error[type]) {
- this.errorService.setError(type, error.error[type]);
- return;
- }
- }
- this.errorService.clearError();
+ const errorMessage =
+ error instanceof Error ? error.message : 'An unknown error occurred';
+ this.errorService.errorMsg(errorMessage);
}
}
}
diff --git a/frontend/src/app/components/home/home.component.html b/frontend/src/app/components/home/home.component.html
index fc24b03..22e6d11 100644
--- a/frontend/src/app/components/home/home.component.html
+++ b/frontend/src/app/components/home/home.component.html
@@ -8,4 +8,5 @@
>
+
diff --git a/frontend/src/app/components/home/home.component.scss b/frontend/src/app/components/home/home.component.scss
index 962e72e..7697209 100644
--- a/frontend/src/app/components/home/home.component.scss
+++ b/frontend/src/app/components/home/home.component.scss
@@ -2,11 +2,3 @@ section {
width: 100vw;
height: 100vh;
}
-
-// .bg-home {
-// background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)),
-// url(./../../../assets/img/backgrounds/home.png);
-// background-size: cover;
-// background-position: center;
-// background-repeat: no-repeat;
-// }
diff --git a/frontend/src/app/components/home/home.component.ts b/frontend/src/app/components/home/home.component.ts
index 1921979..e187254 100644
--- a/frontend/src/app/components/home/home.component.ts
+++ b/frontend/src/app/components/home/home.component.ts
@@ -9,6 +9,8 @@ import { LoginComponent } from '../auth/login/login.component';
import { ForgotPasswordComponent } from '../auth/forgot-password/forgot-password.component';
import { BrowseComponent } from './browse/browse.component';
import { VerifyEmailComponent } from '../auth/verify-email/verify-email.component';
+import { ErrorToastComponent } from '../../shared/components/error-toast/error-toast.component';
+import { ErrorService } from '../../services/error.service';
@Component({
selector: 'app-home',
@@ -23,14 +25,19 @@ import { VerifyEmailComponent } from '../auth/verify-email/verify-email.componen
ForgotPasswordComponent,
VerifyEmailComponent,
BrowseComponent,
+ ErrorToastComponent,
],
templateUrl: './home.component.html',
styleUrl: './home.component.scss',
})
export class HomeComponent implements OnInit {
currentRoute: any;
+ displayErrorToast: boolean = false;
- constructor(private route: ActivatedRoute) {}
+ constructor(
+ private route: ActivatedRoute,
+ public errorService: ErrorService
+ ) {}
ngOnInit(): void {
this.route.url.subscribe((url) => {
diff --git a/frontend/src/app/services/error.service.ts b/frontend/src/app/services/error.service.ts
index b4d8b7a..8e4038f 100644
--- a/frontend/src/app/services/error.service.ts
+++ b/frontend/src/app/services/error.service.ts
@@ -1,49 +1,31 @@
-import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
-import { BehaviorSubject, Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
-
-export interface ErrorDetail {
- type: string;
- message: string;
-}
+import { BehaviorSubject } from 'rxjs';
+import { HttpErrorResponse } from '@angular/common/http';
@Injectable({
providedIn: 'root',
})
export class ErrorService {
- private errorSubject = new BehaviorSubject(null);
+ private errorSubject = new BehaviorSubject('');
+ errorText$ = this.errorSubject.asObservable();
+ displayError = false;
- error$: Observable<{ [key: string]: string } | null> = this.errorSubject
- .asObservable()
- .pipe(
- map((errorDetail) => {
- if (errorDetail) {
- return { [errorDetail.type]: errorDetail.message };
- }
- return null;
- })
- );
-
- setError(type: string, message: string) {
- const errorDetail: ErrorDetail = { type, message };
- this.errorSubject.next(errorDetail);
+ errorMsg(message: string) {
+ this.errorSubject.next(message);
+ this.displayError = true;
}
clearError() {
- this.errorSubject.next(null);
+ this.errorSubject.next('');
+ this.displayError = false;
}
- errorMsg(error: any) {
+ handleError(error: unknown) {
if (error instanceof HttpErrorResponse) {
- const errorTypes = ['mail', 'password', 'error'];
- for (const type of errorTypes) {
- if (error.error[type]) {
- this.setError(type, error.error[type]);
- return;
- }
- }
- this.clearError();
+ const errorMessage = error.error.error || 'An unknown error occurred';
+ this.errorMsg(errorMessage);
+ } else {
+ this.errorMsg('An unexpected error occurred');
}
}
}
diff --git a/frontend/src/app/shared/components/error-toast/error-toast.component.html b/frontend/src/app/shared/components/error-toast/error-toast.component.html
index a8fe40f..29e65c4 100644
--- a/frontend/src/app/shared/components/error-toast/error-toast.component.html
+++ b/frontend/src/app/shared/components/error-toast/error-toast.component.html
@@ -1,20 +1,21 @@
-
-
-
-
-
- Lorem ipsum dolor sit amet consectetur adipisicing elit. Provident aliquam
- ex earum esse, totam placeat omnis sequi sint eveniet maiores explicabo
- necessitatibus, est voluptatibus aperiam velit alias quae! Dicta aliquam
- aspernatur libero maiores tenetur aut ratione et esse nesciunt nostrum,
- cupiditate recusandae perferendis? Sapiente reprehenderit nemo repellendus
- libero adipisci explicabo!
-
-
-
-
-
-
+
+
+
+
+
+
+ {{ errorText }}
+
-
-
+
+
+
+
+
+
+
+
diff --git a/frontend/src/app/shared/components/error-toast/error-toast.component.scss b/frontend/src/app/shared/components/error-toast/error-toast.component.scss
index 201880a..556cb94 100644
--- a/frontend/src/app/shared/components/error-toast/error-toast.component.scss
+++ b/frontend/src/app/shared/components/error-toast/error-toast.component.scss
@@ -8,6 +8,16 @@ section {
border-radius: 20px;
background-color: $purple;
box-shadow: 1px 1px 3px rgba($black, 0.5);
+ opacity: 0;
+ transform: translateY(100vh);
+ animation: slide-in-bottom 500ms forwards;
+}
+
+@keyframes slide-in-bottom {
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
.left {
@@ -26,6 +36,7 @@ section {
display: flex;
align-items: center;
width: 82%;
+ min-height: 48px;
margin-left: 24px;
p {
font-size: 18px;
@@ -64,3 +75,19 @@ section {
}
}
}
+
+.overlay {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 100vw;
+ height: 100vh;
+ backdrop-filter: blur(5px);
+ background-color: rgba($color: #000000, $alpha: 0.2);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 999;
+}
diff --git a/frontend/src/app/shared/components/error-toast/error-toast.component.ts b/frontend/src/app/shared/components/error-toast/error-toast.component.ts
index e3b2283..0536bf2 100644
--- a/frontend/src/app/shared/components/error-toast/error-toast.component.ts
+++ b/frontend/src/app/shared/components/error-toast/error-toast.component.ts
@@ -1,4 +1,5 @@
-import { Component, Input } from '@angular/core';
+import { Component, Input, OnInit } from '@angular/core';
+import { ErrorService } from '../../../services/error.service';
@Component({
selector: 'app-error-toast',
@@ -7,6 +8,18 @@ import { Component, Input } from '@angular/core';
templateUrl: './error-toast.component.html',
styleUrl: './error-toast.component.scss',
})
-export class ErrorToastComponent {
- @Input() errorText: string = '';
+export class ErrorToastComponent implements OnInit {
+ errorText: string = '';
+
+ constructor(private errorService: ErrorService) {}
+
+ ngOnInit(): void {
+ this.errorService.errorText$.subscribe((message: string) => {
+ this.errorText = message;
+ });
+ }
+
+ closeError() {
+ this.errorService.clearError();
+ }
}