|
@@ -1,9 +1,30 @@
|
|
|
-import { Component, HostListener, inject, OnInit } from '@angular/core';
|
|
|
|
|
-import { ActivatedRoute, Router, RouterModule, RouterOutlet, RoutesRecognized } from '@angular/router';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ Component,
|
|
|
|
|
+ HostListener,
|
|
|
|
|
+ inject,
|
|
|
|
|
+ OnInit,
|
|
|
|
|
+ ChangeDetectionStrategy,
|
|
|
|
|
+} from '@angular/core';
|
|
|
|
|
+import {
|
|
|
|
|
+ ActivatedRoute,
|
|
|
|
|
+ Router,
|
|
|
|
|
+ RouterModule,
|
|
|
|
|
+ RouterOutlet,
|
|
|
|
|
+ RoutesRecognized,
|
|
|
|
|
+} from '@angular/router';
|
|
|
import { MatModule } from '../dependencies/angularlib/mat.module';
|
|
import { MatModule } from '../dependencies/angularlib/mat.module';
|
|
|
import { Angularlib } from 'angularlib/angularlib.module';
|
|
import { Angularlib } from 'angularlib/angularlib.module';
|
|
|
import { BaseComponent, untilDestroy } from 'angularlib/base.component';
|
|
import { BaseComponent, untilDestroy } from 'angularlib/base.component';
|
|
|
-import { Subject, Subscription, filter, map, repeat, take, takeUntil, timer } from 'rxjs';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ Subject,
|
|
|
|
|
+ Subscription,
|
|
|
|
|
+ filter,
|
|
|
|
|
+ map,
|
|
|
|
|
+ repeat,
|
|
|
|
|
+ take,
|
|
|
|
|
+ takeUntil,
|
|
|
|
|
+ timer,
|
|
|
|
|
+} from 'rxjs';
|
|
|
import { Title } from '@angular/platform-browser';
|
|
import { Title } from '@angular/platform-browser';
|
|
|
import { LoginService } from 'angularlib/login/login.service';
|
|
import { LoginService } from 'angularlib/login/login.service';
|
|
|
import { CommonModule, DatePipe } from '@angular/common';
|
|
import { CommonModule, DatePipe } from '@angular/common';
|
|
@@ -28,22 +49,21 @@ import { ChatComponent } from 'angularlib/chat/chat.component';
|
|
|
import { HttpClient } from '@angular/common/http';
|
|
import { HttpClient } from '@angular/common/http';
|
|
|
|
|
|
|
|
@Component({
|
|
@Component({
|
|
|
- selector: 'app-root',
|
|
|
|
|
- imports: [
|
|
|
|
|
- CommonModule,
|
|
|
|
|
- RouterOutlet,
|
|
|
|
|
- MatModule,
|
|
|
|
|
- RouterModule,
|
|
|
|
|
- Angularlib,
|
|
|
|
|
- NotificationModule,
|
|
|
|
|
- BusinessDataModule,
|
|
|
|
|
- ChatComponent
|
|
|
|
|
- ],
|
|
|
|
|
- providers: [DatePipe, FISMessaging],
|
|
|
|
|
- templateUrl: './app.component.html',
|
|
|
|
|
- styleUrls: [
|
|
|
|
|
- './app.component.scss'
|
|
|
|
|
- ]
|
|
|
|
|
|
|
+ selector: 'app-root',
|
|
|
|
|
+ imports: [
|
|
|
|
|
+ CommonModule,
|
|
|
|
|
+ RouterOutlet,
|
|
|
|
|
+ MatModule,
|
|
|
|
|
+ RouterModule,
|
|
|
|
|
+ Angularlib,
|
|
|
|
|
+ NotificationModule,
|
|
|
|
|
+ BusinessDataModule,
|
|
|
|
|
+ ChatComponent,
|
|
|
|
|
+ ],
|
|
|
|
|
+ providers: [DatePipe, FISMessaging],
|
|
|
|
|
+ templateUrl: './app.component.html',
|
|
|
|
|
+ changeDetection: ChangeDetectionStrategy.Eager,
|
|
|
|
|
+ styleUrls: ['./app.component.scss'],
|
|
|
})
|
|
})
|
|
|
export class AppComponent extends BaseComponent implements OnInit {
|
|
export class AppComponent extends BaseComponent implements OnInit {
|
|
|
title = 'Financial Information System';
|
|
title = 'Financial Information System';
|
|
@@ -56,15 +76,17 @@ export class AppComponent extends BaseComponent implements OnInit {
|
|
|
private startTimeout$ = new Subject();
|
|
private startTimeout$ = new Subject();
|
|
|
private stopTimeout$ = new Subject();
|
|
private stopTimeout$ = new Subject();
|
|
|
private timeout = timer(this.duration).pipe(
|
|
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$})
|
|
|
|
|
|
|
+ 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 */
|
|
/**current theme of application */
|
|
@@ -80,14 +102,34 @@ export class AppComponent extends BaseComponent implements OnInit {
|
|
|
private tr = inject(TranslatePipe);
|
|
private tr = inject(TranslatePipe);
|
|
|
|
|
|
|
|
protected sampleMap = {
|
|
protected sampleMap = {
|
|
|
- hidden:true,
|
|
|
|
|
|
|
+ hidden: true,
|
|
|
markers: [
|
|
markers: [
|
|
|
- {position:{lat:1.55176,lng:110.33429},title:'Software Optima'}
|
|
|
|
|
|
|
+ { position: { lat: 1.55176, lng: 110.33429 }, title: 'Software Optima' },
|
|
|
],
|
|
],
|
|
|
polygons: [
|
|
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'}
|
|
|
|
|
- ]
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ 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.3341 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ fillColor: 'red',
|
|
|
|
|
+ strokeColor: 'red',
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
private http = inject(HttpClient);
|
|
private http = inject(HttpClient);
|
|
@@ -102,7 +144,7 @@ export class AppComponent extends BaseComponent implements OnInit {
|
|
|
private route: ActivatedRoute,
|
|
private route: ActivatedRoute,
|
|
|
private platform: Platform
|
|
private platform: Platform
|
|
|
) {
|
|
) {
|
|
|
- super(store,cs);
|
|
|
|
|
|
|
+ super(store, cs);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@HostListener('window:mousedown')
|
|
@HostListener('window:mousedown')
|
|
@@ -113,50 +155,59 @@ export class AppComponent extends BaseComponent implements OnInit {
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
|
ngOnInit(): void {
|
|
|
// check if site is under maintenance
|
|
// check if site is under maintenance
|
|
|
- this.http.get('./config/config.json').pipe(take(1)).subscribe({
|
|
|
|
|
- next: (cfg:any) => {
|
|
|
|
|
- if (cfg?.maintenance?.active) {
|
|
|
|
|
- this.cs.dialog.showWarningDialog({
|
|
|
|
|
- title: 'Site Under Maintenance',
|
|
|
|
|
- content: `FIS is currently under maintenance.<br/>This maintenance is expected to continue until ${cfg?.maintenance?.endDatetime}.<br/>Sorry for any inconvenience caused.`,
|
|
|
|
|
- disableClose: true,
|
|
|
|
|
- hideCloseButton: true
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ this.http
|
|
|
|
|
+ .get('./config/config.json')
|
|
|
|
|
+ .pipe(take(1))
|
|
|
|
|
+ .subscribe({
|
|
|
|
|
+ next: (cfg: any) => {
|
|
|
|
|
+ if (cfg?.maintenance?.active) {
|
|
|
|
|
+ this.cs.dialog.showWarningDialog({
|
|
|
|
|
+ title: 'Site Under Maintenance',
|
|
|
|
|
+ content: `FIS is currently under maintenance.<br/>This maintenance is expected to continue until ${cfg?.maintenance?.endDatetime}.<br/>Sorry for any inconvenience caused.`,
|
|
|
|
|
+ disableClose: true,
|
|
|
|
|
+ hideCloseButton: true,
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- 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.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;
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+ 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();
|
|
if (this.platform.ANDROID || this.platform.IOS) this.pwaPrompt();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ngAfterViewInit() {
|
|
ngAfterViewInit() {
|
|
|
/**subsribe user changes and initiate timeout timer */
|
|
/**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.loginService.user$.pipe(untilDestroy(this)).subscribe((user: any) => {
|
|
|
|
|
+ if (user)
|
|
|
|
|
+ this.timeout
|
|
|
|
|
+ .pipe(untilDestroy(this), takeUntil(this.loginService.loggedOut))
|
|
|
|
|
+ .subscribe();
|
|
|
this.subscribePushNotifications();
|
|
this.subscribePushNotifications();
|
|
|
});
|
|
});
|
|
|
if (this.cs.isMobileClient) this.mobile.init();
|
|
if (this.cs.isMobileClient) this.mobile.init();
|
|
@@ -168,40 +219,49 @@ export class AppComponent extends BaseComponent implements OnInit {
|
|
|
*/
|
|
*/
|
|
|
protected changeLanguage(language: string) {
|
|
protected changeLanguage(language: string) {
|
|
|
this.store.dispatch(new ChangeLanguage(language));
|
|
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'));
|
|
|
|
|
|
|
+ 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() {
|
|
protected addNotification() {
|
|
|
- this.store.dispatch(new Notification.Add({
|
|
|
|
|
- message:{title:generateId(),desc:generateId(),timestamp: new Date()}
|
|
|
|
|
- }));
|
|
|
|
|
|
|
+ this.store.dispatch(
|
|
|
|
|
+ new Notification.Add({
|
|
|
|
|
+ message: {
|
|
|
|
|
+ title: generateId(),
|
|
|
|
|
+ desc: generateId(),
|
|
|
|
|
+ timestamp: new Date(),
|
|
|
|
|
+ },
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**prompt to install PWA App */
|
|
/**prompt to install PWA App */
|
|
|
private pwaPrompt() {
|
|
private pwaPrompt() {
|
|
|
let installPrompt = null;
|
|
let installPrompt = null;
|
|
|
- const installButton = document.querySelector("#installApp");
|
|
|
|
|
|
|
+ const installButton = document.querySelector('#installApp');
|
|
|
|
|
|
|
|
- const disableInAppInstallPrompt = () => {
|
|
|
|
|
|
|
+ const disableInAppInstallPrompt = () => {
|
|
|
installPrompt = null;
|
|
installPrompt = null;
|
|
|
- installButton.setAttribute("hidden","");
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ installButton.setAttribute('hidden', '');
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- window.addEventListener("beforeinstallprompt",(event) => {
|
|
|
|
|
|
|
+ window.addEventListener('beforeinstallprompt', (event) => {
|
|
|
event.preventDefault();
|
|
event.preventDefault();
|
|
|
installPrompt = event;
|
|
installPrompt = event;
|
|
|
- installButton.removeAttribute("hidden");
|
|
|
|
|
|
|
+ installButton.removeAttribute('hidden');
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- installButton.addEventListener("click", async () => {
|
|
|
|
|
|
|
+ installButton.addEventListener('click', async () => {
|
|
|
if (!installPrompt) return;
|
|
if (!installPrompt) return;
|
|
|
const result = await installPrompt.prompt();
|
|
const result = await installPrompt.prompt();
|
|
|
disableInAppInstallPrompt();
|
|
disableInAppInstallPrompt();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- window.addEventListener("appinstalled", () => {
|
|
|
|
|
|
|
+ window.addEventListener('appinstalled', () => {
|
|
|
disableInAppInstallPrompt();
|
|
disableInAppInstallPrompt();
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
@@ -226,13 +286,16 @@ export class AppComponent extends BaseComponent implements OnInit {
|
|
|
protected mobile = {
|
|
protected mobile = {
|
|
|
/**init mobile controls */
|
|
/**init mobile controls */
|
|
|
init: () => {
|
|
init: () => {
|
|
|
- const chatButton = document.getElementById('chat-toggle-button') as HTMLElement;
|
|
|
|
|
|
|
+ const chatButton = document.getElementById(
|
|
|
|
|
+ 'chat-toggle-button'
|
|
|
|
|
+ ) as HTMLElement;
|
|
|
if (chatButton) chatButton.style.display = 'none';
|
|
if (chatButton) chatButton.style.display = 'none';
|
|
|
},
|
|
},
|
|
|
/**toggle chat window */
|
|
/**toggle chat window */
|
|
|
toggleChat: () => {
|
|
toggleChat: () => {
|
|
|
const chat = document.getElementById('chat-panel') as HTMLElement;
|
|
const chat = document.getElementById('chat-panel') as HTMLElement;
|
|
|
- if (chat) chat.style.display = chat.style.display === 'none' ? 'flex' : 'none';
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (chat)
|
|
|
|
|
+ chat.style.display = chat.style.display === 'none' ? 'flex' : 'none';
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
}
|
|
}
|