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';
import { AccountModule } from './account';
import { CoreModule } from './core';
import { LoginModule } from './login';
+import { SignupModule } from './signup';
import { SharedModule } from './shared';
import { VideosModule } from './videos';
@@ -49,6 +50,7 @@ const APP_PROVIDERS = [
AccountModule,
CoreModule,
LoginModule,
+ SignupModule,
SharedModule,
VideosModule,
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 @@
+
+
My account
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';
import { Router } from '@angular/router';
import { AuthService, AuthStatus } from '../auth';
+import { ConfigService } from '../config';
@Component({
selector: 'my-menu',
@@ -12,6 +13,7 @@ export class MenuComponent implements OnInit {
constructor (
private authService: AuthService,
+ private configService: ConfigService,
private router: Router
) {}
@@ -33,6 +35,10 @@ export class MenuComponent implements OnInit {
);
}
+ isRegistrationEnabled() {
+ return this.configService.getConfig().signup.enabled;
+ }
+
isUserAdmin() {
return this.authService.isAdmin();
}
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 @@
import { Injectable } from '@angular/core';
+import { Http } from '@angular/http';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
@@ -11,6 +12,7 @@ export class UserService {
static BASE_USERS_URL = '/api/v1/users/';
constructor(
+ private http: Http,
private authHttp: AuthHttp,
private authService: AuthService,
private restExtractor: RestExtractor
@@ -41,4 +43,16 @@ export class UserService {
.map(this.restExtractor.extractDataBool)
.catch((res) => this.restExtractor.handleError(res));
}
+
+ signup(username: string, password: string, email: string) {
+ const body = {
+ username,
+ email,
+ password
+ };
+
+ return this.http.post(UserService.BASE_USERS_URL + 'register', body)
+ .map(this.restExtractor.extractDataBool)
+ .catch(this.restExtractor.handleError);
+ }
}
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 @@
+export * from './signup-routing.module';
+export * from './signup.component';
+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 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { SignupComponent } from './signup.component';
+
+const signupRoutes: Routes = [
+ {
+ path: 'signup',
+ component: SignupComponent,
+ data: {
+ meta: {
+ title: 'Signup'
+ }
+ }
+ }
+];
+
+@NgModule({
+ imports: [ RouterModule.forChild(signupRoutes) ],
+ exports: [ RouterModule ]
+})
+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 @@
+
Signup
+
+
{{ error }}
+
+
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 @@
+import { Component, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+
+import { NotificationsService } from 'angular2-notifications';
+
+import { AuthService } from '../core';
+import {
+ FormReactive,
+ UserService,
+ USER_USERNAME,
+ USER_EMAIL,
+ USER_PASSWORD
+} from '../shared';
+
+@Component({
+ selector: 'my-signup',
+ templateUrl: './signup.component.html'
+})
+export class SignupComponent extends FormReactive implements OnInit {
+ error: string = null;
+
+ form: FormGroup;
+ formErrors = {
+ 'username': '',
+ 'email': '',
+ 'password': ''
+ };
+ validationMessages = {
+ 'username': USER_USERNAME.MESSAGES,
+ 'email': USER_EMAIL.MESSAGES,
+ 'password': USER_PASSWORD.MESSAGES,
+ };
+
+ constructor(
+ private formBuilder: FormBuilder,
+ private router: Router,
+ private notificationsService: NotificationsService,
+ private userService: UserService
+ ) {
+ super();
+ }
+
+ buildForm() {
+ this.form = this.formBuilder.group({
+ username: [ '', USER_USERNAME.VALIDATORS ],
+ email: [ '', USER_EMAIL.VALIDATORS ],
+ password: [ '', USER_PASSWORD.VALIDATORS ],
+ });
+
+ this.form.valueChanges.subscribe(data => this.onValueChanged(data));
+ }
+
+ ngOnInit() {
+ this.buildForm();
+ }
+
+ signup() {
+ this.error = null;
+
+ const { username, password, email } = this.form.value;
+
+ this.userService.signup(username, password, email).subscribe(
+ () => {
+ this.notificationsService.success('Success', `Registration for ${username} complete.`);
+ this.router.navigate([ '/videos/list' ]);
+ },
+
+ err => this.error = err.text
+ );
+ }
+}
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 @@
+import { NgModule } from '@angular/core';
+
+import { SignupRoutingModule } from './signup-routing.module';
+import { SignupComponent } from './signup.component';
+import { SharedModule } from '../shared';
+
+@NgModule({
+ imports: [
+ SignupRoutingModule,
+ SharedModule
+ ],
+
+ declarations: [
+ SignupComponent
+ ],
+
+ exports: [
+ SignupComponent
+ ],
+
+ providers: [
+ ]
+})
+export class SignupModule { }