import { Component, OnInit, OnDestroy, Inject, Optional,ViewEncapsulation, RendererFactory2, PLATFORM_ID, ChangeDetectionStrategy, HostListener, Input } from '@angular/core'; import { Router, NavigationStart, NavigationEnd, RouteConfigLoadStart, RouteConfigLoadEnd, ActivatedRoute, PRIMARY_OUTLET } from '@angular/router'; import { Meta, Title, MetaDefinition } from '@angular/platform-browser'; import { DOCUMENT } from "@angular/common"; import { Subscription, Observable } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; import { Store, Action } from '@ngrx/store'; import { IUser } from '../../models/user'; import { OAuthService, OAuthErrorEvent } from 'angular-oauth2-oidc'; import { FM_COMMON_STARTPAGE} from '../../common.module'; //AppCommon import { IEventMessage } from '../../models/event.message'; import { IListItem } from '../../models/list.item'; import { EventService } from '../../services/event.service'; import { ItemTypeService } from '../../services/itemtype.service'; import * as commonActions from '../../actions/app-common.actions'; import { HealthCheckService } from '../../services/healthcheck.service'; import { AppConfig } from '../../shared/app.config'; import * as appReducers from '../../reducers/app-common.reducer'; @Component({ selector: 'fm-app', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush }) export class AppComponent implements OnInit, OnDestroy { // This will go at the END of your title for example "Home - Angular Universal..." <-- after the dash (-) private endPageTitle = 'Farmmaps'; // If no Title is provided, we'll use a default one before the dash(-) private defaultPageTitle = 'Farmmaps'; private routerSub$: Subscription; private eventSub$: Subscription; public currentFolder: Observable; public folderParents: Observable; public fullScreen: Observable = this.store$.select(appReducers.selectGetFullScreen); public isOnline: Observable = this.store$.select(appReducers.SelectGetIsOnline); public routeLoading: Observable = this.store$.select(appReducers.selectGetRouteLoading); public menuVisible: Observable = this.store$.select(appReducers.SelectGetMenuVisible); public accountMenuVisible: Observable = this.store$.select(appReducers.SelectGetAccountMenuVisible); public appMenuVisible: Observable = this.store$.select(appReducers.SelectGetAppMenuVisible); public notificationMenuVisible: Observable = this.store$.select(appReducers.SelectGetNotificationMenuVisible); public helpMenuVisible: Observable = this.store$.select(appReducers.SelectGetHelpMenuVisible); public unreadNotifications: Observable = this.store$.select(appReducers.SelectgetUnreadNotifications); public user: Observable = this.store$.select(appReducers.SelectGetUser); public isPageMode: Observable = this.store$.select(appReducers.SelectGetIsPageMode); @Input() showUploadProgress = true; constructor( @Optional() @Inject(FM_COMMON_STARTPAGE) public startPage: string, public router: Router, private activatedRoute$: ActivatedRoute, private title$: Title, private meta$: Meta, private store$: Store, private eventService$: EventService, private healthCheckService$: HealthCheckService, private itemTypeService$: ItemTypeService, private oauthService$: OAuthService, private appConfig$: AppConfig ) { } getActionFromEvent(event: IEventMessage): Action { let action: Action = null; console.debug(`${event.eventType} Event received`); switch (event.eventType) { case "ItemChanged": { action = new commonActions.ItemChangedEvent(event.itemCode, event.attributes); break; } case "ItemAdded": { action = new commonActions.ItemAddedEvent(event.itemCode, event.attributes); break; } case "ItemDeleted": { action = new commonActions.ItemDeletedEvent(event.itemCode, event.attributes); break; } case "taskStart": { action = new commonActions.TaskStartEvent(event.itemCode, event.attributes); break; } case "taskEnd": { action = new commonActions.TaskEndEvent(event.itemCode, event.attributes); break; } case "taskError": { action = new commonActions.TaskErrorEvent(event.itemCode, event.attributes); break; } case "taskProgress": { action = new commonActions.TaskProgressEvent(event.itemCode, event.attributes); break; } case "deviceUpdate": { action = new commonActions.DeviceUpdateEvent(event.itemCode, event.attributes); break; } case "notification": { action = new commonActions.NotificationEvent(event.attributes); break; } case "DeleteUser": { action = new commonActions.Logout(); break; } } return action; } async loadItemTypes() { await this.itemTypeService$.load(this.appConfig$) } ngOnInit() { this.InstallRouteEventHandler(); this.InstallEventServiceEventHandler(); this.InstallAuthenticationEventHandler(); this.InstallHealthCheck(); //load item types this.loadItemTypes(); } @HostListener('document:keyup', ['$event']) onKeyUp(event: KeyboardEvent) { const x = event.keyCode; if (x === 27) { this.store$.dispatch(new commonActions.Escape(true, false)); } } ngOnDestroy() { // Subscription clean-up if (this.routerSub$) this.routerSub$.unsubscribe(); if (this.eventSub$) this.eventSub$.unsubscribe(); } private InstallAuthenticationEventHandler() { // auth event handler this.oauthService$.events.subscribe((event) => { console.debug(event.type); if (event.type == 'token_error' || event.type == 'silent_refresh_timeout' || event.type == 'logout') { const e = event as OAuthErrorEvent; const p = e.params as any; if (event.type == 'silent_refresh_timeout' || event.type == 'logout' || (p.error && p.error == 'login_required')) { console.debug("Session expired"); this.router.navigate(['loggedout'], { queryParams: { redirectTo: this.router.url } }); } } if(event.type == 'token_received') { this.store$.dispatch(new commonActions.InitUser()); } }); if(this.oauthService$.hasValidAccessToken()) { this.store$.dispatch(new commonActions.InitUser()); } else { if(this.oauthService$.getRefreshToken() !=null) { this.oauthService$.refreshToken(); } } } private InstallRouteEventHandler() { const other = this; this.routerSub$ = this.router.events.subscribe(event => { if (event instanceof RouteConfigLoadStart) { other.store$.dispatch(new commonActions.StartRouteLoading()); } if (event instanceof NavigationEnd && (event.url == "/" || event.url.startsWith("/content") )) { other.store$.dispatch(new commonActions.SetPageMode(true)); } else if (event instanceof NavigationEnd) { other.store$.dispatch(new commonActions.SetPageMode(false)); } if (event instanceof RouteConfigLoadEnd) { other.store$.dispatch(new commonActions.EndRouteLoading()); } if (event instanceof NavigationStart) { other.store$.dispatch(new commonActions.SetMenuVisible(false)); } }); } private InstallEventServiceEventHandler() { const other = this; this.eventSub$ = this.eventService$.event.subscribe(event => { const action = other.getActionFromEvent(event); if (action) other.store$.dispatch(action); }); } private InstallHealthCheck() { //check health every 30 seconds this.healthCheckService$.check(30000).pipe(distinctUntilChanged()).subscribe((online) => { if (online) { this.store$.dispatch(new commonActions.Online()); } else { this.store$.dispatch(new commonActions.Offline()); } }); } handleClick(event: MouseEvent) { this.store$.dispatch(new commonActions.Escape(false, true)); } handleStopBubble(event: MouseEvent) { event.stopPropagation(); } handleToggleMenu(event: MouseEvent) { event.stopPropagation(); this.store$.dispatch(new commonActions.ToggleMenu()); } handleHome(event: MouseEvent) { this.router.navigate(['/']); } }