diff --git a/package.json b/package.json
index 12cba8f..857e607 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
"@ngrx/effects": "^2.0.0",
"@ngrx/store": "^2.2.1",
"@types/lodash": "4.14.50",
+ "angular2-image-upload": "^0.5.1",
"core-js": "^2.4.1",
"lodash": "^4.17.4",
"ng2-validation": "^3.9.1",
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 14b7f2c..d4a3c8a 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -19,6 +19,7 @@ export class AppComponent implements OnInit {
ngOnInit() {
this.treeElements = [
{ title: 'Home', targetUrl: '/home', imageCssClass: 'glyphicon-globe' },
+ { title: 'Register', targetUrl: '/register', imageCssClass: 'glyphicon-user' },
{ title: 'Search', targetUrl: '/search', imageCssClass: 'glyphicon-search' },
{ title: 'Car', targetUrl: '/car', imageCssClass: 'glyphicon-road' },
{ title: 'Housing', targetUrl: '/housing', imageCssClass: 'glyphicon-home' }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index d44215e..d122a42 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,5 +1,6 @@
+import { registration } from './registration/reducers/registration.reducer';
import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
+import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
@@ -9,23 +10,28 @@ import { WidgitModule } from './widgit/widgit.module';
import { CarRouteModule } from './car/car.route';
import { HomeComponent } from './home/home.component';
import { PageNotFoundComponent } from './404/pageNotFound.component';
-import {StoreModule, ActionReducer, combineReducers} from '@ngrx/store';
-import {cars} from './car/reducers/car.reducer';
-import {EffectsModule} from '@ngrx/effects';
-import {CarEffects} from './car/effects/cars.';
-import {HousingRouteModule} from './housing/housing.route';
-import {houses} from './housing/reducers/houses.reducer';
-import {HousingEffects} from 'app/housing/effects/housing';
-
+import { StoreModule, ActionReducer, combineReducers } from '@ngrx/store';
+import { cars } from './car/reducers/car.reducer';
+import { EffectsModule } from '@ngrx/effects';
+import { CarEffects } from './car/effects/cars.';
+import { HousingRouteModule } from './housing/housing.route';
+import { houses } from './housing/reducers/houses.reducer';
+import { HousingEffects } from 'app/housing/effects/housing';
+import { RegistrationModule } from './registration/registration.module';
+import { RegistrationEffects } from './registration/effects/registration';
+import { RegistrationRouteModule } from './registration/registration.route';
+import { ImageUploadModule } from 'angular2-image-upload';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'home' },
{ path: 'home', component: HomeComponent },
+ { path: 'register', loadChildren: './registration/registration.route#RegistrationRouteModule' },
{ path: 'car', loadChildren: './car/car.route#CarRouteModule' },
{ path: 'housing', loadChildren: './housing/housing.route#HousingRouteModule' },
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [
AppComponent,
HomeComponent,
@@ -35,16 +41,19 @@ const routes: Routes = [
RouterModule.forRoot(routes),
BrowserModule,
FormsModule,
+ RegistrationModule,
ReactiveFormsModule,
HttpModule,
RouterModule,
CarRouteModule,
HousingRouteModule,
+ RegistrationRouteModule,
WidgitModule,
NgbModule.forRoot(),
- StoreModule.provideStore({cars, houses}),
+ StoreModule.provideStore({ cars, houses, registration }),
EffectsModule.run(CarEffects),
- EffectsModule.run(HousingEffects)
+ EffectsModule.run(HousingEffects),
+ EffectsModule.run(RegistrationEffects)
],
providers: [],
bootstrap: [AppComponent]
diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
index deb8367..eae1217 100644
--- a/src/app/home/home.component.html
+++ b/src/app/home/home.component.html
@@ -1,3 +1,3 @@
Welcome to the Angular 2 playground!
-
+
\ No newline at end of file
diff --git a/src/app/registration/actions/registring.ts b/src/app/registration/actions/registring.ts
new file mode 100644
index 0000000..4881575
--- /dev/null
+++ b/src/app/registration/actions/registring.ts
@@ -0,0 +1,54 @@
+import { Registration } from './../domain/registration';
+import { type } from '../../utilities/type';
+import { Action } from '@ngrx/store';
+import { of } from 'rxjs/observable/of';
+
+export const RegistrationAction = {
+ START_REGISTRATION: type('Registration - start registration'),
+ CREATE_REGISTRATION: type('Registration - Add registration'),
+ ABORT_REGISTRATIONS: type('Registration - abort registrations'),
+};
+
+
+export class ActionFactory {
+
+
+ static startRegistration(registration: Registration): Action {
+ return new StartRegistrationAction(registration);
+ }
+
+ static createRegistration(registration: Registration): Action {
+ return new CreateRegistrationAction(registration);
+ }
+
+ static abortRegistration(registration: Registration): Action {
+ return new AbortRegistrationsAction(registration);
+ }
+
+ static getRegistration(registration) {
+ return registration;
+ }
+
+ static empty() {
+ return new Registration();
+ }
+}
+
+export class StartRegistrationAction implements Action {
+ type = RegistrationAction.START_REGISTRATION;
+
+ constructor(public payload: Registration) { }
+}
+
+
+export class CreateRegistrationAction implements Action {
+ type = RegistrationAction.CREATE_REGISTRATION;
+
+ constructor(public payload: Registration) { }
+}
+
+export class AbortRegistrationsAction implements Action {
+ type = RegistrationAction.ABORT_REGISTRATIONS;
+
+ constructor(public payload: Registration) { }
+}
diff --git a/src/app/registration/components/avatar/registration-avatar.component.html b/src/app/registration/components/avatar/registration-avatar.component.html
new file mode 100644
index 0000000..6a5420c
--- /dev/null
+++ b/src/app/registration/components/avatar/registration-avatar.component.html
@@ -0,0 +1,18 @@
+
+
diff --git a/src/app/registration/components/avatar/registration-avatar.component.ts b/src/app/registration/components/avatar/registration-avatar.component.ts
new file mode 100644
index 0000000..0e2e09b
--- /dev/null
+++ b/src/app/registration/components/avatar/registration-avatar.component.ts
@@ -0,0 +1,41 @@
+import { ActionFactory } from './../../actions/registring';
+import { RegistrationsState, User } from './../../domain/registration';
+import { Router } from '@angular/router';
+import { Component, OnInit, Input, Output, EventEmitter, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { CustomValidators } from 'ng2-validation';
+import { Registration } from '../../domain/registration';
+import { Store } from '@ngrx/store';
+
+@Component({
+ selector: 'app-registration-avatar',
+ templateUrl: 'registration-avatar.component.html',
+
+})
+export class RegistrationAvatarComponent implements OnInit {
+
+
+ public registration: Registration;
+
+ public constructor(private router: Router, private registringStore: Store) {
+ }
+
+ ngOnInit() {
+ this.registringStore.select(state => state.registration).subscribe(registration => this.registration = registration);
+ }
+
+ upload(data: any) {
+ this.registration.user.avatar = data.src;
+ }
+
+ public register() {
+ this.registringStore.dispatch(ActionFactory.createRegistration(this.registration));
+ this.router.navigate(['/profile']);
+ }
+
+ public abort() {
+ this.registringStore.dispatch(ActionFactory.abortRegistration(this.registration));
+ this.router.navigate(['/home']);
+ }
+
+}
\ No newline at end of file
diff --git a/src/app/registration/components/contact/registration-info.component.html b/src/app/registration/components/contact/registration-info.component.html
new file mode 100644
index 0000000..e5d5d44
--- /dev/null
+++ b/src/app/registration/components/contact/registration-info.component.html
@@ -0,0 +1,48 @@
+
\ No newline at end of file
diff --git a/src/app/registration/components/contact/registration-info.component.ts b/src/app/registration/components/contact/registration-info.component.ts
new file mode 100644
index 0000000..f6a6f55
--- /dev/null
+++ b/src/app/registration/components/contact/registration-info.component.ts
@@ -0,0 +1,53 @@
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { CustomValidators } from 'ng2-validation';
+import { Registration, User, RegistrationsState } from '../../domain/registration';
+import { Router } from '@angular/router';
+import { Store } from '@ngrx/store';
+
+@Component({
+ selector: 'app-registration-info',
+ templateUrl: 'registration-info.component.html',
+})
+export class RegistrationInfoComponent implements OnInit {
+
+ @Input()
+ public registration: Registration;
+
+ public user: User = new User();
+
+ @Output()
+ public registrationStarted: EventEmitter;
+
+ @Output()
+ public registrationAborted: EventEmitter;
+
+ public registrationForm: FormGroup;
+ public constructor(private formBuilder: FormBuilder) {
+ this.registrationStarted = new EventEmitter();
+ this.registrationAborted = new EventEmitter();
+
+ this.registrationForm = this.formBuilder.group({
+ firstName: [this.user.firstName, Validators.required],
+ lastName: [this.user.lastName, Validators.required],
+ username: [this.user.username, Validators.required],
+ email: [this.user.email, Validators.required],
+ password: [this.user.password, Validators.required]
+ });
+ }
+
+ ngOnInit() {
+ }
+
+ public startRegistration() {
+ /* if (!this.registrationForm.valid) {
+ return;
+ }*/
+ this.registration.user = this.user;
+ this.registrationStarted.emit(this.registration);
+ }
+ public abort() {
+ this.registration = new Registration();
+ this.registrationAborted.emit(this.registration);
+ }
+}
\ No newline at end of file
diff --git a/src/app/registration/components/index.ts b/src/app/registration/components/index.ts
new file mode 100644
index 0000000..ed1ca2f
--- /dev/null
+++ b/src/app/registration/components/index.ts
@@ -0,0 +1,4 @@
+export * from './avatar/registration-avatar.component'
+export * from './contact/registration-info.component'
+export * from './profile/profile.component'
+
diff --git a/src/app/registration/components/profile/profile.component.html b/src/app/registration/components/profile/profile.component.html
new file mode 100644
index 0000000..8fb90c8
--- /dev/null
+++ b/src/app/registration/components/profile/profile.component.html
@@ -0,0 +1,13 @@
+
+
Hi {{registration.user.firstName}}!
+
your profile page
+ {{registration.user.email}}
+
+
+
+
Logout
+
\ No newline at end of file
diff --git a/src/app/registration/components/profile/profile.component.ts b/src/app/registration/components/profile/profile.component.ts
new file mode 100644
index 0000000..b098397
--- /dev/null
+++ b/src/app/registration/components/profile/profile.component.ts
@@ -0,0 +1,24 @@
+import { RegistrationsState } from './../../domain/registration';
+import { Store } from '@ngrx/store';
+import { Component, OnInit } from '@angular/core';
+import { User, Registration } from '../../domain/registration';
+import { Router } from '@angular/router';
+
+@Component({
+ moduleId: module.id,
+ templateUrl: 'profile.component.html'
+
+})
+export class ProfileComponent implements OnInit {
+ public registration: Registration;
+
+ public constructor(private router: Router, private registringStore: Store) {
+ }
+
+ ngOnInit() {
+ this.registringStore.select(state => state.registration).subscribe(registration => this.registration = registration);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/src/app/registration/containers/registration/registration.component.html b/src/app/registration/containers/registration/registration.component.html
new file mode 100644
index 0000000..6b09534
--- /dev/null
+++ b/src/app/registration/containers/registration/registration.component.html
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/src/app/registration/containers/registration/registration.component.ts b/src/app/registration/containers/registration/registration.component.ts
new file mode 100644
index 0000000..62f6568
--- /dev/null
+++ b/src/app/registration/containers/registration/registration.component.ts
@@ -0,0 +1,33 @@
+import { Router } from '@angular/router';
+import { Component, OnInit } from '@angular/core';
+import { Store } from '@ngrx/store';
+import { ActionFactory } from '../../actions/registring';
+import { SearchOptions } from '../../../widgit/search-form/search-options';
+import { RegistrationsState, Registration } from '../../domain/registration';
+
+@Component({
+ selector: 'app-registration',
+ templateUrl: 'registration.component.html',
+})
+export class RegistrationComponent implements OnInit {
+
+ registration: Registration;
+ constructor(private router: Router, private registringStore: Store) {
+ }
+
+ ngOnInit() {
+ this.registringStore.select(state => state.registration).subscribe(registration => this.registration = registration);
+ }
+
+ public registrationStarted() {
+ this.registringStore.dispatch(ActionFactory.startRegistration(this.registration));
+ this.router.navigate(['/avatar']);
+ }
+
+ public registrationAborted() {
+ this.registringStore.dispatch(ActionFactory.abortRegistration(this.registration));
+ this.router.navigate(['/home']);
+ }
+
+
+}
diff --git a/src/app/registration/domain/registration.ts b/src/app/registration/domain/registration.ts
new file mode 100644
index 0000000..3cf05e8
--- /dev/null
+++ b/src/app/registration/domain/registration.ts
@@ -0,0 +1,20 @@
+
+export class User {
+ id: number;
+ username: string;
+ email: string;
+ password: string;
+ firstName: string;
+ lastName: string;
+ avatar: string;
+
+}
+
+export class Registration {
+ status: string;
+ user: User;
+}
+
+export interface RegistrationsState {
+ registration: Registration;
+}
diff --git a/src/app/registration/effects/registration.ts b/src/app/registration/effects/registration.ts
new file mode 100644
index 0000000..37e6c8b
--- /dev/null
+++ b/src/app/registration/effects/registration.ts
@@ -0,0 +1,54 @@
+import { RegistrationAction, ActionFactory } from '../actions/registring';
+import { Injectable } from '@angular/core';
+import { Effect, Actions, toPayload } from '@ngrx/effects';
+import { Action } from '@ngrx/store';
+import { Observable } from 'rxjs/Observable';
+import { of } from 'rxjs/observable/of';
+import { empty } from 'rxjs/observable/empty';
+import 'rxjs/add/operator/skip';
+import 'rxjs/add/operator/takeUntil';
+import { StartRegistrationAction } from '../actions/registring';
+import { RegistrationService } from '../service/registration.service';
+
+@Injectable()
+export class RegistrationEffects {
+
+ @Effect()
+ startRegistration$: Observable = this.actions$
+ .ofType(RegistrationAction.START_REGISTRATION)
+ .map(toPayload)
+ .switchMap(newRegistration => {
+ return this.registrationService.startRegistration(newRegistration)
+ .catch(error => {
+ return of(null);
+ });
+ });
+
+ @Effect()
+ createRegistration$: Observable = this.actions$
+ .ofType(RegistrationAction.CREATE_REGISTRATION)
+ .map(toPayload)
+ .switchMap(registration => {
+ return this.registrationService.createRegistration(registration)
+ .catch(error => {
+ return of(null);
+ });
+ });
+
+ @Effect()
+ abortRegistration$: Observable = this.actions$
+ .ofType(RegistrationAction.ABORT_REGISTRATIONS)
+ .map(toPayload)
+ .switchMap(registration => {
+ return this.registrationService.abortRegistration(registration)
+ .catch(error => {
+ return of(null);
+ });
+ });
+
+
+ constructor(private actions$: Actions, private registrationService: RegistrationService) {
+ }
+
+
+}
diff --git a/src/app/registration/guards/registration.guard.ts b/src/app/registration/guards/registration.guard.ts
new file mode 100644
index 0000000..77092a5
--- /dev/null
+++ b/src/app/registration/guards/registration.guard.ts
@@ -0,0 +1,35 @@
+import { Injectable } from '@angular/core';
+import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/take';
+import 'rxjs/add/operator/filter';
+import 'rxjs/add/operator/do';
+import 'rxjs/add/operator/map';
+import 'rxjs/add/operator/switchMap';
+import 'rxjs/add/operator/catch';
+import 'rxjs/add/operator/let';
+import { RegistrationService } from '../service/registration.service';
+import { ActionFactory } from '../actions/registring';
+import { RegistrationsState } from '../domain/registration';
+
+@Injectable()
+export class RegistrationGuard implements CanActivate {
+
+ constructor(private store: Store,
+ private registrationService: RegistrationService) {
+ }
+
+ getRegistration(): Observable {
+ return this.registrationService.getLatestRegistration()
+ .do(registration => {
+ this.store.dispatch(ActionFactory.getRegistration(registration))
+ })
+ .map(registration =>
+ ['started','created'].indexOf(registration.status) !== -1)
+ }
+
+ canActivate(route: ActivatedRouteSnapshot): Observable {
+ return this.getRegistration();
+ }
+}
diff --git a/src/app/registration/reducers/registration.reducer.ts b/src/app/registration/reducers/registration.reducer.ts
new file mode 100644
index 0000000..14f226e
--- /dev/null
+++ b/src/app/registration/reducers/registration.reducer.ts
@@ -0,0 +1,16 @@
+import { Action } from '@ngrx/store';
+import { Registration } from '../domain/registration';
+import { RegistrationAction } from '../actions/registring';
+
+export const registration = (state: any = new Registration(), action: Action) => {
+ switch (action.type) {
+ case RegistrationAction.START_REGISTRATION:
+ return action.payload;
+ case RegistrationAction.CREATE_REGISTRATION:
+ return action.payload;
+ case RegistrationAction.ABORT_REGISTRATIONS:
+ return action.payload;
+ default:
+ return state;
+ }
+};
diff --git a/src/app/registration/registration.module.ts b/src/app/registration/registration.module.ts
new file mode 100644
index 0000000..fc34876
--- /dev/null
+++ b/src/app/registration/registration.module.ts
@@ -0,0 +1,43 @@
+import { RouterModule } from '@angular/router';
+import { ImageUploadModule } from 'angular2-image-upload';
+import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { WidgitModule } from '../widgit/widgit.module';
+import { UtilitiesModule } from '../utilities/utilities.module';
+import { RegistrationComponent } from './containers/registration/registration.component';
+import { ProfileComponent, RegistrationInfoComponent, RegistrationAvatarComponent } from './components/index';
+import { RegistrationService } from './service/registration.service';
+import { RegistrationGuard } from './guards/registration.guard';
+
+@NgModule({
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ imports: [
+ CommonModule,
+ WidgitModule,
+ UtilitiesModule,
+ NgbModule,
+ FormsModule,
+ RouterModule,
+ ImageUploadModule.forRoot(),
+ ReactiveFormsModule
+ ],
+ exports: [
+ ProfileComponent,
+ RegistrationAvatarComponent,
+ RegistrationInfoComponent,
+ RegistrationComponent,
+ ],
+ declarations: [
+ ProfileComponent,
+ RegistrationAvatarComponent,
+ RegistrationInfoComponent,
+ RegistrationComponent,
+ ],
+ providers: [
+ RegistrationService,
+ RegistrationGuard
+ ]
+})
+export class RegistrationModule { }
diff --git a/src/app/registration/registration.route.ts b/src/app/registration/registration.route.ts
new file mode 100644
index 0000000..87a39c3
--- /dev/null
+++ b/src/app/registration/registration.route.ts
@@ -0,0 +1,48 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Routes, RouterModule } from '@angular/router';
+import { RegistrationInfoComponent } from './components/contact/registration-info.component';
+import { RegistrationAvatarComponent } from './components/avatar/registration-avatar.component';
+import { ProfileComponent } from './components/profile/profile.component';
+import { RegistrationGuard } from './guards/registration.guard';
+import { RegistrationModule } from './registration.module';
+import { RegistrationComponent } from './containers/registration/registration.component';
+
+
+const routes: Routes = [
+ {
+ path: 'register',
+ redirectTo: '/register/init',
+ pathMatch: 'full'
+ },
+ {
+ path: 'init',
+ component: RegistrationComponent
+ },
+ {
+ path: 'contact',
+ component: RegistrationInfoComponent
+ },
+ {
+ path: 'avatar',
+ canActivate: [RegistrationGuard],
+ component: RegistrationAvatarComponent
+ },
+ {
+ path: 'profile',
+ canActivate: [RegistrationGuard],
+ component: ProfileComponent
+ }
+
+];
+
+@NgModule({
+ exports: [
+ ],
+ imports: [
+ RouterModule.forChild(routes),
+ RegistrationModule,
+ CommonModule
+ ], declarations: []
+})
+export class RegistrationRouteModule { }
diff --git a/src/app/registration/service/registration.service.ts b/src/app/registration/service/registration.service.ts
new file mode 100644
index 0000000..dca11eb
--- /dev/null
+++ b/src/app/registration/service/registration.service.ts
@@ -0,0 +1,39 @@
+import { Injectable } from '@angular/core';
+import { Response, Http } from '@angular/http';
+import { Observable } from 'rxjs/Observable';
+import { of } from 'rxjs/observable/of';
+import 'rxjs/add/operator/map';
+import { Registration } from '../domain/registration';
+
+@Injectable()
+export class RegistrationService {
+
+ private record: Registration;
+
+ constructor(private http: Http) {
+ this.record = new Registration();
+ }
+
+ startRegistration(newRegistration: Registration): Observable {
+ this.record.status = 'started';
+ this.record.user = newRegistration.user;
+ return of(this.record);
+ }
+
+ createRegistration(registration: Registration): Observable {
+ this.record.status = 'created';
+ this.record.user = registration.user;
+ return of(this.record);
+ }
+
+ abortRegistration(registration: Registration): Observable {
+ this.record.status = 'aborted';
+ this.record.user = registration.user;
+ return of(registration);
+ }
+
+ getLatestRegistration() {
+ return of(this.record);
+ }
+
+}
diff --git a/src/app/widgit/widgit.module.ts b/src/app/widgit/widgit.module.ts
index ba40f06..b1565f5 100644
--- a/src/app/widgit/widgit.module.ts
+++ b/src/app/widgit/widgit.module.ts
@@ -2,22 +2,24 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
-import {UtilitiesModule} from '../utilities/utilities.module';
-import {SearchFormComponent} from './search-form/search-form.component';
+import { UtilitiesModule } from '../utilities/utilities.module';
+import { SearchFormComponent } from './search-form/search-form.component';
import { NavigationComponent } from './navigation/navigation.component';
import { NavigationItemComponent } from './navigation/navigation-item.component';
+
@NgModule({
imports: [
CommonModule,
RouterModule,
UtilitiesModule,
- ReactiveFormsModule
+ ReactiveFormsModule,
+
],
exports: [
SearchFormComponent,
NavigationComponent,
- NavigationItemComponent
+ NavigationItemComponent,
],
declarations: [
SearchFormComponent,