diff options
-rw-r--r-- | client/src/app/app.module.ts | 2 | ||||
-rw-r--r-- | client/src/app/core/menu/menu.component.html | 5 | ||||
-rw-r--r-- | client/src/app/core/menu/menu.component.ts | 6 | ||||
-rw-r--r-- | client/src/app/shared/users/user.service.ts | 14 | ||||
-rw-r--r-- | client/src/app/signup/index.ts | 3 | ||||
-rw-r--r-- | client/src/app/signup/signup-routing.module.ts | 22 | ||||
-rw-r--r-- | client/src/app/signup/signup.component.html | 40 | ||||
-rw-r--r-- | client/src/app/signup/signup.component.ts | 72 | ||||
-rw-r--r-- | client/src/app/signup/signup.module.ts | 24 |
9 files changed, 188 insertions, 0 deletions
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts index 2d6fbaf21..534651cea 100644 --- a/client/src/app/app.module.ts +++ b/client/src/app/app.module.ts | |||
@@ -13,6 +13,7 @@ import { AppState } from './app.service'; | |||
13 | import { AccountModule } from './account'; | 13 | import { AccountModule } from './account'; |
14 | import { CoreModule } from './core'; | 14 | import { CoreModule } from './core'; |
15 | import { LoginModule } from './login'; | 15 | import { LoginModule } from './login'; |
16 | import { SignupModule } from './signup'; | ||
16 | import { SharedModule } from './shared'; | 17 | import { SharedModule } from './shared'; |
17 | import { VideosModule } from './videos'; | 18 | import { VideosModule } from './videos'; |
18 | 19 | ||
@@ -49,6 +50,7 @@ const APP_PROVIDERS = [ | |||
49 | AccountModule, | 50 | AccountModule, |
50 | CoreModule, | 51 | CoreModule, |
51 | LoginModule, | 52 | LoginModule, |
53 | SignupModule, | ||
52 | SharedModule, | 54 | SharedModule, |
53 | VideosModule, | 55 | VideosModule, |
54 | 56 | ||
diff --git a/client/src/app/core/menu/menu.component.html b/client/src/app/core/menu/menu.component.html index 1e9a53246..de17940a1 100644 --- a/client/src/app/core/menu/menu.component.html +++ b/client/src/app/core/menu/menu.component.html | |||
@@ -12,6 +12,11 @@ | |||
12 | </span> | 12 | </span> |
13 | </div> | 13 | </div> |
14 | 14 | ||
15 | <div *ngIf="!isLoggedIn && isRegistrationEnabled()" id="panel-user-register" class="panel-button"> | ||
16 | <span class="hidden-xs glyphicon glyphicon-user"></span> | ||
17 | <a [routerLink]="['/signup']">Signup</a> | ||
18 | </div> | ||
19 | |||
15 | <div *ngIf="isLoggedIn" id="panel-user-account" class="panel-button"> | 20 | <div *ngIf="isLoggedIn" id="panel-user-account" class="panel-button"> |
16 | <span class="hidden-xs glyphicon glyphicon-user"></span> | 21 | <span class="hidden-xs glyphicon glyphicon-user"></span> |
17 | <a [routerLink]="['/account']">My account</a> | 22 | <a [routerLink]="['/account']">My account</a> |
diff --git a/client/src/app/core/menu/menu.component.ts b/client/src/app/core/menu/menu.component.ts index 5ca60e5e0..d1f0fa807 100644 --- a/client/src/app/core/menu/menu.component.ts +++ b/client/src/app/core/menu/menu.component.ts | |||
@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; | |||
2 | import { Router } from '@angular/router'; | 2 | import { Router } from '@angular/router'; |
3 | 3 | ||
4 | import { AuthService, AuthStatus } from '../auth'; | 4 | import { AuthService, AuthStatus } from '../auth'; |
5 | import { ConfigService } from '../config'; | ||
5 | 6 | ||
6 | @Component({ | 7 | @Component({ |
7 | selector: 'my-menu', | 8 | selector: 'my-menu', |
@@ -12,6 +13,7 @@ export class MenuComponent implements OnInit { | |||
12 | 13 | ||
13 | constructor ( | 14 | constructor ( |
14 | private authService: AuthService, | 15 | private authService: AuthService, |
16 | private configService: ConfigService, | ||
15 | private router: Router | 17 | private router: Router |
16 | ) {} | 18 | ) {} |
17 | 19 | ||
@@ -33,6 +35,10 @@ export class MenuComponent implements OnInit { | |||
33 | ); | 35 | ); |
34 | } | 36 | } |
35 | 37 | ||
38 | isRegistrationEnabled() { | ||
39 | return this.configService.getConfig().signup.enabled; | ||
40 | } | ||
41 | |||
36 | isUserAdmin() { | 42 | isUserAdmin() { |
37 | return this.authService.isAdmin(); | 43 | return this.authService.isAdmin(); |
38 | } | 44 | } |
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts index 0d41b900d..0727b76fd 100644 --- a/client/src/app/shared/users/user.service.ts +++ b/client/src/app/shared/users/user.service.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Injectable } from '@angular/core'; | 1 | import { Injectable } from '@angular/core'; |
2 | import { Http } from '@angular/http'; | ||
2 | import 'rxjs/add/operator/catch'; | 3 | import 'rxjs/add/operator/catch'; |
3 | import 'rxjs/add/operator/map'; | 4 | import 'rxjs/add/operator/map'; |
4 | 5 | ||
@@ -11,6 +12,7 @@ export class UserService { | |||
11 | static BASE_USERS_URL = '/api/v1/users/'; | 12 | static BASE_USERS_URL = '/api/v1/users/'; |
12 | 13 | ||
13 | constructor( | 14 | constructor( |
15 | private http: Http, | ||
14 | private authHttp: AuthHttp, | 16 | private authHttp: AuthHttp, |
15 | private authService: AuthService, | 17 | private authService: AuthService, |
16 | private restExtractor: RestExtractor | 18 | private restExtractor: RestExtractor |
@@ -41,4 +43,16 @@ export class UserService { | |||
41 | .map(this.restExtractor.extractDataBool) | 43 | .map(this.restExtractor.extractDataBool) |
42 | .catch((res) => this.restExtractor.handleError(res)); | 44 | .catch((res) => this.restExtractor.handleError(res)); |
43 | } | 45 | } |
46 | |||
47 | signup(username: string, password: string, email: string) { | ||
48 | const body = { | ||
49 | username, | ||
50 | email, | ||
51 | password | ||
52 | }; | ||
53 | |||
54 | return this.http.post(UserService.BASE_USERS_URL + 'register', body) | ||
55 | .map(this.restExtractor.extractDataBool) | ||
56 | .catch(this.restExtractor.handleError); | ||
57 | } | ||
44 | } | 58 | } |
diff --git a/client/src/app/signup/index.ts b/client/src/app/signup/index.ts new file mode 100644 index 000000000..1f4290ab5 --- /dev/null +++ b/client/src/app/signup/index.ts | |||
@@ -0,0 +1,3 @@ | |||
1 | export * from './signup-routing.module'; | ||
2 | export * from './signup.component'; | ||
3 | export * from './signup.module'; | ||
diff --git a/client/src/app/signup/signup-routing.module.ts b/client/src/app/signup/signup-routing.module.ts new file mode 100644 index 000000000..367eed90c --- /dev/null +++ b/client/src/app/signup/signup-routing.module.ts | |||
@@ -0,0 +1,22 @@ | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule, Routes } from '@angular/router'; | ||
3 | |||
4 | import { SignupComponent } from './signup.component'; | ||
5 | |||
6 | const signupRoutes: Routes = [ | ||
7 | { | ||
8 | path: 'signup', | ||
9 | component: SignupComponent, | ||
10 | data: { | ||
11 | meta: { | ||
12 | title: 'Signup' | ||
13 | } | ||
14 | } | ||
15 | } | ||
16 | ]; | ||
17 | |||
18 | @NgModule({ | ||
19 | imports: [ RouterModule.forChild(signupRoutes) ], | ||
20 | exports: [ RouterModule ] | ||
21 | }) | ||
22 | export class SignupRoutingModule {} | ||
diff --git a/client/src/app/signup/signup.component.html b/client/src/app/signup/signup.component.html new file mode 100644 index 000000000..6c9c60e8b --- /dev/null +++ b/client/src/app/signup/signup.component.html | |||
@@ -0,0 +1,40 @@ | |||
1 | <h3>Signup</h3> | ||
2 | |||
3 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | ||
4 | |||
5 | <form role="form" (ngSubmit)="signup()" [formGroup]="form"> | ||
6 | <div class="form-group"> | ||
7 | <label for="username">Username</label> | ||
8 | <input | ||
9 | type="text" class="form-control" id="username" placeholder="Username" | ||
10 | formControlName="username" | ||
11 | > | ||
12 | <div *ngIf="formErrors.username" class="alert alert-danger"> | ||
13 | {{ formErrors.username }} | ||
14 | </div> | ||
15 | </div> | ||
16 | |||
17 | <div class="form-group"> | ||
18 | <label for="email">Email</label> | ||
19 | <input | ||
20 | type="text" class="form-control" id="email" placeholder="Email" | ||
21 | formControlName="email" | ||
22 | > | ||
23 | <div *ngIf="formErrors.email" class="alert alert-danger"> | ||
24 | {{ formErrors.email }} | ||
25 | </div> | ||
26 | </div> | ||
27 | |||
28 | <div class="form-group"> | ||
29 | <label for="password">Password</label> | ||
30 | <input | ||
31 | type="password" class="form-control" id="password" placeholder="Password" | ||
32 | formControlName="password" | ||
33 | > | ||
34 | <div *ngIf="formErrors.password" class="alert alert-danger"> | ||
35 | {{ formErrors.password }} | ||
36 | </div> | ||
37 | </div> | ||
38 | |||
39 | <input type="submit" value="Signup" class="btn btn-default" [disabled]="!form.valid"> | ||
40 | </form> | ||
diff --git a/client/src/app/signup/signup.component.ts b/client/src/app/signup/signup.component.ts new file mode 100644 index 000000000..85f93793b --- /dev/null +++ b/client/src/app/signup/signup.component.ts | |||
@@ -0,0 +1,72 @@ | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | ||
3 | import { Router } from '@angular/router'; | ||
4 | |||
5 | import { NotificationsService } from 'angular2-notifications'; | ||
6 | |||
7 | import { AuthService } from '../core'; | ||
8 | import { | ||
9 | FormReactive, | ||
10 | UserService, | ||
11 | USER_USERNAME, | ||
12 | USER_EMAIL, | ||
13 | USER_PASSWORD | ||
14 | } from '../shared'; | ||
15 | |||
16 | @Component({ | ||
17 | selector: 'my-signup', | ||
18 | templateUrl: './signup.component.html' | ||
19 | }) | ||
20 | export class SignupComponent extends FormReactive implements OnInit { | ||
21 | error: string = null; | ||
22 | |||
23 | form: FormGroup; | ||
24 | formErrors = { | ||
25 | 'username': '', | ||
26 | 'email': '', | ||
27 | 'password': '' | ||
28 | }; | ||
29 | validationMessages = { | ||
30 | 'username': USER_USERNAME.MESSAGES, | ||
31 | 'email': USER_EMAIL.MESSAGES, | ||
32 | 'password': USER_PASSWORD.MESSAGES, | ||
33 | }; | ||
34 | |||
35 | constructor( | ||
36 | private formBuilder: FormBuilder, | ||
37 | private router: Router, | ||
38 | private notificationsService: NotificationsService, | ||
39 | private userService: UserService | ||
40 | ) { | ||
41 | super(); | ||
42 | } | ||
43 | |||
44 | buildForm() { | ||
45 | this.form = this.formBuilder.group({ | ||
46 | username: [ '', USER_USERNAME.VALIDATORS ], | ||
47 | email: [ '', USER_EMAIL.VALIDATORS ], | ||
48 | password: [ '', USER_PASSWORD.VALIDATORS ], | ||
49 | }); | ||
50 | |||
51 | this.form.valueChanges.subscribe(data => this.onValueChanged(data)); | ||
52 | } | ||
53 | |||
54 | ngOnInit() { | ||
55 | this.buildForm(); | ||
56 | } | ||
57 | |||
58 | signup() { | ||
59 | this.error = null; | ||
60 | |||
61 | const { username, password, email } = this.form.value; | ||
62 | |||
63 | this.userService.signup(username, password, email).subscribe( | ||
64 | () => { | ||
65 | this.notificationsService.success('Success', `Registration for ${username} complete.`); | ||
66 | this.router.navigate([ '/videos/list' ]); | ||
67 | }, | ||
68 | |||
69 | err => this.error = err.text | ||
70 | ); | ||
71 | } | ||
72 | } | ||
diff --git a/client/src/app/signup/signup.module.ts b/client/src/app/signup/signup.module.ts new file mode 100644 index 000000000..acb7e5515 --- /dev/null +++ b/client/src/app/signup/signup.module.ts | |||
@@ -0,0 +1,24 @@ | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | |||
3 | import { SignupRoutingModule } from './signup-routing.module'; | ||
4 | import { SignupComponent } from './signup.component'; | ||
5 | import { SharedModule } from '../shared'; | ||
6 | |||
7 | @NgModule({ | ||
8 | imports: [ | ||
9 | SignupRoutingModule, | ||
10 | SharedModule | ||
11 | ], | ||
12 | |||
13 | declarations: [ | ||
14 | SignupComponent | ||
15 | ], | ||
16 | |||
17 | exports: [ | ||
18 | SignupComponent | ||
19 | ], | ||
20 | |||
21 | providers: [ | ||
22 | ] | ||
23 | }) | ||
24 | export class SignupModule { } | ||