app.component.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import { Component, HostListener, inject, OnInit } from '@angular/core';
  2. import { ActivatedRoute, Router, RouterModule, RouterOutlet, RoutesRecognized } from '@angular/router';
  3. import { MatModule } from '../dependencies/angularlib/mat.module';
  4. import { Angularlib } from 'angularlib/angularlib.module';
  5. import { BaseComponent, untilDestroy } from 'angularlib/base.component';
  6. import { Subject, Subscription, filter, map, repeat, takeUntil, timer } from 'rxjs';
  7. import { Title } from '@angular/platform-browser';
  8. import { LoginService } from 'angularlib/login/login.service';
  9. import { CommonModule, DatePipe } from '@angular/common';
  10. import { ChangeLanguage } from 'angularlib/labels/label.actions';
  11. import { ComponentService } from 'angularlib/component.service';
  12. import { NotificationModule } from 'angularlib/notification/notification.module';
  13. import { NOTIFICATION_STATE_TOKEN } from 'angularlib/notification/notification.state';
  14. import { Notification } from 'angularlib/notification/notification.actions';
  15. import { generateId } from 'angularlib/base.service';
  16. import { Store } from '@ngxs/store';
  17. import config from '../config/config.json';
  18. import { UIAuthActions } from 'angularlib/login/state/login.actions';
  19. import { Platform } from '@angular/cdk/platform';
  20. import { AppSettingsAction } from 'angularlib/ui.state/ui.state.actions';
  21. import { PushNotificationDecorator as LeavePushNotif } from 'fis/leave/decorators/push.notification.decorator';
  22. import { FISMessaging } from 'fis/index';
  23. import { BusinessDataModule } from 'fis/business.data/business.data.module';
  24. import { NotificationService } from 'angularlib/notification/notification.service';
  25. import { DecoratorSubject } from 'fis-commons/decorator';
  26. @Component({
  27. selector: 'app-root',
  28. standalone: true,
  29. imports: [
  30. CommonModule,
  31. RouterOutlet,
  32. MatModule,
  33. RouterModule,
  34. Angularlib,
  35. NotificationModule,
  36. BusinessDataModule
  37. ],
  38. providers:[DatePipe,FISMessaging],
  39. templateUrl: './app.component.html',
  40. styleUrls: [
  41. './app.component.scss'
  42. ]
  43. })
  44. export class AppComponent extends BaseComponent implements OnInit {
  45. title = 'Financial Information System';
  46. /**current date */
  47. protected currentDate = new Date();
  48. /**session timeout duration in milliseconds*/
  49. private duration: number = config?.sessionTimeoutDuration;
  50. private startTimeout$ = new Subject();
  51. private stopTimeout$ = new Subject();
  52. private timeout = timer(this.duration).pipe(
  53. map(() => {
  54. if(this.loginService.user){
  55. console.warn('session inactive timeout, logging out...');
  56. this.store.dispatch(new UIAuthActions.RedirectAfterLogin(this.route.snapshot));
  57. this.loginService.logout();
  58. }
  59. }),
  60. takeUntil(this.stopTimeout$),
  61. repeat({delay:() => this.startTimeout$})
  62. );
  63. /**current theme of application */
  64. protected theme;
  65. /**number of notifications */
  66. protected notificationCount: number = 0;
  67. private leavePushNotif$: Subscription;
  68. private messaging = inject(FISMessaging);
  69. private notification = inject(NotificationService);
  70. constructor(
  71. private router: Router,
  72. private store: Store,
  73. protected loginService: LoginService,
  74. /**Platform Browser title */
  75. protected pbTitle: Title,
  76. protected cs: ComponentService,
  77. private route: ActivatedRoute,
  78. private platform: Platform
  79. ) {
  80. super(store,cs);
  81. }
  82. @HostListener('window:mousedown')
  83. private refreshTimeout() {
  84. this.stopTimeout$.next(null);
  85. this.startTimeout$.next(null);
  86. }
  87. ngOnInit(): void {
  88. this.router.events.pipe(untilDestroy(this),
  89. filter((event) => event instanceof RoutesRecognized),
  90. map((res:any) => {
  91. const data = res.state.root.firstChild.firstChild || res.state.root.firstChild;
  92. return data.data?.title;
  93. })
  94. ).subscribe(title => {
  95. if (typeof title === 'string')
  96. this.title = title;
  97. else this.title = this.getLabel(title?.key,title?.default);
  98. this.pbTitle.setTitle(this.title);
  99. });
  100. this.store.select(NOTIFICATION_STATE_TOKEN).pipe(untilDestroy(this)).subscribe({
  101. next: (state:any) => {
  102. this.notificationCount = state.notifications.length;
  103. }
  104. });
  105. if (this.platform.ANDROID || this.platform.IOS) this.pwaPrompt();
  106. }
  107. ngAfterViewInit() {
  108. /**subsribe user changes and initiate timeout timer */
  109. this.loginService.user$.pipe(untilDestroy(this)).subscribe((user:any) => {
  110. if (user) this.timeout.pipe(untilDestroy(this),takeUntil(this.loginService.loggedOut)).subscribe();
  111. this.subscribePushNotifications();
  112. });
  113. }
  114. /**
  115. * change application language
  116. * @param {string} language
  117. */
  118. protected changeLanguage(language: string) {
  119. this.store.dispatch(new ChangeLanguage(language));
  120. if (language.startsWith('en')) this.store.dispatch(new AppSettingsAction.SetLocale('en-MY'));
  121. if (language.startsWith('zh')) this.store.dispatch(new AppSettingsAction.SetLocale('zh-CN'));
  122. if (language.startsWith('ms')) this.store.dispatch(new AppSettingsAction.SetLocale('ms-MY'));
  123. }
  124. protected addNotification() {
  125. this.store.dispatch(new Notification.Add({
  126. message:{title:generateId(),desc:generateId(),timestamp: new Date()}
  127. }));
  128. }
  129. /**prompt to install PWA App */
  130. private pwaPrompt() {
  131. let installPrompt = null;
  132. const installButton = document.querySelector("#installApp");
  133. const disableInAppInstallPrompt = () => {
  134. installPrompt = null;
  135. installButton.setAttribute("hidden","");
  136. }
  137. window.addEventListener("beforeinstallprompt",(event) => {
  138. event.preventDefault();
  139. installPrompt = event;
  140. installButton.removeAttribute("hidden");
  141. });
  142. installButton.addEventListener("click", async () => {
  143. if (!installPrompt) return;
  144. const result = await installPrompt.prompt();
  145. disableInAppInstallPrompt();
  146. });
  147. window.addEventListener("appinstalled", () => {
  148. disableInAppInstallPrompt();
  149. });
  150. }
  151. private subscribePushNotifications() {
  152. if (this.loginService.user?.fisInfo) {
  153. if (this.leavePushNotif$ === undefined) {
  154. this.leavePushNotif$ = new LeavePushNotif(
  155. this,
  156. this.loginService,
  157. this.messaging,
  158. this.notification
  159. ).subscribe();
  160. }
  161. } else {
  162. if (this.leavePushNotif$) this.leavePushNotif$.unsubscribe();
  163. this.leavePushNotif$ = undefined;
  164. }
  165. }
  166. }