diff --git a/src/app/app.component.html b/src/app/app.component.html
index 0680b43f9..199f49375 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 391675003..ccb2e143c 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -95,6 +95,11 @@ import { SearchUserComponent } from './modules/shared/components/search-user/sea
import { TimeRangeCustomComponent } from './modules/reports/components/time-range-custom/time-range-custom.component';
import { TimeRangeHeaderComponent } from './modules/reports/components/time-range-custom/time-range-header/time-range-header.component';
import { TimeRangeOptionsComponent } from './modules/reports/components/time-range-custom/time-range-options/time-range-options.component';
+import { InternetConnectionStatusComponent } from './modules/internet-connection-status/internet-connection-status.component';
+import { FastDirective} from './modules/internet-connection-status/internet-connection-directives/fast.directive';
+import { SlowDirective} from './modules/internet-connection-status/internet-connection-directives/slow.directive';
+import { OfflineDirective} from './modules/internet-connection-status/internet-connection-directives/offline.directive';
+import { ConnectionDirective } from './modules/internet-connection-status/internet-connection-directives/connection.directive';
const maskConfig: Partial = {
validation: false,
@@ -154,6 +159,11 @@ const maskConfig: Partial = {
TimeRangeCustomComponent,
TimeRangeHeaderComponent,
TimeRangeOptionsComponent,
+ InternetConnectionStatusComponent,
+ SlowDirective,
+ FastDirective,
+ OfflineDirective,
+ ConnectionDirective
],
imports: [
NgxMaskModule.forRoot(maskConfig),
diff --git a/src/app/modules/activities-management/store/activity-management.effects.ts b/src/app/modules/activities-management/store/activity-management.effects.ts
index 3b16dd15d..08d08e11c 100644
--- a/src/app/modules/activities-management/store/activity-management.effects.ts
+++ b/src/app/modules/activities-management/store/activity-management.effects.ts
@@ -9,13 +9,15 @@ import { ToastrService } from 'ngx-toastr';
import * as actions from './activity-management.actions';
import { Activity, ActivityStatus } from './../../shared/models/activity.model';
import { ActivityService } from './../services/activity.service';
+import { StatusNetworkService } from '../../shared/services/status-network.service';
@Injectable()
export class ActivityEffects {
constructor(
private actions$: Actions,
private activityService: ActivityService,
- private toastrService: ToastrService
+ private toastrService: ToastrService,
+ private statusNetworkService: StatusNetworkService
) { }
@Effect()
@@ -27,7 +29,7 @@ export class ActivityEffects {
return new actions.LoadActivitiesSuccess(activities);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.LoadActivitiesFail(error));
})
)
@@ -45,7 +47,7 @@ export class ActivityEffects {
return new actions.CreateActivitySuccess(activityData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.CreateActivityFail(error));
})
)
@@ -66,7 +68,7 @@ export class ActivityEffects {
return new actions.ArchiveActivitySuccess(activity);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.ArchiveActivityFail(error));
})
)
@@ -84,7 +86,7 @@ export class ActivityEffects {
return new actions.UpdateActivitySuccess(activityData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateActivityFail(error));
})
)
@@ -106,7 +108,7 @@ export class ActivityEffects {
return new actions.UnarchiveActivitySuccess(activityData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UnarchiveActivityFail(error));
})
)
diff --git a/src/app/modules/customer-management/components/projects-type/services/project-type.service.ts b/src/app/modules/customer-management/components/projects-type/services/project-type.service.ts
index 6d9e672c2..685c5d0df 100644
--- a/src/app/modules/customer-management/components/projects-type/services/project-type.service.ts
+++ b/src/app/modules/customer-management/components/projects-type/services/project-type.service.ts
@@ -1,7 +1,6 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
-
import { environment } from '../../../../../../environments/environment';
import { ProjectType } from '../../../../shared/models';
diff --git a/src/app/modules/customer-management/components/projects-type/store/project-type.effects.ts b/src/app/modules/customer-management/components/projects-type/store/project-type.effects.ts
index d11294c8a..2646dc762 100644
--- a/src/app/modules/customer-management/components/projects-type/store/project-type.effects.ts
+++ b/src/app/modules/customer-management/components/projects-type/store/project-type.effects.ts
@@ -9,13 +9,15 @@ import * as actions from './project-type.actions';
import { ProjectType } from '../../../../shared/models';
import { ProjectTypeService } from '../services/project-type.service';
import { ToastrService } from 'ngx-toastr';
+import { StatusNetworkService } from '../../../../shared/services/status-network.service';
@Injectable()
export class ProjectTypeEffects {
constructor(
private actions$: Actions,
private projectTypeService: ProjectTypeService,
- private toastrService: ToastrService
+ private toastrService: ToastrService,
+ private statusNetworkService: StatusNetworkService
) { }
@Effect()
@@ -27,7 +29,7 @@ export class ProjectTypeEffects {
return new actions.LoadProjectTypesSuccess(projectTypes);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.LoadProjectTypesFail(error));
})
)
@@ -45,7 +47,7 @@ export class ProjectTypeEffects {
return new actions.CreateProjectTypeSuccess(projectTypeData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.CreateProjectTypeFail(error));
})
)
@@ -63,7 +65,7 @@ export class ProjectTypeEffects {
return new actions.DeleteProjectTypeSuccess(protectTypeId);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.DeleteProjectTypeFail(error));
})
)
@@ -81,7 +83,7 @@ export class ProjectTypeEffects {
return new actions.UpdateProjectTypeSuccess(projectTypeData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateProjectTypeFail(error));
})
)
diff --git a/src/app/modules/customer-management/components/projects/components/store/project.effects.ts b/src/app/modules/customer-management/components/projects/components/store/project.effects.ts
index 5067b1b85..a80d12d29 100644
--- a/src/app/modules/customer-management/components/projects/components/store/project.effects.ts
+++ b/src/app/modules/customer-management/components/projects/components/store/project.effects.ts
@@ -8,13 +8,15 @@ import { ProjectService } from '../services/project.service';
import * as actions from './project.actions';
import { ToastrService } from 'ngx-toastr';
import { Status } from 'src/app/modules/shared/models';
+import { StatusNetworkService } from '../../../../../shared/services/status-network.service';
@Injectable()
export class ProjectEffects {
constructor(
private actions$: Actions,
private projectService: ProjectService,
- private toastrService: ToastrService
+ private toastrService: ToastrService,
+ private statusNetworkService: StatusNetworkService
) { }
@Effect()
@@ -26,7 +28,7 @@ export class ProjectEffects {
return new actions.LoadProjectsSuccess(projects);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.LoadProjectsFail(error));
})
)
@@ -42,7 +44,7 @@ export class ProjectEffects {
return new actions.LoadCustomerProjectsSuccess(project);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.LoadCustomerProjectsFail(error));
})
)
@@ -58,7 +60,7 @@ export class ProjectEffects {
return new actions.LoadRecentProjectsSuccess(projects);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.LoadRecentProjectsFail(error));
})
)
@@ -76,7 +78,7 @@ export class ProjectEffects {
return new actions.CreateProjectSuccess(projectData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.CreateProjectFail(error));
})
)
@@ -94,7 +96,7 @@ export class ProjectEffects {
return new actions.UpdateProjectSuccess(projectData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateProjectFail(error));
})
)
@@ -112,7 +114,7 @@ export class ProjectEffects {
return new actions.DeleteProjectSuccess(projectId);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.DeleteProjectFail(error));
})
)
@@ -133,7 +135,7 @@ export class ProjectEffects {
return new actions.UnarchiveProjectSuccess(projectData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UnarchiveProjectFail(error));
})
)
diff --git a/src/app/modules/customer-management/store/customer-management.effects.ts b/src/app/modules/customer-management/store/customer-management.effects.ts
index 7485396b7..7c5e7030f 100644
--- a/src/app/modules/customer-management/store/customer-management.effects.ts
+++ b/src/app/modules/customer-management/store/customer-management.effects.ts
@@ -9,13 +9,15 @@ import { ToastrService } from 'ngx-toastr';
import { CustomerService } from '../services/customer.service';
import * as actions from './customer-management.actions';
import { Status } from '../../shared/models/customer.model';
+import { StatusNetworkService } from '../../shared/services/status-network.service';
@Injectable()
export class CustomerEffects {
constructor(
private actions$: Actions,
private customerService: CustomerService,
- private toastrService: ToastrService
+ private toastrService: ToastrService,
+ private statusNetworkService: StatusNetworkService
) { }
@Effect()
@@ -27,7 +29,7 @@ export class CustomerEffects {
return new actions.LoadCustomersSuccess(customers);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.LoadCustomersFail(error));
}
)
@@ -46,7 +48,7 @@ export class CustomerEffects {
return new actions.CreateCustomerSuccess(customerData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.CreateCustomerFail(error));
})
)
@@ -64,7 +66,7 @@ export class CustomerEffects {
return new actions.DeleteCustomerSuccesss(customerId);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.DeleteCustomerFail(error));
})
)
@@ -82,7 +84,7 @@ export class CustomerEffects {
return new actions.UpdateCustomerSuccess(customerData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateCustomerFail(error));
})
)
@@ -104,7 +106,7 @@ export class CustomerEffects {
return new actions.UpdateCustomerSuccess(customerData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateCustomerFail(error));
})
)
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/connection.directive.spec.ts b/src/app/modules/internet-connection-status/internet-connection-directives/connection.directive.spec.ts
new file mode 100644
index 000000000..7f0ff2649
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/connection.directive.spec.ts
@@ -0,0 +1,15 @@
+import { TestBed } from '@angular/core/testing';
+import { ConnectionDirective } from './connection.directive';
+
+describe('ConnectionDirective', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [ConnectionDirective]
+ });
+ });
+
+ it('should create an instance', () => {
+ const directive = new ConnectionDirective('slowSrc', 'fastSrc', 'offlineSrc', undefined);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/connection.directive.ts b/src/app/modules/internet-connection-status/internet-connection-directives/connection.directive.ts
new file mode 100644
index 000000000..e366eb991
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/connection.directive.ts
@@ -0,0 +1,29 @@
+import { Directive, Attribute, ElementRef, OnInit } from '@angular/core';
+
+@Directive({
+ selector: '[appConnection]'
+})
+
+export class ConnectionDirective implements OnInit {
+ constructor(
+ @Attribute('slowSrc') private slowSrc,
+ @Attribute('fastSrc') private fastSrc,
+ @Attribute('offlineSrc') private offlineSrc,
+ private host: ElementRef
+ ) {
+ }
+
+ ngOnInit() {
+ const { effectiveType } = navigator.connection;
+ let networkStatus;
+ if (/\fast-5g|3g|4g/.test(effectiveType)) {
+ networkStatus = this.fastSrc;
+ } else if (/\slow-2g|2g/.test(effectiveType)) {
+ networkStatus = this.slowSrc;
+ } else {
+ networkStatus = this.offlineSrc;
+ }
+
+ this.host.nativeElement.setAttribute('src', networkStatus);
+ }
+}
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/fast.directive.spec.ts b/src/app/modules/internet-connection-status/internet-connection-directives/fast.directive.spec.ts
new file mode 100644
index 000000000..f738749a3
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/fast.directive.spec.ts
@@ -0,0 +1,14 @@
+import { TestBed } from '@angular/core/testing';
+import { FastDirective } from './fast.directive';
+
+describe('FastDirective', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [FastDirective]
+ });
+ });
+ it('should create an instance', () => {
+ const directive = new FastDirective(undefined);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/fast.directive.ts b/src/app/modules/internet-connection-status/internet-connection-directives/fast.directive.ts
new file mode 100644
index 000000000..50faa29a3
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/fast.directive.ts
@@ -0,0 +1,11 @@
+import { Directive, TemplateRef } from '@angular/core';
+
+@Directive({
+ selector: '[appFast]'
+})
+
+export class FastDirective {
+
+ constructor(public tpl: TemplateRef) { }
+
+}
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/offline.directive.spec.ts b/src/app/modules/internet-connection-status/internet-connection-directives/offline.directive.spec.ts
new file mode 100644
index 000000000..bf6960c45
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/offline.directive.spec.ts
@@ -0,0 +1,14 @@
+import { TestBed } from '@angular/core/testing';
+import { OfflineDirective } from './offline.directive';
+
+describe('FastDirective', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [OfflineDirective]
+ });
+ });
+ it('should create an instance', () => {
+ const directive = new OfflineDirective(undefined);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/offline.directive.ts b/src/app/modules/internet-connection-status/internet-connection-directives/offline.directive.ts
new file mode 100644
index 000000000..986c8542c
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/offline.directive.ts
@@ -0,0 +1,11 @@
+import { Directive, TemplateRef } from '@angular/core';
+
+@Directive({
+ selector: '[appOffline]'
+})
+
+export class OfflineDirective {
+
+ constructor(public tpl: TemplateRef) { }
+
+}
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/slow.directive.spec.ts b/src/app/modules/internet-connection-status/internet-connection-directives/slow.directive.spec.ts
new file mode 100644
index 000000000..59287917a
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/slow.directive.spec.ts
@@ -0,0 +1,14 @@
+import { TestBed } from '@angular/core/testing';
+import { SlowDirective } from './slow.directive';
+
+describe('FastDirective', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [SlowDirective]
+ });
+ });
+ it('should create an instance', () => {
+ const directive = new SlowDirective(undefined);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/app/modules/internet-connection-status/internet-connection-directives/slow.directive.ts b/src/app/modules/internet-connection-status/internet-connection-directives/slow.directive.ts
new file mode 100644
index 000000000..9095e34a1
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-directives/slow.directive.ts
@@ -0,0 +1,11 @@
+import { Directive, TemplateRef } from '@angular/core';
+
+@Directive({
+ selector: '[appSlow]'
+})
+
+export class SlowDirective {
+
+ constructor(public tpl: TemplateRef) { }
+
+}
diff --git a/src/app/modules/internet-connection-status/internet-connection-status.component.html b/src/app/modules/internet-connection-status/internet-connection-status.component.html
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/app/modules/internet-connection-status/internet-connection-status.component.spec.ts b/src/app/modules/internet-connection-status/internet-connection-status.component.spec.ts
new file mode 100644
index 000000000..4f273fff8
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-status.component.spec.ts
@@ -0,0 +1,88 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { InternetConnectionStatusComponent } from './internet-connection-status.component';
+import { ToastrService } from 'ngx-toastr';
+import { of } from 'rxjs';
+
+describe('InternetConnectionStatusComponent', () => {
+ let component: InternetConnectionStatusComponent;
+ let fixture: ComponentFixture;
+ const toastrServiceStub = {
+ error: () => {
+ return 'test error';
+ },
+ warning: () => {
+ return 'warning error';
+ },
+ success: () => {
+ return 'success error';
+ }
+ };
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ InternetConnectionStatusComponent ],
+ providers: [{ provide: ToastrService, useValue: toastrServiceStub }]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(InternetConnectionStatusComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('component.isFast should be true when the connection is 4g', () => {
+ component.connection$ = of('4g');
+ fixture.detectChanges();
+ component.ngOnInit();
+ expect(component.isFast).toBe(true);
+ });
+
+ it('component.isFast should be false when the connection is 2g', () => {
+ component.connection$ = of('2g');
+ fixture.detectChanges();
+ component.ngOnInit();
+ expect(component.isFast).toBe(false);
+ });
+
+ it('component.isFast should be false when the connection is Offline', () => {
+ component.connection$ = of('Offline');
+ fixture.detectChanges();
+ component.ngOnInit();
+ expect(component.isFast).toBe(false);
+ });
+
+ it('should change the network type', () => {
+ component.connection$ = of('5g');
+ fixture.detectChanges();
+ component.ngOnInit();
+ component.connection$.subscribe((networkType: string) => {
+ expect(networkType).toEqual('5g');
+ });
+
+ jasmine.clock().install();
+ jasmine.clock().tick(300);
+
+ component.connection$ = of('2g');
+ fixture.detectChanges();
+ console.log(window.navigator);
+ component.connection$.subscribe((networkType: string) => {
+ expect(networkType).toEqual('2g');
+ });
+
+ jasmine.clock().uninstall();
+ });
+
+ it('should return when window.navigator.connection is undefined', () => {
+ const attributeCustome = '__defineGetter__';
+ window.navigator[attributeCustome]('connection', () => {
+ return undefined;
+ });
+ fixture = TestBed.createComponent(InternetConnectionStatusComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ const statusInit = component.ngOnInit();
+ expect(statusInit).toEqual(undefined);
+ });
+});
diff --git a/src/app/modules/internet-connection-status/internet-connection-status.component.ts b/src/app/modules/internet-connection-status/internet-connection-status.component.ts
new file mode 100644
index 000000000..b1ed09223
--- /dev/null
+++ b/src/app/modules/internet-connection-status/internet-connection-status.component.ts
@@ -0,0 +1,84 @@
+import { Component, OnInit, ContentChild, Attribute} from '@angular/core';
+import { FastDirective} from '../../modules/internet-connection-status/internet-connection-directives/fast.directive';
+import { SlowDirective} from '../../modules/internet-connection-status/internet-connection-directives/slow.directive';
+import { OfflineDirective} from '../../modules/internet-connection-status/internet-connection-directives/offline.directive';
+import { Observable, Subscription } from 'rxjs';
+import { take } from 'rxjs/operators';
+import { ToastrService } from 'ngx-toastr';
+
+type Connection = {
+ effectiveType: string;
+};
+
+declare global {
+ interface Navigator {
+ connection: {
+ effectiveType: string;
+ addEventListener: (a: any, b: any) => {};
+ removeEventListener: (a: any, b: any) => {};
+ };
+ }
+}
+
+
+@Component({
+ selector: 'app-internet-connection-status',
+ templateUrl: './internet-connection-status.component.html'
+})
+export class InternetConnectionStatusComponent implements OnInit {
+ isFast = true;
+ connectionType: string;
+ networkType: string;
+ @ContentChild(FastDirective) fast: FastDirective;
+ @ContentChild(SlowDirective) slow: SlowDirective;
+ @ContentChild(OfflineDirective) offline: OfflineDirective;
+
+ private subscription: Subscription;
+
+ constructor(@Attribute('listen') private withChanges: boolean, private toastrService: ToastrService) {
+ }
+
+ connection$ = new Observable((observer) => {
+ const { effectiveType } = navigator.connection;
+ observer.next(effectiveType);
+
+ const onConnectionChange = () => {
+ this.networkType = navigator.connection.effectiveType;
+ observer.next(this.networkType);
+ };
+
+ navigator.connection.addEventListener('change', onConnectionChange);
+
+ return () => {
+ navigator.connection.removeEventListener('change', onConnectionChange);
+ observer.complete();
+ };
+ });
+
+ ngOnInit(){
+ const connection = navigator.connection;
+ console.log('navigator component', connection);
+ if (!connection || !connection.effectiveType) {
+ return;
+ }
+
+ this.subscription = this.connection$
+ .pipe(take(this.withChanges ? Number.POSITIVE_INFINITY : 1))
+ .subscribe((effectiveType: string) => {
+
+ this.connectionType = effectiveType;
+
+ if (/\fast-5g|3g|4g/.test(effectiveType)) {
+ this.isFast = true;
+ return;
+ }
+ if (/\slow-2g|2g/.test(effectiveType)) {
+ this.toastrService.warning('Caution your connection is slow');
+ this.isFast = false;
+ return;
+ }
+ this.toastrService.warning('Caution your connection is slow');
+ this.isFast = false;
+ });
+ }
+}
diff --git a/src/app/modules/shared/services/status-network.service.spec.ts b/src/app/modules/shared/services/status-network.service.spec.ts
new file mode 100644
index 000000000..8ae41a12b
--- /dev/null
+++ b/src/app/modules/shared/services/status-network.service.spec.ts
@@ -0,0 +1,47 @@
+import { TestBed } from '@angular/core/testing';
+import { catchError } from 'rxjs/operators';
+import { IndividualConfig, ToastrService } from 'ngx-toastr';
+import { StatusNetworkService } from './status-network.service';
+
+export interface ErrorType {
+ error: any;
+ message?: string;
+ isError?: boolean;
+}
+describe('StatusNetworkService', () => {
+ let service: StatusNetworkService;
+ const toastrServiceStub = {
+ error: (message?: string, title?: string, override?: Partial) => { },
+ warning: (message?: string, title?: string, override?: Partial) => { }
+ };
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [ToastrService, {
+ provide: ToastrService, useValue: toastrServiceStub
+ }]
+ });
+ service = TestBed.inject(StatusNetworkService);
+ });
+
+ it('showTypeToastrServiceAlert is error', () => {
+ const errorType: ErrorType = {error: catchError, message: 'The server is disconnected', isError: true};
+ spyOn(toastrServiceStub, 'error');
+ service.showTypeToastrServiceAlert(errorType);
+ expect(toastrServiceStub.error).toHaveBeenCalled();
+ });
+
+ it('showTypeToastrServiceAlert is warning with message', () => {
+ const errorType: ErrorType = {error: catchError, message: 'The server is disconnected', isError: false};
+ spyOn(toastrServiceStub, 'warning');
+ service.showTypeToastrServiceAlert(errorType);
+ expect(toastrServiceStub.warning).toHaveBeenCalled();
+ });
+
+ it('showTypeToastrServiceAlert is warning without message', () => {
+ const errorType: ErrorType = {error: catchError, isError: false};
+ spyOn(toastrServiceStub, 'warning');
+ service.showTypeToastrServiceAlert(errorType);
+ expect(toastrServiceStub.warning).toHaveBeenCalled();
+ });
+});
diff --git a/src/app/modules/shared/services/status-network.service.ts b/src/app/modules/shared/services/status-network.service.ts
new file mode 100644
index 000000000..e268962cb
--- /dev/null
+++ b/src/app/modules/shared/services/status-network.service.ts
@@ -0,0 +1,37 @@
+import { Injectable } from '@angular/core';
+import { ToastrService } from 'ngx-toastr';
+
+export interface ErrorType {
+ error: any;
+ message?: string;
+ isError?: boolean;
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class StatusNetworkService {
+
+ constructor(
+ private toastrService: ToastrService
+ ) { }
+
+ showTypeToastrServiceAlert(dataError: ErrorType) {
+ const { isError = false, message = 'The server is disconnected', error } = dataError;
+ const effectiveTypenetwork = navigator.connection;
+
+ if (effectiveTypenetwork.effectiveType === '2g') {
+ this.toastrService.warning('Your request was not completed, your connection is slow');
+ return;
+ }
+
+ if (!isError) {
+ this.toastrService.warning(message);
+ return;
+ }
+
+ const errorMessa = (error.error && error.error.message ? error.error.message :
+ 'There was an error in the server, your request was not completed');
+ this.toastrService.error(errorMessa);
+
+ }}
diff --git a/src/app/modules/time-clock/store/entry.effects.ts b/src/app/modules/time-clock/store/entry.effects.ts
index f9fc9d769..77c355c3e 100644
--- a/src/app/modules/time-clock/store/entry.effects.ts
+++ b/src/app/modules/time-clock/store/entry.effects.ts
@@ -8,11 +8,16 @@ import { catchError, map, mergeMap, switchMap } from 'rxjs/operators';
import { EntryService } from '../services/entry.service';
import * as actions from './entry.actions';
import * as moment from 'moment';
+import { StatusNetworkService } from '../../shared/services/status-network.service';
@Injectable()
export class EntryEffects {
- constructor(private actions$: Actions, private entryService: EntryService, private toastrService: ToastrService) {
- }
+ constructor(
+ private actions$: Actions,
+ private entryService: EntryService,
+ private toastrService: ToastrService,
+ private statusNetworkService: StatusNetworkService
+ ) { }
@Effect()
switchEntryRunning$: Observable = this.actions$.pipe(
@@ -32,7 +37,8 @@ export class EntryEffects {
return new actions.ClockIn(entry);
}),
catchError((error) => {
- this.toastrService.warning('We could not perform this operation, try again later');
+ this.statusNetworkService.showTypeToastrServiceAlert(
+ {error, message: 'We could not perform this operation, try again later', isError: false});
return of(new actions.StopTimeEntryRunningFail(error));
})
)
@@ -51,7 +57,8 @@ export class EntryEffects {
return new actions.LoadEntriesSummarySuccess(response);
}),
catchError((error) => {
- this.toastrService.warning('Your summary information could not be loaded');
+ this.statusNetworkService.showTypeToastrServiceAlert(
+ {error, message: 'Your summary information could not be loaded', isError: false});
return of(new actions.LoadEntriesSummaryFail());
})
)
@@ -96,7 +103,7 @@ export class EntryEffects {
this.entryService.loadEntries({ month: date.month, year: date.year }).pipe(
map((entries) => new actions.LoadEntriesSuccess(entries)),
catchError((error) => {
- this.toastrService.warning(`The data could not be loaded`);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, message: 'The data could not be loaded', isError: false});
return of(new actions.LoadEntriesFail(error));
})
)
@@ -118,7 +125,7 @@ export class EntryEffects {
return new actions.CreateEntrySuccess(entryData);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.CreateEntryFail(error.error.message));
})
)
@@ -146,7 +153,8 @@ export class EntryEffects {
if (error.status === 404) {
return of(new actions.CreateEntry(entry));
} else {
- this.toastrService.error('We could not clock you in, try again later.');
+ this.statusNetworkService.showTypeToastrServiceAlert(
+ {error, message: 'We could not clock you in, try again later.', isError: true});
return of(new actions.CreateEntryFail('Error'));
}
})
@@ -165,7 +173,7 @@ export class EntryEffects {
return new actions.DeleteEntrySuccess(entryId);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.DeleteEntryFail(error));
})
)
@@ -183,7 +191,7 @@ export class EntryEffects {
return new actions.UpdateEntrySuccess(entryResponse);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateEntryFail(error));
})
)
@@ -201,7 +209,7 @@ export class EntryEffects {
return new actions.UpdateEntrySuccess(entryResponse);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateEntryFail(error));
})
)
@@ -219,7 +227,7 @@ export class EntryEffects {
return new actions.StopTimeEntryRunningSuccess(response);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.StopTimeEntryRunningFail(error.error.message));
})
)
@@ -246,7 +254,7 @@ export class EntryEffects {
}
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.UpdateCurrentOrLastEntryFail('error'));
})
)
@@ -279,7 +287,7 @@ export class EntryEffects {
return new actions.RestartEntrySuccess(entryResponse);
}),
catchError((error) => {
- this.toastrService.error(error.error.message, 'This entry could not be restarted');
+ this.statusNetworkService.showTypeToastrServiceAlert({error, message: 'This entry could not be restarted', isError: true});
return of(new actions.RestartEntryFail(error));
})
)
diff --git a/src/app/modules/users/store/user.effects.ts b/src/app/modules/users/store/user.effects.ts
index 87f97eaef..6090f07a0 100644
--- a/src/app/modules/users/store/user.effects.ts
+++ b/src/app/modules/users/store/user.effects.ts
@@ -7,10 +7,16 @@ import { map, catchError, mergeMap } from 'rxjs/operators';
import { ToastrService } from 'ngx-toastr';
import { UsersService } from '../services/users.service';
import * as actions from './user.actions';
+import { StatusNetworkService } from '../../shared/services/status-network.service';
@Injectable()
export class UserEffects {
- constructor(private actions$: Actions, private userService: UsersService, private toastrService: ToastrService) {}
+ constructor(
+ private actions$: Actions,
+ private userService: UsersService,
+ private toastrService: ToastrService,
+ private statusNetworkService: StatusNetworkService
+ ) {}
@Effect()
loadUsers$: Observable = this.actions$.pipe(
@@ -21,7 +27,7 @@ export class UserEffects {
return new actions.LoadUsersSuccess(users);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.LoadUsersFail(error));
})
)
@@ -39,7 +45,7 @@ export class UserEffects {
return new actions.AddUserToGroupSuccess(response);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.AddUserToGroupFail(error));
})
)
@@ -57,7 +63,7 @@ export class UserEffects {
return new actions.RemoveUserFromGroupSuccess(response);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.RemoveUserFromGroupFail(error));
})
)
@@ -75,7 +81,7 @@ export class UserEffects {
return new actions.GrantUserRoleSuccess(response);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.GrantUserRoleFail(error));
})
)
@@ -93,7 +99,7 @@ export class UserEffects {
return new actions.RevokeUserRoleSuccess(response);
}),
catchError((error) => {
- this.toastrService.error(error.error.message);
+ this.statusNetworkService.showTypeToastrServiceAlert({error, isError: true});
return of(new actions.RevokeUserRoleFail(error));
})
)