Modify member name checking

This commit is contained in:
Steven Zou 2017-05-16 18:01:54 -07:00
parent cf65c39cef
commit 26d20bd9aa
3 changed files with 162 additions and 94 deletions

View File

@ -72,6 +72,10 @@ export class GlobalSearchComponent implements OnInit, OnDestroy {
if (this.searchSub) { if (this.searchSub) {
this.searchSub.unsubscribe(); this.searchSub.unsubscribe();
} }
if (this.closeSub) {
this.closeSub.unsubscribe();
}
} }
//Handle the term inputting event //Handle the term inputting event

View File

@ -5,29 +5,32 @@
<form #memberForm="ngForm"> <form #memberForm="ngForm">
<section class="form-block"> <section class="form-block">
<div class="form-group"> <div class="form-group">
<label for="member_name" class="col-md-4 form-group-label-override">{{'MEMBER.NAME' | translate}}</label> <label for="member_name" class="col-md-4 form-group-label-override required">{{'MEMBER.NAME' | translate}}</label>
<label for="member_name" aria-haspopup="true" role="tooltip" [class.invalid]="memberName.invalid && (memberName.dirty || memberName.touched)" [class.valid]="memberName.valid" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-left"> <label for="member_name" aria-haspopup="true" role="tooltip" [class.invalid]="!isMemberNameValid" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left">
<input type="text" id="member_name" [(ngModel)]="member.username" name="name" size="20" #memberName="ngModel" required targetExists="MEMBER_NAME" [projectId]="projectId"> <input type="text" id="member_name" [(ngModel)]="member.username"
<span class="tooltip-content" *ngIf="memberName.errors && memberName.errors.required && (memberName.dirty || memberName.touched)"> name="member_name"
{{ 'MEMBER.USERNAME_IS_REQUIRED' | translate }} size="20"
</span> #memberName="ngModel"
<span class="tooltip-content" *ngIf="memberName.errors && memberName.errors.targetExists && (memberName.dirty || memberName.touched)"> required
{{ 'MEMBER.USERNAME_ALREADY_EXISTS' | translate }} (keyup)='handleValidation()'>
<span class="tooltip-content">
{{ memberTooltip | translate }}
</span> </span>
</label> </label>
<span class="spinner spinner-inline" [hidden]="!checkOnGoing"></span>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-md-4 form-group-label-override">{{'MEMBER.ROLE' | translate}}</label> <label class="col-md-4 form-group-label-override">{{'MEMBER.ROLE' | translate}}</label>
<div class="radio"> <div class="radio">
<input type="radio" name="roleRadios" id="checkrads_project_admin" [value]="1" [(ngModel)]="member.role_id"> <input type="radio" name="member_role" id="checkrads_project_admin" [value]="1" [(ngModel)]="member.role_id">
<label for="checkrads_project_admin">{{'MEMBER.PROJECT_ADMIN' | translate}}</label> <label for="checkrads_project_admin">{{'MEMBER.PROJECT_ADMIN' | translate}}</label>
</div> </div>
<div class="radio"> <div class="radio">
<input type="radio" name="roleRadios" id="checkrads_developer" [value]="2" [(ngModel)]="member.role_id"> <input type="radio" name="member_role" id="checkrads_developer" [value]="2" [(ngModel)]="member.role_id">
<label for="checkrads_developer">{{'MEMBER.DEVELOPER' | translate}}</label> <label for="checkrads_developer">{{'MEMBER.DEVELOPER' | translate}}</label>
</div> </div>
<div class="radio"> <div class="radio">
<input type="radio" name="roleRadios" id="checkrads_guest" [value]="3" [(ngModel)]="member.role_id"> <input type="radio" name="member_role" id="checkrads_guest" [value]="3" [(ngModel)]="member.role_id">
<label for="checkrads_guest">{{'MEMBER.GUEST' | translate}}</label> <label for="checkrads_guest">{{'MEMBER.GUEST' | translate}}</label>
</div> </div>
</div> </div>
@ -36,6 +39,6 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="onCancel()">{{'BUTTON.CANCEL' | translate}}</button> <button type="button" class="btn btn-outline" (click)="onCancel()">{{'BUTTON.CANCEL' | translate}}</button>
<button type="button" class="btn btn-primary" [disabled]="memberForm.form.invalid" (click)="onSubmit()">{{'BUTTON.OK' | translate}}</button> <button type="button" class="btn btn-primary" [disabled]="!isValid" (click)="onSubmit()">{{'BUTTON.OK' | translate}}</button>
</div> </div>
</clr-modal> </clr-modal>

