implement password settings

This commit is contained in:
Steven Zou 2017-02-21 14:05:36 +08:00
parent 59bea0e365
commit b92e3b2e7e
12 changed files with 276 additions and 0 deletions

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'forgot-password',
templateUrl: "forgot-password.component.html"
})
export class ForgotPasswordComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,55 @@
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true">
<h3 class="modal-title">Change Password</h3>
<div class="modal-body" style="min-height: 250px; overflow-y: hidden;">
<form #changepwdForm="ngForm" class="form">
<section class="form-block">
<div class="form-group">
<label for="oldPassword">Current Password</label>
<label for="oldPassword" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]="oldPassInput.invalid && (oldPassInput.dirty || oldPassInput.touched)">
<input type="password" id="oldPassword" placeholder="Enter current password"
required
name="oldPassword"
[(ngModel)]="oldPwd"
#oldPassInput="ngModel" size="25">
<span class="tooltip-content">
Current password is Required.
</span>
</label>
</div>
<div class="form-group">
<label for="newPassword">New Password</label>
<label for="newPassword" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]="newPassInput.invalid && (newPassInput.dirty || newPassInput.touched)">
<input type="password" id="newPassword" placeholder="Enter new password"
required
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{7,}$"
name="newPassword"
[(ngModel)]="newPwd"
#newPassInput="ngModel" size="25">
<span class="tooltip-content">
Password should be at least 7 characters with 1 uppercase,lowercase letetr and 1 number
</span>
</label>
</div>
<div class="form-group">
<label for="reNewPassword">Confirm Password</label>
<label for="reNewPassword" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]="(reNewPassInput.invalid && (reNewPassInput.dirty || reNewPassInput.touched)) || (!newPassInput.invalid && reNewPassInput.value != newPassInput.value)">
<input type="password" id="reNewPassword" placeholder="Confirm new password"
required
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{7,}$"
name="reNewPassword"
[(ngModel)]="reNewPwd"
#reNewPassInput="ngModel" size="25">
<span class="tooltip-content">
Password should be at least 7 characters with 1 uppercase,lowercase letetr and 1 number and consisted with new password
</span>
</label>
</div>
</section>
</form>
</div>
<div class="modal-footer">
<span class="spinner spinner-inline" style="top:8px;" [hidden]="showProgress === false"></span>
<button type="button" class="btn btn-outline" (click)="close()">Cancel</button>
<button type="button" class="btn btn-primary" [disabled]="!isValid || showProgress" (click)="doOk()">Ok</button>
</div>
</clr-modal>

View File

@ -0,0 +1,104 @@
import { Component, ViewChild, AfterViewChecked, Output, EventEmitter } from '@angular/core';
import { Router } from '@angular/router';
import { NgForm } from '@angular/forms';
import { PasswordSettingService } from './password-setting.service';
import { SessionService } from '../../shared/session.service';
@Component({
selector: 'password-setting',
templateUrl: "password-setting.component.html"
})
export class PasswordSettingComponent implements AfterViewChecked {
opened: boolean = false;
oldPwd: string = "";
newPwd: string = "";
reNewPwd: string = "";
private formValueChanged: boolean = false;
private onCalling: boolean = false;
pwdFormRef: NgForm;
@ViewChild("changepwdForm") pwdForm: NgForm;
@Output() private pwdChange = new EventEmitter<any>();
constructor(private passwordService: PasswordSettingService, private session: SessionService){}
//If form is valid
public get isValid(): boolean {
if (this.pwdForm && this.pwdForm.form.get("newPassword")) {
return this.pwdForm.valid &&
this.pwdForm.form.get("newPassword").value === this.pwdForm.form.get("reNewPassword").value;
}
return false;
}
public get valueChanged(): boolean {
return this.formValueChanged;
}
public get showProgress(): boolean {
return this.onCalling;
}
ngAfterViewChecked() {
if (this.pwdFormRef != this.pwdForm) {
this.pwdFormRef = this.pwdForm;
if (this.pwdFormRef) {
this.pwdFormRef.valueChanges.subscribe(data => {
this.formValueChanged = true;
});
}
}
}
//Open modal dialog
open(): void {
this.opened = true;
this.pwdForm.reset();
}
//Close the moal dialog
close(): void {
this.opened = false;
}
//handle the ok action
doOk(): void {
if (this.onCalling) {
return;//To avoid duplicate click events
}
if (!this.isValid) {
return;//Double confirm
}
//Double confirm session is valid
let cUser = this.session.getCurrentUser();
if(!cUser){
return;
}
//Call service
this.onCalling = true;
this.passwordService.changePassword(cUser.user_id,
{
new_password: this.pwdForm.value.newPassword,
old_password: this.pwdForm.value.oldPassword
})
.then(() => {
this.onCalling = false;
//Tell shell to reset current view
this.pwdChange.emit(true);
this.close();
})
.catch(error => {
this.onCalling = false;
console.error(error);//TODO:
});
//TODO:publish the successful message to general messae box
}
}

View File

@ -0,0 +1,35 @@
import { Injectable } from '@angular/core';
import { Headers, Http, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { PasswordSetting } from './password-setting';
const passwordChangeEndpoint = "/api/users/:user_id/password";
@Injectable()
export class PasswordSettingService {
private headers: Headers = new Headers({
"Accept": 'application/json',
"Content-Type": 'application/json'
});
private options: RequestOptions = new RequestOptions({
'headers': this.headers
});
constructor(private http: Http) { }
changePassword(userId: number, setting: PasswordSetting): Promise<any> {
if(!setting || setting.new_password.trim()==="" || setting.old_password.trim()===""){
return Promise.reject("Invalid data");
}
let putUrl = passwordChangeEndpoint.replace(":user_id", userId+"");
return this.http.put(putUrl, JSON.stringify(setting), this.options)
.toPromise()
.then(() => null)
.catch(error=>{
return Promise.reject(error);
});
}
}

View File

@ -0,0 +1,11 @@
/**
*
* Struct for password change
*
* @export
* @class PasswordSetting
*/
export class PasswordSetting {
old_password: string;
new_password: string;
}

View File

@ -0,0 +1 @@
<p>Placeholder for signup</p>

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'sign-up',
templateUrl: "sign-up.component.html"
})
export class SignUpComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import {
Router, Resolve, ActivatedRouteSnapshot, RouterStateSnapshot
} from '@angular/router';
import { SessionService } from '../shared/session.service';
import { SessionUser } from '../shared/session-user';
@Injectable()
export class BaseRoutingResolver implements Resolve<SessionUser> {
constructor(private session: SessionService, private router: Router) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<SessionUser> {
return this.session.retrieveUser()
.then(sessionUser => {
return sessionUser;
})
.catch(error => {
console.info("Anonymous user");
});
}
}

View File

@ -0,0 +1,2 @@
export const modalAccountSettings= "account-settings";
export const modalPasswordSetting = "password-setting";

View File

@ -0,0 +1,16 @@
.sign-in-override {
padding-left: 0px !important;
padding-right: 5px !important;
}
.sign-up-override {
padding-left: 5px !important;
}
.custom-divider {
display: inline-block;
border-right: 2px inset snow;
padding: 2px 0px 2px 0px;
vertical-align: middle;
height: 24px;
}

View File

@ -0,0 +1,9 @@
//Define the session user
export class SessionUser {
user_id: number;
username: string;
email: string;
role_name: string;
role_id: number;
has_admin_role: number;
}