From 57ea0dade0b0f289bd5851e0358ed00e6f2fc950 Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Mon, 28 Aug 2023 21:55:51 +0200 Subject: [PATCH 01/11] done, refactoring needed --- .../reset-password.component.css | 93 ++++++++++++++++++- .../reset-password.component.html | 78 +++++++--------- .../reset-password.component.ts | 7 ++ frontend/src/assets/lock-svgrepo-com.svg | 5 + frontend/src/styles.scss | 5 + 5 files changed, 142 insertions(+), 46 deletions(-) create mode 100644 frontend/src/assets/lock-svgrepo-com.svg diff --git a/frontend/src/app/reset-password/reset-password.component.css b/frontend/src/app/reset-password/reset-password.component.css index f89d326f6..119a385af 100644 --- a/frontend/src/app/reset-password/reset-password.component.css +++ b/frontend/src/app/reset-password/reset-password.component.css @@ -23,8 +23,6 @@ h1{ grid-column: 3 / 4; text-align: center; /* background-color: var(--white); */ - padding: 80px 50px 20px; - margin-bottom: 80px; } .howToStart { @@ -105,4 +103,95 @@ h1{ background-color: var(--green); text-align: center; padding: 5px; +} + +.resetContainer{ + display: flex; + flex-direction: column; + align-items: center; + border: 2px solid gray; + margin: 20px; + width: 390px; + border-radius: 4px; +} + +.centeredPage { + display: flex; + flex-direction: column; + align-items: center; + height: 100%; + margin: 15px; +} + +.vertCenter { + display: flex; + flex-direction: row; + align-items: center; + height: 100%; + width: 100%; + justify-content: center; +} + +#message { + font-size: 14px; + width: 300px; + margin-bottom: 15px; + text-align: center; +} + +.darkLock { + width: 80px; + margin: 20px; + stroke: white; + opacity: 80%; + +} + +.lightLock { + width: 80px; + margin: 20px; + stroke: var(--dark-grey); +} + +.centered-line { + width: 100%; + display: flex; + justify-content: center; + align-items: center; + border-top: 1px solid grey; + margin: 0 20px; + } + +#orLine { + display: flex; + flex-direction: row; + align-items: center; + height: 100%; + width: 100%; + justify-content: center; + margin: 20px 0; + opacity: 70%; + font-size: 12px; +} + +#returnButton { + margin-top: 145px; + width: inherit; + margin-left: 0px; + margin-right: 0px; + font-style: inherit; + border: 1px; + font-size: 10pt; + font-weight: bold; + outline: none; + padding: 10px !important; + border: 2px solid gray; + border-bottom: 0px; + border-radius: 4px; + /* background: var(--dark-grey); */ +} + +#sendReset { + width: 100%; + border-radius: 4px; } \ No newline at end of file diff --git a/frontend/src/app/reset-password/reset-password.component.html b/frontend/src/app/reset-password/reset-password.component.html index 2dcf99113..de08110b0 100644 --- a/frontend/src/app/reset-password/reset-password.component.html +++ b/frontend/src/app/reset-password/reset-password.component.html @@ -1,47 +1,37 @@ -
- -
-
-

Can't log in?

-
-
-
-
1.Don't have an account yet?
-

If you don't have an account yet you can register an new account - -
-
-

2. Reset password for an existing account
-

If you already have an account but forgot your password you can reset your password here. -
-
- 1. Type in the e-mail address connected to your account. -
- 2. Choose a new password of miminum 8 characters. -
- 3. Press the 'reset' button and you will receive an automated e-mail with a reset-token. -

-
-
+
+
+
+
+ + + + +
+

Trouble loging in?

+
Enter your email of your account and we'll send you a link to get back into your account.
+
+

{{error}}

+

{{defaultSuccessMessage}}

+
+ + + +
+
+ + +
+
+ +
+
+
OR
+
+
-
-

{{error}}

-

{{defaultSuccessMessage}}

- -

Reset Your Password

-
-
-
-
- - - -
-
- - - -
-
+ + +
+
\ No newline at end of file diff --git a/frontend/src/app/reset-password/reset-password.component.ts b/frontend/src/app/reset-password/reset-password.component.ts index 862e85983..6b7786bd2 100644 --- a/frontend/src/app/reset-password/reset-password.component.ts +++ b/frontend/src/app/reset-password/reset-password.component.ts @@ -63,6 +63,13 @@ export class ResetPasswordComponent{ this.router.navigate(['/register']); } + /** + * Redirects the user to the login component + */ + redirectToLogin(){ + this.router.navigate(['/']); + } + isDarkModeOn () { this.isDark = this.themeService.isDarkMode(); return this.isDark diff --git a/frontend/src/assets/lock-svgrepo-com.svg b/frontend/src/assets/lock-svgrepo-com.svg new file mode 100644 index 000000000..79a30272a --- /dev/null +++ b/frontend/src/assets/lock-svgrepo-com.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index 3d1808cdc..fce54c1b5 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -670,6 +670,11 @@ $dark-theme: mat.define-dark-theme( background: var(--marine-blue); } +.normalButton:disabled{ + opacity: 20%; + pointer-events: none; +} + .darkTheme .normalButton:hover { background: var(--buttonHover); } From 97749f2eb3403cb7d5b37c38b4ef2406f7ae88fa Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Tue, 29 Aug 2023 11:13:53 +0200 Subject: [PATCH 02/11] resetPassowrd page done --- frontend/src/app/reset-password/reset-password.component.css | 1 - frontend/src/app/reset-password/reset-password.component.html | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/app/reset-password/reset-password.component.css b/frontend/src/app/reset-password/reset-password.component.css index 119a385af..40f0e9546 100644 --- a/frontend/src/app/reset-password/reset-password.component.css +++ b/frontend/src/app/reset-password/reset-password.component.css @@ -120,7 +120,6 @@ h1{ flex-direction: column; align-items: center; height: 100%; - margin: 15px; } .vertCenter { diff --git a/frontend/src/app/reset-password/reset-password.component.html b/frontend/src/app/reset-password/reset-password.component.html index de08110b0..30f0ec121 100644 --- a/frontend/src/app/reset-password/reset-password.component.html +++ b/frontend/src/app/reset-password/reset-password.component.html @@ -8,7 +8,7 @@

Trouble loging in?

-
Enter your email of your account and we'll send you a link to get back into your account.
+
Enter the email linked to your account, and we'll send you a link to regain access.

{{error}}

{{defaultSuccessMessage}}

From 6a3cb1c9bf3f91c738174fa48f93b493c633802d Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Tue, 29 Aug 2023 11:38:43 +0200 Subject: [PATCH 03/11] refactored --- .../src/app/reset-password/reset-password.component.css | 8 +++----- .../src/app/reset-password/reset-password.component.html | 6 +++--- frontend/src/assets/lock-svgrepo-com.svg | 5 ----- 3 files changed, 6 insertions(+), 13 deletions(-) delete mode 100644 frontend/src/assets/lock-svgrepo-com.svg diff --git a/frontend/src/app/reset-password/reset-password.component.css b/frontend/src/app/reset-password/reset-password.component.css index 40f0e9546..ccfcea26d 100644 --- a/frontend/src/app/reset-password/reset-password.component.css +++ b/frontend/src/app/reset-password/reset-password.component.css @@ -115,14 +115,14 @@ h1{ border-radius: 4px; } -.centeredPage { +.horCenetered { display: flex; flex-direction: column; align-items: center; height: 100%; } -.vertCenter { +.vertCentered { display: flex; flex-direction: row; align-items: center; @@ -131,7 +131,7 @@ h1{ justify-content: center; } -#message { +#resetText { font-size: 14px; width: 300px; margin-bottom: 15px; @@ -179,7 +179,6 @@ h1{ margin-left: 0px; margin-right: 0px; font-style: inherit; - border: 1px; font-size: 10pt; font-weight: bold; outline: none; @@ -187,7 +186,6 @@ h1{ border: 2px solid gray; border-bottom: 0px; border-radius: 4px; - /* background: var(--dark-grey); */ } #sendReset { diff --git a/frontend/src/app/reset-password/reset-password.component.html b/frontend/src/app/reset-password/reset-password.component.html index 30f0ec121..51cb6aab5 100644 --- a/frontend/src/app/reset-password/reset-password.component.html +++ b/frontend/src/app/reset-password/reset-password.component.html @@ -1,5 +1,5 @@ -
-
+
+
@@ -8,7 +8,7 @@

Trouble loging in?

-
Enter the email linked to your account, and we'll send you a link to regain access.
+
Enter the email linked to your account, and we'll send you a link to regain access.

{{error}}

{{defaultSuccessMessage}}

diff --git a/frontend/src/assets/lock-svgrepo-com.svg b/frontend/src/assets/lock-svgrepo-com.svg deleted file mode 100644 index 79a30272a..000000000 --- a/frontend/src/assets/lock-svgrepo-com.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file From 6559a4ef43f0c7a1e73f0d283a864d666f9cfa40 Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Tue, 29 Aug 2023 12:42:22 +0200 Subject: [PATCH 04/11] redesigned --- .../reset-password.component.css | 250 +++++++++--------- .../reset-password.component.html | 73 ++--- 2 files changed, 163 insertions(+), 160 deletions(-) diff --git a/frontend/src/app/reset-password/reset-password.component.css b/frontend/src/app/reset-password/reset-password.component.css index ccfcea26d..a1d547b87 100644 --- a/frontend/src/app/reset-password/reset-password.component.css +++ b/frontend/src/app/reset-password/reset-password.component.css @@ -1,194 +1,192 @@ * { - padding: 0px; - margin: 0px; - font-family: Klavika, sans-serif; + padding: 0px; + margin: 0px; + font-family: Klavika, sans-serif; } -h1{ - margin: 5px; +h1 { + margin: 5px; } -.grid{ - display: grid; - grid-template-rows: auto; - grid-template-columns: 1fr 1fr 1fr 1fr; - grid-template-areas: "howToStart" "formular"; - /* background-color: var(--white); */ - place-items: center; +.grid { + display: grid; + grid-template-rows: auto; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-areas: "howToStart" "formular"; + /* background-color: var(--white); */ + place-items: center; } -.formular{ - grid-area: formular; - grid-row: 2 / 3; - grid-column: 3 / 4; - text-align: center; - /* background-color: var(--white); */ +.formular { + grid-area: formular; + grid-row: 2 / 3; + grid-column: 3 / 4; + text-align: center; + /* background-color: var(--white); */ } .howToStart { - grid-area: howToStart; - grid-row: 2 / 3; - grid-column: 2 / 3; - background-color: var(--white); - padding: 50px 10px 50px; - text-align: center; - font-size: small; + grid-area: howToStart; + grid-row: 2 / 3; + grid-column: 2 / 3; + background-color: var(--white); + padding: 50px 10px 50px; + text-align: center; + font-size: small; } .darkTheme .howToStart { - background-color: #455A64; + background-color: #455a64; } -.instructionText{ - width: 350px; - border: double 5px var(--dark-grey); - padding: 30px; +.instructionText { + width: 350px; + border: double 5px var(--dark-grey); + padding: 30px; } .darkTheme .instructionText { - border: double 5px #90A4AE; + border: double 5px #90a4ae; } -.req{ - text-decoration: underline; +.req { + text-decoration: underline; } -#headerFont{ - color:var(--ocean-blue); +#headerFont { + color: var(--ocean-blue); } .darkTheme #headerFont { - color:var(--light-blue); + color: var(--light-blue); } - -.uk-form-controls{ - border-radius: 3px; - padding: 5px 5px 5px 5px; +.uk-form-controls { + border-radius: 3px; + padding: 5px 5px 5px 5px; } .darkTheme .uk-form-controls { - background: #455A64; + background: #455a64; } -.linkButton{ - font-style: inherit; - border: 0px; - background-color: transparent; - color:var(--ocean-blue); - font-size: 10pt; - font-weight: bold; - outline: none; +.linkButton { + font-style: inherit; + border: 0px; + background-color: transparent; + color: var(--ocean-blue); + font-size: 10pt; + font-weight: bold; + outline: none; } .darkTheme .linkButton { - color: var(--light-blue); + color: var(--light-blue); } @media screen and (max-width: 600px) { - .grid{ - display: grid; - grid-template-rows: auto; - grid-template-areas: "howToStart" "formular"; - } + .grid { + display: grid; + grid-template-rows: auto; + grid-template-areas: "howToStart" "formular"; + } } -.wrongReset{ - background-color: var(--grape); - text-align: center; - padding: 5px; +.wrongReset { + background-color: var(--grape); + text-align: center; + padding: 5px; } -.successReset{ - background-color: var(--green); - text-align: center; - padding: 5px; +.successReset { + background-color: var(--green); + text-align: center; + padding: 5px; } -.resetContainer{ - display: flex; - flex-direction: column; - align-items: center; - border: 2px solid gray; - margin: 20px; - width: 390px; - border-radius: 4px; +.resetContainer { + display: flex; + flex-direction: column; + align-items: center; + border: 2px solid gray; + margin: 20px; + width: 390px; + border-radius: 4px; } -.horCenetered { - display: flex; - flex-direction: column; - align-items: center; - height: 100%; +.vertCentered { + display: flex; + flex-direction: column; + align-items: center; + height: 100%; } -.vertCentered { - display: flex; - flex-direction: row; - align-items: center; - height: 100%; - width: 100%; - justify-content: center; +.horCentered { + display: flex; + flex-direction: row; + align-items: center; + height: 100%; + width: 100%; + justify-content: center; } #resetText { - font-size: 14px; - width: 300px; - margin-bottom: 15px; - text-align: center; + font-size: 14px; + width: 300px; + margin-bottom: 15px; + text-align: center; } .darkLock { - width: 80px; - margin: 20px; - stroke: white; - opacity: 80%; - + width: 80px; + margin: 20px; + stroke: white; + opacity: 80%; } .lightLock { - width: 80px; - margin: 20px; - stroke: var(--dark-grey); + width: 80px; + margin: 20px; + stroke: var(--dark-grey); } .centered-line { - width: 100%; - display: flex; - justify-content: center; - align-items: center; - border-top: 1px solid grey; - margin: 0 20px; - } + width: 100%; + display: flex; + justify-content: center; + align-items: center; + border-top: 1px solid grey; + margin: 0 20px; +} #orLine { - display: flex; - flex-direction: row; - align-items: center; - height: 100%; - width: 100%; - justify-content: center; - margin: 20px 0; - opacity: 70%; - font-size: 12px; + display: flex; + flex-direction: row; + align-items: center; + height: 100%; + width: 100%; + justify-content: center; + margin: 20px 0; + opacity: 70%; + font-size: 12px; } #returnButton { - margin-top: 145px; - width: inherit; - margin-left: 0px; - margin-right: 0px; - font-style: inherit; - font-size: 10pt; - font-weight: bold; - outline: none; - padding: 10px !important; - border: 2px solid gray; - border-bottom: 0px; - border-radius: 4px; + margin-top: 145px; + width: inherit; + margin-left: 0px; + margin-right: 0px; + font-style: inherit; + font-size: 10pt; + font-weight: bold; + outline: none; + padding: 10px !important; + border: 2px solid gray; + border-bottom: 0px; + border-radius: 4px; } #sendReset { - width: 100%; - border-radius: 4px; -} \ No newline at end of file + width: 100%; + border-radius: 4px; +} diff --git a/frontend/src/app/reset-password/reset-password.component.html b/frontend/src/app/reset-password/reset-password.component.html index 51cb6aab5..263e24089 100644 --- a/frontend/src/app/reset-password/reset-password.component.html +++ b/frontend/src/app/reset-password/reset-password.component.html @@ -1,37 +1,42 @@ -
-
-
-
- - - - -
-

Trouble loging in?

-
Enter the email linked to your account, and we'll send you a link to regain access.
-
-

{{error}}

-

{{defaultSuccessMessage}}

-
- - - -
-
- - -
-
+
+
+
+
+ + + + +
+

Trouble loging in?

+
Enter the email linked to your account, and we'll send you a link to regain access. +
+
+

{{error}}

+

{{defaultSuccessMessage}}

+
+ + + +
+
+ + +
+
-
-
-
OR
-
-
+
+
+
OR
+
+
- - + + +
-
-
- \ No newline at end of file +
\ No newline at end of file From 7f30e53b10b4d0ac1beceaceac80f6630f0f7c33 Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Tue, 29 Aug 2023 13:01:59 +0200 Subject: [PATCH 05/11] Fixed error messages --- .../reset-password.component.css | 8 ++- .../reset-password.component.html | 4 +- .../reset-password.component.ts | 62 +++++++++---------- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/frontend/src/app/reset-password/reset-password.component.css b/frontend/src/app/reset-password/reset-password.component.css index a1d547b87..fafbe598f 100644 --- a/frontend/src/app/reset-password/reset-password.component.css +++ b/frontend/src/app/reset-password/reset-password.component.css @@ -93,15 +93,17 @@ h1 { } .wrongReset { - background-color: var(--grape); + background-color: var(--danger); text-align: center; - padding: 5px; + padding: 7px; + border-radius: 4px; } .successReset { background-color: var(--green); text-align: center; - padding: 5px; + padding: 7px; + border-radius: 4px; } .resetContainer { diff --git a/frontend/src/app/reset-password/reset-password.component.html b/frontend/src/app/reset-password/reset-password.component.html index 263e24089..3d18417a6 100644 --- a/frontend/src/app/reset-password/reset-password.component.html +++ b/frontend/src/app/reset-password/reset-password.component.html @@ -13,9 +13,9 @@

Trouble loging in?

Enter the email linked to your account, and we'll send you a link to regain access.
+

{{error}}

+

{{defaultSuccessMessage}}

-

{{error}}

-

{{defaultSuccessMessage}}

diff --git a/frontend/src/app/reset-password/reset-password.component.ts b/frontend/src/app/reset-password/reset-password.component.ts index 6b7786bd2..c246a88a0 100644 --- a/frontend/src/app/reset-password/reset-password.component.ts +++ b/frontend/src/app/reset-password/reset-password.component.ts @@ -1,39 +1,40 @@ -import { Component} from '@angular/core'; -import { NgForm } from '@angular/forms'; -import {Router} from '@angular/router'; -import { ThemingService } from '../Services/theming.service'; -import { LoginService } from '../Services/login.service'; +import { Component } from "@angular/core"; +import { NgForm } from "@angular/forms"; +import { Router } from "@angular/router"; +import { ThemingService } from "../Services/theming.service"; +import { LoginService } from "../Services/login.service"; /** * Component to reset the password */ @Component({ - selector: 'app-reset-password', - templateUrl: './reset-password.component.html', - styleUrls: ['./reset-password.component.css'] + selector: "app-reset-password", + templateUrl: "./reset-password.component.html", + styleUrls: ["./reset-password.component.css"], }) - -export class ResetPasswordComponent{ - +export class ResetPasswordComponent { /** * Error during reset password */ error: string; - defaultErrorMessage = 'Reset password email faild'; + defaultErrorMessage = "Reset password email faild"; /** * Successfully sent email */ success: string; - defaultSuccessMessage = "Email with password reset link has been send!" + defaultSuccessMessage = "Email has been sent!"; - isDark :boolean; + isDark: boolean; /** * @ignore */ - constructor(public loginService: LoginService, private router: Router, public themeService:ThemingService) { - } + constructor( + public loginService: LoginService, + private router: Router, + public themeService: ThemingService + ) {} ngOnInit(): void { this.isDark = this.themeService.isDarkMode(); @@ -41,38 +42,37 @@ export class ResetPasswordComponent{ /** * Request a reset of the password - * @param form + * @param form */ - requestReset(form : NgForm) { + requestReset(form: NgForm) { this.loginService.requestReset(form.value.email).subscribe({ - next: value => { + next: (value) => { this.error = undefined; this.success = this.defaultSuccessMessage; }, - error: error => { + error: (error) => { this.success = undefined; - this.error = this.defaultErrorMessage + ": " + error.error; + this.error = error.error; }, - }) + }); } /** * Redirects the user to the register component */ - redirectToRegister(){ - this.router.navigate(['/register']); + redirectToRegister() { + this.router.navigate(["/register"]); } - /** + /** * Redirects the user to the login component */ - redirectToLogin(){ - this.router.navigate(['/']); - } + redirectToLogin() { + this.router.navigate(["/"]); + } - isDarkModeOn () { + isDarkModeOn() { this.isDark = this.themeService.isDarkMode(); - return this.isDark + return this.isDark; } - } From 885b82ba4562b9b0d21e0fce506bd34c998eded5 Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Tue, 29 Aug 2023 19:07:02 +0200 Subject: [PATCH 06/11] styled email --- backend/src/nodemailer.js | 99 ++++++++++++++++--- .../reset-password.component.html | 4 +- .../reset-password.component.ts | 6 ++ 3 files changed, 93 insertions(+), 16 deletions(-) diff --git a/backend/src/nodemailer.js b/backend/src/nodemailer.js index ba547e721..26d8c15a9 100644 --- a/backend/src/nodemailer.js +++ b/backend/src/nodemailer.js @@ -3,12 +3,12 @@ const nodemailer = require('nodemailer'); async function sendResetLink(email, id) { if (process.env.EMAIL_HOST === undefined || process.env.EMAIL_PORT === undefined) { - log("To send emails please provide a email server and port. You can see how to do it in the README."); - throw new Error("Bad email config") + log('To send emails please provide a email server and port. You can see how to do it in the README.'); + throw new Error('Bad email config'); } if (process.env.EMAIL_AUTH === undefined || process.env.EMAIL_PW === undefined) { - log("To send emails please provide a valid email account. You can see how to do it in the README."); - throw new Error("Bad email config") + log('To send emails please provide a valid email account. You can see how to do it in the README.'); + throw new Error('Bad email config'); } const transporter = nodemailer.createTransport({ @@ -28,16 +28,87 @@ async function sendResetLink(email, id) { from: 'seed-test@mail.de', to: email, subject: 'Seed-Test-Password-Reset', - html: `

- Sie haben kürzlich versucht das Passwort Ihres Seed-Test-Account zu ändern.
- Falls das nicht Sie waren, oder Sie keine Änderung der Passworts wünschen, ignorieren Sie diese Mail.

- Klicken Sie auf folgenden Link, um jetzt Ihr Passwort zu ändern: - Click here

- Dieser Link und die Anfrage verfallen in 60 Minuten.
- Dies ist eine automatische E-Mail, bitte antworten Sie nicht darauf.


- Mit freundlichen Grüßen
- Das Seed-Test Team -

` + html: ` + + + + + + + + + +
+ + + + + + + + + + + + +
+ +
+
+

Hello Seed-User,

+

We're sorry to hear that you have trouble logging into your account. + We have been informed that you have forgotten your password. + You can reset your password by clicking the button below:

+

+ + + + +
+ + Reset password + +
+

+ +
+

If it wasn't you who requested the reset, then you can just ignore this email.

+

This email was sent automatically, please don't respond to this email.

+
+ + + + +
+
+

Hallo Seed-Benutzer,

+

Es tut uns leid zu hören, dass Sie Probleme beim Einloggen in Ihr Konto haben. + Wir haben erfahren, dass Sie Ihr Passwort vergessen haben. + Sie können Ihr Passwort zurücksetzen, indem Sie auf den unten stehenden Button klicken: +

+

+ + + + +
+ + Passwort zurücksetzen + +
+

+ +
+

Wenn Sie die Zurücksetzung nicht angefordert haben, können Sie diese E-Mail einfach + ignorieren.

+

Diese E-Mail wurde automatisch versendet, bitte antworten Sie nicht darauf.

+
+
+ + +` }; transporter.sendMail(mailOptions, (error, info) => { diff --git a/frontend/src/app/reset-password/reset-password.component.html b/frontend/src/app/reset-password/reset-password.component.html index 3d18417a6..263e24089 100644 --- a/frontend/src/app/reset-password/reset-password.component.html +++ b/frontend/src/app/reset-password/reset-password.component.html @@ -13,9 +13,9 @@

Trouble loging in?

Enter the email linked to your account, and we'll send you a link to regain access.
-

{{error}}

-

{{defaultSuccessMessage}}

+

{{error}}

+

{{defaultSuccessMessage}}

diff --git a/frontend/src/app/reset-password/reset-password.component.ts b/frontend/src/app/reset-password/reset-password.component.ts index c246a88a0..5ffe02ed0 100644 --- a/frontend/src/app/reset-password/reset-password.component.ts +++ b/frontend/src/app/reset-password/reset-password.component.ts @@ -45,6 +45,8 @@ export class ResetPasswordComponent { * @param form */ requestReset(form: NgForm) { + this.error = undefined; + this.success = undefined; this.loginService.requestReset(form.value.email).subscribe({ next: (value) => { this.error = undefined; @@ -52,6 +54,10 @@ export class ResetPasswordComponent { }, error: (error) => { this.success = undefined; + if (error !== "No user found with the given email adress!") { + this.error = "Email couldn't be send."; + return; + } this.error = error.error; }, }); From 4fa420d2e78a888c1d32655a8f7556800f66d9c7 Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Wed, 30 Aug 2023 14:50:07 +0200 Subject: [PATCH 07/11] resetPassword redesigned --- frontend/src/app/Services/login.service.ts | 199 ++++++++++-------- .../confirm-reset-password.component.css | 164 +++++++++++---- .../confirm-reset-password.component.html | 68 +++--- .../confirm-reset-password.component.ts | 88 ++++++-- .../reset-password.component.css | 1 + 5 files changed, 341 insertions(+), 179 deletions(-) diff --git a/frontend/src/app/Services/login.service.ts b/frontend/src/app/Services/login.service.ts index 3f480eed7..2899e027d 100644 --- a/frontend/src/app/Services/login.service.ts +++ b/frontend/src/app/Services/login.service.ts @@ -1,94 +1,99 @@ -import { EventEmitter, Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { ApiService } from '../Services/api.service'; -import { HttpClient } from '@angular/common/http'; -import { catchError, tap } from 'rxjs/operators'; +import { EventEmitter, Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { ApiService } from "../Services/api.service"; +import { HttpClient } from "@angular/common/http"; +import { catchError, tap } from "rxjs/operators"; /** * Service for communication between login component and the backend */ @Injectable({ - providedIn: 'root' + providedIn: "root", }) export class LoginService { - /** - * @ignore - */ - constructor(public apiService: ApiService, private http: HttpClient) { } + * @ignore + */ + constructor(public apiService: ApiService, private http: HttpClient) {} /** - * Event emitter to logout the user - */ + * Event emitter to logout the user + */ public logoutEvent = new EventEmitter(); /** - * Starts the github login - */ + * Starts the github login + */ public githubLogin() { - const scope = 'repo'; - const AUTHORIZE_URL = 'https://github.com/login/oauth/authorize'; - const s = `${AUTHORIZE_URL}?scope=${scope}&client_id=${localStorage.getItem('clientId')}`; + const scope = "repo"; + const AUTHORIZE_URL = "https://github.com/login/oauth/authorize"; + const s = `${AUTHORIZE_URL}?scope=${scope}&client_id=${localStorage.getItem( + "clientId" + )}`; window.location.href = s; } /** - * Returns the callback from github to the backend - * @param code - * @returns - */ + * Returns the callback from github to the backend + * @param code + * @returns + */ githubCallback(code: string): Observable { - const url = this.apiService.apiServer + '/user/callback?code=' + code; - return this.http.get(url, { withCredentials: true }) - .pipe(tap(_ => { + const url = this.apiService.apiServer + "/user/callback?code=" + code; + return this.http.get(url, { withCredentials: true }).pipe( + tap((_) => { // }), - catchError(this.apiService.handleError)); + catchError(this.apiService.handleError) + ); } /** - * Loggs in the user with a github token - * @param login - * @param id - * @returns - */ + * Loggs in the user with a github token + * @param login + * @param id + * @returns + */ loginGithubToken(login: string, id): Observable { - const str = this.apiService.apiServer + '/user/githubLogin'; + const str = this.apiService.apiServer + "/user/githubLogin"; const user = { login, id }; - return this.http.post(str, user, ApiService.getOptions()) - .pipe(tap(_ => { + return this.http.post(str, user, ApiService.getOptions()).pipe( + tap((_) => { // }), - catchError(this.apiService.handleError)); + catchError(this.apiService.handleError) + ); } /** - * Merges Seed-Test account and github account - * @param userId - * @param login - * @param id - * @returns - */ + * Merges Seed-Test account and github account + * @param userId + * @param login + * @param id + * @returns + */ mergeAccountGithub(userId: string, login: string, id: any) { - const str = this.apiService.apiServer + '/user/mergeGithub'; - const body = {userId, login, id}; + const str = this.apiService.apiServer + "/user/mergeGithub"; + const body = { userId, login, id }; - return this.http.post(str, body, ApiService.getOptions()) - .pipe(tap(_ => { - // - }), - catchError(this.apiService.handleError)); + return this.http.post(str, body, ApiService.getOptions()).pipe( + tap((_) => { + // + }), + catchError(this.apiService.handleError) + ); } /** - * Loggs in a user - * @param user - * @returns - */ + * Loggs in a user + * @param user + * @returns + */ loginUser(user): Observable { - const str = this.apiService.apiServer + '/user/login'; + const str = this.apiService.apiServer + "/user/login"; - return this.http.post(str, user, ApiService.getOptions()) - .pipe(tap(_ => { + return this.http.post(str, user, ApiService.getOptions()).pipe( + tap((_) => { // }), - catchError(this.apiService.handleError)); + catchError(this.apiService.handleError) + ); } /** * Loggs in the user into jira @@ -96,30 +101,39 @@ export class LoginService { * @param jiraPassword * @param jiraServer * @returns - */ + */ jiraLogin(jiraName: string, jiraPassword: string, jiraServer: string) { const body = { jiraAccountName: jiraName, jiraPassword: jiraPassword, - jiraServer: jiraServer + jiraServer: jiraServer, }; - return this.http.post(this.apiService.apiServer + '/jira/login', body, ApiService.getOptions()) - .pipe(tap(resp => { - localStorage.setItem('JiraSession', resp.toString()); - })); + return this.http + .post( + this.apiService.apiServer + "/jira/login", + body, + ApiService.getOptions() + ) + .pipe( + tap((resp) => { + localStorage.setItem("JiraSession", resp.toString()); + }) + ); } /** * Requests a password reset * @param email * @returns - */ + */ public requestReset(email: string): Observable { - const body = { 'email': email }; + const body = { email: email }; return this.http - .post(this.apiService.apiServer + '/user/resetpassword/', body) - .pipe(tap(_ => { - // - })); + .post(this.apiService.apiServer + "/user/resetpassword/", body) + .pipe( + tap((_) => { + // + }) + ); } /** @@ -127,34 +141,38 @@ export class LoginService { * @param uuid * @param password * @returns - */ + */ confirmReset(uuid: string, password: string): Observable { - const body = { 'uuid': uuid, 'password': password }; + const body = { uuid: uuid, password: password }; return this.http - .patch(this.apiService.apiServer + '/user/reset', body) - .pipe(tap(_ => { - // - })); + .patch(this.apiService.apiServer + "/user/reset", body) + .pipe( + tap((_) => { + // + }), + catchError(this.apiService.handleError) + ); } /** - * If the user is logged in - * @returns - */ + * If the user is logged in + * @returns + */ isLoggedIn(): boolean { - return !!localStorage.getItem('login'); + return !!localStorage.getItem("login"); } /** * Logs out the user * @returns - */ + */ logoutUser() { - const url = this.apiService.apiServer + '/user/logout'; - localStorage.removeItem('login'); - return this.http.get(url, ApiService.getOptions()) - .pipe(tap(_ => { + const url = this.apiService.apiServer + "/user/logout"; + localStorage.removeItem("login"); + return this.http.get(url, ApiService.getOptions()).pipe( + tap((_) => { // }), - catchError(this.apiService.handleError)); + catchError(this.apiService.handleError) + ); } /** * Registers a user for a seed-test account @@ -162,15 +180,16 @@ export class LoginService { * @param password * @param userId * @returns - */ + */ registerUser(email: string, password: string, userId: any): Observable { const user = { email, password, userId }; return this.http - .post(this.apiService.apiServer + '/user/register', user) - .pipe(tap(_ => { - // - }), - catchError(this.apiService.handleError)); + .post(this.apiService.apiServer + "/user/register", user) + .pipe( + tap((_) => { + // + }), + catchError(this.apiService.handleError) + ); } - } diff --git a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css index 97f8c32ed..72a85acf0 100644 --- a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css +++ b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css @@ -1,67 +1,147 @@ * { - padding: 0px; - margin: 0px; + padding: 0px; + margin: 0px; } - -#headerFont{ - color:var(--ocean-blue); +#headerFont { + color: var(--ocean-blue); } -.grid{ - display: grid; - grid-template-rows: auto; - grid-template-columns: 1fr 1fr 1fr; - grid-template-areas: "formular"; - background-color: var(--white); - place-items: center; +.grid { + display: grid; + grid-template-rows: auto; + grid-template-columns: 1fr 1fr 1fr; + grid-template-areas: "formular"; + background-color: var(--white); + place-items: center; } -.formular{ - grid-area: formular; - grid-column: 2 / 3; - text-align: center; - background-color: var(--white); - padding: 80px 50px 20px; - margin-bottom: 80px; +.formular { + grid-area: formular; + grid-row: 2 / 3; + grid-column: 3 / 4; + text-align: center; + /* background-color: var(--white); */ } +#passwordLengthInfo { + font-size: small; + color: black; +} -#passwordLengthInfo{ - font-size: small; - color: black; +#headerFont { + color: var(--ocean-blue); } -#headerFont{ - color:var(--ocean-blue); +.uk-form-controls { + border-radius: 3px; + padding: 5px 5px 5px 5px; } -.uk-form-controls{ - border-radius: 3px; - padding: 5px 5px 5px 5px; +.ng-valid[required], +.ng-valid.required { + border-left: 5px solid #53d35a; } -.ng-valid[required], .ng-valid.required { - border-left: 5px solid #53d35a; - } - -.ng-invalid:not(form) { - border-left: 5px solid var(--ocean-blue); - } +.ng-invalid:not(form) { + border-left: 5px solid var(--ocean-blue); +} .cross-validation-error input { - border-left: 5px solid #d15553; - } + border-left: 5px solid #d15553; +} input.wrongEmail { border-left: 5px solid #d15553; } -#email, #confirmPassword{ - margin: 25px; +#email, +#confirmPassword { + margin: 25px; +} + +.wrongLogin { + background-color: rgb(228, 92, 92); + text-align: center; +} + +#returnButton { + margin-top: 145px; + width: inherit; + margin-left: 0px; + margin-right: 0px; + font-style: inherit; + font-size: 10pt; + font-weight: bold; + outline: none; + padding: 10px !important; + border: 2px solid gray; + border-bottom: 0px; + border-radius: 4px; +} + +#sendReset { + width: 100%; + border-radius: 4px; +} + +.wrongReset { + background-color: var(--danger); + text-align: center; + padding: 7px; + border-radius: 4px; } -.wrongLogin{ - background-color: rgb(228, 92, 92); - text-align: center; -} \ No newline at end of file +.successReset { + background-color: var(--green); + text-align: center; + padding: 7px; + border-radius: 4px; +} + +.resetContainer { + display: flex; + flex-direction: column; + align-items: center; + border: 2px solid gray; + margin: 20px; + width: 390px; + border-radius: 4px; + background-color: #d3d3d345; +} + +.vertCentered { + display: flex; + flex-direction: column; + align-items: center; + height: 100%; +} + +.horCentered { + display: flex; + flex-direction: row; + align-items: center; + height: 100%; + width: 100%; + justify-content: center; +} + +#resetText { + font-size: 14px; + width: 300px; + margin-bottom: 15px; + text-align: center; +} + +.darkLock { + width: 80px; + margin: 20px; + stroke: white; + opacity: 80%; +} + +.lightLock { + width: 80px; + margin: 20px; + stroke: var(--dark-grey); +} diff --git a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html index ef83c2c87..c49009a64 100644 --- a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html +++ b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html @@ -1,30 +1,46 @@ -
- -
- -

Reset Your Password

- -
-
-
- - - - - Password must be at least 8 characters long -
- +
+
+
+
+ + + +
+

Set a secure password

+
Your password must consist of at least 8 characters. +
+
+

{{error}}

+

{{defaultSuccessMessage}}

+ + +
+ +
+
+
+ +
+ +
+
+ + + +
-
-
- - - + +
\ No newline at end of file diff --git a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts index 9733e0285..710cb3f63 100644 --- a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts +++ b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts @@ -1,19 +1,18 @@ -import { Component} from '@angular/core'; -import { NgForm } from '@angular/forms'; -import {ActivatedRoute, Router} from '@angular/router'; -import { LoginService } from '../Services/login.service'; +import { Component } from "@angular/core"; +import { NgForm } from "@angular/forms"; +import { ActivatedRoute, Router } from "@angular/router"; +import { ThemingService } from "../Services/theming.service"; +import { LoginService } from "../Services/login.service"; /** * Component to enable to reset the password */ @Component({ - selector: 'app-confirm-reset-password', - templateUrl: './confirm-reset-password.component.html', - styleUrls: ['./confirm-reset-password.component.css'] + selector: "app-confirm-reset-password", + templateUrl: "./confirm-reset-password.component.html", + styleUrls: ["./confirm-reset-password.component.css"], }) - export class ConfirmResetPasswordComponent { - /** * Id of the reset password request */ @@ -22,30 +21,77 @@ export class ConfirmResetPasswordComponent { /** * New Password of the user */ - password: string; + password: string; + + /** + * Error during reset password + */ + error: string; + defaultErrorMessage = "Couldn't set password!"; + + /** + * Successfully sent email + */ + success: string; + defaultSuccessMessage = "Password set!"; - + isDark: boolean; /** * Constructor * @param loginService - * @param router - * @param route + * @param router + * @param route */ - constructor(public loginService: LoginService, private router: Router, private route: ActivatedRoute) { + constructor( + public loginService: LoginService, + private router: Router, + private route: ActivatedRoute, + private themeService: ThemingService + ) { this.route.queryParams.subscribe((params) => { - if (params.uuid){ - this.uuid = params.uuid; - } - }) + if (params.uuid) { + this.uuid = params.uuid; + } + }); + } + + ngOnInit(): void { + this.isDark = this.themeService.isDarkMode(); } /** * Confirm the reset and send new password * @param form form with the new password value */ - confirmReset(form : NgForm) { - this.loginService.confirmReset(this.uuid, form.value.password).toPromise() - this.router.navigate(['/login']); + confirmReset(form: NgForm) { + this.error = undefined; + this.success = undefined; + this.loginService.confirmReset(this.uuid, form.value.password).subscribe({ + next: (value) => { + this.error = undefined; + this.success = this.defaultSuccessMessage; + // setTimeout(function () { + // // this.router.navigate(["/login"]); + // }, 1500); + console.log(value); + }, + error: (error) => { + this.success = undefined; + this.error = this.defaultErrorMessage; + console.log(error); + }, + }); } + /** + * Redirects the user to the login component + */ + redirectToLogin() { + this.router.navigate(["/"]); + } + + isDarkModeOn() { + this.isDark = this.themeService.isDarkMode(); + return this.isDark; + } } diff --git a/frontend/src/app/reset-password/reset-password.component.css b/frontend/src/app/reset-password/reset-password.component.css index fafbe598f..c726b4446 100644 --- a/frontend/src/app/reset-password/reset-password.component.css +++ b/frontend/src/app/reset-password/reset-password.component.css @@ -114,6 +114,7 @@ h1 { margin: 20px; width: 390px; border-radius: 4px; + background-color: #d3d3d345; } .vertCentered { From f6138c7b9ebe6553b277c63c89f23102662a66f6 Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Wed, 30 Aug 2023 17:27:48 +0200 Subject: [PATCH 08/11] edited error handling --- .../app/Services/http-logger.interceptor.ts | 56 ++++++++++++------- .../confirm-reset-password.component.css | 16 ++++++ .../confirm-reset-password.component.html | 8 ++- .../confirm-reset-password.component.ts | 21 +++++-- .../reset-password.component.html | 4 +- 5 files changed, 78 insertions(+), 27 deletions(-) diff --git a/frontend/src/app/Services/http-logger.interceptor.ts b/frontend/src/app/Services/http-logger.interceptor.ts index f8b547dd5..edf17ecb9 100644 --- a/frontend/src/app/Services/http-logger.interceptor.ts +++ b/frontend/src/app/Services/http-logger.interceptor.ts @@ -1,6 +1,13 @@ -import { Injectable } from '@angular/core'; -import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse, HttpStatusCode} from '@angular/common/http'; -import { tap, catchError} from 'rxjs/operators'; +import { Injectable } from "@angular/core"; +import { + HttpInterceptor, + HttpRequest, + HttpHandler, + HttpEvent, + HttpErrorResponse, + HttpStatusCode, +} from "@angular/common/http"; +import { tap, catchError } from "rxjs/operators"; import { NGXLogger } from "ngx-logger"; import { Observable, throwError } from "rxjs"; @@ -8,27 +15,38 @@ import { Observable, throwError } from "rxjs"; export class HttpLoggerInterceptor implements HttpInterceptor { constructor(private logger: NGXLogger) { console.log("constructor http interceptor"); - } - intercept(req: HttpRequest, next: HttpHandler): Observable> { + intercept( + req: HttpRequest, + next: HttpHandler + ): Observable> { const startTime = Date.now(); - const detail = {'Time': startTime, 'reqMethod': req.method, 'reqURL': req.urlWithParams}; - this.logger.log('sended request', detail, req.headers); + const detail = { + Time: startTime, + reqMethod: req.method, + reqURL: req.urlWithParams, + }; + this.logger.log("sended request", detail, req.headers); return next.handle(req).pipe( - tap( event => { - console.debug('http-logger tap', event) - }), - catchError((err: HttpErrorResponse)=>{ - if(window.localStorage.getItem('login') !== 'true') { - if(err.status == HttpStatusCode.Unauthorized){ - if(window.location.pathname != '/login')window.location.href = '/login' - window.localStorage.setItem("login", 'false')} + tap((event) => { + console.debug("http-logger tap", event); + }), + catchError((err: HttpErrorResponse) => { + if (window.localStorage.getItem("login") !== "true") { + if (err.status == HttpStatusCode.Unauthorized) { + if ( + window.location.pathname != "/login" && + window.location.pathname != "/resetpasswordconfirm" + ) + window.location.href = "/login"; + window.localStorage.setItem("login", "false"); } - console.error(err); - return throwError(()=> err) - }) + } + console.error(err); + return throwError(() => err); + }) ); } -} \ No newline at end of file +} diff --git a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css index 72a85acf0..e0ebdea1a 100644 --- a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css +++ b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.css @@ -87,9 +87,11 @@ input.wrongEmail { .wrongReset { background-color: var(--danger); + color: white; text-align: center; padding: 7px; border-radius: 4px; + margin-bottom: 20px; } .successReset { @@ -145,3 +147,17 @@ input.wrongEmail { margin: 20px; stroke: var(--dark-grey); } + +.linkButton { + font-style: inherit; + border: 0px; + background-color: transparent; + color: var(--ocean-blue); + font-size: 10pt; + font-weight: bold; + outline: none; +} + +.darkTheme .linkButton { + color: var(--light-blue); +} diff --git a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html index c49009a64..eb6a6d95a 100644 --- a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html +++ b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html @@ -9,11 +9,15 @@

Set a secure password

+
Your password must consist of at least 8 characters.
-

{{error}}

-

{{defaultSuccessMessage}}

{ this.error = undefined; this.success = this.defaultSuccessMessage; - // setTimeout(function () { - // // this.router.navigate(["/login"]); - // }, 1500); + setTimeout(() => { + this.router.navigate(["/login"]); + }, 1500); console.log(value); }, error: (error) => { this.success = undefined; + if (error.status === 401) { + this.tokenError = "error"; + return; + } this.error = this.defaultErrorMessage; - console.log(error); }, }); } @@ -90,6 +99,10 @@ export class ConfirmResetPasswordComponent { this.router.navigate(["/"]); } + redirectToReset() { + this.router.navigate(["/resetpassword"]); + } + isDarkModeOn() { this.isDark = this.themeService.isDarkMode(); return this.isDark; diff --git a/frontend/src/app/reset-password/reset-password.component.html b/frontend/src/app/reset-password/reset-password.component.html index 263e24089..b5ed1b646 100644 --- a/frontend/src/app/reset-password/reset-password.component.html +++ b/frontend/src/app/reset-password/reset-password.component.html @@ -11,11 +11,11 @@

Trouble loging in?

+

{{error}}

+

{{defaultSuccessMessage}}

Enter the email linked to your account, and we'll send you a link to regain access.
-

{{error}}

-

{{defaultSuccessMessage}}

From 6c2902b33f95974f8cf13717590cf32b2c2fdb0e Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Thu, 31 Aug 2023 12:54:41 +0200 Subject: [PATCH 09/11] popup --- frontend/src/app/app.module.ts | 181 ++++++++++-------- ...confirm-reset-password-popup.component.css | 31 +++ ...onfirm-reset-password-popup.component.html | 8 + ...irm-reset-password-popup.component.spec.ts | 23 +++ .../confirm-reset-password-popup.component.ts | 18 ++ .../confirm-reset-password.component.html | 2 + .../confirm-reset-password.component.ts | 33 ++-- 7 files changed, 195 insertions(+), 101 deletions(-) create mode 100644 frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css create mode 100644 frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.html create mode 100644 frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.spec.ts create mode 100644 frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.ts diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 783c1afb0..92ca8576b 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -1,75 +1,82 @@ -import {BrowserModule} from '@angular/platform-browser'; -import {NgModule, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; -import {RouterModule} from '@angular/router'; -import {ROUTES} from './routes/routes'; -import {AppComponent} from './app.component'; -import {ScenarioEditorComponent} from './scenario-editor/scenario-editor.component'; -import {HttpClientModule, HTTP_INTERCEPTORS} from '@angular/common/http'; -import {ApiService} from './Services/api.service'; -import {StoriesBarComponent} from './stories-bar/stories-bar.component'; -import {ParentComponent} from './parent/parent.component'; -import {LoginComponent} from './login/login.component'; -import {FormsModule, ReactiveFormsModule} from '@angular/forms'; -import {AuthGuard} from './guards/auth.guard'; -import {MatTableModule} from '@angular/material/table'; -import {MatListModule} from '@angular/material/list'; -import {ExampleComponent, ExampleTableComponent} from './example-table/example-table.component'; -import {EditableComponent} from './editable/editable.component'; -import {ViewModeDirective} from './directives/view-mode.directive'; -import {EditModeDirective} from './directives/edit-mode.directive'; -import {EditableOnEnterDirective} from './directives/edit-on-enter.directive'; -import {FocusableDirective} from './editable/focusable.directive'; -import {DragDropModule} from '@angular/cdk/drag-drop'; -import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; -import { FeedbackComponent } from './feedback/feedback.component'; -import { TermsComponent } from './terms/terms.component'; -import { StoryEditorComponent } from './story-editor/story-editor.component'; -import { AccountManagementComponent } from './account-management/account-management.component'; -import {CookieService } from 'ngx-cookie-service'; -import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; -import { ReportComponent } from './report/report.component'; -import { RegistrationComponent } from './registration/registration.component'; -import { PasswordConfirmedValidatorDirective } from './directives/password-confirmed.directive'; -import { ToastrModule } from 'ngx-toastr'; -import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; -import { CarouselModule } from 'ngx-owl-carousel-o'; -import { ResetPasswordComponent } from './reset-password/reset-password.component'; -import { ConfirmResetPasswordComponent } from './confirm-reset-password/confirm-reset-password.component'; -import { DeleteToast } from './delete-toast'; -import { DEFAULT_TIMEOUT, TimeoutInterceptor } from './Services/timeout-interceptor.interceptor'; -import {HttpLoggerInterceptor} from "./Services/http-logger.interceptor"; -import { ReportHistoryComponent } from './report-history/report-history.component'; -import {ClipboardModule} from '@angular/cdk/clipboard'; +import { BrowserModule } from "@angular/platform-browser"; +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; +import { RouterModule } from "@angular/router"; +import { ROUTES } from "./routes/routes"; +import { AppComponent } from "./app.component"; +import { ScenarioEditorComponent } from "./scenario-editor/scenario-editor.component"; +import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http"; +import { ApiService } from "./Services/api.service"; +import { StoriesBarComponent } from "./stories-bar/stories-bar.component"; +import { ParentComponent } from "./parent/parent.component"; +import { LoginComponent } from "./login/login.component"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { AuthGuard } from "./guards/auth.guard"; +import { MatTableModule } from "@angular/material/table"; +import { MatListModule } from "@angular/material/list"; +import { + ExampleComponent, + ExampleTableComponent, +} from "./example-table/example-table.component"; +import { EditableComponent } from "./editable/editable.component"; +import { ViewModeDirective } from "./directives/view-mode.directive"; +import { EditModeDirective } from "./directives/edit-mode.directive"; +import { EditableOnEnterDirective } from "./directives/edit-on-enter.directive"; +import { FocusableDirective } from "./editable/focusable.directive"; +import { DragDropModule } from "@angular/cdk/drag-drop"; +import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; +import { FeedbackComponent } from "./feedback/feedback.component"; +import { TermsComponent } from "./terms/terms.component"; +import { StoryEditorComponent } from "./story-editor/story-editor.component"; +import { AccountManagementComponent } from "./account-management/account-management.component"; +import { CookieService } from "ngx-cookie-service"; +import { MatProgressSpinnerModule } from "@angular/material/progress-spinner"; +import { ReportComponent } from "./report/report.component"; +import { RegistrationComponent } from "./registration/registration.component"; +import { PasswordConfirmedValidatorDirective } from "./directives/password-confirmed.directive"; +import { ToastrModule } from "ngx-toastr"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { CarouselModule } from "ngx-owl-carousel-o"; +import { ResetPasswordComponent } from "./reset-password/reset-password.component"; +import { ConfirmResetPasswordComponent } from "./confirm-reset-password/confirm-reset-password.component"; +import { DeleteToast } from "./delete-toast"; +import { + DEFAULT_TIMEOUT, + TimeoutInterceptor, +} from "./Services/timeout-interceptor.interceptor"; +import { HttpLoggerInterceptor } from "./Services/http-logger.interceptor"; +import { ReportHistoryComponent } from "./report-history/report-history.component"; +import { ClipboardModule } from "@angular/cdk/clipboard"; import { LoggerModule, NgxLoggerLevel } from "ngx-logger"; -import { ThemingService } from './Services/theming.service'; -import { MatSlideToggleModule } from '@angular/material/slide-toggle'; -import { MatIconModule } from '@angular/material/icon'; -import { MatTabsModule } from '@angular/material/tabs'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import {MatSelectModule} from '@angular/material/select'; -import { LayoutModalComponent } from './modals/layout-modal/layout-modal.component'; -import { CreateNewGroupComponent } from './modals/create-new-group/create-new-group.component'; -import { CreateCustomProjectComponent } from './modals/create-custom-project/create-custom-project.component'; -import { DisconnectJiraAccountComponent} from './modals/disconnect-jira-account/disconnect-jira-account.component'; -import { DeleteAccountComponent } from './modals/delete-account/delete-account.component'; -import { AddBlockFormComponent } from './modals/add-block-form/add-block-form.component'; -import { SaveBlockFormComponent } from './modals/save-block-form/save-block-form.component'; -import { NewStepRequestComponent } from './modals/new-step-request/new-step-request.component'; -import { RenameScenarioComponent } from './modals/rename-scenario/rename-scenario.component'; -import { RenameStoryComponent } from './modals/rename-story/rename-story.component'; -import { WorkgroupEditComponent } from './modals/workgroup-edit/workgroup-edit.component'; -import { CreateNewStoryComponent } from './modals/create-new-story/create-new-story.component'; -import { UpdateGroupComponent } from './modals/update-group/update-group.component'; -import { ChangeJiraAccountComponent } from './modals/change-jira-account/change-jira-account.component'; -import { RepoSwichComponent } from './modals/repo-swich/repo-swich.component'; -import {MatExpansionModule} from '@angular/material/expansion'; -import { CreateScenarioComponent } from './modals/create-scenario/create-scenario.component'; -import { ResizeInputDirective } from './directives/resize-input.directive'; -import { RenameBackgroundComponent } from './modals/rename-background/rename-background.component'; -import { BaseEditorComponent } from './base-editor/base-editor.component'; -import { NewExampleComponent } from './modals/new-example/new-example.component'; -import { TransferOwnershipToast } from './transferOwnership-toastr'; -import { InfoWarningToast } from './info-warning-toast'; +import { ThemingService } from "./Services/theming.service"; +import { MatSlideToggleModule } from "@angular/material/slide-toggle"; +import { MatIconModule } from "@angular/material/icon"; +import { MatTabsModule } from "@angular/material/tabs"; +import { MatTooltipModule } from "@angular/material/tooltip"; +import { MatSelectModule } from "@angular/material/select"; +import { LayoutModalComponent } from "./modals/layout-modal/layout-modal.component"; +import { CreateNewGroupComponent } from "./modals/create-new-group/create-new-group.component"; +import { CreateCustomProjectComponent } from "./modals/create-custom-project/create-custom-project.component"; +import { DisconnectJiraAccountComponent } from "./modals/disconnect-jira-account/disconnect-jira-account.component"; +import { DeleteAccountComponent } from "./modals/delete-account/delete-account.component"; +import { AddBlockFormComponent } from "./modals/add-block-form/add-block-form.component"; +import { SaveBlockFormComponent } from "./modals/save-block-form/save-block-form.component"; +import { NewStepRequestComponent } from "./modals/new-step-request/new-step-request.component"; +import { RenameScenarioComponent } from "./modals/rename-scenario/rename-scenario.component"; +import { RenameStoryComponent } from "./modals/rename-story/rename-story.component"; +import { WorkgroupEditComponent } from "./modals/workgroup-edit/workgroup-edit.component"; +import { CreateNewStoryComponent } from "./modals/create-new-story/create-new-story.component"; +import { UpdateGroupComponent } from "./modals/update-group/update-group.component"; +import { ChangeJiraAccountComponent } from "./modals/change-jira-account/change-jira-account.component"; +import { RepoSwichComponent } from "./modals/repo-swich/repo-swich.component"; +import { MatExpansionModule } from "@angular/material/expansion"; +import { CreateScenarioComponent } from "./modals/create-scenario/create-scenario.component"; +import { ResizeInputDirective } from "./directives/resize-input.directive"; +import { RenameBackgroundComponent } from "./modals/rename-background/rename-background.component"; +import { BaseEditorComponent } from "./base-editor/base-editor.component"; +import { NewExampleComponent } from "./modals/new-example/new-example.component"; +import { TransferOwnershipToast } from "./transferOwnership-toastr"; +import { InfoWarningToast } from "./info-warning-toast"; +import { ConfirmResetPasswordPopupComponent } from "./confirm-reset-password-popup/confirm-reset-password-popup.component"; @NgModule({ declarations: [ @@ -118,7 +125,8 @@ import { InfoWarningToast } from './info-warning-toast'; NewExampleComponent, ExampleComponent, DeleteToast, - TransferOwnershipToast + TransferOwnershipToast, + ConfirmResetPasswordPopupComponent, ], imports: [ NgbModule, @@ -138,12 +146,12 @@ import { InfoWarningToast } from './info-warning-toast'; CarouselModule, HttpClientModule, LoggerModule.forRoot({ - serverLoggingUrl: localStorage.getItem('url_backend') + '/user/log', + serverLoggingUrl: localStorage.getItem("url_backend") + "/user/log", level: NgxLoggerLevel.DEBUG, - serverLogLevel: NgxLoggerLevel.DEBUG + serverLogLevel: NgxLoggerLevel.DEBUG, }), ToastrModule.forRoot({ - timeOut: 3000 + timeOut: 3000, }), MatSlideToggleModule, MatIconModule, @@ -152,11 +160,22 @@ import { InfoWarningToast } from './info-warning-toast'; MatTooltipModule, ], entryComponents: [InfoWarningToast], - providers: [ApiService, AuthGuard, CookieService, - [{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }], [{ provide: HTTP_INTERCEPTORS, useClass: HttpLoggerInterceptor, multi: true }], - [{ provide: DEFAULT_TIMEOUT, useValue: 120000 }], ThemingService], + providers: [ + ApiService, + AuthGuard, + CookieService, + [{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }], + [ + { + provide: HTTP_INTERCEPTORS, + useClass: HttpLoggerInterceptor, + multi: true, + }, + ], + [{ provide: DEFAULT_TIMEOUT, useValue: 120000 }], + ThemingService, + ], bootstrap: [AppComponent], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA], }) -export class AppModule { -} +export class AppModule {} diff --git a/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css new file mode 100644 index 000000000..eeeddd63e --- /dev/null +++ b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css @@ -0,0 +1,31 @@ +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.7); + display: flex; + align-items: center; + justify-content: center; +} + +.popup { + background-color: white; + padding: 20px; + border-radius: 5px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); +} + +.content { + text-align: center; +} + +button { + background-color: #007bff; + color: white; + border: none; + padding: 5px 10px; + border-radius: 3px; + cursor: pointer; +} diff --git a/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.html b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.html new file mode 100644 index 000000000..967690da4 --- /dev/null +++ b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.html @@ -0,0 +1,8 @@ +
+ +
\ No newline at end of file diff --git a/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.spec.ts b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.spec.ts new file mode 100644 index 000000000..ddd90405b --- /dev/null +++ b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfirmResetPasswordPopupComponent } from './confirm-reset-password-popup.component'; + +describe('ConfirmResetPasswordPopupComponent', () => { + let component: ConfirmResetPasswordPopupComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfirmResetPasswordPopupComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ConfirmResetPasswordPopupComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.ts b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.ts new file mode 100644 index 000000000..5fc98fc0f --- /dev/null +++ b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.ts @@ -0,0 +1,18 @@ +import { Component, Input } from "@angular/core"; +import { Router } from "@angular/router"; + +@Component({ + selector: "app-confirm-reset-password-popup", + templateUrl: "./confirm-reset-password-popup.component.html", + styleUrls: ["./confirm-reset-password-popup.component.css"], +}) +export class ConfirmResetPasswordPopupComponent { + @Input() backgroundColor: string = "red"; // Default background color is red + @Input() message: string = "Reset your password?"; // Default message + + constructor(private router: Router) {} + + navigateToLogin() { + this.router.navigateByUrl("/login"); + } +} diff --git a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html index eb6a6d95a..752eb64fd 100644 --- a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html +++ b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.html @@ -9,6 +9,8 @@

Set a secure password

+
Your password must consist of at least 8 characters.
diff --git a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts index ffb8d1c7c..ad70ec101 100644 --- a/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts +++ b/frontend/src/app/confirm-reset-password/confirm-reset-password.component.ts @@ -32,7 +32,7 @@ export class ConfirmResetPasswordComponent { * Successfully sent email */ success: boolean; - defaultSuccessMessage = "Password set!"; + defaultSuccessMessage = "Your Password Has Been Updated!"; /** * The message to display @@ -78,7 +78,7 @@ export class ConfirmResetPasswordComponent { error: (error) => { this.message = this.defaultErrorMessage; if (error.status === 401) { - this.message = "This link has expired."; + this.message = "This Link Has Expired!"; } this.error = true; }, From 7cb5fc7be6667e2ecb2658edc6d522bc2d5ba5a0 Mon Sep 17 00:00:00 2001 From: i3rotlher Date: Fri, 1 Sep 2023 10:47:02 +0200 Subject: [PATCH 11/11] styling --- .../confirm-reset-password-popup.component.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css index 879ed20a3..cf2561207 100644 --- a/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css +++ b/frontend/src/app/confirm-reset-password-popup/confirm-reset-password-popup.component.css @@ -15,7 +15,6 @@ text-align: center; border-radius: 4px; background-color: var(--green); - border-radius: 4px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); color: white; padding: 15px; @@ -27,7 +26,6 @@ text-align: center; border-radius: 4px; background-color: var(--danger); - border-radius: 4px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3); color: white; padding: 15px;