View File

@ -11,7 +11,16 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { Component, Input, EventEmitter, Output, ViewChild, AfterViewChecked } from '@angular/core'; import {
Component,
Input,
EventEmitter,
Output,
ViewChild,
AfterViewChecked,
OnInit,
OnDestroy
} from '@angular/core';
import { Response } from '@angular/http'; import { Response } from '@angular/http';
import { NgForm } from '@angular/forms'; import { NgForm } from '@angular/forms';
@ -24,15 +33,18 @@ import { TranslateService } from '@ngx-translate/core';
import { Member } from '../member'; import { Member } from '../member';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
@Component({ @Component({
selector: 'add-member', selector: 'add-member',
templateUrl: 'add-member.component.html', templateUrl: 'add-member.component.html',
styleUrls: ['add-member.component.css'] styleUrls: ['add-member.component.css']
}) })
export class AddMemberComponent implements AfterViewChecked { export class AddMemberComponent implements AfterViewChecked, OnInit, OnDestroy {
member: Member = new Member(); member: Member = new Member();
initVal: Member = new Member();
addMemberOpened: boolean; addMemberOpened: boolean;
@ -52,10 +64,48 @@ export class AddMemberComponent implements AfterViewChecked {
@Input() projectId: number; @Input() projectId: number;
@Output() added = new EventEmitter<boolean>(); @Output() added = new EventEmitter<boolean>();
isMemberNameValid: boolean = true;
memberTooltip: string = 'MEMBER.USERNAME_IS_REQUIRED';
nameChecker: Subject<string> = new Subject<string>();
checkOnGoing: boolean = false;
constructor(private memberService: MemberService, constructor(private memberService: MemberService,
private messageHandlerService: MessageHandlerService, private messageHandlerService: MessageHandlerService,
private translateService: TranslateService) { } private translateService: TranslateService) { }
ngOnInit(): void {
this.nameChecker
.debounceTime(500)
.distinctUntilChanged()
.subscribe((name: string) => {
let cont = this.currentForm.controls['member_name'];
if (cont) {
this.isMemberNameValid = cont.valid;
if (cont.valid) {
this.checkOnGoing = true;
this.memberService
.listMembers(this.projectId, cont.value).toPromise()
.then((members: Member[]) => {
if (members.filter(m => { return m.username === cont.value }).length > 0) {
this.isMemberNameValid = false;
this.memberTooltip = 'MEMBER.USERNAME_ALREADY_EXISTS';
}
this.checkOnGoing = false;
})
.catch(error => {
this.checkOnGoing = false;
});
} else {
this.memberTooltip = 'MEMBER.USERNAME_IS_REQUIRED';
}
}
});
}
ngOnDestroy(): void {
this.nameChecker.unsubscribe();
}
onSubmit(): void { onSubmit(): void {
if (!this.member.username || this.member.username.length === 0) { return; } if (!this.member.username || this.member.username.length === 0) { return; }
this.memberService this.memberService
@ -102,19 +152,17 @@ export class AddMemberComponent implements AfterViewChecked {
} }
ngAfterViewChecked(): void { ngAfterViewChecked(): void {
if (this.memberForm !== this.currentForm) {
this.memberForm = this.currentForm; this.memberForm = this.currentForm;
}
if (this.memberForm) { if (this.memberForm) {
this.memberForm.valueChanges.subscribe(data => { this.memberForm.valueChanges.subscribe(data => {
for(let i in data) { let memberName = data['member_name'];
let origin = this.initVal[i]; if (memberName && memberName !== '') {
let current = data[i];
if(current && current !== origin) {
this.hasChanged = true; this.hasChanged = true;
break; this.inlineAlert.close();
} else { } else {
this.hasChanged = false; this.hasChanged = false;
this.inlineAlert.close();
}
} }
}); });
} }
@ -132,6 +180,19 @@ export class AddMemberComponent implements AfterViewChecked {
this.addMemberOpened = true; this.addMemberOpened = true;
this.hasChanged = false; this.hasChanged = false;
this.member.role_id = 1; this.member.role_id = 1;
this.member.username = '';
this.isMemberNameValid = true;
this.memberTooltip = 'MEMBER.USERNAME_IS_REQUIRED';
} }
handleValidation(): void {
let cont = this.currentForm.controls['member_name'];
if (cont) {
this.nameChecker.next(cont.value);
}
}
public get isValid(): boolean {
return this.currentForm && this.currentForm.valid && this.isMemberNameValid;
}
} }