mirror of https://github.com/Chocobozzz/PeerTube
Client: reactive forms
parent
ab32b0fc80
commit
4b2f33f3c6
|
@ -3,25 +3,25 @@
|
||||||
<div *ngIf="information" class="alert alert-success">{{ information }}</div>
|
<div *ngIf="information" class="alert alert-success">{{ information }}</div>
|
||||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||||
|
|
||||||
<form role="form" (ngSubmit)="changePassword()" [formGroup]="changePasswordForm">
|
<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="new-password">New password</label>
|
<label for="new-password">New password</label>
|
||||||
<input
|
<input
|
||||||
type="password" class="form-control" name="new-password" id="new-password"
|
type="password" class="form-control" id="new-password"
|
||||||
[(ngModel)]="newPassword" #newPasswordInput="ngModel"
|
formControlName="new-password"
|
||||||
>
|
>
|
||||||
<div [hidden]="changePasswordForm.controls['new-password'].valid || changePasswordForm.controls['new-password'].pristine" class="alert alert-warning">
|
<div *ngIf="formErrors['new-password']" class="alert alert-danger">
|
||||||
The password should have more than 5 characters
|
{{ formErrors['new-password'] }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name">Confirm new password</label>
|
<label for="name">Confirm new password</label>
|
||||||
<input
|
<input
|
||||||
type="password" class="form-control" name="new-confirmed-password" id="new-confirmed-password"
|
type="password" class="form-control" id="new-confirmed-password"
|
||||||
[(ngModel)]="newConfirmedPassword" #newConfirmedPasswordInput="ngModel"
|
formControlName="new-confirmed-password"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="submit" value="Change password" class="btn btn-default" [disabled]="!changePasswordForm.valid">
|
<input type="submit" value="Change password" class="btn btn-default" [disabled]="!form.valid">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,44 +1,64 @@
|
||||||
import { } from '@angular/common';
|
import { } from '@angular/common';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { AccountService } from './account.service';
|
import { AccountService } from './account.service';
|
||||||
|
import { FormReactive, USER_PASSWORD } from '../shared';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-account',
|
selector: 'my-account',
|
||||||
template: require('./account.component.html')
|
template: require('./account.component.html')
|
||||||
})
|
})
|
||||||
|
|
||||||
export class AccountComponent implements OnInit {
|
export class AccountComponent extends FormReactive implements OnInit {
|
||||||
newPassword = '';
|
|
||||||
newConfirmedPassword = '';
|
|
||||||
changePasswordForm: FormGroup;
|
|
||||||
information: string = null;
|
information: string = null;
|
||||||
error: string = null;
|
error: string = null;
|
||||||
|
|
||||||
|
form: FormGroup;
|
||||||
|
formErrors = {
|
||||||
|
'new-password': '',
|
||||||
|
'new-confirmed-password': ''
|
||||||
|
};
|
||||||
|
validationMessages = {
|
||||||
|
'new-password': USER_PASSWORD.MESSAGES,
|
||||||
|
'new-confirmed-password': USER_PASSWORD.MESSAGES
|
||||||
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {}
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm() {
|
||||||
|
this.form = this.formBuilder.group({
|
||||||
|
'new-password': [ '', USER_PASSWORD.VALIDATORS ],
|
||||||
|
'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.changePasswordForm = new FormGroup({
|
this.buildForm();
|
||||||
'new-password': new FormControl('', [ <any>Validators.required, <any>Validators.minLength(6) ]),
|
|
||||||
'new-confirmed-password': new FormControl('', [ <any>Validators.required, <any>Validators.minLength(6) ]),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changePassword() {
|
changePassword() {
|
||||||
|
const newPassword = this.form.value['new-password'];
|
||||||
|
const newConfirmedPassword = this.form.value['new-confirmed-password'];
|
||||||
|
|
||||||
this.information = null;
|
this.information = null;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
if (this.newPassword !== this.newConfirmedPassword) {
|
if (newPassword !== newConfirmedPassword) {
|
||||||
this.error = 'The new password and the confirmed password do not correspond.';
|
this.error = 'The new password and the confirmed password do not correspond.';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.accountService.changePassword(this.newPassword).subscribe(
|
this.accountService.changePassword(newPassword).subscribe(
|
||||||
ok => this.information = 'Password updated.',
|
ok => this.information = 'Password updated.',
|
||||||
|
|
||||||
err => this.error = err
|
err => this.error = err
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||||
|
|
||||||
<form (ngSubmit)="makeFriends()" [formGroup]="friendAddForm">
|
<form (ngSubmit)="makeFriends()" [formGroup]="form">
|
||||||
<div class="form-group" *ngFor="let url of urls; let id = index; trackBy:customTrackBy">
|
<div class="form-group" *ngFor="let url of urls; let id = index; trackBy:customTrackBy">
|
||||||
<label for="username">Url</label>
|
<label for="username">Url</label>
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input
|
<input
|
||||||
type="text" class="form-control" placeholder="http://domain.com"
|
type="text" class="form-control" placeholder="http://domain.com"
|
||||||
[name]="'url-' + id" [id]="'url-' + id" [formControlName]="'url-' + id" [(ngModel)]="urls[id]"
|
[id]="'url-' + id" [formControlName]="'url-' + id"
|
||||||
/>
|
/>
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button *ngIf="displayAddField(id)" (click)="addField()" class="btn btn-default" type="button">+</button>
|
<button *ngIf="displayAddField(id)" (click)="addField()" class="btn btn-default" type="button">+</button>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div [hidden]="friendAddForm.controls['url-' + id].valid || friendAddForm.controls['url-' + id].pristine" class="alert alert-warning">
|
<div [hidden]="form.controls['url-' + id].valid || form.controls['url-' + id].pristine" class="alert alert-warning">
|
||||||
It should be a valid url.
|
It should be a valid url.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,19 +11,19 @@ import { FriendService } from '../shared';
|
||||||
styles: [ require('./friend-add.component.scss') ]
|
styles: [ require('./friend-add.component.scss') ]
|
||||||
})
|
})
|
||||||
export class FriendAddComponent implements OnInit {
|
export class FriendAddComponent implements OnInit {
|
||||||
friendAddForm: FormGroup;
|
form: FormGroup;
|
||||||
urls = [ ];
|
urls = [ ];
|
||||||
error: string = null;
|
error: string = null;
|
||||||
|
|
||||||
constructor(private router: Router, private friendService: FriendService) {}
|
constructor(private router: Router, private friendService: FriendService) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.friendAddForm = new FormGroup({});
|
this.form = new FormGroup({});
|
||||||
this.addField();
|
this.addField();
|
||||||
}
|
}
|
||||||
|
|
||||||
addField() {
|
addField() {
|
||||||
this.friendAddForm.addControl(`url-${this.urls.length}`, new FormControl('', [ validateUrl ]));
|
this.form.addControl(`url-${this.urls.length}`, new FormControl('', [ validateUrl ]));
|
||||||
this.urls.push('');
|
this.urls.push('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ export class FriendAddComponent implements OnInit {
|
||||||
isFormValid() {
|
isFormValid() {
|
||||||
// Do not check the last input
|
// Do not check the last input
|
||||||
for (let i = 0; i < this.urls.length - 1; i++) {
|
for (let i = 0; i < this.urls.length - 1; i++) {
|
||||||
if (!this.friendAddForm.controls[`url-${i}`].valid) return false;
|
if (!this.form.controls[`url-${i}`].valid) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastIndex = this.urls.length - 1;
|
const lastIndex = this.urls.length - 1;
|
||||||
|
@ -50,13 +50,13 @@ export class FriendAddComponent implements OnInit {
|
||||||
if (this.urls[lastIndex] === '' && lastIndex !== 0) {
|
if (this.urls[lastIndex] === '' && lastIndex !== 0) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return this.friendAddForm.controls[`url-${lastIndex}`].valid;
|
return this.form.controls[`url-${lastIndex}`].valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeField(index: number) {
|
removeField(index: number) {
|
||||||
// Remove the last control
|
// Remove the last control
|
||||||
this.friendAddForm.removeControl(`url-${this.urls.length - 1}`);
|
this.form.removeControl(`url-${this.urls.length - 1}`);
|
||||||
this.urls.splice(index, 1);
|
this.urls.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,8 @@ export class FriendAddComponent implements OnInit {
|
||||||
private getNotEmptyUrls() {
|
private getNotEmptyUrls() {
|
||||||
const notEmptyUrls = [];
|
const notEmptyUrls = [];
|
||||||
|
|
||||||
this.urls.forEach((url) => {
|
Object.keys(this.form.value).forEach((urlKey) => {
|
||||||
|
const url = this.form.value[urlKey];
|
||||||
if (url !== '') notEmptyUrls.push(url);
|
if (url !== '') notEmptyUrls.push(url);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,28 +2,28 @@
|
||||||
|
|
||||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||||
|
|
||||||
<form role="form" (ngSubmit)="addUser()" [formGroup]="userAddForm">
|
<form role="form" (ngSubmit)="addUser()" [formGroup]="form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<input
|
<input
|
||||||
type="text" class="form-control" name="username" id="username" placeholder="Username"
|
type="text" class="form-control" id="username" placeholder="Username"
|
||||||
[(ngModel)]="username"
|
formControlName="username"
|
||||||
>
|
>
|
||||||
<div [hidden]="userAddForm.controls.username.valid || userAddForm.controls.username.pristine" class="alert alert-danger">
|
<div *ngIf="formErrors.username" class="alert alert-danger">
|
||||||
Username is required with a length >= 3 and <= 20
|
{{ formErrors.username }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input
|
<input
|
||||||
type="password" class="form-control" name="password" id="password" placeholder="Password"
|
type="password" class="form-control" id="password" placeholder="Password"
|
||||||
[(ngModel)]="password"
|
formControlName="password"
|
||||||
>
|
>
|
||||||
<div [hidden]="userAddForm.controls.password.valid || userAddForm.controls.password.pristine" class="alert alert-danger">
|
<div *ngIf="formErrors.password" class="alert alert-danger">
|
||||||
Password is required with a length >= 6
|
{{ formErrors.password }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="submit" value="Add user" class="btn btn-default" [disabled]="!userAddForm.valid">
|
<input type="submit" value="Add user" class="btn btn-default" [disabled]="!form.valid">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,32 +1,54 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { UserService } from '../shared';
|
import { UserService } from '../shared';
|
||||||
|
import { FormReactive, USER_USERNAME, USER_PASSWORD } from '../../../shared';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-user-add',
|
selector: 'my-user-add',
|
||||||
template: require('./user-add.component.html')
|
template: require('./user-add.component.html')
|
||||||
})
|
})
|
||||||
export class UserAddComponent implements OnInit {
|
export class UserAddComponent extends FormReactive implements OnInit {
|
||||||
userAddForm: FormGroup;
|
|
||||||
error: string = null;
|
error: string = null;
|
||||||
username = '';
|
|
||||||
password = '';
|
|
||||||
|
|
||||||
constructor(private router: Router, private userService: UserService) {}
|
form: FormGroup;
|
||||||
|
formErrors = {
|
||||||
|
'username': '',
|
||||||
|
'password': ''
|
||||||
|
};
|
||||||
|
validationMessages = {
|
||||||
|
'username': USER_USERNAME.MESSAGES,
|
||||||
|
'password': USER_PASSWORD.MESSAGES,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
private router: Router,
|
||||||
|
private userService: UserService
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm() {
|
||||||
|
this.form = this.formBuilder.group({
|
||||||
|
username: [ '', USER_USERNAME.VALIDATORS ],
|
||||||
|
password: [ '', USER_PASSWORD.VALIDATORS ],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.userAddForm = new FormGroup({
|
this.buildForm();
|
||||||
username: new FormControl('', [ <any>Validators.required, <any>Validators.minLength(3), <any>Validators.maxLength(20) ]),
|
|
||||||
password: new FormControl('', [ <any>Validators.required, <any>Validators.minLength(6) ]),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addUser() {
|
addUser() {
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
this.userService.addUser(this.username, this.password).subscribe(
|
const { username, password } = this.form.value;
|
||||||
|
|
||||||
|
this.userService.addUser(username, password).subscribe(
|
||||||
ok => this.router.navigate([ '/admin/users/list' ]),
|
ok => this.router.navigate([ '/admin/users/list' ]),
|
||||||
|
|
||||||
err => this.error = err.text
|
err => this.error = err.text
|
||||||
|
|
|
@ -28,7 +28,8 @@ import {
|
||||||
VideoMiniatureComponent,
|
VideoMiniatureComponent,
|
||||||
VideoSortComponent,
|
VideoSortComponent,
|
||||||
VideoWatchComponent,
|
VideoWatchComponent,
|
||||||
VideoService
|
VideoService,
|
||||||
|
WebTorrentService
|
||||||
} from './videos';
|
} from './videos';
|
||||||
import {
|
import {
|
||||||
FriendsComponent,
|
FriendsComponent,
|
||||||
|
@ -59,7 +60,7 @@ const APP_PROVIDERS = [
|
||||||
|
|
||||||
AuthService,
|
AuthService,
|
||||||
RestExtractor,
|
RestExtractor,
|
||||||
RestExtractor, RestService, VideoService, SearchService, FriendService, UserService, AccountService
|
RestExtractor, RestService, VideoService, SearchService, FriendService, UserService, AccountService, WebTorrentService
|
||||||
];
|
];
|
||||||
/**
|
/**
|
||||||
* `AppModule` is the main entry point into Angular2's bootstraping process
|
* `AppModule` is the main entry point into Angular2's bootstraping process
|
||||||
|
|
|
@ -2,28 +2,28 @@
|
||||||
|
|
||||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||||
|
|
||||||
<form role="form" (ngSubmit)="login()" [formGroup]="loginForm">
|
<form role="form" (ngSubmit)="login()" [formGroup]="form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<input
|
<input
|
||||||
type="text" class="form-control" name="username" id="username" placeholder="Username"
|
type="text" class="form-control" id="username" placeholder="Username" required
|
||||||
[(ngModel)]="username"
|
formControlName="username"
|
||||||
>
|
>
|
||||||
<div [hidden]="loginForm.controls.username.valid || loginForm.controls.username.pristine" class="alert alert-danger">
|
<div *ngIf="formErrors.username" class="alert alert-danger">
|
||||||
Username is required
|
{{ formErrors.username }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input
|
<input
|
||||||
type="password" class="form-control" name="password" id="password" placeholder="Password"
|
type="password" class="form-control" name="password" id="password" placeholder="Password" required
|
||||||
[(ngModel)]="password"
|
formControlName="password"
|
||||||
>
|
>
|
||||||
<div [hidden]="loginForm.controls.password.valid || loginForm.controls.password.pristine" class="alert alert-danger">
|
<div *ngIf="formErrors.password" class="alert alert-danger">
|
||||||
Password is required
|
{{ formErrors.password }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="submit" value="Login" class="btn btn-default" [disabled]="!loginForm.valid">
|
<input type="submit" value="Login" class="btn btn-default" [disabled]="!form.valid">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,39 +1,60 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { AuthService } from '../shared';
|
import { AuthService, FormReactive } from '../shared';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-login',
|
selector: 'my-login',
|
||||||
template: require('./login.component.html')
|
template: require('./login.component.html')
|
||||||
})
|
})
|
||||||
|
|
||||||
export class LoginComponent implements OnInit {
|
export class LoginComponent extends FormReactive implements OnInit {
|
||||||
error: string = null;
|
error: string = null;
|
||||||
username = '';
|
|
||||||
password: '';
|
form: FormGroup;
|
||||||
loginForm: FormGroup;
|
formErrors = {
|
||||||
|
'username': '',
|
||||||
|
'password': ''
|
||||||
|
};
|
||||||
|
validationMessages = {
|
||||||
|
'username': {
|
||||||
|
'required': 'Username is required.',
|
||||||
|
},
|
||||||
|
'password': {
|
||||||
|
'required': 'Password is required.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {}
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm() {
|
||||||
|
this.form = this.formBuilder.group({
|
||||||
|
username: [ '', Validators.required ],
|
||||||
|
password: [ '', Validators.required ],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.loginForm = new FormGroup({
|
this.buildForm();
|
||||||
username: new FormControl('', [ <any>Validators.required ]),
|
|
||||||
password: new FormControl('', [ <any>Validators.required ]),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
login() {
|
login() {
|
||||||
this.authService.login(this.username, this.password).subscribe(
|
this.error = null;
|
||||||
result => {
|
|
||||||
this.error = null;
|
const { username, password } = this.form.value;
|
||||||
|
|
||||||
|
this.authService.login(username, password).subscribe(
|
||||||
|
result => this.router.navigate(['/videos/list']),
|
||||||
|
|
||||||
this.router.navigate(['/videos/list']);
|
|
||||||
},
|
|
||||||
error => {
|
error => {
|
||||||
console.error(error.json);
|
console.error(error.json);
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './url.validator';
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
|
export abstract class FormReactive {
|
||||||
|
abstract form: FormGroup;
|
||||||
|
abstract formErrors: Object;
|
||||||
|
abstract validationMessages: Object;
|
||||||
|
|
||||||
|
abstract buildForm(): void;
|
||||||
|
|
||||||
|
protected onValueChanged(data?: any) {
|
||||||
|
for (const field in this.formErrors) {
|
||||||
|
// clear previous error message (if any)
|
||||||
|
this.formErrors[field] = '';
|
||||||
|
const control = this.form.get(field);
|
||||||
|
|
||||||
|
if (control && control.dirty && !control.valid) {
|
||||||
|
const messages = this.validationMessages[field];
|
||||||
|
for (const key in control.errors) {
|
||||||
|
this.formErrors[field] += messages[key] + ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './url.validator';
|
||||||
|
export * from './user';
|
||||||
|
export * from './video';
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
export const USER_USERNAME = {
|
||||||
|
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(20) ],
|
||||||
|
MESSAGES: {
|
||||||
|
'required': 'Username is required.',
|
||||||
|
'minlength': 'Username must be at least 3 characters long.',
|
||||||
|
'maxlength': 'Username cannot be more than 20 characters long.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const USER_PASSWORD = {
|
||||||
|
VALIDATORS: [ Validators.required, Validators.minLength(6) ],
|
||||||
|
MESSAGES: {
|
||||||
|
'required': 'Password is required.',
|
||||||
|
'minlength': 'Password must be at least 6 characters long.',
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
export const VIDEO_NAME = {
|
||||||
|
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(50) ],
|
||||||
|
MESSAGES: {
|
||||||
|
'required': 'Video name is required.',
|
||||||
|
'minlength': 'Video name must be at least 3 characters long.',
|
||||||
|
'maxlength': 'Video name cannot be more than 50 characters long.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const VIDEO_DESCRIPTION = {
|
||||||
|
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ],
|
||||||
|
MESSAGES: {
|
||||||
|
'required': 'Video description is required.',
|
||||||
|
'minlength': 'Video description must be at least 3 characters long.',
|
||||||
|
'maxlength': 'Video description cannot be more than 250 characters long.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const VIDEO_TAGS = {
|
||||||
|
VALIDATORS: [ Validators.pattern('^[a-zA-Z0-9]{2,10}$') ],
|
||||||
|
MESSAGES: {
|
||||||
|
'pattern': 'A tag should be between 2 and 10 alphanumeric characters long.'
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './form-validators';
|
||||||
|
export * from './form-reactive';
|
|
@ -1,5 +1,5 @@
|
||||||
export * from './auth';
|
export * from './auth';
|
||||||
export * from './form-validators';
|
export * from './forms';
|
||||||
export * from './rest';
|
export * from './rest';
|
||||||
export * from './search';
|
export * from './search';
|
||||||
export * from './users';
|
export * from './users';
|
||||||
|
|
|
@ -2,31 +2,31 @@
|
||||||
|
|
||||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
||||||
|
|
||||||
<form novalidate (ngSubmit)="upload()" [formGroup]="videoForm">
|
<form novalidate (ngSubmit)="upload()" [formGroup]="form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name">Name</label>
|
<label for="name">Name</label>
|
||||||
<input
|
<input
|
||||||
type="text" class="form-control" name="name" id="name"
|
type="text" class="form-control" id="name"
|
||||||
[(ngModel)]="video.name"
|
formControlName="name"
|
||||||
>
|
>
|
||||||
<div [hidden]="videoForm.controls.name.valid || videoForm.controls.name.pristine" class="alert alert-warning">
|
<div *ngIf="formErrors.name" class="alert alert-danger">
|
||||||
A name is required and should be between 3 and 50 characters long
|
{{ formErrors.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tags">Tags</label>
|
<label for="tags">Tags</label>
|
||||||
<input
|
<input
|
||||||
type="text" class="form-control" name="tags" id="tags"
|
type="text" class="form-control" id="currentTag"
|
||||||
[disabled]="isTagsInputDisabled" (keyup)="onTagKeyPress($event)" [(ngModel)]="currentTag"
|
formControlName="currentTag" (keyup)="onTagKeyPress($event)"
|
||||||
>
|
>
|
||||||
<div [hidden]="videoForm.controls.tags.valid || videoForm.controls.tags.pristine" class="alert alert-warning">
|
<div *ngIf="formErrors.currentTag" class="alert alert-danger">
|
||||||
A tag should be between 2 and 10 characters (alphanumeric) long
|
{{ formErrors.currentTag }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
<div class="label label-primary tag" *ngFor="let tag of video.tags">
|
<div class="label label-primary tag" *ngFor="let tag of tags">
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
<span class="remove" (click)="removeTag(tag)">x</span>
|
<span class="remove" (click)="removeTag(tag)">x</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,12 +53,12 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="description">Description</label>
|
<label for="description">Description</label>
|
||||||
<textarea
|
<textarea
|
||||||
name="description" id="description" class="form-control" placeholder="Description..."
|
id="description" class="form-control" placeholder="Description..."
|
||||||
[(ngModel)]="video.description"
|
formControlName="description"
|
||||||
>
|
>
|
||||||
</textarea>
|
</textarea>
|
||||||
<div [hidden]="videoForm.controls.description.valid || videoForm.controls.description.pristine" class="alert alert-warning">
|
<div *ngIf="formErrors.description" class="alert alert-danger">
|
||||||
A description is required and should be between 3 and 250 characters long
|
{{ formErrors.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input
|
<input
|
||||||
type="submit" value="Upload" class="btn btn-default form-control" [title]="getInvalidFieldsTitle()"
|
type="submit" value="Upload" class="btn btn-default form-control" [title]="getInvalidFieldsTitle()"
|
||||||
[disabled]="!videoForm.valid || video.tags.length === 0 || filename === null"
|
[disabled]="!form.valid || tags.length === 0 || filename === null"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Component, ElementRef, OnInit } from '@angular/core';
|
import { Component, ElementRef, OnInit } from '@angular/core';
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
|
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
|
||||||
|
|
||||||
import { AuthService } from '../../shared';
|
import { AuthService, FormReactive, VIDEO_NAME, VIDEO_DESCRIPTION, VIDEO_TAGS } from '../../shared';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-videos-add',
|
selector: 'my-videos-add',
|
||||||
|
@ -12,22 +12,31 @@ import { AuthService } from '../../shared';
|
||||||
template: require('./video-add.component.html')
|
template: require('./video-add.component.html')
|
||||||
})
|
})
|
||||||
|
|
||||||
export class VideoAddComponent implements OnInit {
|
export class VideoAddComponent extends FormReactive implements OnInit {
|
||||||
currentTag: string; // Tag the user is writing in the input
|
tags: string[] = [];
|
||||||
error: string = null;
|
|
||||||
videoForm: FormGroup;
|
|
||||||
uploader: FileUploader;
|
uploader: FileUploader;
|
||||||
video = {
|
|
||||||
|
error: string = null;
|
||||||
|
form: FormGroup;
|
||||||
|
formErrors = {
|
||||||
name: '',
|
name: '',
|
||||||
tags: [],
|
description: '',
|
||||||
description: ''
|
currentTag: ''
|
||||||
|
};
|
||||||
|
validationMessages = {
|
||||||
|
name: VIDEO_NAME.MESSAGES,
|
||||||
|
description: VIDEO_DESCRIPTION.MESSAGES,
|
||||||
|
currentTag: VIDEO_TAGS.MESSAGES
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private elementRef: ElementRef,
|
private elementRef: ElementRef,
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {}
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
get filename() {
|
get filename() {
|
||||||
if (this.uploader.queue.length === 0) {
|
if (this.uploader.queue.length === 0) {
|
||||||
|
@ -37,20 +46,26 @@ export class VideoAddComponent implements OnInit {
|
||||||
return this.uploader.queue[0].file.name;
|
return this.uploader.queue[0].file.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isTagsInputDisabled () {
|
buildForm() {
|
||||||
return this.video.tags.length >= 3;
|
this.form = this.formBuilder.group({
|
||||||
|
name: [ '', VIDEO_NAME.VALIDATORS ],
|
||||||
|
description: [ '', VIDEO_DESCRIPTION.VALIDATORS ],
|
||||||
|
currentTag: [ '', VIDEO_TAGS.VALIDATORS ]
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
getInvalidFieldsTitle() {
|
getInvalidFieldsTitle() {
|
||||||
let title = '';
|
let title = '';
|
||||||
const nameControl = this.videoForm.controls['name'];
|
const nameControl = this.form.controls['name'];
|
||||||
const descriptionControl = this.videoForm.controls['description'];
|
const descriptionControl = this.form.controls['description'];
|
||||||
|
|
||||||
if (!nameControl.valid) {
|
if (!nameControl.valid) {
|
||||||
title += 'A name is required\n';
|
title += 'A name is required\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.video.tags.length === 0) {
|
if (this.tags.length === 0) {
|
||||||
title += 'At least one tag is required\n';
|
title += 'At least one tag is required\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,13 +81,6 @@ export class VideoAddComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.videoForm = new FormGroup({
|
|
||||||
name: new FormControl('', [ <any>Validators.required, <any>Validators.minLength(3), <any>Validators.maxLength(50) ]),
|
|
||||||
description: new FormControl('', [ <any>Validators.required, <any>Validators.minLength(3), <any>Validators.maxLength(250) ]),
|
|
||||||
tags: new FormControl('', <any>Validators.pattern('^[a-zA-Z0-9]{2,10}$'))
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
this.uploader = new FileUploader({
|
this.uploader = new FileUploader({
|
||||||
authToken: this.authService.getRequestHeaderValue(),
|
authToken: this.authService.getRequestHeaderValue(),
|
||||||
queueLimit: 1,
|
queueLimit: 1,
|
||||||
|
@ -81,26 +89,37 @@ export class VideoAddComponent implements OnInit {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.uploader.onBuildItemForm = (item, form) => {
|
this.uploader.onBuildItemForm = (item, form) => {
|
||||||
form.append('name', this.video.name);
|
const name = this.form.value['name'];
|
||||||
form.append('description', this.video.description);
|
const description = this.form.value['description'];
|
||||||
|
|
||||||
for (let i = 0; i < this.video.tags.length; i++) {
|
form.append('name', name);
|
||||||
form.append(`tags[${i}]`, this.video.tags[i]);
|
form.append('description', description);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.tags.length; i++) {
|
||||||
|
form.append(`tags[${i}]`, this.tags[i]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.buildForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
onTagKeyPress(event: KeyboardEvent) {
|
onTagKeyPress(event: KeyboardEvent) {
|
||||||
|
const currentTag = this.form.value['currentTag'];
|
||||||
|
|
||||||
// Enter press
|
// Enter press
|
||||||
if (event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
// Check if the tag is valid and does not already exist
|
// Check if the tag is valid and does not already exist
|
||||||
if (
|
if (
|
||||||
this.currentTag !== '' &&
|
currentTag !== '' &&
|
||||||
this.videoForm.controls['tags'].valid &&
|
this.form.controls['currentTag'].valid &&
|
||||||
this.video.tags.indexOf(this.currentTag) === -1
|
this.tags.indexOf(currentTag) === -1
|
||||||
) {
|
) {
|
||||||
this.video.tags.push(this.currentTag);
|
this.tags.push(currentTag);
|
||||||
this.currentTag = '';
|
this.form.patchValue({ currentTag: '' });
|
||||||
|
|
||||||
|
if (this.tags.length >= 3) {
|
||||||
|
this.form.get('currentTag').disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +129,7 @@ export class VideoAddComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeTag(tag: string) {
|
removeTag(tag: string) {
|
||||||
this.video.tags.splice(this.video.tags.indexOf(tag), 1);
|
this.tags.splice(this.tags.indexOf(tag), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
upload() {
|
upload() {
|
||||||
|
|
Loading…
Reference in New Issue