diff --git a/projects/common/src/fm/components/app/app.component.ts b/projects/common/src/fm/components/app/app.component.ts index 3aae906..3dedeea 100644 --- a/projects/common/src/fm/components/app/app.component.ts +++ b/projects/common/src/fm/components/app/app.component.ts @@ -10,6 +10,7 @@ import { IEventMessage } from '../../models/event.message'; import { IListItem} from '../../models/list.item'; import { EventService } from '../../services/event.service'; import * as commonActions from '../../actions/app-common.actions'; +import { HealthCheckService } from '../../services/healthcheck.service'; import * as appReducers from '../../reducers/app-common.reducer'; @@ -46,26 +47,18 @@ export class AppComponent implements OnInit, OnDestroy { private meta: Meta, private store: Store, private eventService: EventService, + private healthCheckService: HealthCheckService ) { - var connection = navigator['connection'] || navigator['mozConnection'] || navigator['webkitConnection']; - if(connection) { - this.setOnOffline(connection); - connection.addEventListener('change', () => { - this.setOnOffline(connection); - }); - } - } - - setOnOffline(connection:any) { - console.debug(connection); - if(connection.downlink == 0) { - this.store.dispatch(new commonActions.Offline()); - } else { + //check health every 30 seconds + this.healthCheckService.check(30000).subscribe((online) => { + if(online) { this.store.dispatch(new commonActions.Online()); - } + } else { + this.store.dispatch(new commonActions.Offline()); + } + }); } - getActionFromEvent(event: IEventMessage): Action { diff --git a/projects/common/src/fm/effects/app-common.effects.ts b/projects/common/src/fm/effects/app-common.effects.ts index 1553140..65fbd62 100644 --- a/projects/common/src/fm/effects/app-common.effects.ts +++ b/projects/common/src/fm/effects/app-common.effects.ts @@ -165,18 +165,21 @@ export class AppCommonEffects { @Effect({ dispatch: false }) online$: Observable = this.actions$.pipe( ofType(appCommonActions.ONLINE), - map((action) => { - console.debug("Online: Check token"); - if(!this.oauthService$.hasValidAccessToken()) { - console.debug("No valid token, try to refresh"); - if(this.oauthService$.getRefreshToken() != null ) { - console.debug("We have a refresh token"); - this.oauthService$.refreshToken().then(() => { - this.store$.dispatch(new appCommonActions.InitUser()); - }); - } + withLatestFrom(this.store$.select(appCommonReducers.SelectGetIsOnline)), + switchMap(([action,isOnline]) => { + if(!isOnline) { + console.debug("Online: Check token"); + if(!this.oauthService$.hasValidAccessToken()) { + console.debug("No valid token, try to refresh"); + if(this.oauthService$.getRefreshToken() != null ) { + console.debug("We have a refresh token"); + this.oauthService$.refreshToken().then(() => { + this.store$.dispatch(new appCommonActions.InitUser()); + }); + } + } } - return null; + return of(undefined); })); diff --git a/projects/common/src/fm/services/healthcheck.service.ts b/projects/common/src/fm/services/healthcheck.service.ts new file mode 100644 index 0000000..8888196 --- /dev/null +++ b/projects/common/src/fm/services/healthcheck.service.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import { Observable,BehaviorSubject,of } from 'rxjs'; +import { map, catchError } from 'rxjs/operators'; +import { HttpClient, HttpXhrBackend } from "@angular/common/http"; +import { AppConfig } from "../shared/app.config"; + +@Injectable({ + providedIn: 'root', + }) + export class HealthCheckService { + private httpClient: HttpClient; + + constructor(xhrBackend: HttpXhrBackend, public appConfig: AppConfig) { + this.httpClient = new HttpClient(xhrBackend); + } + + ApiEndpoint() { + return this.appConfig.getConfig("apiEndPoint"); + } + + check(interval:number): Observable { + let retval = new BehaviorSubject(false); + setInterval(() => { + this.httpClient.get(`${this.ApiEndpoint()}/api/v1/healthcheck`).pipe(map(() => true),catchError((error) => of(false))).toPromise().then((status) => { + retval.next(status); + }); + },interval); + return retval; + } +} \ No newline at end of file diff --git a/projects/common/src/fm/shared/accesstoken.interceptor.ts b/projects/common/src/fm/shared/accesstoken.interceptor.ts index 357aabf..94a1908 100644 --- a/projects/common/src/fm/shared/accesstoken.interceptor.ts +++ b/projects/common/src/fm/shared/accesstoken.interceptor.ts @@ -1,47 +1,45 @@ -import { Injectable, Injector, Inject } from '@angular/core'; -import { DOCUMENT } from '@angular/common' -import { AppConfig } from "./app.config"; -import { - HttpRequest, - HttpHandler, - HttpEvent, - HttpInterceptor -} from '@angular/common/http'; -import { OAuthService } from 'angular-oauth2-oidc'; -import { Observable } from 'rxjs'; - -@Injectable() -export class AccessTokenInterceptor implements HttpInterceptor { - private oauthService: OAuthService = null; - private audience: string[] = []; - private base: string; - - constructor(private injector: Injector, private appConfig: AppConfig, @Inject(DOCUMENT) private document: any) { - this.base = document.location.href; - } - - hasAudience(url: string): boolean { - let u = new URL(url,this.base); - for (let audience of this.audience) { - if (u.href.startsWith(audience)) return true; - } - return false; - } - - intercept(request: HttpRequest, next: HttpHandler): Observable> { - if (this.oauthService && this.hasAudience(request.url)) { - request = request.clone({ - setHeaders: { - Authorization: `Bearer ${this.oauthService.getAccessToken()}` - } - // Please uncomment the next line if you need to connect to the backend running in Docker. - //, url: `http://localhost:8082${request.url}` - }); - } else { - this.oauthService = this.injector.get(OAuthService, null); - if(this.oauthService && this.oauthService.issuer) this.audience = (this.appConfig.getConfig("audience") as string).split(","); - } - return next.handle(request); - } -} - +import { Injectable, Injector, Inject } from '@angular/core'; +import { DOCUMENT } from '@angular/common' +import { AppConfig } from "./app.config"; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor +} from '@angular/common/http'; +import { OAuthService } from 'angular-oauth2-oidc'; +import { Observable } from 'rxjs'; + +@Injectable() +export class AccessTokenInterceptor implements HttpInterceptor { + private oauthService: OAuthService = null; + private audience: string[] = []; + private base: string; + + constructor(private injector: Injector, private appConfig: AppConfig, @Inject(DOCUMENT) private document: any) { + this.base = document.location.href; + } + + hasAudience(url: string): boolean { + let u = new URL(url,this.base); + for (let audience of this.audience) { + if (u.href.startsWith(audience)) return true; + } + return false; + } + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + if (this.oauthService && this.hasAudience(request.url)) { + request = request.clone({ + setHeaders: { + Authorization: `Bearer ${this.oauthService.getAccessToken()}` + } + }); + } else { + this.oauthService = this.injector.get(OAuthService, null); + if(this.oauthService && this.oauthService.issuer) this.audience = (this.appConfig.getConfig("audience") as string).split(","); + } + return next.handle(request); + } +} + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index fa37eb8..d4ea6d2 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -6,4 +6,9 @@ import { Component } from '@angular/core'; }) export class AppRootComponent { title = 'FarmMaps'; + constructor() { + + window.addEventListener('online', () => console.log('came online')); + window.addEventListener('offline', () => console.log('came offline')); + } }