Skip to content

Commit

Permalink
Snackbar service (#151)
Browse files Browse the repository at this point in the history
* Update Yarn lockfile

* Optimize sig storage (#137)

* Stringify and destringify signature

* Provided the ability to work with pre existing sigs

* Omit the sig when returning a visit

* Re implement login function using ngrx (#149)

* Re implement login function using ngrx

* Use Rx functions for creates in getting-started

* Generate snackBarService with message functions

* Update usages and specs

* Update usage in ErrorService
  • Loading branch information
tlmader authored Sep 27, 2017
1 parent cb23f6e commit 1a60ec6
Show file tree
Hide file tree
Showing 22 changed files with 264 additions and 161 deletions.
8 changes: 5 additions & 3 deletions client/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ import { CheckInFormComponent } from './components/location-check-in/check-in-fo
import { SignatureFieldComponent } from './components/location-check-in/check-in-form/signature-field/signature-field.component';
import { NewVolunteerFormComponent } from './components/location-check-in/new-volunteer-form/new-volunteer-form.component';

import { OrganizationService } from './services/organization.service';
import { ErrorService } from './services/error.service';
import { LocationService } from './services/location.service';
import { UserService } from './services/user.service';
import { OrganizationService } from './services/organization.service';
import { SnackBarService } from './services/snack-bar.service';
import { VisitService } from './services/visit.service';
import { VolunteerService } from './services/volunteer.service';
import { ErrorService } from './services/error.service';
import { UserService } from './services/user.service';

import { locationReducer } from './reducers/location';
import { visitReducer } from './reducers/visit';
Expand Down Expand Up @@ -113,6 +114,7 @@ import { userReducer } from './reducers/user';
Guard,
LocationService,
OrganizationService,
SnackBarService,
UserService,
VisitService,
VolunteerService,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { MdButtonModule, MdSnackBarModule, MdTabsModule } from '@angular/material';
import { MdButtonModule, MdTabsModule } from '@angular/material';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MockComponent } from 'ng2-mock-component';

import { GettingStartedComponent } from './getting-started.component';
import { LocationService, MockLocationService } from '../../services/location.service';
import { MockOrganizationService, OrganizationService } from '../../services/organization.service';
import { MockSnackBarService, SnackBarService } from '../../services/snack-bar.service';
import { MockUserService, UserService } from '../../services/user.service';
import { testUsers } from '../../models/user';

describe('GettingStartedComponent', () => {
let component: GettingStartedComponent;
Expand All @@ -26,14 +26,14 @@ describe('GettingStartedComponent', () => {
],
imports: [
MdButtonModule,
MdSnackBarModule,
MdTabsModule,
NoopAnimationsModule,
RouterTestingModule
],
providers: [
{ provide: LocationService, useClass: MockLocationService },
{ provide: OrganizationService, useClass: MockOrganizationService },
{ provide: SnackBarService, useClass: MockSnackBarService },
{ provide: UserService, useClass: MockUserService }
]
}).compileComponents();
Expand All @@ -56,11 +56,4 @@ describe('GettingStartedComponent', () => {
it('does not set step to the next step when backtracking', () => {
expect(component.nextStep(2, 1)).toEqual(2);
});

it('sets the local storage items', () => {
component.setLocalStorageItems(testUsers[0], 'token');
expect(localStorage.getItem('token')).toBe('token');
expect(localStorage.getItem('userId')).toBe(testUsers[0]._id);
expect(localStorage.getItem('organizationId')).toBe(testUsers[0].organizationId);
});
});
44 changes: 10 additions & 34 deletions client/app/components/getting-started/getting-started.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { MdSnackBar } from '@angular/material';
import { Router } from '@angular/router';

import { Location } from '../../models/location';
import { Organization } from '../../models/organization';
import { User } from '../../models/user';
import { LocationService } from '../../services/location.service';
import { OrganizationService } from '../../services/organization.service';
import { SnackBarService } from '../../services/snack-bar.service';
import { UserService } from '../../services/user.service';

@Component({
Expand All @@ -22,8 +21,10 @@ export class GettingStartedComponent implements OnInit {
organization: Organization;
user: User;

constructor(private router: Router, private snackBar: MdSnackBar, private locationService: LocationService,
private organizationService: OrganizationService, private userService: UserService) { }
constructor(private locationService: LocationService,
private organizationService: OrganizationService,
private snackBarService: SnackBarService,
private userService: UserService) { }

ngOnInit() {
this.step = 0;
Expand All @@ -46,9 +47,7 @@ export class GettingStartedComponent implements OnInit {
userWithOrgId.organizationId = organization._id;
this.createLocation(organization, () => {
this.createUser(userWithOrgId, () => {
this.snackBar.open('Your organization was successfully added!', '', {
duration: 3000
});
this.snackBarService.addOrganizationSuccess();
this.login(this.user);
});
});
Expand All @@ -61,12 +60,7 @@ export class GettingStartedComponent implements OnInit {
* @param successCb
*/
createOrganization(organization: Organization, successCb): void {
this.organizationService.create(organization).subscribe(successCb,
error => this.snackBar.open(error
? `Error creating your organization: ${error}`
: 'Error creating your organization!', '', {
duration: 3000
}));
this.organizationService.createRx(organization, successCb);
}

/**
Expand All @@ -85,28 +79,10 @@ export class GettingStartedComponent implements OnInit {
* @param successCb
*/
createUser(user: User, successCb): void {
this.userService.create(user).subscribe(successCb,
error => this.snackBar.open(error
? `Error creating your user account: ${error}`
: 'Error creating your user account!', '', {
duration: 3000
}));
this.userService.createRx(user, successCb);
}

login(user: User): void {
this.userService.login(user)
.subscribe(res => {
this.setLocalStorageItems(res.user, res.token);
this.router.navigateByUrl('/dashboard');
this.snackBar.open(`Welcome to Cerberus, ${res.user.firstName}.`, '', { duration: 3000 });
},
error => this.error = <any>error
);
}

setLocalStorageItems(user: User, token: string) {
localStorage.setItem('token', token);
localStorage.setItem('userId', user._id);
localStorage.setItem('organizationId', user.organizationId);
login(user: User) {
this.userService.login(user, () => this.snackBarService.welcome(user.firstName));
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { MdAutocompleteModule, MdInputModule, MdRadioModule, MdSnackBarModule } from '@angular/material';
import { MdAutocompleteModule, MdInputModule, MdRadioModule } from '@angular/material';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { StoreModule } from '@ngrx/store';
import { SignaturePadModule } from 'angular2-signaturepad';

import { CheckInFormComponent } from './check-in-form.component';
import { SignatureFieldComponent } from './signature-field/signature-field.component';
import { MockSnackBarService, SnackBarService } from '../../../services/snack-bar.service';
import { MockVisitService, VisitService } from '../../../services/visit.service';
import { testVisits } from '../../../models/visit';
import { testVolunteers } from '../../../models/volunteer';
import { StoreModule } from '@ngrx/store';
import { visitReducer } from '../../../reducers/visit';
import { volunteerReducer } from '../../../reducers/volunteer';
import { SignaturePadModule } from 'angular2-signaturepad';
import { SignatureFieldComponent } from './signature-field/signature-field.component';

describe('CheckInFormComponent', () => {
let component: CheckInFormComponent;
Expand All @@ -28,14 +29,14 @@ describe('CheckInFormComponent', () => {
MdAutocompleteModule,
MdInputModule,
MdRadioModule,
MdSnackBarModule,
NoopAnimationsModule,
ReactiveFormsModule,
RouterTestingModule,
SignaturePadModule,
StoreModule.provideStore({ visits: visitReducer, volunteers: volunteerReducer })
],
providers: [
{ provide: SnackBarService, useClass: MockSnackBarService },
{ provide: VisitService, useClass: MockVisitService }
]
}).compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { ActivatedRoute, Router } from '@angular/router';
import { MdSnackBar } from '@angular/material';
import { state, style, trigger, transition, animate } from '@angular/animations';
import { animate, state, style, transition, trigger } from '@angular/animations';

import { Visit } from '../../../models/visit';
import { Volunteer } from '../../../models/volunteer';
import { VisitService } from '../../../services/visit.service';
import { SignatureFieldComponent } from './signature-field/signature-field.component';
import { SnackBarService } from '../../../services/snack-bar.service';

@Component({
selector: 'app-check-in-form',
Expand Down Expand Up @@ -43,8 +43,12 @@ export class CheckInFormComponent implements OnInit {
/**
* Creates the form group and subscribes on construction.
*/
constructor(private route: ActivatedRoute, private fb: FormBuilder, private store: Store<any>, private snackBar: MdSnackBar,
private visitService: VisitService, private router: Router) {
constructor(private route: ActivatedRoute,
private fb: FormBuilder,
private store: Store<any>,
private snackBarService: SnackBarService,
private visitService: VisitService,
private router: Router) {
this.createForm();
this.subscribeToForm();
}
Expand Down Expand Up @@ -213,7 +217,7 @@ export class CheckInFormComponent implements OnInit {
this.visitService.createRx(
new Visit(organizationId, locationId, volunteer._id, new Date(), null, 'America/Chicago', signature),
() => {
this.snackBar.open('Volunteer successfully checked in!', '', { duration: 3000 });
this.snackBarService.checkInSuccess();
this.router.navigateByUrl('/dashboard');
}
);
Expand All @@ -225,7 +229,7 @@ export class CheckInFormComponent implements OnInit {
endVisit(visit: Visit): void {
this.visitService.updateRx(Object.assign({}, visit, { endedAt: new Date() }),
() => {
this.snackBar.open('Volunteer successfully checked out!', '', { duration: 3000 });
this.snackBarService.checkOutSuccess();
this.router.navigateByUrl('/dashboard');
}
);
Expand Down Expand Up @@ -314,6 +318,14 @@ export class CheckInFormComponent implements OnInit {
}
}

/**
* Assigns signature to existing signature passed in. The signature will be displayed in the signature pad once set.
* @param signature
*/
setSignature(signature): void {
this.signatures.first.signature.setSignatureToExistingSignature(signature);
}

/**
* Formats the name of a volunteer as one string.
* @param volunteer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class SignatureFieldComponent implements ControlValueAccessor {
return;
}
this._signature = value;
this.signaturePad.fromDataURL(this.signature);
this.signaturePad.fromData(this.signature);
}

/**
Expand Down Expand Up @@ -85,11 +85,19 @@ export class SignatureFieldComponent implements ControlValueAccessor {
* After the user has finished drawing, save the signature as an array of point groups.
*/
public drawComplete(): void {
this.signature = this.signaturePad.toDataURL();
this.signature = this.signaturePad.toData();
}

public clear(): void {
this.signaturePad.clear();
this.signature = '';
}

/**
* Sets the signature to pre existing signature.
* @param signature - the signature
*/
public setSignatureToExistingSignature(signature): void {
this.signature = this.signaturePad.fromData(signature);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AbstractControl, ReactiveFormsModule } from '@angular/forms';
import { MdAutocompleteModule, MdInputModule, MdSnackBarModule } from '@angular/material';
import { MdAutocompleteModule, MdInputModule } from '@angular/material';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { StoreModule } from '@ngrx/store';

import { NewVolunteerFormComponent } from './new-volunteer-form.component';
import { MockSnackBarService, SnackBarService } from '../../../services/snack-bar.service';
import { MockVolunteerService, VolunteerService } from '../../../services/volunteer.service';
import { volunteerReducer } from '../../../reducers/volunteer';

Expand All @@ -21,11 +22,13 @@ describe('NewVolunteerFormComponent', () => {
ReactiveFormsModule,
MdAutocompleteModule,
MdInputModule,
MdSnackBarModule,
RouterTestingModule,
StoreModule.provideStore({ volunteers: volunteerReducer })
],
providers: [{ provide: VolunteerService, useClass: MockVolunteerService }]
providers: [
{ provide: SnackBarService, useClass: MockSnackBarService },
{ provide: VolunteerService, useClass: MockVolunteerService }
]
}).compileComponents();
}));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MdSnackBar } from '@angular/material';
import { ActivatedRoute } from '@angular/router';

import { SnackBarService } from '../../../services/snack-bar.service';
import { Volunteer } from '../../../models/volunteer';
import { VolunteerService } from '../../../services/volunteer.service';

Expand All @@ -17,7 +16,8 @@ export class NewVolunteerFormComponent implements OnInit {
public formGroup: FormGroup;
public forms;

constructor(private route: ActivatedRoute, private fb: FormBuilder, private snackBar: MdSnackBar,
constructor(private fb: FormBuilder,
private snackBarService: SnackBarService,
private volunteerService: VolunteerService) {
this.changeTab = new EventEmitter<number>();
this.createForm();
Expand All @@ -41,10 +41,7 @@ export class NewVolunteerFormComponent implements OnInit {
}

createVolunteer(volunteer: Volunteer): void {
this.volunteerService.createRx(volunteer,
() => this.snackBar.open('Volunteer successfully signed up!', '', {
duration: 3000
}));
this.volunteerService.createRx(volunteer, () => this.snackBarService.signUpSuccess());
}

createForm(): void {
Expand Down
18 changes: 7 additions & 11 deletions client/app/components/login/login.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MdInputModule, MdListModule, MdSnackBarModule } from '@angular/material';
import { MdInputModule, MdListModule } from '@angular/material';
import { RouterTestingModule } from '@angular/router/testing';
import 'hammerjs';
import { StoreModule } from '@ngrx/store';

import { LoginComponent } from './login.component';
import { MockSnackBarService, SnackBarService } from '../../services/snack-bar.service';
import { MockUserService, UserService } from '../../services/user.service';
import { MockVisitService, VisitService } from '../../services/visit.service';
import { testUsers } from '../../models/user';
import { userReducer } from '../../reducers/user';

describe('LoginComponent', () => {
let component: LoginComponent;
Expand All @@ -23,11 +25,12 @@ describe('LoginComponent', () => {
ReactiveFormsModule,
MdInputModule,
MdListModule,
MdSnackBarModule
StoreModule.provideStore({ users: userReducer, volunteers: userReducer })
],
providers: [
{ provide: VisitService, useClass: MockVisitService },
{ provide: SnackBarService, useClass: MockSnackBarService },
{ provide: UserService, useClass: MockUserService },
{ provide: VisitService, useClass: MockVisitService },
]
}).compileComponents();
}));
Expand All @@ -51,13 +54,6 @@ describe('LoginComponent', () => {
expect(component).toBeTruthy();
});

it('sets the local storage items', () => {
component.setLocalStorageItems(testUsers[0], 'token');
expect(localStorage.getItem('token')).toBe('token');
expect(localStorage.getItem('userId')).toBe(testUsers[0]._id);
expect(localStorage.getItem('organizationId')).toBe(testUsers[0].organizationId);
});

describe('email control', () => {
it('validates requirement', () => {
const control = component.loginForm.controls['email'];
Expand Down
Loading

0 comments on commit 1a60ec6

Please sign in to comment.