From 9c80bf4bac7c4fa5d19dd85dfdcaaea987f3ab16 Mon Sep 17 00:00:00 2001 From: Rene Enriquez Date: Thu, 7 May 2020 15:25:51 -0500 Subject: [PATCH 1/3] fix: #216 add suport for toast messages --- angular.json | 3 +- package-lock.json | 11 +++- package.json | 3 +- src/app/app.component.ts | 1 + src/app/app.module.ts | 6 +- .../activities-management.component.html | 1 - .../activities-management.component.spec.ts | 62 ++++++++++++++----- .../pages/activities-management.component.ts | 29 +++++---- .../create-customer/create-customer.html | 11 ---- .../create-customer/create-customer.spec.ts | 29 ++++----- .../create-customer/create-customer.ts | 35 +++-------- .../customer-list.component.html | 13 +--- .../customer-list.component.spec.ts | 14 ++++- .../customer-list/customer-list.component.ts | 21 ++----- .../create-project-type.component.spec.ts | 12 +++- .../create-project-type.component.ts | 6 +- .../project-type-list.component.spec.ts | 11 +++- .../project-type-list.component.ts | 4 +- .../create-project.component.spec.ts | 30 ++++++++- .../create-project.component.ts | 5 +- .../project-list.component.spec.ts | 11 +++- .../project-list/project-list.component.ts | 5 +- .../pages/customer.component.ts | 6 +- .../notification/notification.component.html | 8 --- .../notification/notification.component.scss | 0 .../notification.component.spec.ts | 25 -------- .../notification/notification.component.ts | 14 ----- .../shared/store/technology.selectors.spec.ts | 13 ++++ .../project-list-hover.component.spec.ts | 8 ++- .../project-list-hover.component.ts | 4 +- .../pages/time-clock.component.html | 1 - .../pages/time-clock.component.spec.ts | 32 +++------- .../time-clock/pages/time-clock.component.ts | 37 ++++------- 33 files changed, 238 insertions(+), 233 deletions(-) delete mode 100644 src/app/modules/shared/components/notification/notification/notification.component.html delete mode 100644 src/app/modules/shared/components/notification/notification/notification.component.scss delete mode 100644 src/app/modules/shared/components/notification/notification/notification.component.spec.ts delete mode 100644 src/app/modules/shared/components/notification/notification/notification.component.ts create mode 100644 src/app/modules/shared/store/technology.selectors.spec.ts diff --git a/angular.json b/angular.json index ce28b0bb4..ed981b32f 100644 --- a/angular.json +++ b/angular.json @@ -25,7 +25,8 @@ ], "styles": [ "./node_modules/bootstrap/dist/css/bootstrap.min.css", - "src/styles.scss" + "src/styles.scss", + "node_modules/ngx-toastr/toastr.css" ], "scripts": [ "./node_modules/jquery/dist/jquery.min.js", diff --git a/package-lock.json b/package-lock.json index bd4ac9221..25988fe03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -201,9 +201,9 @@ } }, "@angular/animations": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-9.0.5.tgz", - "integrity": "sha512-WGs4Jxw5sr8GCpxMcwEVuZnDIkdNp9qtmuI2j13v/XAaMjvJ7jssCj9+JG5uI8joCi7PFVAWokPT1DdPwWb13Q==" + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-9.0.7.tgz", + "integrity": "sha512-74gY7onajmmnksy5E0/32bFv3B9NuWxV64kqD15YjGrh8AWe1BHt5enQI+rJ2tO8m2DKnwZsctis6k0Kcy+YKQ==" }, "@angular/cli": { "version": "9.0.5", @@ -9386,6 +9386,11 @@ "resolved": "https://registry.npmjs.org/ngx-pagination/-/ngx-pagination-5.0.0.tgz", "integrity": "sha512-Ur0pTWRe2ZXoJ8impEzo0IZKxY5aEcQfSmL5uBqW1rHI2J6nfzgZAHsSLagKHFGchXq0PkRlDVVMcIaNxYJwvQ==" }, + "ngx-toastr": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-12.0.1.tgz", + "integrity": "sha512-PABtbn2dyHweVSbo/py1W3veXzcmZO7uVItfTW9AykSSeAUju3gOCgauAw89km0aJ9EBcPOieaoI+9tAR7Pfug==" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", diff --git a/package.json b/package.json index 7b23b7d34..ad5942c01 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.0.3", + "@angular/animations": "^9.0.7", "@angular/common": "~9.0.3", "@angular/compiler": "~9.0.3", "@angular/core": "~9.0.3", @@ -29,6 +29,7 @@ "minimist": "^1.2.5", "msal": "^1.2.1", "ngx-pagination": "^5.0.0", + "ngx-toastr": "^12.0.1", "rxjs": "~6.5.4", "tslib": "^1.10.0", "zone.js": "~0.10.2" diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b98cec34e..854c9caa7 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -7,4 +7,5 @@ import { Component } from '@angular/core'; }) export class AppComponent { title = 'time-tracker'; + } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 54b7775eb..66f1389d9 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,3 +1,5 @@ +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ToastrModule } from 'ngx-toastr'; import { CommonModule } from '@angular/common'; import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; @@ -54,7 +56,6 @@ import { CreateProjectTypeComponent } from './modules/customer-management/compon import { CustomerEffects } from './modules/customer-management/store/customer-management.effects'; import { EntryEffects } from './modules/time-clock/store/entry.effects'; import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.token.interceptor'; -import { NotificationComponent } from './modules/shared/components/notification/notification/notification.component'; @NgModule({ declarations: [ @@ -89,11 +90,11 @@ import { NotificationComponent } from './modules/shared/components/notification/ ProjectTypeListComponent, CreateProjectTypeComponent, EntryFieldsComponent, - NotificationComponent, ], imports: [ CommonModule, BrowserModule, + BrowserAnimationsModule, AppRoutingModule, FormsModule, ReactiveFormsModule, @@ -116,6 +117,7 @@ import { NotificationComponent } from './modules/shared/components/notification/ ProjectTypeEffects, EntryEffects, ]), + ToastrModule.forRoot() ], providers: [ { diff --git a/src/app/modules/activities-management/pages/activities-management.component.html b/src/app/modules/activities-management/pages/activities-management.component.html index f0b8b20b7..cbcf2ec88 100644 --- a/src/app/modules/activities-management/pages/activities-management.component.html +++ b/src/app/modules/activities-management/pages/activities-management.component.html @@ -1,5 +1,4 @@
-
diff --git a/src/app/modules/activities-management/pages/activities-management.component.spec.ts b/src/app/modules/activities-management/pages/activities-management.component.spec.ts index 55482c917..d20faee04 100644 --- a/src/app/modules/activities-management/pages/activities-management.component.spec.ts +++ b/src/app/modules/activities-management/pages/activities-management.component.spec.ts @@ -6,18 +6,28 @@ import { ActivityService } from './../services/activity.service'; import { ActivitiesManagementComponent } from './activities-management.component'; import { ActionsSubject } from '@ngrx/store'; import { ActivityManagementActionTypes } from '../store'; +import { ToastrService, ToastrModule, IndividualConfig } from 'ngx-toastr'; describe('ActivitiesManagementComponent', () => { let component: ActivitiesManagementComponent; let fixture: ComponentFixture; let activityService: ActivityService; const activitiesFromApi: Activity[] = [{ id: '123', name: 'aaa', description: 'xxx' }]; + const toastrService = { + success: (message?: string, title?: string, override?: Partial) => { }, + error: (message?: string, title?: string, override?: Partial) => { } + }; + let injectedToastrService; beforeEach(async(() => { const actionSub: ActionsSubject = new ActionsSubject(); TestBed.configureTestingModule({ + imports: [ToastrModule.forRoot()], declarations: [ActivitiesManagementComponent], - providers: [ActivityService, HttpClient, HttpHandler, { provide: ActionsSubject, useValue: actionSub }], + providers: [ActivityService, HttpClient, HttpHandler, + { provide: ActionsSubject, useValue: actionSub }, + { provide: ToastrService, useValue: toastrService } + ], }).compileComponents(); })); @@ -25,7 +35,8 @@ describe('ActivitiesManagementComponent', () => { fixture = TestBed.createComponent(ActivitiesManagementComponent); component = fixture.componentInstance; fixture.detectChanges(); - + injectedToastrService = TestBed.inject(ToastrService); + console.log(injectedToastrService); activityService = TestBed.inject(ActivityService); spyOn(activityService, 'getActivities').and.returnValue(of(activitiesFromApi)); }); @@ -47,9 +58,17 @@ describe('ActivitiesManagementComponent', () => { }); it('has a succesfull message on CREATE_ACTIVITY_SUCCESS', () => { + spyOn(injectedToastrService, 'success'); component.setDataNotification(ActivityManagementActionTypes.CREATE_ACTIVITY_SUCCESS); - expect(component.notificationMsg).toBe('The activity has been saved successfully.'); + expect(injectedToastrService.success).toHaveBeenCalled(); + }); + + it('has a succesfull message on UPDATE_ACTIVITY_SUCCESS', () => { + spyOn(injectedToastrService, 'success'); + component.setDataNotification(ActivityManagementActionTypes.UPDATE_ACTIVITY_SUCCESS); + + expect(injectedToastrService.success).toHaveBeenCalled(); }); it('should destroy the subscription', () => { @@ -62,6 +81,7 @@ describe('ActivitiesManagementComponent', () => { }); it('#setDataNotification should show an success notification with DELETE_ACTIVITY_SUCCESS case', () => { + spyOn(injectedToastrService, 'success').and.returnValue(of(activitiesFromApi)); const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; const action = { type: '[ActivityManagement] DELETE_ACTIVITY_SUCESS', @@ -69,23 +89,35 @@ describe('ActivitiesManagementComponent', () => { actionSubject.next(action); component.setDataNotification(action.type); - expect(component.showNotification).toBeTrue(); - expect(component.isError).toBeFalse(); + expect(injectedToastrService.success).toHaveBeenCalled(); }); - it('#setDataNotification should show an error notification with CREATE_ACTIVITY_FAIL case', () => { - const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; - const action = { - type: '[ActivityManagement] CREATE_ACTIVITY_FAIL', - }; - actionSubject.next(action); + it('shows an error notification with CREATE_ACTIVITY_FAIL case', () => { + spyOn(injectedToastrService, 'error'); - component.setDataNotification(action.type); - expect(component.showNotification).toBeTrue(); - expect(component.isError).toBeTrue(); + component.setDataNotification(ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL); + + expect(injectedToastrService.error).toHaveBeenCalled(); + }); + + it('shows an error notification with UPDATE_ACTIVITY_FAIL case', () => { + spyOn(injectedToastrService, 'error'); + + component.setDataNotification(ActivityManagementActionTypes.UPDATE_ACTIVITY_FAIL); + + expect(injectedToastrService.error).toHaveBeenCalled(); + }); + + it('shows an error notification with DELETE_ACTIVITY_FAIL case', () => { + spyOn(injectedToastrService, 'error'); + + component.setDataNotification(ActivityManagementActionTypes.DELETE_ACTIVITY_FAIL); + + expect(injectedToastrService.error).toHaveBeenCalled(); }); it('#setDataNotification should not show an error notification with incorrect action', () => { + spyOn(injectedToastrService, 'success').and.returnValue(of(activitiesFromApi)); const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; const action = { type: '[ActivityManagement] TEST', @@ -93,7 +125,5 @@ describe('ActivitiesManagementComponent', () => { actionSubject.next(action); component.setDataNotification(action.type); - expect(component.showNotification).toBeFalse(); - expect(component.isError).toBeFalse(); }); }); diff --git a/src/app/modules/activities-management/pages/activities-management.component.ts b/src/app/modules/activities-management/pages/activities-management.component.ts index 414c4d13a..c35b4f80e 100644 --- a/src/app/modules/activities-management/pages/activities-management.component.ts +++ b/src/app/modules/activities-management/pages/activities-management.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, OnDestroy } from '@angular/core'; import { ActionsSubject } from '@ngrx/store'; import { Subscription } from 'rxjs'; import { ActivityManagementActionTypes } from '../store'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-activities-management', @@ -9,12 +10,9 @@ import { ActivityManagementActionTypes } from '../store'; styleUrls: ['./activities-management.component.scss'], }) export class ActivitiesManagementComponent implements OnInit, OnDestroy { - notificationMsg = ''; - showNotification = false; - isError = false; actionsSubscription: Subscription; - constructor(private actionsSubject$: ActionsSubject) {} + constructor(private actionsSubject$: ActionsSubject, private toastrService: ToastrService) {} ngOnInit() { this.actionsSubscription = this.actionsSubject$.subscribe((action) => { @@ -27,26 +25,31 @@ export class ActivitiesManagementComponent implements OnInit, OnDestroy { } setDataNotification(action: any) { - this.showNotification = true; switch (action) { case ActivityManagementActionTypes.CREATE_ACTIVITY_SUCCESS: { - this.notificationMsg = 'The activity has been saved successfully.'; + this.toastrService.success('The activity has been saved successfully.'); + break; + } + case ActivityManagementActionTypes.UPDATE_ACTIVITY_SUCCESS: { + this.toastrService.success('The activity has been saved successfully.'); break; } case ActivityManagementActionTypes.DELETE_ACTIVITY_SUCCESS: { - this.notificationMsg = 'The activity has been removed successfully.'; + this.toastrService.success('The activity has been removed successfully.'); + break; + } + case ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL: { + this.toastrService.error('An unexpected error happened, please try again later.'); break; } - case ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL || ActivityManagementActionTypes.DELETE_ACTIVITY_FAIL: { - this.notificationMsg = 'An unexpected error happened, please try again later.'; - this.isError = true; + case ActivityManagementActionTypes.UPDATE_ACTIVITY_FAIL: { + this.toastrService.error('An unexpected error happened, please try again later.'); break; } - default: { - this.showNotification = false; + case ActivityManagementActionTypes.DELETE_ACTIVITY_FAIL : { + this.toastrService.error('An unexpected error happened, please try again later.'); break; } } - setTimeout(() => ((this.showNotification = false), (this.isError = false)), 3000); } } diff --git a/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.html b/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.html index 9e1fb3385..1bdc0d541 100644 --- a/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.html +++ b/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.html @@ -1,16 +1,5 @@
-
- -
{ let component: CreateCustomerComponent; let fixture: ComponentFixture; let store: MockStore; + const toastrService = { + success: (message?: string, title?: string, override?: Partial) => { }, + error: (message?: string, title?: string, override?: Partial) => { } + }; const state = { data: [], @@ -28,17 +33,19 @@ describe('CreateCustomerComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [CreateCustomerComponent], - providers: [FormBuilder, provideMockStore({ initialState: state })], + providers: [ + FormBuilder, + provideMockStore({ initialState: state }), + { provide: ToastrService, useValue: toastrService }, + ], }).compileComponents(); - })); - beforeEach(() => { fixture = TestBed.createComponent(CreateCustomerComponent); component = fixture.componentInstance; fixture.detectChanges(); store = TestBed.inject(MockStore); store.setState(state); - }); + })); afterEach(() => { fixture.destroy(); @@ -87,30 +94,20 @@ describe('CreateCustomerComponent', () => { it('should be enable tabs and show message Customer created successfully! ', () => { component.areTabsActive = false; - component.messageToShow = ''; - - spyOn(store, 'dispatch'); component.ngOnInit(); component.onSubmit(customerData); - component.setStatusOnScreen('Customer created successfully!'); - expect(component.messageToShow).toEqual('Customer created successfully!'); expect(component.areTabsActive).toBeTrue(); }); it('should be disabled tabs and show message An error occurred, try again later. ', () => { component.areTabsActive = false; - component.messageToShow = ''; - - spyOn(store, 'dispatch'); component.ngOnInit(); component.onSubmit(customerData); - component.setStatusOnScreen('An error occurred, try again later.'); - expect(component.messageToShow).toEqual('An error occurred, try again later.'); - expect(component.areTabsActive).toBeFalse(); + expect(component.areTabsActive).toBeTruthy(); }); it('set data to update ', () => { @@ -119,6 +116,6 @@ describe('CreateCustomerComponent', () => { component.ngOnInit(); component.setDataToUpdate(customerData); - expect(component.messageToShow).toEqual(undefined); + expect(store.dispatch).toHaveBeenCalledTimes(2); }); }); diff --git a/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.ts b/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.ts index b18daf4bd..6aa352af2 100644 --- a/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.ts +++ b/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.ts @@ -3,7 +3,7 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { Store, select } from '@ngrx/store'; import { Subscription } from 'rxjs'; -import { getStatusMessage, getCustomerById } from './../../../../store/customer-management.selectors'; +import { getCustomerById } from './../../../../store/customer-management.selectors'; import { Customer } from 'src/app/modules/shared/models'; import { CustomerState, @@ -13,6 +13,7 @@ import { } from 'src/app/modules/customer-management/store'; import { LoadProjectTypes } from '../../../projects-type/store'; import { LoadCustomerProjects } from '../../../projects/components/store/project.actions'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-create-customer', @@ -23,13 +24,11 @@ export class CreateCustomerComponent implements OnInit, OnDestroy { customerForm: FormGroup; @Input() areTabsActive: boolean; @Output() changeValueAreTabsActives = new EventEmitter(); - showAlert = false; - messageToShow = ''; customerToEdit: Customer; - saveSubscription: Subscription; editSubscription: Subscription; - constructor(private formBuilder: FormBuilder, private store: Store) { + constructor(private formBuilder: FormBuilder, private store: Store, + private toastrService: ToastrService) { this.customerForm = this.formBuilder.group({ name: ['', Validators.required], description: ['', Validators.required], @@ -37,11 +36,8 @@ export class CreateCustomerComponent implements OnInit, OnDestroy { } ngOnInit() { - const messages$ = this.store.pipe(select(getStatusMessage)); - this.saveSubscription = messages$.subscribe((valueMessage) => { - this.setStatusOnScreen(valueMessage); - }); - + this.areTabsActive = true; + this.changeValueAreTabsActives.emit(this.areTabsActive); const customers$ = this.store.pipe(select(getCustomerById)); this.editSubscription = customers$.subscribe((customer) => { this.customerToEdit = customer; @@ -51,7 +47,6 @@ export class CreateCustomerComponent implements OnInit, OnDestroy { ngOnDestroy() { this.areTabsActive = false; - this.saveSubscription.unsubscribe(); this.editSubscription.unsubscribe(); } @@ -65,21 +60,9 @@ export class CreateCustomerComponent implements OnInit, OnDestroy { } else { this.store.dispatch(new CreateCustomer(customerData)); } - this.showAlert = true; - setTimeout(() => (this.showAlert = false), 3000); - } - - setStatusOnScreen(message: string) { - if (message === 'Customer created successfully!') { - this.messageToShow = message; - this.areTabsActive = true; - this.changeValueAreTabsActives.emit(this.areTabsActive); - } else if (message === 'An error occurred, try again later.') { - this.messageToShow = message; - this.areTabsActive = false; - this.changeValueAreTabsActives.emit(this.areTabsActive); - } - this.messageToShow = message; + this.toastrService.success('Customer information saved successfully'); + this.areTabsActive = true; + this.changeValueAreTabsActives.emit(this.areTabsActive); } setDataToUpdate(customerData: Customer) { diff --git a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.html b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.html index 720ccf022..abe79e3ff 100644 --- a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.html +++ b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.html @@ -1,18 +1,7 @@ - - + diff --git a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts index 073c8d74a..2632076b4 100644 --- a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts +++ b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts @@ -1,3 +1,4 @@ +import { ToastrService, IndividualConfig } from 'ngx-toastr'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; @@ -20,11 +21,19 @@ describe('CustomerTableListComponent', () => { customerId: '' }; + const toastrService = { + success: (message?: string, title?: string, override?: Partial) => { }, + error: (message?: string, title?: string, override?: Partial) => { } + }; + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NgxPaginationModule], declarations: [CustomerListComponent], - providers: [provideMockStore({ initialState: state })], + providers: [ + provideMockStore({ initialState: state }), + { provide: ToastrService, useValue: toastrService }, + ], }).compileComponents(); })); @@ -60,13 +69,12 @@ describe('CustomerTableListComponent', () => { expect(component.showCustomerForm).toBeTruthy(); }); - it('onClick delete, dispatch DeleteCustomer and enable show alert', () => { + it('onClick delete, dispatch DeleteCustomer', () => { spyOn(store, 'dispatch'); component.deleteCustomer('1'); expect(store.dispatch).toHaveBeenCalledWith(new DeleteCustomer('1')); - expect(component.showAlert).toBeTruthy(); }); afterEach(() => { diff --git a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.ts b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.ts index 67c985b77..a28a63e2b 100644 --- a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.ts +++ b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.ts @@ -2,10 +2,11 @@ import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angu import { Store, select } from '@ngrx/store'; import { Subscription } from 'rxjs'; -import { allCustomers, getStatusMessage } from './../../../../store/customer-management.selectors'; +import { allCustomers } from './../../../../store/customer-management.selectors'; import { LoadCustomers, DeleteCustomer, SetCustomerToEdit } from './../../../../store/customer-management.actions'; import { Customer } from './../../../../../shared/models/customer.model'; import { ITEMS_PER_PAGE } from 'src/environments/environment'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-customer-list', @@ -19,12 +20,9 @@ export class CustomerListComponent implements OnInit, OnDestroy { @Output() changeValueShowCustomerForm = new EventEmitter(); customers: Customer[] = []; - messageToShow = ''; - showAlert = false; customerSubscription: Subscription; - customerMessageSubscription: Subscription; - constructor(private store: Store) {} + constructor(private store: Store, private toastrService: ToastrService) { } ngOnInit(): void { this.store.dispatch(new LoadCustomers()); @@ -32,20 +30,10 @@ export class CustomerListComponent implements OnInit, OnDestroy { this.customerSubscription = customers$.subscribe((response) => { this.customers = response; }); - - const messages$ = this.store.pipe(select(getStatusMessage)); - this.customerMessageSubscription = messages$.subscribe((valueMessage) => { - this.setStatusOnScreen(valueMessage); - }); } ngOnDestroy() { this.customerSubscription.unsubscribe(); - this.customerMessageSubscription.unsubscribe(); - } - - setStatusOnScreen(message: string) { - this.messageToShow = message; } editCustomer(customerId: string) { @@ -55,8 +43,7 @@ export class CustomerListComponent implements OnInit, OnDestroy { } deleteCustomer(customerId: string) { - this.showAlert = true; - setTimeout(() => (this.showAlert = false), 3000); this.store.dispatch(new DeleteCustomer(customerId)); + this.toastrService.success('Customer has been deleted'); } } diff --git a/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts b/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts index e6f872c29..06003ba68 100644 --- a/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts +++ b/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts @@ -1,3 +1,4 @@ +import { ToastrService, IndividualConfig } from 'ngx-toastr'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { FormBuilder } from '@angular/forms'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; @@ -38,10 +39,19 @@ describe('InputProjectTypeComponent', () => { description: 'It is good for learning', }; + const toastrService = { + success: (message?: string, title?: string, override?: Partial) => { }, + error: (message?: string, title?: string, override?: Partial) => { } + }; + beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [CreateProjectTypeComponent], - providers: [FormBuilder, provideMockStore({ initialState: state })], + providers: [ + FormBuilder, + provideMockStore({ initialState: state }), + { provide: ToastrService, useValue: toastrService }, + ], }).compileComponents(); })); diff --git a/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.ts b/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.ts index 099e2c425..abdf46db2 100644 --- a/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.ts +++ b/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.ts @@ -1,3 +1,4 @@ +import { ToastrService } from 'ngx-toastr'; import { Component, OnInit, OnDestroy } from '@angular/core'; import { FormBuilder, Validators, FormGroup } from '@angular/forms'; import { Store, select } from '@ngrx/store'; @@ -19,7 +20,9 @@ export class CreateProjectTypeComponent implements OnInit, OnDestroy { customerId: string; getCustomerIdSubscription: Subscription; - constructor(private formBuilder: FormBuilder, private store: Store) { + constructor(private formBuilder: FormBuilder, + private store: Store, + private toastrService: ToastrService) { this.projectTypeForm = this.formBuilder.group({ name: ['', Validators.required], description: [''], @@ -66,6 +69,7 @@ export class CreateProjectTypeComponent implements OnInit, OnDestroy { this.store.dispatch(new CreateProjectType({ ...projectTypeData, customer_id: this.customerId })); this.projectTypeForm.get('description').setValue(''); } + this.toastrService.success('Information has been saved succesfully'); } cancelButton() { diff --git a/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts b/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts index 6f1b8f7e8..ae63ef7f5 100644 --- a/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts +++ b/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts @@ -1,3 +1,4 @@ +import { IndividualConfig, ToastrService } from 'ngx-toastr'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { NgxPaginationModule } from 'ngx-pagination'; @@ -19,11 +20,19 @@ describe('ProjectTypeTableListComponent', () => { projectTypeIdToEdit: '', }; + const toastrService = { + success: (message?: string, title?: string, override?: Partial) => { }, + error: (message?: string, title?: string, override?: Partial) => { } + }; + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NgxPaginationModule], declarations: [ProjectTypeListComponent], - providers: [provideMockStore({ initialState: state })], + providers: [ + provideMockStore({ initialState: state }), + { provide: ToastrService, useValue: toastrService }, + ], }).compileComponents(); })); diff --git a/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.ts b/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.ts index b27a03591..48bc7536e 100644 --- a/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.ts +++ b/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.ts @@ -1,3 +1,4 @@ +import { ToastrService } from 'ngx-toastr'; import { Component, OnInit } from '@angular/core'; import { ITEMS_PER_PAGE } from 'src/environments/environment'; import { Store, select } from '@ngrx/store'; @@ -17,7 +18,7 @@ export class ProjectTypeListComponent implements OnInit { initPage2 = 1; itemsPerPage = ITEMS_PER_PAGE; - constructor(private store: Store) {} + constructor(private store: Store, private toastrService: ToastrService) {} ngOnInit(): void { const projectTypes$ = this.store.pipe(select(allProjectTypes)); @@ -28,6 +29,7 @@ export class ProjectTypeListComponent implements OnInit { deleteProjectType(projectTypeId: string) { this.store.dispatch(new DeleteProjectType(projectTypeId)); + this.toastrService.success('Information has been removed successfully'); } updateProjectType(projectTypeId: string) { diff --git a/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts b/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts index b53a88060..4bce1ec25 100644 --- a/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts +++ b/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts @@ -1,3 +1,4 @@ +import { ToastrService, IndividualConfig } from 'ngx-toastr'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { FormBuilder } from '@angular/forms'; @@ -35,10 +36,19 @@ describe('InputProjectComponent', () => { project_type_id: '123', }; + const toastrService = { + success: (message?: string, title?: string, override?: Partial) => { }, + error: (message?: string, title?: string, override?: Partial) => { } + }; + beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [CreateProjectComponent], - providers: [FormBuilder, provideMockStore({ initialState: state })], + providers: [ + FormBuilder, + provideMockStore({ initialState: state }), + { provide: ToastrService, useValue: toastrService }, + ], }).compileComponents(); })); @@ -62,6 +72,24 @@ describe('InputProjectComponent', () => { expect(component).toBeTruthy(); }); + it('gets description from form', () => { + spyOn(component.projectForm, 'get'); + + // tslint:disable-next-line:no-unused-expression + component.description; + + expect(component.projectForm.get).toHaveBeenCalledWith('description'); + }); + + it('gets project_type_id from form', () => { + spyOn(component.projectForm, 'get'); + + // tslint:disable-next-line:no-unused-expression + component.project_type_id; + + expect(component.projectForm.get).toHaveBeenCalledWith('project_type_id'); + }); + it('should destroy the subscriptions', () => { component.projectToEditSubscription = new Subscription(); component.projectTypesSubscription = new Subscription(); diff --git a/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.ts b/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.ts index fa303e86d..296dea23a 100644 --- a/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.ts +++ b/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.ts @@ -1,3 +1,4 @@ +import { ToastrService } from 'ngx-toastr'; import { Component, OnInit, OnDestroy } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; import { Store, select } from '@ngrx/store'; @@ -27,7 +28,8 @@ export class CreateProjectComponent implements OnInit, OnDestroy { constructor( private formBuilder: FormBuilder, private store: Store, - private projectTypeStore: Store + private projectTypeStore: Store, + private toastrService: ToastrService ) { this.projectForm = this.formBuilder.group({ name: ['', Validators.required], @@ -71,6 +73,7 @@ export class CreateProjectComponent implements OnInit, OnDestroy { this.store.dispatch(new actions.CreateProject({ ...formData, customer_id: this.customerId })); } this.resetValuesForm(); + this.toastrService.success('The information has been saved successfully'); } get name() { diff --git a/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.spec.ts b/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.spec.ts index 7fc38ab06..692367381 100644 --- a/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.spec.ts +++ b/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.spec.ts @@ -1,3 +1,4 @@ +import { IndividualConfig, ToastrService } from 'ngx-toastr'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { NgxPaginationModule } from 'ngx-pagination'; @@ -17,6 +18,11 @@ describe('ProjectListComponent', () => { let getCustomerProjectsSelectorMock; let allCustomerProjectsSelectorMock; + const toastrService = { + success: (message?: string, title?: string, override?: Partial) => { }, + error: (message?: string, title?: string, override?: Partial) => { } + }; + const state: ProjectState = { projects: [], customerProjects: [], @@ -32,7 +38,10 @@ describe('ProjectListComponent', () => { TestBed.configureTestingModule({ imports: [NgxPaginationModule], declarations: [ProjectListComponent, FilterProjectPipe], - providers: [provideMockStore({ initialState: state })], + providers: [ + provideMockStore({ initialState: state }), + { provide: ToastrService, useValue: toastrService }, + ], }).compileComponents(); fixture = TestBed.createComponent(ProjectListComponent); diff --git a/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.ts b/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.ts index 36c799727..6ce099374 100644 --- a/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.ts +++ b/src/app/modules/customer-management/components/projects/components/project-list/project-list.component.ts @@ -1,3 +1,4 @@ +import { ToastrService } from 'ngx-toastr'; import { Component, OnInit, OnDestroy } from '@angular/core'; import { Store, select } from '@ngrx/store'; import { Subscription } from 'rxjs'; @@ -21,7 +22,8 @@ export class ProjectListComponent implements OnInit, OnDestroy { projectsSubscription: Subscription; - constructor(private store: Store) {} + constructor(private store: Store, + private toastrService: ToastrService) {} ngOnInit(): void { const projects$ = this.store.pipe(select(getCustomerProjects)); @@ -41,5 +43,6 @@ export class ProjectListComponent implements OnInit, OnDestroy { deleteProject(projectId: string) { this.store.dispatch(new actions.DeleteProject(projectId)); + this.toastrService.success('The project has been removed successfully'); } } diff --git a/src/app/modules/customer-management/pages/customer.component.ts b/src/app/modules/customer-management/pages/customer.component.ts index 4bbad559b..b681e7cf3 100644 --- a/src/app/modules/customer-management/pages/customer.component.ts +++ b/src/app/modules/customer-management/pages/customer.component.ts @@ -6,12 +6,10 @@ import { Component } from '@angular/core'; styleUrls: ['./customer.component.scss'], }) export class CustomerComponent { - showCustomerForm = false; - constructor() {} + showCustomerForm = false; - activateCustomerForm(): boolean { + activateCustomerForm() { this.showCustomerForm = true; - return this.showCustomerForm; } } diff --git a/src/app/modules/shared/components/notification/notification/notification.component.html b/src/app/modules/shared/components/notification/notification/notification.component.html deleted file mode 100644 index 9a7f654d6..000000000 --- a/src/app/modules/shared/components/notification/notification/notification.component.html +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/src/app/modules/shared/components/notification/notification/notification.component.scss b/src/app/modules/shared/components/notification/notification/notification.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/app/modules/shared/components/notification/notification/notification.component.spec.ts b/src/app/modules/shared/components/notification/notification/notification.component.spec.ts deleted file mode 100644 index 69192c5e3..000000000 --- a/src/app/modules/shared/components/notification/notification/notification.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { NotificationComponent } from './notification.component'; - -describe('NotificationComponent', () => { - let component: NotificationComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ NotificationComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(NotificationComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/modules/shared/components/notification/notification/notification.component.ts b/src/app/modules/shared/components/notification/notification/notification.component.ts deleted file mode 100644 index 61160475d..000000000 --- a/src/app/modules/shared/components/notification/notification/notification.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component, OnInit, Input } from '@angular/core'; - -@Component({ - selector: 'app-notification', - templateUrl: './notification.component.html', - styleUrls: ['./notification.component.scss'], -}) -export class NotificationComponent implements OnInit { - @Input() notificationMsg = ''; - @Input() isError: boolean; - constructor() {} - - ngOnInit(): void {} -} diff --git a/src/app/modules/shared/store/technology.selectors.spec.ts b/src/app/modules/shared/store/technology.selectors.spec.ts new file mode 100644 index 000000000..d187e1028 --- /dev/null +++ b/src/app/modules/shared/store/technology.selectors.spec.ts @@ -0,0 +1,13 @@ +import * as selectors from './technology.selectors'; +import { TechnologyState } from './technology.reducers'; + +describe('Technology selectors', () => { + + it('should select technologies', () => { + + const state: TechnologyState = { technologyList: {items: []}, isLoading: false }; + + expect(selectors.allTechnologies.projector(state)).toEqual(state); + }); +}); + diff --git a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts index 5886cda7c..791bb6c81 100644 --- a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts +++ b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts @@ -2,6 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ToastrService } from 'ngx-toastr'; import { ProjectListHoverComponent } from './project-list-hover.component'; import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer'; import { getCustomerProjects } from '../../../customer-management/components/projects/components/store/project.selectors'; @@ -33,10 +34,14 @@ describe('ProjectListHoverComponent', () => { }, }; + const toastrService = { + success: () => {} + }; + beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ProjectListHoverComponent, FilterProjectPipe], - providers: [provideMockStore({ initialState: state })], + providers: [provideMockStore({ initialState: state }), { provide: ToastrService, useValue: toastrService }], imports: [HttpClientTestingModule], }).compileComponents(); store = TestBed.inject(MockStore); @@ -60,4 +65,5 @@ describe('ProjectListHoverComponent', () => { expect(store.dispatch).toHaveBeenCalled(); }); + }); diff --git a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts index 01ebe20fb..708f63c23 100644 --- a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts +++ b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts @@ -7,6 +7,7 @@ import { Project } from 'src/app/modules/shared/models'; import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer'; import * as actions from '../../../customer-management/components/projects/components/store/project.actions'; import * as entryActions from '../../store/entry.actions'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-project-list-hover', @@ -22,7 +23,7 @@ export class ProjectListHoverComponent implements OnInit { keyword = 'name'; nameActiveProject: string; - constructor(private store: Store) { } + constructor(private store: Store, private toastr: ToastrService) { } ngOnInit(): void { this.store.dispatch(new actions.LoadProjects()); @@ -55,5 +56,6 @@ export class ProjectListHoverComponent implements OnInit { clockIn(id: string) { const newEntry = { project_id: id, start_date: new Date().toISOString() }; this.store.dispatch(new entryActions.CreateEntry(newEntry)); + this.toastr.success('You just clocked-in'); } } diff --git a/src/app/modules/time-clock/pages/time-clock.component.html b/src/app/modules/time-clock/pages/time-clock.component.html index 4bbf55b90..9cd581ea5 100644 --- a/src/app/modules/time-clock/pages/time-clock.component.html +++ b/src/app/modules/time-clock/pages/time-clock.component.html @@ -1,4 +1,3 @@ -
Summary
diff --git a/src/app/modules/time-clock/pages/time-clock.component.spec.ts b/src/app/modules/time-clock/pages/time-clock.component.spec.ts index da1f29201..27317751a 100644 --- a/src/app/modules/time-clock/pages/time-clock.component.spec.ts +++ b/src/app/modules/time-clock/pages/time-clock.component.spec.ts @@ -1,21 +1,25 @@ -import {EntryActionTypes, StopTimeEntryRunning } from './../store/entry.actions'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; +import { ToastrService } from 'ngx-toastr'; +import { StopTimeEntryRunning } from './../store/entry.actions'; import { TimeClockComponent } from './time-clock.component'; import { ProjectState } from '../../customer-management/components/projects/components/store/project.reducer'; import { ProjectListHoverComponent } from '../components'; import { FilterProjectPipe } from '../../shared/pipes'; import { AzureAdB2CService } from '../../login/services/azure.ad.b2c.service'; -import {ActionsSubject} from '@ngrx/store'; describe('TimeClockComponent', () => { let component: TimeClockComponent; let fixture: ComponentFixture; let store: MockStore; let azureAdB2CService: AzureAdB2CService; - const actionSub: ActionsSubject = new ActionsSubject(); + let injectedToastrService; + + const toastrService = { + success: () => {} + }; const state = { projects: { projects: [{ id: 'id', name: 'name', project_type_id: '' }], @@ -46,7 +50,7 @@ describe('TimeClockComponent', () => { declarations: [TimeClockComponent, ProjectListHoverComponent, FilterProjectPipe], providers: [ AzureAdB2CService, - { provide: ActionsSubject, useValue: actionSub }, + { provide: ToastrService, useValue: toastrService }, provideMockStore({ initialState: state })], }).compileComponents(); store = TestBed.inject(MockStore); @@ -57,6 +61,7 @@ describe('TimeClockComponent', () => { component = fixture.componentInstance; fixture.detectChanges(); azureAdB2CService = TestBed.inject(AzureAdB2CService); + injectedToastrService = TestBed.inject(ToastrService); }); it('should be created', () => { @@ -86,23 +91,4 @@ describe('TimeClockComponent', () => { expect(store.dispatch).toHaveBeenCalledWith(new StopTimeEntryRunning('id')); }); - - it('on success create entry, the notification is shown', () => { - const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; - const action = { - type: EntryActionTypes.CREATE_ENTRY_SUCCESS - }; - actionSubject.next(action); - expect(component.showNotification).toEqual(true); - }); - - it('on success stop entry, the notification is shown', () => { - const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; - const action = { - type: EntryActionTypes.STOP_TIME_ENTRY_RUNNING_SUCCESS - }; - actionSubject.next(action); - expect(component.showNotification).toEqual(true); - }); - }); diff --git a/src/app/modules/time-clock/pages/time-clock.component.ts b/src/app/modules/time-clock/pages/time-clock.component.ts index 50b5a2131..4f2b8b3b7 100644 --- a/src/app/modules/time-clock/pages/time-clock.component.ts +++ b/src/app/modules/time-clock/pages/time-clock.component.ts @@ -1,12 +1,11 @@ -import {getStatusMessage} from './../../time-clock/store/entry.selectors'; -import {getActiveTimeEntry} from './../store/entry.selectors'; -import {EntryActionTypes, StopTimeEntryRunning} from './../store/entry.actions'; -import {Entry} from './../../shared/models/entry.model'; -import {Store, select, ActionsSubject} from '@ngrx/store'; -import {Component, OnInit} from '@angular/core'; -import {AzureAdB2CService} from '../../login/services/azure.ad.b2c.service'; -import {Observable, Subscription} from 'rxjs'; -import {filter} from 'rxjs/operators'; +import { getActiveTimeEntry } from './../store/entry.selectors'; +import { StopTimeEntryRunning } from './../store/entry.actions'; +import { Entry } from './../../shared/models/entry.model'; +import { Store, select } from '@ngrx/store'; +import { Component, OnInit } from '@angular/core'; +import { AzureAdB2CService } from '../../login/services/azure.ad.b2c.service'; +import { Subscription } from 'rxjs'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-time-clock', @@ -17,16 +16,13 @@ export class TimeClockComponent implements OnInit { username: string; areFieldsVisible = false; activeTimeEntry: Entry; - message: Observable; - showNotification = false; - isError = false; actionsSubscription: Subscription; - constructor(private azureAdB2CService: AzureAdB2CService, private store: Store, private actionsSubject$: ActionsSubject) { + constructor(private azureAdB2CService: AzureAdB2CService, private store: Store, + private toastr: ToastrService) { } ngOnInit() { - this.message = this.store.pipe(select(getStatusMessage)); this.username = this.azureAdB2CService.isLogin() ? this.azureAdB2CService.getName() : ''; this.store.pipe(select(getActiveTimeEntry)).subscribe((activeTimeEntry) => { this.activeTimeEntry = activeTimeEntry; @@ -36,22 +32,11 @@ export class TimeClockComponent implements OnInit { this.areFieldsVisible = false; } }); - - this.actionsSubscription = this.actionsSubject$.pipe( - filter((action: any) => (action.type === EntryActionTypes.CREATE_ENTRY_SUCCESS) || - action.type === EntryActionTypes.STOP_TIME_ENTRY_RUNNING_SUCCESS) - ).subscribe((action) => { - this.displayNotification(); - }); } clockOut() { this.store.dispatch(new StopTimeEntryRunning(this.activeTimeEntry.id)); this.areFieldsVisible = false; - } - - displayNotification() { - this.showNotification = true; - setTimeout(() => ((this.showNotification = false), (this.isError = false)), 3000); + this.toastr.success('You clocked-out successfully'); } } From 2563e2bb601071c7d916813dc28f0c732babc279 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 7 May 2020 20:32:04 +0000 Subject: [PATCH 2/3] chore(release): 1.1.3 [skip ci]nn --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 25988fe03..0b6772138 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "time-tracker", - "version": "1.1.2", + "version": "1.1.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ad5942c01..3a2acb93d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "time-tracker", - "version": "1.1.2", + "version": "1.1.3", "scripts": { "ng": "ng", "start": "ng serve", From 2b5e1a4b14c781a54726cc939506db40a1c155eb Mon Sep 17 00:00:00 2001 From: Cristina Guncay Date: Thu, 7 May 2020 22:35:42 -0500 Subject: [PATCH 3/3] fix: #203 Update-customer-for-active-clock-ins --- .../project-list-hover.component.spec.ts | 32 +++++++++++++++++-- .../project-list-hover.component.ts | 14 +++++--- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts index 791bb6c81..218b9ea65 100644 --- a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts +++ b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts @@ -7,6 +7,7 @@ import { ProjectListHoverComponent } from './project-list-hover.component'; import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer'; import { getCustomerProjects } from '../../../customer-management/components/projects/components/store/project.selectors'; import { FilterProjectPipe } from '../../../shared/pipes'; +import { CreateEntry, UpdateActiveEntry } from '../../store/entry.actions'; describe('ProjectListHoverComponent', () => { let component: ProjectListHoverComponent; @@ -58,12 +59,37 @@ describe('ProjectListHoverComponent', () => { expect(component).toBeTruthy(); }); - it('clock-in dispatchs a new action', () => { + it('clock-in dispatchs a CreateEntry action', () => { + const entry = { + project_id: '2b87372b-3d0d-4dc0-832b-ae5863cd39e5', + start_date: new Date().toISOString(), + }; + + component.activeEntry = null; + spyOn(store, 'dispatch'); + + component.clockIn('2b87372b-3d0d-4dc0-832b-ae5863cd39e5'); + + expect(store.dispatch).toHaveBeenCalledWith(new CreateEntry(entry)); + }); + + it('clock-in dispatchs a UpdateActiveEntry action', () => { + const entry = { + id: '123', + project_id: '2b87372b-3d0d-4dc0-832b-ae5863cd39e5', + start_date: new Date().toISOString(), + }; + const updatedEntry = { + id: '123', + project_id: '123372b-3d0d-4dc0-832b-ae5863cd39e5', + }; + + component.activeEntry = entry; spyOn(store, 'dispatch'); - component.clockIn('id'); + component.clockIn('123372b-3d0d-4dc0-832b-ae5863cd39e5'); - expect(store.dispatch).toHaveBeenCalled(); + expect(store.dispatch).toHaveBeenCalledWith(new UpdateActiveEntry(updatedEntry)); }); }); diff --git a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts index 708f63c23..341dd2a37 100644 --- a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts +++ b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts @@ -22,6 +22,7 @@ export class ProjectListHoverComponent implements OnInit { showButton = ''; keyword = 'name'; nameActiveProject: string; + activeEntry; constructor(private store: Store, private toastr: ToastrService) { } @@ -33,13 +34,13 @@ export class ProjectListHoverComponent implements OnInit { this.listProjects = projects; this.loadActiveTimeEntry(); }); - } private loadActiveTimeEntry() { this.store.dispatch(new entryActions.LoadActiveEntry()); const activeEntry$ = this.store.pipe(select(getActiveTimeEntry)); activeEntry$.subscribe((activeEntry) => { + this.activeEntry = activeEntry; if (activeEntry) { for (const project of this.listProjects) { if (project.id === activeEntry.project_id) { @@ -54,8 +55,13 @@ export class ProjectListHoverComponent implements OnInit { } clockIn(id: string) { - const newEntry = { project_id: id, start_date: new Date().toISOString() }; - this.store.dispatch(new entryActions.CreateEntry(newEntry)); - this.toastr.success('You just clocked-in'); + if (this.activeEntry) { + const entry = {id: this.activeEntry.id, project_id: id}; + this.store.dispatch(new entryActions.UpdateActiveEntry(entry)); + } else { + const newEntry = { project_id: id, start_date: new Date().toISOString() }; + this.store.dispatch(new entryActions.CreateEntry(newEntry)); + this.toastr.success('You just clocked-in'); + } } }
Customer nameName