Skip to content

Commit 05b3a52

Browse files
authored
Merge pull request #192 from ioet/169-Display-message-after-saving/deleting-activities
fix: #169 Display message after saving/deleting activities
2 parents 36765fd + 0ed456d commit 05b3a52

File tree

8 files changed

+166
-10
lines changed

8 files changed

+166
-10
lines changed

src/app/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import { CreateProjectTypeComponent } from './modules/customer-management/compon
5454
import { CustomerEffects } from './modules/customer-management/store/customer-management.effects';
5555
import { EntryEffects } from './modules/time-clock/store/entry.effects';
5656
import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.token.interceptor';
57+
import { NotificationComponent } from './modules/shared/components/notification/notification/notification.component';
5758

5859
@NgModule({
5960
declarations: [
@@ -88,6 +89,7 @@ import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.tok
8889
ProjectTypeListComponent,
8990
CreateProjectTypeComponent,
9091
EntryFieldsComponent,
92+
NotificationComponent,
9193
],
9294
imports: [
9395
CommonModule,

src/app/modules/activities-management/pages/activities-management.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<div class="container">
2+
<app-notification [notificationMsg]="notificationMsg" [isError]="isError" *ngIf="showNotification"></app-notification>
23
<div class="row">
34
<div class="col">
45
<app-create-activity></app-create-activity>
Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,92 @@
11
import { HttpClient, HttpHandler } from '@angular/common/http';
2-
import { async, TestBed } from '@angular/core/testing';
3-
import { of } from 'rxjs';
2+
import { async, TestBed, ComponentFixture } from '@angular/core/testing';
3+
import { of, Subscription } from 'rxjs';
44
import { Activity } from '../../shared/models';
55
import { ActivityService } from './../services/activity.service';
66
import { ActivitiesManagementComponent } from './activities-management.component';
7+
import { ActionsSubject } from '@ngrx/store';
78

89
describe('ActivitiesManagementComponent', () => {
910
let component: ActivitiesManagementComponent;
11+
let fixture: ComponentFixture<ActivitiesManagementComponent>;
1012
let activityService: ActivityService;
1113
const activitiesFromApi: Activity[] = [{ id: '123', name: 'aaa', description: 'xxx' }];
1214

1315
beforeEach(async(() => {
16+
const actionSub: ActionsSubject = new ActionsSubject();
1417
TestBed.configureTestingModule({
1518
declarations: [ActivitiesManagementComponent],
16-
providers: [ActivityService, HttpClient, HttpHandler],
17-
});
18-
component = TestBed.createComponent(ActivitiesManagementComponent).componentInstance;
19+
providers: [ActivityService, HttpClient, HttpHandler, { provide: ActionsSubject, useValue: actionSub }],
20+
}).compileComponents();
21+
}));
22+
23+
beforeEach(() => {
24+
fixture = TestBed.createComponent(ActivitiesManagementComponent);
25+
component = fixture.componentInstance;
26+
fixture.detectChanges();
27+
1928
activityService = TestBed.inject(ActivityService);
2029
spyOn(activityService, 'getActivities').and.returnValue(of(activitiesFromApi));
21-
}));
30+
});
2231

