import { Component, HostListener, inject, OnInit } from '@angular/core'; import { ActivatedRoute, Router, RouterModule, RouterOutlet, RoutesRecognized } from '@angular/router'; import { MatModule } from '../dependencies/angularlib/mat.module'; import { Angularlib } from 'angularlib/angularlib.module'; import { BaseComponent, untilDestroy } from 'angularlib/base.component'; import { Subject, Subscription, filter, map, repeat, takeUntil, timer } from 'rxjs'; import { Title } from '@angular/platform-browser'; import { LoginService } from 'angularlib/login/login.service'; import { CommonModule, DatePipe } from '@angular/common'; import { ChangeLanguage } from 'angularlib/labels/label.actions'; import { ComponentService } from 'angularlib/component.service'; import { NotificationModule } from 'angularlib/notification/notification.module'; import { NOTIFICATION_STATE_TOKEN } from 'angularlib/notification/notification.state'; import { Notification } from 'angularlib/notification/notification.actions'; import { generateId } from 'angularlib/base.service'; import { Store } from '@ngxs/store'; import config from '../config/config.json'; import { UIAuthActions } from 'angularlib/login/state/login.actions'; import { Platform } from '@angular/cdk/platform'; import { AppSettingsAction } from 'angularlib/ui.state/ui.state.actions'; import { PushNotificationDecorator as LeavePushNotif } from 'fis/leave/decorators/push.notification.decorator'; import { FISMessaging } from 'fis/index'; import { BusinessDataModule } from 'fis/business.data/business.data.module'; import { NotificationService } from 'angularlib/notification/notification.service'; import { env } from 'angularlib/environments/environment'; import { TranslatePipe } from 'angularlib/labels/translate.pipe'; @Component({ selector: 'app-root', imports: [ CommonModule, RouterOutlet, MatModule, RouterModule, Angularlib, NotificationModule, BusinessDataModule, ], providers: [DatePipe, FISMessaging], templateUrl: './app.component.html', styleUrls: [ './app.component.scss' ] }) export class AppComponent extends BaseComponent implements OnInit { title = 'Financial Information System'; /**current date */ protected currentDate = new Date(); /**session timeout duration in milliseconds*/ private duration: number = config?.sessionTimeoutDuration; private startTimeout$ = new Subject(); private stopTimeout$ = new Subject(); private timeout = timer(this.duration).pipe( map(() => { if(this.loginService.user){ console.warn('session inactive timeout, logging out...'); this.store.dispatch(new UIAuthActions.RedirectAfterLogin(this.route.snapshot)); this.loginService.logout(); } }), takeUntil(this.stopTimeout$), repeat({delay:() => this.startTimeout$}) ); /**current theme of application */ protected theme; /**number of notifications */ protected notificationCount: number = 0; private leavePushNotif$: Subscription; private messaging = inject(FISMessaging); private notification = inject(NotificationService); private tr = inject(TranslatePipe); protected sampleMap = { hidden:true, markers: [ {position:{lat:1.55176,lng:110.33429},title:'Software Optima'} ], polygons: [ {paths: [{lat:1.551703,lng:110.334149},{lat:1.551703,lng:110.334409},{lat:1.55222,lng:110.33444},{lat:1.552223,lng:110.33417}],fillColor: "blue",strokeColor:'navy'}, {paths: [{lat:1.55222,lng:110.33413},{lat:1.55224,lng:110.33375},{lat:1.551432,lng:110.333715},{lat:1.551404,lng:110.334387},{lat:1.551685,lng:110.334395},{lat:1.551704,lng:110.334100}],fillColor: "red",strokeColor:'red'} ] }; constructor( private router: Router, private store: Store, protected loginService: LoginService, /**Platform Browser title */ protected pbTitle: Title, protected cs: ComponentService, private route: ActivatedRoute, private platform: Platform ) { super(store,cs); } @HostListener('window:mousedown') private refreshTimeout() { this.stopTimeout$.next(null); this.startTimeout$.next(null); } ngOnInit(): void { this.router.events.pipe(untilDestroy(this), filter((event) => event instanceof RoutesRecognized), map((res:any) => { const data = res.state.root.firstChild.firstChild || res.state.root.firstChild; return data.data?.title; }) ).subscribe(title => { if (typeof title === 'string') this.title = title; else this.title = this.getLabel(title?.key,title?.default); if (env !== 'PROD') this.title += ` (${this.tr.transform('test','Test')})`; this.pbTitle.setTitle(this.title); }); this.store.select(NOTIFICATION_STATE_TOKEN).pipe(untilDestroy(this)).subscribe({ next: (state:any) => { this.notificationCount = state.notifications.length; } }); if (this.platform.ANDROID || this.platform.IOS) this.pwaPrompt(); } ngAfterViewInit() { /**subsribe user changes and initiate timeout timer */ this.loginService.user$.pipe(untilDestroy(this)).subscribe((user:any) => { if (user) this.timeout.pipe(untilDestroy(this),takeUntil(this.loginService.loggedOut)).subscribe(); this.subscribePushNotifications(); }); } /** * change application language * @param {string} language */ protected changeLanguage(language: string) { this.store.dispatch(new ChangeLanguage(language)); if (language.startsWith('en')) this.store.dispatch(new AppSettingsAction.SetLocale('en-MY')); if (language.startsWith('zh')) this.store.dispatch(new AppSettingsAction.SetLocale('zh-CN')); if (language.startsWith('ms')) this.store.dispatch(new AppSettingsAction.SetLocale('ms-MY')); } protected addNotification() { this.store.dispatch(new Notification.Add({ message:{title:generateId(),desc:generateId(),timestamp: new Date()} })); } /**prompt to install PWA App */ private pwaPrompt() { let installPrompt = null; const installButton = document.querySelector("#installApp"); const disableInAppInstallPrompt = () => { installPrompt = null; installButton.setAttribute("hidden",""); } window.addEventListener("beforeinstallprompt",(event) => { event.preventDefault(); installPrompt = event; installButton.removeAttribute("hidden"); }); installButton.addEventListener("click", async () => { if (!installPrompt) return; const result = await installPrompt.prompt(); disableInAppInstallPrompt(); }); window.addEventListener("appinstalled", () => { disableInAppInstallPrompt(); }); } private subscribePushNotifications() { if (this.loginService.user?.fisInfo) { if (this.leavePushNotif$ === undefined) { this.leavePushNotif$ = new LeavePushNotif( this, this.loginService, this.messaging, this.notification ).subscribe(); } } else { if (this.leavePushNotif$) this.leavePushNotif$.unsubscribe(); this.leavePushNotif$ = undefined; } } }