diff options
Diffstat (limited to 'client/src/app')
-rw-r--r-- | client/src/app/login/login.component.html | 68 | ||||
-rw-r--r-- | client/src/app/login/login.component.scss | 42 | ||||
-rw-r--r-- | client/src/app/login/login.component.ts | 24 |
3 files changed, 101 insertions, 33 deletions
diff --git a/client/src/app/login/login.component.html b/client/src/app/login/login.component.html index 3e53e5854..b0639d8ca 100644 --- a/client/src/app/login/login.component.html +++ b/client/src/app/login/login.component.html | |||
@@ -23,40 +23,54 @@ | |||
23 | <span *ngIf="error === 'User email is not verified.'"> <a i18n routerLink="/verify-account/ask-send-email">Request new verification email.</a></span> | 23 | <span *ngIf="error === 'User email is not verified.'"> <a i18n routerLink="/verify-account/ask-send-email">Request new verification email.</a></span> |
24 | </div> | 24 | </div> |
25 | 25 | ||
26 | <form role="form" (ngSubmit)="login()" [formGroup]="form"> | 26 | <div class="login-form-and-externals"> |
27 | <div class="form-group"> | 27 | |
28 | <div> | 28 | <form role="form" (ngSubmit)="login()" [formGroup]="form"> |
29 | <label i18n for="username">User</label> | 29 | <div class="form-group"> |
30 | <input | 30 | <div> |
31 | type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1" | 31 | <label i18n for="username">User</label> |
32 | formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" #emailInput | 32 | <input |
33 | > | 33 | type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1" |
34 | <a i18n *ngIf="signupAllowed === true" routerLink="/signup" class="create-an-account"> | 34 | formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" #usernameInput |
35 | or create an account | 35 | > |
36 | </a> | 36 | <a i18n *ngIf="signupAllowed === true" routerLink="/signup" class="create-an-account"> |
37 | or create an account | ||
38 | </a> | ||
39 | </div> | ||
40 | |||
41 | <div *ngIf="formErrors.username" class="form-error"> | ||
42 | {{ formErrors.username }} | ||
43 | </div> | ||
37 | </div> | 44 | </div> |
38 | 45 | ||
39 | <div *ngIf="formErrors.username" class="form-error"> | 46 | <div class="form-group"> |
40 | {{ formErrors.username }} | 47 | <label i18n for="password">Password</label> |
48 | <div> | ||
49 | <input | ||
50 | type="password" name="password" id="password" i18n-placeholder placeholder="Password" required tabindex="2" autocomplete="current-password" | ||
51 | formControlName="password" class="form-control" [ngClass]="{ 'input-error': formErrors['password'] }" | ||
52 | > | ||
53 | <a i18n-title class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a> | ||
54 | </div> | ||
55 | <div *ngIf="formErrors.password" class="form-error"> | ||
56 | {{ formErrors.password }} | ||
57 | </div> | ||
41 | </div> | 58 | </div> |
42 | </div> | ||
43 | 59 | ||
44 | <div class="form-group"> | 60 | <input type="submit" i18n-value value="Login" [disabled]="!form.valid"> |
45 | <label i18n for="password">Password</label> | 61 | </form> |
46 | <div> | 62 | |
47 | <input | 63 | <div class="external-login-blocks" *ngIf="getExternalLogins().length !== 0"> |
48 | type="password" name="password" id="password" i18n-placeholder placeholder="Password" required tabindex="2" autocomplete="current-password" | 64 | <div class="block-title" i18n>Or sign in with</div> |
49 | formControlName="password" class="form-control" [ngClass]="{ 'input-error': formErrors['password'] }" | 65 | |
50 | > | 66 | <div class="external-login-block"> |
51 | <a i18n-title class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a> | 67 | <a *ngFor="let auth of getExternalLogins()" [href]="getAuthHref(auth)" role="button"> |
52 | </div> | 68 | {{ auth.authDisplayName }} |
53 | <div *ngIf="formErrors.password" class="form-error"> | 69 | </a> |
54 | {{ formErrors.password }} | ||
55 | </div> | 70 | </div> |
56 | </div> | 71 | </div> |
72 | </div> | ||
57 | 73 | ||
58 | <input type="submit" i18n-value value="Login" [disabled]="!form.valid"> | ||
59 | </form> | ||
60 | </ng-container> | 74 | </ng-container> |
61 | </div> | 75 | </div> |
62 | 76 | ||
diff --git a/client/src/app/login/login.component.scss b/client/src/app/login/login.component.scss index 8ac231475..ccc98c12a 100644 --- a/client/src/app/login/login.component.scss +++ b/client/src/app/login/login.component.scss | |||
@@ -21,9 +21,49 @@ input[type=submit] { | |||
21 | color: var(--mainForegroundColor); | 21 | color: var(--mainForegroundColor); |
22 | cursor: pointer; | 22 | cursor: pointer; |
23 | transition: opacity cubic-bezier(0.39, 0.575, 0.565, 1); | 23 | transition: opacity cubic-bezier(0.39, 0.575, 0.565, 1); |
24 | 24 | ||
25 | &:hover { | 25 | &:hover { |
26 | text-decoration: none !important; | 26 | text-decoration: none !important; |
27 | opacity: .7 !important; | 27 | opacity: .7 !important; |
28 | } | 28 | } |
29 | } | 29 | } |
30 | |||
31 | .login-form-and-externals { | ||
32 | display: flex; | ||
33 | flex-wrap: wrap; | ||
34 | font-size: 15px; | ||
35 | |||
36 | form { | ||
37 | margin: 0 50px 20px 0; | ||
38 | } | ||
39 | |||
40 | .external-login-blocks { | ||
41 | padding: 0 10px 10px 10px; | ||
42 | min-width: 200px; | ||
43 | |||
44 | .block-title { | ||
45 | font-weight: $font-semibold; | ||
46 | } | ||
47 | |||
48 | .external-login-block { | ||
49 | cursor: pointer; | ||
50 | border: 1px solid #d1d7e0; | ||
51 | border-radius: 5px; | ||
52 | margin: 10px 10px 0 0; | ||
53 | display: flex; | ||
54 | justify-content: center; | ||
55 | align-items: center; | ||
56 | min-height: 35px; | ||
57 | min-width: 100px; | ||
58 | |||
59 | &:hover { | ||
60 | background-color: rgba(209, 215, 224, 0.5) | ||
61 | } | ||
62 | |||
63 | a { | ||
64 | @include disable-default-a-behaviour; | ||
65 | color: var(--mainForegroundColor); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | } | ||
diff --git a/client/src/app/login/login.component.ts b/client/src/app/login/login.component.ts index 9c8f5c52e..5db8d3dbb 100644 --- a/client/src/app/login/login.component.ts +++ b/client/src/app/login/login.component.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, OnInit, ViewChild, AfterViewInit } from '@angular/core' |
2 | import { Notifier, RedirectService } from '@app/core' | 2 | import { Notifier, RedirectService } from '@app/core' |
3 | import { UserService } from '@app/shared' | 3 | import { UserService } from '@app/shared' |
4 | import { AuthService } from '../core' | 4 | import { AuthService } from '../core' |
@@ -8,7 +8,8 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val | |||
8 | import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service' | 8 | import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service' |
9 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' | 9 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' |
10 | import { ActivatedRoute } from '@angular/router' | 10 | import { ActivatedRoute } from '@angular/router' |
11 | import { ServerConfig } from '@shared/models/server/server-config.model' | 11 | import { ServerConfig, RegisteredExternalAuthConfig } from '@shared/models/server/server-config.model' |
12 | import { environment } from 'src/environments/environment' | ||
12 | 13 | ||
13 | @Component({ | 14 | @Component({ |
14 | selector: 'my-login', | 15 | selector: 'my-login', |
@@ -16,13 +17,14 @@ import { ServerConfig } from '@shared/models/server/server-config.model' | |||
16 | styleUrls: [ './login.component.scss' ] | 17 | styleUrls: [ './login.component.scss' ] |
17 | }) | 18 | }) |
18 | 19 | ||
19 | export class LoginComponent extends FormReactive implements OnInit { | 20 | export class LoginComponent extends FormReactive implements OnInit, AfterViewInit { |
20 | @ViewChild('emailInput', { static: true }) input: ElementRef | 21 | @ViewChild('usernameInput', { static: false }) usernameInput: ElementRef |
21 | @ViewChild('forgotPasswordModal', { static: true }) forgotPasswordModal: ElementRef | 22 | @ViewChild('forgotPasswordModal', { static: true }) forgotPasswordModal: ElementRef |
22 | 23 | ||
23 | error: string = null | 24 | error: string = null |
24 | forgotPasswordEmail = '' | 25 | forgotPasswordEmail = '' |
25 | isAuthenticatedWithExternalAuth = false | 26 | isAuthenticatedWithExternalAuth = false |
27 | externalLogins: string[] = [] | ||
26 | 28 | ||
27 | private openedForgotPasswordModal: NgbModalRef | 29 | private openedForgotPasswordModal: NgbModalRef |
28 | private serverConfig: ServerConfig | 30 | private serverConfig: ServerConfig |
@@ -63,8 +65,20 @@ export class LoginComponent extends FormReactive implements OnInit { | |||
63 | username: this.loginValidatorsService.LOGIN_USERNAME, | 65 | username: this.loginValidatorsService.LOGIN_USERNAME, |
64 | password: this.loginValidatorsService.LOGIN_PASSWORD | 66 | password: this.loginValidatorsService.LOGIN_PASSWORD |
65 | }) | 67 | }) |
68 | } | ||
69 | |||
70 | ngAfterViewInit () { | ||
71 | if (this.usernameInput) { | ||
72 | this.usernameInput.nativeElement.focus() | ||
73 | } | ||
74 | } | ||
75 | |||
76 | getExternalLogins () { | ||
77 | return this.serverConfig.plugin.registeredExternalAuths | ||
78 | } | ||
66 | 79 | ||
67 | this.input.nativeElement.focus() | 80 | getAuthHref (auth: RegisteredExternalAuthConfig) { |
81 | return environment.apiUrl + `/plugins/${auth.name}/${auth.version}/auth/${auth.authName}` | ||
68 | } | 82 | } |
69 | 83 | ||
70 | login () { | 84 | login () { |