app.component.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 { env } from 'angularlib/environments/environment';
  26. import { TranslatePipe } from 'angularlib/labels/translate.pipe';
  27. @Component({
  28. selector: 'app-root',
  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. private tr = inject(TranslatePipe);
  71. protected sampleMap = {
  72. hidden:true,
  73. markers: [
  74. {position:{lat:1.55176,lng:110.33429},title:'Software Optima'}
  75. ],
  76. polygons: [
  77. {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'},
  78. {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'}
  79. ]
  80. };
  81. constructor(
  82. private router: Router,
  83. private store: Store,
  84. protected loginService: LoginService,
  85. /**Platform Browser title */
  86. protected pbTitle: Title,
  87. protected cs: ComponentService,
  88. private route: ActivatedRoute,
  89. private platform: Platform
  90. ) {
  91. super(store,cs);
  92. }
  93. @HostListener('window:mousedown')
  94. private refreshTimeout() {
  95. this.stopTimeout$.next(null);
  96. this.startTimeout$.next(null);
  97. }
  98. ngOnInit(): void {
  99. this.router.events.pipe(untilDestroy(this),
  100. filter((event) => event instanceof RoutesRecognized),
  101. map((res:any) => {
  102. const data = res.state.root.firstChild.firstChild || res.state.root.firstChild;
  103. return data.data?.title;
  104. })
  105. ).subscribe(title => {
  106. if (typeof title === 'string')
  107. this.title = title;
  108. else this.title = this.getLabel(title?.key,title?.default);
  109. if (env !== 'PROD') this.title += ` (${this.tr.transform('test','Test')})`;
  110. this.pbTitle.setTitle(this.title);
  111. });
  112. this.store.select(NOTIFICATION_STATE_TOKEN).pipe(untilDestroy(this)).subscribe({
  113. next: (state:any) => {
  114. this.notificationCount = state.notifications.length;
  115. }
  116. });
  117. if (this.platform.ANDROID || this.platform.IOS) this.pwaPrompt();
  118. }
  119. ngAfterViewInit() {
  120. /**subsribe user changes and initiate timeout timer */
  121. this.loginService.user$.pipe(untilDestroy(this)).subscribe((user:any) => {
  122. if (user) this.timeout.pipe(untilDestroy(this),takeUntil(this.loginService.loggedOut)).subscribe();
  123. this.subscribePushNotifications();
  124. });
  125. }
  126. /**
  127. * change application language
  128. * @param {string} language
  129. */
  130. protected changeLanguage(language: string) {
  131. this.store.dispatch(new ChangeLanguage(language));
  132. if (language.startsWith('en')) this.store.dispatch(new AppSettingsAction.SetLocale('en-MY'));
  133. if (language.startsWith('zh')) this.store.dispatch(new AppSettingsAction.SetLocale('zh-CN'));
  134. if (language.startsWith('ms')) this.store.dispatch(new AppSettingsAction.SetLocale('ms-MY'));
  135. }
  136. protected addNotification() {
  137. this.store.dispatch(new Notification.Add({
  138. message:{title:generateId(),desc:generateId(),timestamp: new Date()}
  139. }));
  140. }
  141. /**prompt to install PWA App */
  142. private pwaPrompt() {
  143. let installPrompt = null;
  144. const installButton = document.querySelector("#installApp");
  145. const disableInAppInstallPrompt = () => {
  146. installPrompt = null;
  147. installButton.setAttribute("hidden","");
  148. }
  149. window.addEventListener("beforeinstallprompt",(event) => {
  150. event.preventDefault();
  151. installPrompt = event;
  152. installButton.removeAttribute("hidden");
  153. });
  154. installButton.addEventListener("click", async () => {
  155. if (!installPrompt) return;
  156. const result = await installPrompt.prompt();
  157. disableInAppInstallPrompt();
  158. });
  159. window.addEventListener("appinstalled", () => {
  160. disableInAppInstallPrompt();
  161. });
  162. }
  163. private subscribePushNotifications() {
  164. if (this.loginService.user?.fisInfo) {
  165. if (this.leavePushNotif$ === undefined) {
  166. this.leavePushNotif$ = new LeavePushNotif(
  167. this,
  168. this.loginService,
  169. this.messaging,
  170. this.notification
  171. ).subscribe();
  172. }
  173. } else {
  174. if (this.leavePushNotif$) this.leavePushNotif$.unsubscribe();
  175. this.leavePushNotif$ = undefined;
  176. }
  177. }
  178. }