import { ChangeDetectionStrategy, Component, HostListener, Inject, Input, OnDestroy, OnInit, Optional, ViewEncapsulation } from '@angular/core'; import { NavigationEnd, NavigationStart, RouteConfigLoadEnd, RouteConfigLoadStart, Router } from '@angular/router'; import { Action, Store } from '@ngrx/store'; import { OAuthErrorEvent, OAuthService } from 'angular-oauth2-oidc'; import { Observable, Subscription } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; import { FM_COMMON_STARTPAGE } from '../../common.module'; import { IUser } from '../../models/user'; //AppCommon import * as commonActions from '../../actions/app-common.actions'; import { IEventMessage } from '../../models/event.message'; import { IListItem } from '../../models/list.item'; import { EventService } from '../../services/event.service'; import { HealthCheckService } from '../../services/healthcheck.service'; 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 { 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 store$: Store, private eventService$: EventService, private healthCheckService$: HealthCheckService, private oauthService$: OAuthService) { } 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; } ngOnInit() { this.InstallRouteEventHandler(); this.InstallEventServiceEventHandler(); this.InstallAuthenticationEventHandler(); this.InstallHealthCheck(); } @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.oauthService$.loadUserProfile(); 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() { this.routerSub$ = this.router.events.subscribe(event => { if (event instanceof RouteConfigLoadStart) { this.store$.dispatch(new commonActions.StartRouteLoading()); } if (event instanceof NavigationEnd && (event.url == "/" || event.url.startsWith("/content"))) { this.store$.dispatch(new commonActions.SetPageMode(true)); } else if (event instanceof NavigationEnd) { this.store$.dispatch(new commonActions.SetPageMode(false)); } if (event instanceof RouteConfigLoadEnd) { this.store$.dispatch(new commonActions.EndRouteLoading()); } if (event instanceof NavigationStart) { this.store$.dispatch(new commonActions.SetMenuVisible(false)); } }); } private InstallEventServiceEventHandler() { this.eventSub$ = this.eventService$.event.subscribe(event => { const action = this.getActionFromEvent(event); if (action) this.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() { 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() { this.router.navigate(['/']); } }