aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+login
diff options
context:
space:
mode:
authorKimsible <1877318+kimsible@users.noreply.github.com>2020-12-07 16:34:07 +0100
committerGitHub <noreply@github.com>2020-12-07 16:34:07 +0100
commit40360c17d82b33accb34ea974c275e17880c37aa (patch)
treee0ddac1174e54897b4871daa4dca43dce121f590 /client/src/app/+login
parent10f26f4203b8cef32778bf3435d8112eaea3c093 (diff)
downloadPeerTube-40360c17d82b33accb34ea974c275e17880c37aa.tar.gz
PeerTube-40360c17d82b33accb34ea974c275e17880c37aa.tar.zst
PeerTube-40360c17d82b33accb34ea974c275e17880c37aa.zip
improvements to login and sign-up pages (#3357)
* New login form ui * Move InstanceAboutAccordion to shared components * Update closed registration alert text * Add alert for opened registration and move them bellow login form * Adjust flex block on signup and login views * Replace toggle accordion with expand on links in signup and login + scrollTo * Improve display of login alerts * Fix missing Component suffix * Define min-width instance-information block sign-up and login for mobile screens * Add ability to select specific panels in instanceAboutAccorddion * Add instance title and short-description to common instanceAboutAccordion * Clarify title alert in login page * Add step terms for signup Co-authored-by: kimsible <kimsible@users.noreply.github.com> Co-authored-by: Rigel Kent <sendmemail@rigelk.eu>
Diffstat (limited to 'client/src/app/+login')
-rw-r--r--client/src/app/+login/login.component.html108
-rw-r--r--client/src/app/+login/login.component.scss150
-rw-r--r--client/src/app/+login/login.component.ts25
-rw-r--r--client/src/app/+login/login.module.ts5
4 files changed, 212 insertions, 76 deletions
diff --git a/client/src/app/+login/login.component.html b/client/src/app/+login/login.component.html
index 390d77dd7..a2362d978 100644
--- a/client/src/app/+login/login.component.html
+++ b/client/src/app/+login/login.component.html
@@ -8,73 +8,81 @@
8 </div> 8 </div>
9 9
10 <ng-container *ngIf="!externalAuthError && !isAuthenticatedWithExternalAuth"> 10 <ng-container *ngIf="!externalAuthError && !isAuthenticatedWithExternalAuth">
11 <div class="looking-for-account alert alert-info" *ngIf="signupAllowed === false" role="alert">
12 <h6 class="alert-heading" i18n>
13 If you are looking for an account…
14 </h6>
15
16 <div i18n>
17 Currently this instance doesn't allow for user registration, but you can find an instance
18 that gives you the possibility to sign up for an account and upload your videos there.
19
20 <br />
21
22 Find yours among multiple instances at <a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
23 </div>
24 </div>
25
26 <div *ngIf="error" class="alert alert-danger">{{ error }} 11 <div *ngIf="error" class="alert alert-danger">{{ error }}
27 <span *ngIf="error === 'User email is not verified.'"> <a i18n routerLink="/verify-account/ask-send-email">Request new verification email.</a></span> 12 <span *ngIf="error === 'User email is not verified.'"> <a i18n routerLink="/verify-account/ask-send-email">Request new verification email.</a></span>
28 </div> 13 </div>
29 14
30 <div class="login-form-and-externals"> 15 <div class="wrapper">
31 16 <div class="login-form-and-externals">
32 <form role="form" (ngSubmit)="login()" [formGroup]="form"> 17
33 <div class="form-group"> 18 <form role="form" (ngSubmit)="login()" [formGroup]="form">
34 <div> 19 <div class="form-group">
35 <label i18n for="username">User</label> 20 <div>
36 <input 21 <label i18n for="username">User</label>
37 type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1" 22 <input
38 formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" #usernameInput 23 type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1"
39 > 24 formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" #usernameInput
40 <a i18n *ngIf="signupAllowed === true" routerLink="/signup" class="create-an-account"> 25 >
41 or create an account 26 </div>
42 </a> 27
28 <div *ngIf="formErrors.username" class="form-error">
29 {{ formErrors.username }}
30 </div>
43 </div> 31 </div>
44 32
45 <div *ngIf="formErrors.username" class="form-error"> 33 <div class="form-group">
46 {{ formErrors.username }} 34 <label i18n for="password">Password</label>
47 </div>
48 </div>
49
50 <div class="form-group">
51 <label i18n for="password">Password</label>
52 <div>
53 <my-input-toggle-hidden formControlName="password" id="password" 35 <my-input-toggle-hidden formControlName="password" id="password"
54 i18n-placeholder placeholder="Password" 36 i18n-placeholder placeholder="Password"
55 [ngClass]="{ 'input-error': formErrors['password'] }" 37 [ngClass]="{ 'input-error': formErrors['password'] }"
56 autocomplete="current-password"></my-input-toggle-hidden> 38 autocomplete="current-password" tabindex="2"></my-input-toggle-hidden>
57 <a i18n-title class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a> 39 <div *ngIf="formErrors.password" class="form-error">
40 {{ formErrors.password }}
41 </div>
58 </div> 42 </div>
59 <div *ngIf="formErrors.password" class="form-error"> 43
60 {{ formErrors.password }} 44 <input type="submit" i18n-value value="Login" [disabled]="!form.valid">
45
46 <div class="additionnal-links">
47 <a class="forgot-password-button" (click)="openForgotPasswordModal()" i18n-title title="Click here to reset your password">I forgot my password</a>
48 <div *ngIf="signupAllowed" class="signup-link">
49 <span>·</span>
50 <a i18n routerLink="/signup" class="create-an-account">Create an account</a>
51 </div>
61 </div> 52 </div>
62 </div>
63 53
64 <input type="submit" i18n-value value="Login" [disabled]="!form.valid"> 54 <div class="looking-for-account alert alert-info" role="alert">
65 </form> 55 <h6 class="alert-heading" i18n>
56 Logging into an account lets you publish content
57 </h6>
58
59 <div *ngIf="signupAllowed" i18n>
60 This instance allows registration. However, be careful to check the <a class="terms-anchor" (click)="onTermsClick($event, instanceInformation)" href='#'>Terms</a><a class="terms-link" target="_blank" routerLink="/about/instance" fragment="terms">Terms</a> before creating an account.
61 You may also search for another instance to match your exact needs at: <br /><a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
62 </div>
63
64 <div *ngIf="!signupAllowed" i18n>
65 Currently this instance doesn't allow for user registration, you may check the <a (click)="onTermsClick($event, instanceInformation)" href='#'>Terms</a> for more details or find an instance that gives you the possibility to sign up for an account and upload your videos there.
66 Find yours among multiple instances at: <br /> <a class="alert-link" href="https://joinpeertube.org/instances" target="_blank" rel="noopener noreferrer">https://joinpeertube.org/instances</a>.
67 </div>
68 </div>
69 </form>
66 70
67 <div class="external-login-blocks" *ngIf="getExternalLogins().length !== 0"> 71 <div class="external-login-blocks" *ngIf="getExternalLogins().length !== 0">
68 <div class="block-title" i18n>Or sign in with</div> 72 <div class="block-title" i18n>Or sign in with</div>
69 73
70 <div> 74 <div>
71 <a class="external-login-block" *ngFor="let auth of getExternalLogins()" [href]="getAuthHref(auth)" role="button"> 75 <a class="external-login-block" *ngFor="let auth of getExternalLogins()" [href]="getAuthHref(auth)" role="button">
72 {{ auth.authDisplayName }} 76 {{ auth.authDisplayName }}
73 </a> 77 </a>
78 </div>
74 </div> 79 </div>
75 </div> 80 </div>
76 </div>
77 81
82 <div #instanceInformation class="instance-information">
83 <my-instance-about-accordion (init)="onInstanceAboutAccordionInit($event)" [panels]="instanceInformationPanels"></my-instance-about-accordion>
84 </div>
85 </div>
78 </ng-container> 86 </ng-container>
79</div> 87</div>
80 88
diff --git a/client/src/app/+login/login.component.scss b/client/src/app/+login/login.component.scss
index 9ba09e9e4..3cc302aec 100644
--- a/client/src/app/+login/login.component.scss
+++ b/client/src/app/+login/login.component.scss
@@ -1,5 +1,8 @@
1@import '_variables'; 1@import '_variables';
2@import '_mixins'; 2@import '_mixins';
3@import './_bootstrap-variables';
4@import '~bootstrap/scss/functions';
5@import '~bootstrap/scss/variables';
3 6
4label { 7label {
5 display: block; 8 display: block;
@@ -57,39 +60,138 @@ input[type=submit] {
57 } 60 }
58} 61}
59 62
60.login-form-and-externals { 63.wrapper {
61 display: flex; 64 display: flex;
65 justify-content: space-around;
62 flex-wrap: wrap; 66 flex-wrap: wrap;
63 font-size: 15px;
64 67
65 form { 68 & > div {
66 margin: 0 50px 20px 0; 69 flex: 1 1;
67 } 70 }
68 71
69 .external-login-blocks { 72 .login-form-and-externals {
70 min-width: 200px; 73 display: flex;
74 flex-wrap: wrap;
75 font-size: 15px;
76 max-width: 450px;
77 margin-bottom: 40px;
78 margin-left: 10px;
79 margin-right: 10px;
71 80
72 .block-title { 81 form {
73 font-weight: $font-semibold; 82 margin: 0;
83
84 &, input {
85 width: 100%;
86 }
87
88 .additionnal-links {
89 display: block;
90 text-align: center;
91 margin-top: 20px;
92 margin-bottom: 20px;
93
94 .forgot-password-button,
95 .create-an-account {
96 padding: 4px;
97 display: inline-block;
98
99 color: var(--mainColor);
100
101 &:hover, &:active {
102 color: var(--mainHoverColor);
103 }
104 }
105 }
74 } 106 }
75 107
76 .external-login-block { 108 .external-login-blocks {
77 @include disable-default-a-behaviour; 109 min-width: 200px;
78 110
79 cursor: pointer; 111 .block-title {
80 border: 1px solid #d1d7e0; 112 font-weight: $font-semibold;
81 border-radius: 5px; 113 }
82 color: pvar(--mainForegroundColor); 114
83 margin: 10px 10px 0 0; 115 .external-login-block {
84 display: flex; 116 @include disable-default-a-behaviour;
85 justify-content: center; 117
86 align-items: center; 118 cursor: pointer;
87 min-height: 35px; 119 border: 1px solid #d1d7e0;
88 min-width: 100px; 120 border-radius: 5px;
89 121 color: pvar(--mainForegroundColor);
90 &:hover { 122 margin: 10px 10px 0 0;
91 background-color: rgba(209, 215, 224, 0.5) 123 display: flex;
124 justify-content: center;
125 align-items: center;
126 min-height: 35px;
127 min-width: 100px;
128
129 &:hover {
130 background-color: rgba(209, 215, 224, 0.5)
131 }
92 } 132 }
93 } 133 }
134
135 .signup-link {
136 display: inline-block;
137 }
138 }
139
140 .instance-information {
141 max-width: 600px;
142 min-width: 350px;
143 margin-bottom: 40px;
144 margin-left: 10px;
145 margin-right: 10px;
146 }
147
148 .terms-anchor {
149 display: inline;
150 }
151
152 .terms-link {
153 display: none;
154 }
155}
156
157@mixin columnReverseDisplay {
158 flex-direction: column-reverse;
159
160 .login-form-and-externals,
161 .instance-information {
162 width: 100%;
163 margin-left: 0;
164 margin-right: 0;
165 max-width: 450px;
166 min-width: unset;
167 align-self: center;
168 }
169
170 .instance-information {
171 ::ng-deep .accordion {
172 display: none;
173 }
174 }
175
176 .terms-anchor {
177 display: none;
178 }
179
180 .terms-link {
181 display: inline;
182 }
183}
184
185@media screen and (max-width: breakpoint(md)) {
186 .wrapper {
187 @include columnReverseDisplay();
188 }
189}
190
191@media screen and (max-width: breakpoint(md) + $menu-width) {
192 :host-context(.main-col:not(.expanded)) {
193 .wrapper {
194 @include columnReverseDisplay();
195 }
94 } 196 }
95} 197}
diff --git a/client/src/app/+login/login.component.ts b/client/src/app/+login/login.component.ts
index 351750453..2567f21f1 100644
--- a/client/src/app/+login/login.component.ts
+++ b/client/src/app/+login/login.component.ts
@@ -3,9 +3,10 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angula
3import { ActivatedRoute } from '@angular/router' 3import { ActivatedRoute } from '@angular/router'
4import { AuthService, Notifier, RedirectService, UserService } from '@app/core' 4import { AuthService, Notifier, RedirectService, UserService } from '@app/core'
5import { HooksService } from '@app/core/plugins/hooks.service' 5import { HooksService } from '@app/core/plugins/hooks.service'
6import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance'
6import { LOGIN_PASSWORD_VALIDATOR, LOGIN_USERNAME_VALIDATOR } from '@app/shared/form-validators/login-validators' 7import { LOGIN_PASSWORD_VALIDATOR, LOGIN_USERNAME_VALIDATOR } from '@app/shared/form-validators/login-validators'
7import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' 8import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
8import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' 9import { NgbAccordion, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
9import { RegisteredExternalAuthConfig, ServerConfig } from '@shared/models' 10import { RegisteredExternalAuthConfig, ServerConfig } from '@shared/models'
10 11
11@Component({ 12@Component({
@@ -18,6 +19,7 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
18 @ViewChild('usernameInput', { static: false }) usernameInput: ElementRef 19 @ViewChild('usernameInput', { static: false }) usernameInput: ElementRef
19 @ViewChild('forgotPasswordModal', { static: true }) forgotPasswordModal: ElementRef 20 @ViewChild('forgotPasswordModal', { static: true }) forgotPasswordModal: ElementRef
20 21
22 accordion: NgbAccordion
21 error: string = null 23 error: string = null
22 forgotPasswordEmail = '' 24 forgotPasswordEmail = ''
23 25
@@ -25,6 +27,14 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
25 externalAuthError = false 27 externalAuthError = false
26 externalLogins: string[] = [] 28 externalLogins: string[] = []
27 29
30 instanceInformationPanels = {
31 terms: true,
32 administrators: false,
33 features: false,
34 moderation: false,
35 codeOfConduct: false
36 }
37
28 private openedForgotPasswordModal: NgbModalRef 38 private openedForgotPasswordModal: NgbModalRef
29 private serverConfig: ServerConfig 39 private serverConfig: ServerConfig
30 40
@@ -45,6 +55,15 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
45 return this.serverConfig.signup.allowed === true 55 return this.serverConfig.signup.allowed === true
46 } 56 }
47 57
58 onTermsClick (event: Event, instanceInformation: HTMLElement) {
59 event.preventDefault()
60
61 if (this.accordion) {
62 this.accordion.expand('terms')
63 instanceInformation.scrollIntoView({ behavior: 'smooth' })
64 }
65 }
66
48 isEmailDisabled () { 67 isEmailDisabled () {
49 return this.serverConfig.email.enabled === false 68 return this.serverConfig.email.enabled === false
50 } 69 }
@@ -122,6 +141,10 @@ The link will expire within 1 hour.`
122 this.openedForgotPasswordModal.close() 141 this.openedForgotPasswordModal.close()
123 } 142 }
124 143
144 onInstanceAboutAccordionInit (instanceAboutAccordion: InstanceAboutAccordionComponent) {
145 this.accordion = instanceAboutAccordion.accordion
146 }
147
125 private loadExternalAuthToken (username: string, token: string) { 148 private loadExternalAuthToken (username: string, token: string) {
126 this.isAuthenticatedWithExternalAuth = true 149 this.isAuthenticatedWithExternalAuth = true
127 150
diff --git a/client/src/app/+login/login.module.ts b/client/src/app/+login/login.module.ts
index c41902426..9d8607e5d 100644
--- a/client/src/app/+login/login.module.ts
+++ b/client/src/app/+login/login.module.ts
@@ -1,6 +1,7 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2import { SharedFormModule } from '@app/shared/shared-forms' 2import { SharedFormModule } from '@app/shared/shared-forms'
3import { SharedGlobalIconModule } from '@app/shared/shared-icons' 3import { SharedGlobalIconModule } from '@app/shared/shared-icons'
4import { SharedInstanceModule } from '@app/shared/shared-instance'
4import { SharedMainModule } from '@app/shared/shared-main' 5import { SharedMainModule } from '@app/shared/shared-main'
5import { LoginRoutingModule } from './login-routing.module' 6import { LoginRoutingModule } from './login-routing.module'
6import { LoginComponent } from './login.component' 7import { LoginComponent } from './login.component'
@@ -11,7 +12,9 @@ import { LoginComponent } from './login.component'
11 12
12 SharedMainModule, 13 SharedMainModule,
13 SharedFormModule, 14 SharedFormModule,
14 SharedGlobalIconModule 15 SharedGlobalIconModule,
16
17 SharedInstanceModule
15 ], 18 ],
16 19
17 declarations: [ 20 declarations: [