diff options
author | crupest <crupest@outlook.com> | 2019-03-09 01:42:38 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-03-09 01:42:38 +0800 |
commit | d6e7d702db4e600d2298376ba9310e985ee69079 (patch) | |
tree | b8248d41f5bfccc82c5c110143c5504decf3e16d /Timeline/ClientApp/src | |
parent | 028af6f786ac2664d301614d57bbff053c3dc9c0 (diff) | |
download | timeline-d6e7d702db4e600d2298376ba9310e985ee69079.tar.gz timeline-d6e7d702db4e600d2298376ba9310e985ee69079.tar.bz2 timeline-d6e7d702db4e600d2298376ba9310e985ee69079.zip |
User named route in dialog.
Diffstat (limited to 'Timeline/ClientApp/src')
9 files changed, 81 insertions, 59 deletions
diff --git a/Timeline/ClientApp/src/app/user/entities.ts b/Timeline/ClientApp/src/app/user/entities.ts new file mode 100644 index 00000000..6d432ec6 --- /dev/null +++ b/Timeline/ClientApp/src/app/user/entities.ts @@ -0,0 +1,9 @@ +export interface UserCredentials { + username: string; + password: string; +} + +export interface UserInfo { + username: string; + roles: string[]; +} diff --git a/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.html b/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.html index 50d6ba56..58dff0e4 100644 --- a/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.html +++ b/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.html @@ -1,5 +1,4 @@ -<div [ngSwitch]="state" class="container"> - <mat-progress-spinner *ngSwitchCase="'loading'" mode="indeterminate" diameter="50"></mat-progress-spinner> - <app-user-login *ngSwitchCase="'login'" (login)="login($event)" [message]="loginMessage"></app-user-login> - <app-user-login-success *ngSwitchCase="'success'" [userInfo]="userInfo" [displayLoginSuccessMessage]="displayLoginSuccessMessage"></app-user-login-success> +<div class="container"> + <mat-progress-spinner *ngIf="isLoading" mode="indeterminate" diameter="50"></mat-progress-spinner> + <router-outlet name="user"></router-outlet> </div> diff --git a/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.ts b/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.ts index 7511de16..0edde924 100644 --- a/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.ts +++ b/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.ts @@ -1,43 +1,40 @@ -import { Component, OnInit } from '@angular/core'; -import { UserInfo } from '../user-info'; +import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; import { UserService } from '../user-service/user.service'; -import { LoginEvent, LoginMessage } from '../user-login/user-login.component'; +import { RouterOutlet, Router, ActivationStart } from '@angular/router'; @Component({ selector: 'app-user-dialog', templateUrl: './user-dialog.component.html', styleUrls: ['./user-dialog.component.css'] }) -export class UserDialogComponent implements OnInit { +export class UserDialogComponent implements OnInit, OnDestroy { - constructor(private userService: UserService) { } + constructor(private userService: UserService, private router: Router) { } - state: 'loading' | 'login' | 'success' = 'loading'; + @ViewChild(RouterOutlet) outlet: RouterOutlet; - loginMessage: LoginMessage; - - displayLoginSuccessMessage = false; - userInfo: UserInfo; + isLoading = true; ngOnInit() { + // this is a workaround for a bug. see https://github.com/angular/angular/issues/20694 + this.router.events.subscribe(e => { + if (e instanceof ActivationStart && e.snapshot.outlet === 'user') { + this.outlet.deactivate(); + } + }); + + this.userService.validateUserLoginState().subscribe(result => { + this.isLoading = false; if (result.state === 'success') { - this.userInfo = result.userInfo; - this.state = 'success'; + this.userService.userRouteNavigate(['success', { reason: 'already' }]); } else { - this.loginMessage = result.state; - this.state = 'login'; + this.userService.userRouteNavigate(['login', { reason: result.state }]); } }); } - login(event: LoginEvent) { - this.userService.tryLogin(event.username, event.password).subscribe(result => { - this.userInfo = result; - this.displayLoginSuccessMessage = true; - this.state = 'success'; - }, (error: Error) => { - this.loginMessage = error.message; - }); + ngOnDestroy() { + this.userService.userRouteNavigate(null); } } diff --git a/Timeline/ClientApp/src/app/user/user-info.ts b/Timeline/ClientApp/src/app/user/user-info.ts deleted file mode 100644 index 490b00ba..00000000 --- a/Timeline/ClientApp/src/app/user/user-info.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface UserInfo { - username: string; - roles: string[]; -} diff --git a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.ts b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.ts index 99de5970..d141b3b6 100644 --- a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.ts +++ b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.ts @@ -1,5 +1,7 @@ import { Component, OnInit, Input } from '@angular/core'; -import { UserInfo } from '../user-info'; +import { UserInfo } from '../entities'; +import { UserService } from '../user-service/user.service'; +import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-user-login-success', @@ -8,15 +10,14 @@ import { UserInfo } from '../user-info'; }) export class UserLoginSuccessComponent implements OnInit { - @Input() displayLoginSuccessMessage = false; - @Input() userInfo: UserInfo; - constructor() { } + constructor(private route: ActivatedRoute, private userService: UserService) { } ngOnInit() { + this.userInfo = this.userService.userInfo; + this.displayLoginSuccessMessage = this.route.snapshot.paramMap.get('reason') === 'login'; } - } diff --git a/Timeline/ClientApp/src/app/user/user-login/user-login.component.ts b/Timeline/ClientApp/src/app/user/user-login/user-login.component.ts index da642cb8..971d57ce 100644 --- a/Timeline/ClientApp/src/app/user/user-login/user-login.component.ts +++ b/Timeline/ClientApp/src/app/user/user-login/user-login.component.ts @@ -1,5 +1,7 @@ -import { Component, Output, OnInit, EventEmitter, Input } from '@angular/core'; +import { Component, Output, OnInit, EventEmitter } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; +import { UserService } from '../user-service/user.service'; +import { ActivatedRoute } from '@angular/router'; export type LoginMessage = 'nologin' | 'invalidlogin' | string; @@ -13,20 +15,24 @@ export class LoginEvent { templateUrl: './user-login.component.html', styleUrls: ['./user-login.component.css'] }) -export class UserLoginComponent { +export class UserLoginComponent implements OnInit { - @Input() - message: LoginMessage; + constructor(private route: ActivatedRoute, private userService: UserService) { } - @Output() - login = new EventEmitter<LoginEvent>(); + message: string; form = new FormGroup({ username: new FormControl(''), password: new FormControl('') }); + ngOnInit() { + this.message = this.route.snapshot.paramMap.get('reason'); + } + onLoginButtonClick() { - this.login.emit(this.form.value); + this.userService.tryLogin(this.form.value).subscribe(_ => { + this.userService.userRouteNavigate(['success', { reason: 'login' }]); + }, (error: Error) => this.message = error.message); } } diff --git a/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts b/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts index 0095f031..9effe000 100644 --- a/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts +++ b/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts @@ -2,15 +2,20 @@ import { TestBed } from '@angular/core/testing'; import { HttpRequest } from '@angular/common/http'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { UserInfo } from '../user-info'; +import { UserInfo, UserCredentials } from '../entities'; import { - UserService, UserCredentials, CreateTokenResult, + UserService, CreateTokenResult, UserLoginState, TokenValidationRequest, TokenValidationResult } from './user.service'; describe('UserService', () => { const tokenCreateUrl = '/api/User/CreateToken'; + const mockUserCredentials: UserCredentials = { + username: 'user', + password: 'user' + }; + beforeEach(() => TestBed.configureTestingModule({ imports: [HttpClientTestingModule] })); @@ -35,7 +40,7 @@ describe('UserService', () => { roles: ['user', 'other'] }; - service.tryLogin('user', 'user').subscribe(result => { + service.tryLogin(mockUserCredentials).subscribe(result => { expect(result).toEqual(mockUserInfo); }); @@ -71,7 +76,7 @@ describe('UserService', () => { service = TestBed.get(UserService); httpController = TestBed.get(HttpTestingController); - service.tryLogin('user', 'user').subscribe(); // subscribe to activate login + service.tryLogin(mockUserCredentials).subscribe(); // subscribe to activate login httpController.expectOne(tokenCreateUrl).flush(<CreateTokenResult>{ token: mockToken, diff --git a/Timeline/ClientApp/src/app/user/user-service/user.service.ts b/Timeline/ClientApp/src/app/user/user-service/user.service.ts index 009e5292..e535537d 100644 --- a/Timeline/ClientApp/src/app/user/user-service/user.service.ts +++ b/Timeline/ClientApp/src/app/user/user-service/user.service.ts @@ -3,12 +3,8 @@ import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Observable, of, throwError } from 'rxjs'; import { map, catchError, retry } from 'rxjs/operators'; -import { UserInfo } from '../user-info'; - -export interface UserCredentials { - username: string; - password: string; -} +import { UserCredentials, UserInfo } from '../entities'; +import { Router } from '@angular/router'; export interface CreateTokenResult { token: string; @@ -53,9 +49,17 @@ export class BadCredentialsException extends Error { export class UserService { private token: string; - private userInfo: UserInfo; + userInfo: UserInfo; - constructor(private httpClient: HttpClient) { } + constructor(private httpClient: HttpClient, private router: Router) { } + + userRouteNavigate(commands: any[]) { + this.router.navigate([{ + outlets: { + user: commands + } + }]); + } validateUserLoginState(): Observable<UserLoginState> { if (this.token === undefined || this.token === null) { @@ -86,14 +90,12 @@ export class UserService { ); } - tryLogin(username: string, password: string): Observable<UserInfo> { + tryLogin(credentials: UserCredentials): Observable<UserInfo> { if (this.token) { return throwError(new AlreadyLoginException()); } - return this.httpClient.post<CreateTokenResult>('/api/User/CreateToken', <UserCredentials>{ - username, password - }).pipe( + return this.httpClient.post<CreateTokenResult>('/api/User/CreateToken', credentials).pipe( catchError((error: HttpErrorResponse) => { if (error.error instanceof ErrorEvent) { console.error('An error occurred when login: ' + error.error.message); diff --git a/Timeline/ClientApp/src/app/user/user.module.ts b/Timeline/ClientApp/src/app/user/user.module.ts index 67de90a2..1e70d33d 100644 --- a/Timeline/ClientApp/src/app/user/user.module.ts +++ b/Timeline/ClientApp/src/app/user/user.module.ts @@ -11,14 +11,21 @@ import { UserDialogComponent } from './user-dialog/user-dialog.component'; import { UserLoginComponent } from './user-login/user-login.component'; import { UserLoginSuccessComponent } from './user-login-success/user-login-success.component'; import { UtilityModule } from '../utility/utility.module'; +import { RouterModule } from '@angular/router'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ declarations: [UserDialogComponent, UserLoginComponent, UserLoginSuccessComponent], imports: [ - CommonModule, HttpClientModule, ReactiveFormsModule, + RouterModule.forChild([ + { path: 'login', component: UserLoginComponent, outlet: 'user' }, + { path: 'success', component: UserLoginSuccessComponent, outlet: 'user' } + ]), + CommonModule, HttpClientModule, ReactiveFormsModule, BrowserAnimationsModule, MatFormFieldModule, MatProgressSpinnerModule, MatDialogModule, MatInputModule, MatButtonModule, UtilityModule ], + exports: [RouterModule], entryComponents: [UserDialogComponent] }) export class UserModule { } |