diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b23f7a9d6..54b7775eb 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -54,6 +54,7 @@ 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: [ @@ -88,6 +89,7 @@ import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.tok ProjectTypeListComponent, CreateProjectTypeComponent, EntryFieldsComponent, + NotificationComponent, ], imports: [ CommonModule, 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 cbcf2ec88..f0b8b20b7 100644 --- a/src/app/modules/activities-management/pages/activities-management.component.html +++ b/src/app/modules/activities-management/pages/activities-management.component.html @@ -1,4 +1,5 @@
+
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 e90769281..a3839ed41 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 @@ -1,26 +1,92 @@ import { HttpClient, HttpHandler } from '@angular/common/http'; -import { async, TestBed } from '@angular/core/testing'; -import { of } from 'rxjs'; +import { async, TestBed, ComponentFixture } from '@angular/core/testing'; +import { of, Subscription } from 'rxjs'; import { Activity } from '../../shared/models'; import { ActivityService } from './../services/activity.service'; import { ActivitiesManagementComponent } from './activities-management.component'; +import { ActionsSubject } from '@ngrx/store'; describe('ActivitiesManagementComponent', () => { let component: ActivitiesManagementComponent; + let fixture: ComponentFixture; let activityService: ActivityService; const activitiesFromApi: Activity[] = [{ id: '123', name: 'aaa', description: 'xxx' }]; beforeEach(async(() => { + const actionSub: ActionsSubject = new ActionsSubject(); TestBed.configureTestingModule({ declarations: [ActivitiesManagementComponent], - providers: [ActivityService, HttpClient, HttpHandler], - }); - component = TestBed.createComponent(ActivitiesManagementComponent).componentInstance; + providers: [ActivityService, HttpClient, HttpHandler, { provide: ActionsSubject, useValue: actionSub }], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ActivitiesManagementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + activityService = TestBed.inject(ActivityService); spyOn(activityService, 'getActivities').and.returnValue(of(activitiesFromApi)); - })); + }); it('should create the component', () => { expect(component).toBeTruthy(); }); + + it('should call #setDataNotification with action #ngOnInit', () => { + const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; + spyOn(component, 'setDataNotification'); + const action = { + type: '[ActivityManagement] CREATE_ACTIVITY_SUCCESS', + }; + actionSubject.next(action); + + component.ngOnInit(); + expect(component.setDataNotification).toHaveBeenCalledWith(action.type); + }); + + it('should destroy the subscription', () => { + component.actionsSubscription = new Subscription(); + const subscription = spyOn(component.actionsSubscription, 'unsubscribe'); + + component.ngOnDestroy(); + + expect(subscription).toHaveBeenCalledTimes(1); + }); + + it('#setDataNotification should show an success notification with DELETE_ACTIVITY_SUCCESS case', () => { + const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; + const action = { + type: '[ActivityManagement] DELETE_ACTIVITY_SUCESS', + }; + actionSubject.next(action); + + component.setDataNotification(action.type); + expect(component.showNotification).toBeTrue(); + expect(component.isError).toBeFalse(); + }); + + 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); + + component.setDataNotification(action.type); + expect(component.showNotification).toBeTrue(); + expect(component.isError).toBeTrue(); + }); + + it('#setDataNotification should not show an error notification with incorrect action', () => { + const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; + const action = { + type: '[ActivityManagement] TEST', + }; + 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 da1b103ff..c86dd0595 100644 --- a/src/app/modules/activities-management/pages/activities-management.component.ts +++ b/src/app/modules/activities-management/pages/activities-management.component.ts @@ -1,12 +1,52 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; +import { ActionsSubject } from '@ngrx/store'; +import { Subscription } from 'rxjs'; +import { ActivityManagementActionTypes } from '../store'; @Component({ selector: 'app-activities-management', templateUrl: './activities-management.component.html', styleUrls: ['./activities-management.component.scss'], }) -export class ActivitiesManagementComponent implements OnInit { - constructor() {} +export class ActivitiesManagementComponent implements OnInit, OnDestroy { + notificationMsg = ''; + showNotification = false; + isError = false; + actionsSubscription: Subscription; - ngOnInit(): void {} + constructor(private actionsSubject$: ActionsSubject) {} + + ngOnInit() { + this.actionsSubscription = this.actionsSubject$.subscribe((action) => { + this.setDataNotification(action.type); + }); + } + + ngOnDestroy() { + this.actionsSubscription.unsubscribe(); + } + + setDataNotification(action: any) { + this.showNotification = true; + switch (action) { + case ActivityManagementActionTypes.CREATE_ACTIVITY_SUCCESS: { + this.notificationMsg = 'The activity has been saved successfully.'; + break; + } + case ActivityManagementActionTypes.DELETE_ACTIVITY_SUCCESS: { + this.notificationMsg = 'The activity has been removed successfully.'; + break; + } + case ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL || ActivityManagementActionTypes.DELETE_ACTIVITY_FAIL: { + this.notificationMsg = 'An unexpected error happened, please try again later.'; + this.isError = true; + break; + } + default: { + this.showNotification = false; + break; + } + } + setTimeout(() => ((this.showNotification = false), (this.isError = false)), 3000); + } } diff --git a/src/app/modules/shared/components/notification/notification/notification.component.html b/src/app/modules/shared/components/notification/notification/notification.component.html new file mode 100644 index 000000000..9a7f654d6 --- /dev/null +++ b/src/app/modules/shared/components/notification/notification/notification.component.html @@ -0,0 +1,8 @@ + diff --git a/src/app/modules/shared/components/notification/notification/notification.component.scss b/src/app/modules/shared/components/notification/notification/notification.component.scss new file mode 100644 index 000000000..e69de29bb 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 new file mode 100644 index 000000000..69192c5e3 --- /dev/null +++ b/src/app/modules/shared/components/notification/notification/notification.component.spec.ts @@ -0,0 +1,25 @@ +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 new file mode 100644 index 000000000..61160475d --- /dev/null +++ b/src/app/modules/shared/components/notification/notification/notification.component.ts @@ -0,0 +1,14 @@ +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 {} +}