Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Divide login flow into two steps #6870

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions client/src/app/+login/login.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ <h5 class="alert-heading" i18n>
<div class="wrapper">
<div class="login-form-and-externals">

<form class="w-100 m-0" myPluginSelector pluginSelectorId="login-form" (ngSubmit)="login()" [formGroup]="form">
<form class="w-100 m-0" myPluginSelector pluginSelectorId="login-form" (ngSubmit)="submit()" [formGroup]="form">
<ng-container *ngIf="!otpStep">
<div class="form-group">
<div class="form-group" *ngIf="currentLoginStep === 1">
<p i18n>
Enter your email address or username
</p>
<div>
<label i18n for="username">Username or email address</label>
<input
type="text" id="username" i18n-placeholder placeholder="Example: [email protected]" required
type="text" id="username" i18n-placeholder placeholder="Email or username" required
formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" myAutofocus
autocomplete="username"
>
Expand All @@ -59,11 +61,12 @@ <h5 class="alert-heading" i18n>
<ng-template *ngIf="hasUsernameUppercase()" [ngTemplateOutlet]="uppercaseWarning"></ng-template>
</div>

<div class="form-group">
<label i18n for="password">Password</label>

<div class="form-group" *ngIf="currentLoginStep === 2">
<p i18n>
Enter password for <strong>{{ form.controls.username.value }}</strong> (<a [routerLink]="['./']" [queryParams]="{ step: '1' }">change</a>)
</p>
<my-input-text
formControlName="password" inputId="password" i18n-placeholder placeholder="Password"
formControlName="password" inputId="password" i18n-placeholder placeholder="Password" [autofocus]="true"
[formError]="formErrors['password']" autocomplete="current-password"
></my-input-text>
</div>
Expand All @@ -81,7 +84,7 @@ <h5 class="alert-heading" i18n>
></my-input-text>
</div>

<input type="submit" class="peertube-button primary-button w-100" i18n-value value="Login" [disabled]="!form.valid">
<input type="submit" class="peertube-button primary-button w-100" i18n-value [value]="currentLoginStep === 1 ? 'Continue' : 'Login'" [disabled]="!isFormValid()">

<div *ngIf="!otpStep" class="additional-links d-flex justify-content-center mt-4 mb-5 text-center">
<button type="button" i18n class="button-unstyle link-primary mx-3" (click)="openForgotPasswordModal()" i18n-title title="Click here to reset your password">
Expand Down
38 changes: 35 additions & 3 deletions client/src/app/+login/login.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NgClass, NgFor, NgIf, NgTemplateOutlet } from '@angular/common'
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'
import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { ActivatedRoute, Router, RouterLink } from '@angular/router'
import { AuthService, Notifier, RedirectService, SessionStorageService, UserService } from '@app/core'
Expand All @@ -19,6 +19,7 @@ import { GlobalIconComponent } from '../shared/shared-icons/global-icon.componen
import { InstanceBannerComponent } from '../shared/shared-instance/instance-banner.component'
import { AutofocusDirective } from '../shared/shared-main/common/autofocus.directive'
import { PluginSelectorDirective } from '../shared/shared-main/plugins/plugin-selector.directive'
import { Subscription } from 'rxjs'

@Component({
selector: 'my-login',
Expand All @@ -43,14 +44,15 @@ import { PluginSelectorDirective } from '../shared/shared-main/plugins/plugin-se
]
})

export class LoginComponent extends FormReactive implements OnInit, AfterViewInit {
export class LoginComponent extends FormReactive implements OnInit, AfterViewInit, OnDestroy {
private static SESSION_STORAGE_REDIRECT_URL_KEY = 'login-previous-url'

@ViewChild('forgotPasswordModal', { static: true }) forgotPasswordModal: ElementRef
@ViewChild('otpTokenInput') otpTokenInput: InputTextComponent
@ViewChild('instanceAboutAccordion') instanceAboutAccordion: InstanceAboutAccordionComponent

accordion: NgbAccordionDirective
currentLoginStep = 1
error: string = null
forgotPasswordEmail = ''

Expand All @@ -72,6 +74,7 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni

private openedForgotPasswordModal: NgbModalRef
private serverConfig: ServerConfig
private routeSub: Subscription

constructor (
protected formReactiveService: FormReactiveService,
Expand Down Expand Up @@ -122,6 +125,15 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
}
})

this.routeSub = this.route.queryParams
.subscribe((event) => {
if (this.form.controls.username.invalid) {
this.goToLoginStep(1)
} else {
this.currentLoginStep = !isNaN(event.step) ? +event.step : 1
}
})

this.serverConfig = snapshot.data.serverConfig

if (snapshot.queryParams.externalAuthToken) {
Expand All @@ -144,6 +156,10 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
this.hooks.runAction('action:login.init', 'login')
}

ngOnDestroy () {
if (this.routeSub) this.routeSub.unsubscribe()
}

getExternalLogins () {
return this.serverConfig.plugin.registeredExternalAuths
}
Expand All @@ -156,7 +172,23 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
return getExternalAuthHref(environment.apiUrl, auth)
}

login () {
isFormValid () {
if (this.currentLoginStep === 1) return this.form.controls.username.valid

return this.form.valid
}

goToLoginStep (step: number) {
this.router.navigate([], { relativeTo: this.route, queryParams: { step }, queryParamsHandling: 'merge' })
}

submit () {
if (this.currentLoginStep === 1) {
this.goToLoginStep(2)

return
}

this.error = null

const options = {
Expand Down