2332
it('should create the component', () => {
2433
expect(component).toBeTruthy();
2534
});
35+
36+
it('should call #setDataNotification with action #ngOnInit', () => {
37+
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
38+
spyOn(component, 'setDataNotification');
39+
const action = {
40+
type: '[ActivityManagement] CREATE_ACTIVITY_SUCCESS',
41+
};
42+
actionSubject.next(action);
43+
44+
component.ngOnInit();
45+
expect(component.setDataNotification).toHaveBeenCalledWith(action.type);
46+
});
47+
48+
it('should destroy the subscription', () => {
49+
component.actionsSubscription = new Subscription();
50+
const subscription = spyOn(component.actionsSubscription, 'unsubscribe');
51+
52+
component.ngOnDestroy();
53+
54+
expect(subscription).toHaveBeenCalledTimes(1);
55+
});
56+
57+
it('#setDataNotification should show an success notification with DELETE_ACTIVITY_SUCCESS case', () => {
58+
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
59+
const action = {
60+
type: '[ActivityManagement] DELETE_ACTIVITY_SUCESS',
61+
};
62+
actionSubject.next(action);
63+
64+
component.setDataNotification(action.type);
65+
expect(component.showNotification).toBeTrue();
66+
expect(component.isError).toBeFalse();
67+
});
68+
69+
it('#setDataNotification should show an error notification with CREATE_ACTIVITY_FAIL case', () => {
70+
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
71+
const action = {
72+
type: '[ActivityManagement] CREATE_ACTIVITY_FAIL',
73+
};
74+
actionSubject.next(action);
75+
76+
component.setDataNotification(action.type);
77+
expect(component.showNotification).toBeTrue();
78+
expect(component.isError).toBeTrue();
79+
});
80+
81+
it('#setDataNotification should not show an error notification with incorrect action', () => {
82+
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
83+
const action = {
84+
type: '[ActivityManagement] TEST',
85+
};
86+
actionSubject.next(action);
87+
88+
component.setDataNotification(action.type);
89+
expect(component.showNotification).toBeFalse();
90+
expect(component.isError).toBeFalse();
91+
});
2692
});
Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,52 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
2+
import { ActionsSubject } from '@ngrx/store';
3+
import { Subscription } from 'rxjs';
4+
import { ActivityManagementActionTypes } from '../store';
25

36
@Component({
47
selector: 'app-activities-management',
58
templateUrl: './activities-management.component.html',
69
styleUrls: ['./activities-management.component.scss'],
710
})
8-
export class ActivitiesManagementComponent implements OnInit {
9-
constructor() {}
11+
export class ActivitiesManagementComponent implements OnInit, OnDestroy {
12+
notificationMsg = '';
13+
showNotification = false;
14+
isError = false;
15+
actionsSubscription: Subscription;
1016

11-
ngOnInit(): void {}
17+
constructor(private actionsSubject$: ActionsSubject) {}
18+
19+
ngOnInit() {
20+
this.actionsSubscription = this.actionsSubject$.subscribe((action) => {
21+
this.setDataNotification(action.type);
22+
});
23+
}
24+
25+
ngOnDestroy() {
26+
this.actionsSubscription.unsubscribe();
27+
}
28+
29+
setDataNotification(action: any) {
30+
this.showNotification = true;
31+
switch (action) {
32+
case ActivityManagementActionTypes.CREATE_ACTIVITY_SUCCESS: {
33+
this.notificationMsg = 'The activity has been saved successfully.';
34+
break;
35+
}
36+
case ActivityManagementActionTypes.DELETE_ACTIVITY_SUCCESS: {
37+
this.notificationMsg = 'The activity has been removed successfully.';
38+
break;
39+
}
40+
case ActivityManagementActionTypes.CREATE_ACTIVITY_FAIL || ActivityManagementActionTypes.DELETE_ACTIVITY_FAIL: {
41+
this.notificationMsg = 'An unexpected error happened, please try again later.';
42+
this.isError = true;
43+
break;
44+
}
45+
default: {
46+
this.showNotification = false;
47+
break;
48+
}
49+
}
50+
setTimeout(() => ((this.showNotification = false), (this.isError = false)), 3000);
51+
}
1252
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<div
2+
*ngIf="notificationMsg"
3+
[ngClass]="isError ? 'bg-primary' : 'bg-secondary'"
4+
class="alert alert-dismissible fade fade-in show text-white"
5+
role="alert"
6+
>
7+
<strong>{{ notificationMsg }}</strong>
8+
</div>

src/app/modules/shared/components/notification/notification/notification.component.scss

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { NotificationComponent } from './notification.component';
4+
5+
describe('NotificationComponent', () => {
6+
let component: NotificationComponent;
7+
let fixture: ComponentFixture<NotificationComponent>;
8+
9+
beforeEach(async(() => {
10+
TestBed.configureTestingModule({
11+
declarations: [ NotificationComponent ]
12+
})
13+
.compileComponents();
14+
}));
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(NotificationComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Component, OnInit, Input } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-notification',
5+
templateUrl: './notification.component.html',
6+
styleUrls: ['./notification.component.scss'],
7+
})
8+
export class NotificationComponent implements OnInit {
9+
@Input() notificationMsg = '';
10+
@Input() isError: boolean;
11+
constructor() {}
12+
13+
ngOnInit(): void {}
14+
}

0 commit comments

Comments
 (0)