Bläddra i källkod

update to Angular 22.0.2

tigger 2 veckor sedan
förälder
incheckning
a7b2aac5ec

+ 3 - 6
.browserslistrc

@@ -8,10 +8,7 @@
 # You can see what browsers were selected by your queries by running:
 #   npx browserslist
 
-last 2 Chrome versions
-last 2 Firefox versions
-last 2 Edge versions
-last 2 Safari versions
-Safari >= 13
-iOS >= 13
+last 2 versions
+Safari >= 14.1
+iOS >= 14.5
 not dead

+ 17 - 16
package.json

@@ -16,18 +16,18 @@
   },
   "private": true,
   "dependencies": {
-    "@angular/animations": "^21.1.4",
-    "@angular/cdk": "^21.1.4",
-    "@angular/common": "^21.1.4",
-    "@angular/compiler": "^21.1.4",
-    "@angular/core": "^21.1.4",
-    "@angular/forms": "^21.1.4",
-    "@angular/material": "^21.1.4",
-    "@angular/material-moment-adapter": "^21.1.4",
-    "@angular/platform-browser": "^21.1.4",
-    "@angular/platform-browser-dynamic": "^21.1.4",
-    "@angular/router": "^21.1.4",
-    "@angular/service-worker": "^21.1.4",
+    "@angular/animations": "^22.0.2",
+    "@angular/cdk": "^22.0.2",
+    "@angular/common": "^22.0.2",
+    "@angular/compiler": "^22.0.2",
+    "@angular/core": "^22.0.2",
+    "@angular/forms": "^22.0.2",
+    "@angular/material": "^22.0.2",
+    "@angular/material-moment-adapter": "^22.0.2",
+    "@angular/platform-browser": "^22.0.2",
+    "@angular/platform-browser-dynamic": "^22.0.2",
+    "@angular/router": "^22.0.2",
+    "@angular/service-worker": "^22.0.2",
     "@ngxs/devtools-plugin": "^20.1.0",
     "@ngxs/form-plugin": "^20.1.0",
     "@ngxs/storage-plugin": "^20.1.0",
@@ -43,16 +43,17 @@
     "zone.js": "^0.15.1"
   },
   "devDependencies": {
-    "@angular/build": "^21.1.4",
-    "@angular/cli": "^21.1.4",
-    "@angular/compiler-cli": "^21.1.4",
+    "@angular/build": "^22.0.3",
+    "@angular/cli": "^22.0.3",
+    "@angular/compiler-cli": "^22.0.2",
     "@types/jasmine": "~5.1.0",
+    "istanbul-lib-instrument": "^6.0.3",
     "jasmine-core": "~5.1.0",
     "karma": "~6.4.0",
     "karma-chrome-launcher": "~3.2.0",
     "karma-coverage": "~2.2.0",
     "karma-jasmine": "~5.1.0",
     "karma-jasmine-html-reporter": "~2.1.0",
-    "typescript": "~5.9.3"
+    "typescript": "~6.0.3"
   }
 }

+ 151 - 88
src/app/app.component.ts

@@ -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 { Angularlib } from 'angularlib/angularlib.module';
 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 { LoginService } from 'angularlib/login/login.service';
 import { CommonModule, DatePipe } from '@angular/common';
@@ -28,22 +49,21 @@ import { ChatComponent } from 'angularlib/chat/chat.component';
 import { HttpClient } from '@angular/common/http';
 
 @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 {
   title = 'Financial Information System';
@@ -56,15 +76,17 @@ export class AppComponent extends BaseComponent implements OnInit {
   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$})
+    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 */
@@ -80,14 +102,34 @@ export class AppComponent extends BaseComponent implements OnInit {
   private tr = inject(TranslatePipe);
 
   protected sampleMap = {
-    hidden:true,
+    hidden: true,
     markers: [
-      {position:{lat:1.55176,lng:110.33429},title:'Software Optima'}
+      { 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'}
-    ]
+      {
+        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);
@@ -102,7 +144,7 @@ export class AppComponent extends BaseComponent implements OnInit {
     private route: ActivatedRoute,
     private platform: Platform
   ) {
-    super(store,cs);
+    super(store, cs);
   }
 
   @HostListener('window:mousedown')
@@ -113,50 +155,59 @@ export class AppComponent extends BaseComponent implements OnInit {
 
   ngOnInit(): void {
     // 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();
   }
 
   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.loginService.user$.pipe(untilDestroy(this)).subscribe((user: any) => {
+      if (user)
+        this.timeout
+          .pipe(untilDestroy(this), takeUntil(this.loginService.loggedOut))
+          .subscribe();
       this.subscribePushNotifications();
     });
     if (this.cs.isMobileClient) this.mobile.init();
@@ -168,40 +219,49 @@ export class AppComponent extends BaseComponent implements OnInit {
    */
   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'));
+    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()}
-    }));
+    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 installButton = document.querySelector('#installApp');
 
-    const disableInAppInstallPrompt = () =>  {
+    const disableInAppInstallPrompt = () => {
       installPrompt = null;
-      installButton.setAttribute("hidden","");
-    }
+      installButton.setAttribute('hidden', '');
+    };
 
-    window.addEventListener("beforeinstallprompt",(event) => {
+    window.addEventListener('beforeinstallprompt', (event) => {
       event.preventDefault();
       installPrompt = event;
-      installButton.removeAttribute("hidden");
+      installButton.removeAttribute('hidden');
     });
 
-    installButton.addEventListener("click", async () => {
+    installButton.addEventListener('click', async () => {
       if (!installPrompt) return;
       const result = await installPrompt.prompt();
       disableInAppInstallPrompt();
     });
 
-    window.addEventListener("appinstalled", () => {
+    window.addEventListener('appinstalled', () => {
       disableInAppInstallPrompt();
     });
   }
@@ -226,13 +286,16 @@ export class AppComponent extends BaseComponent implements OnInit {
   protected mobile = {
     /**init mobile controls */
     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';
     },
     /**toggle chat window */
     toggleChat: () => {
       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';
+    },
+  };
 }

+ 21 - 9
src/app/app.config.ts

@@ -1,7 +1,11 @@
 import { ApplicationConfig, importProvidersFrom } from '@angular/core';
-import { provideRouter, withHashLocation, withRouterConfig } from '@angular/router';
+import {
+  provideRouter,
+  withHashLocation,
+  withRouterConfig,
+} from '@angular/router';
 import { routes } from './app.routes';
-import { provideHttpClient } from '@angular/common/http';
+import { provideHttpClient, withXhr } from '@angular/common/http';
 import { BrowserModule } from '@angular/platform-browser';
 import { DpModule } from 'dp-ui/dp.module';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@@ -9,23 +13,31 @@ import { Angularlib } from 'angularlib/angularlib.module';
 import { provideStore } from '@ngxs/store';
 import { withNgxsReduxDevtoolsPlugin } from '@ngxs/devtools-plugin';
 import { withNgxsStoragePlugin } from '@ngxs/storage-plugin';
-import { provideServiceWorker} from '@angular/service-worker';
+import { provideServiceWorker } from '@angular/service-worker';
 import { LoginModule } from 'angularlib/login';
 
 export const appConfig: ApplicationConfig = {
   providers: [
     importProvidersFrom(BrowserModule),
     importProvidersFrom(BrowserAnimationsModule),
-    provideStore([],withNgxsStoragePlugin({keys:'*'}),withNgxsReduxDevtoolsPlugin()),
+    provideStore(
+      [],
+      withNgxsStoragePlugin({ keys: '*' }),
+      withNgxsReduxDevtoolsPlugin()
+    ),
     importProvidersFrom(DpModule),
     importProvidersFrom(Angularlib),
     importProvidersFrom(LoginModule),
-    provideRouter(routes,withHashLocation(),withRouterConfig({onSameUrlNavigation:'reload'})),
-    provideHttpClient(), 
+    provideRouter(
+      routes,
+      withHashLocation(),
+      withRouterConfig({ onSameUrlNavigation: 'reload' })
+    ),
+    provideHttpClient(withXhr()),
     provideServiceWorker('ngsw-worker.js', {
       enabled: true,
-      registrationStrategy: 'registerImmediately'
+      registrationStrategy: 'registerImmediately',
       // registrationStrategy: 'registerWhenStable:30000'
-    })
-  ]
+    }),
+  ],
 };

+ 72 - 74
src/app/dashboard/dashboard.component.html

@@ -1,80 +1,78 @@
 <main class="main" [ngClass]="cs.theme">
-    <div class="content">
-      <div class="left">
+  <div class="content">
+    <div class="left"></div>
+    <!--<div class="divider" role="separator" aria-label="Divider"></div>-->
+    <div class="center">
+      @if (!loginService.user?.token?.ucp) {
+      <div class="header">
+        <img
+          id="site-logo"
+          src="https://cdn.swopt.com/fis/image/fis-logo.webp"
+          alt="FIS"
+        />
+        <!--<h1>{{'welcome'|tr:'Welcome'}}</h1>-->
       </div>
-      <!--<div class="divider" role="separator" aria-label="Divider"></div>-->
-      <div class="center">
-        @if (!loginService.user?.token?.ucp) {
-          <div class="header">
-            <img id="site-logo" src="https://cdn.swopt.com/fis/image/fis-logo.webp" alt="FIS"/>
-            <!--<h1>{{'welcome'|tr:'Welcome'}}</h1>-->
-          </div>
-          <div class="login">
-            <inputx [field]="goto.field" [value]="goto.value" (onChange)="goto.onChange($event)"></inputx>
-            <login/>
-          </div>
-        } @else {
-          <div class="segment">
-            <h3>{{'eleave'|tr:'eLeave'}}</h3>
-            <mat-divider></mat-divider>
-            <div class="dashitems">
-              <leave-submission-dashitem></leave-submission-dashitem>
-              @if (accessRight.leave?.approval|async) {
-                <leave-approval-dashitem></leave-approval-dashitem>
-              }
-              <leave-info-dashitem></leave-info-dashitem>
-            </div>
-          </div>
-          <div class="segment">
-            <h3>{{'spts'|tr:'SPTS'}}</h3>
-            <mat-divider></mat-divider>
-            <div class="dashitems">
-              <sales-tender-submission-dashitem></sales-tender-submission-dashitem>
-            </div>
-          </div>
-        }
-        <div class="social-links">
-          
-          <a
-            aria-label="Twitter"
-            target="_blank"
-            rel="noopener"
+      <div class="login">
+        <inputx
+          [field]="goto.field"
+          [value]="goto.value"
+          (onChange)="goto.onChange($event)"
+        ></inputx>
+        <login />
+      </div>
+      } @else {
+      <div class="segment">
+        <h3>{{ "eleave" | tr : "eLeave" }}</h3>
+        <mat-divider></mat-divider>
+        <div class="dashitems">
+          <leave-submission-dashitem></leave-submission-dashitem>
+          @if ($safeNavigationMigration(accessRight.leave?.approval)|async) {
+          <leave-approval-dashitem></leave-approval-dashitem>
+          }
+          <leave-info-dashitem></leave-info-dashitem>
+        </div>
+      </div>
+      <div class="segment">
+        <h3>{{ "spts" | tr : "SPTS" }}</h3>
+        <mat-divider></mat-divider>
+        <div class="dashitems">
+          <sales-tender-submission-dashitem></sales-tender-submission-dashitem>
+        </div>
+      </div>
+      }
+      <div class="social-links">
+        <a aria-label="Twitter" target="_blank" rel="noopener">
+          <svg
+            width="24"
+            height="24"
+            viewBox="0 0 24 24"
+            fill="none"
+            xmlns="http://www.w3.org/2000/svg"
+            alt="Twitter"
           >
-            <svg
-              width="24"
-              height="24"
-              viewBox="0 0 24 24"
-              fill="none"
-              xmlns="http://www.w3.org/2000/svg"
-              alt="Twitter"
-            >
-              <path
-                d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"
-              />
-            </svg>
-          </a>
-          <a
-            aria-label="Youtube"
-            target="_blank"
-            rel="noopener"
+            <path
+              d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"
+            />
+          </svg>
+        </a>
+        <a aria-label="Youtube" target="_blank" rel="noopener">
+          <svg
+            width="29"
+            height="20"
+            viewBox="0 0 29 20"
+            fill="none"
+            xmlns="http://www.w3.org/2000/svg"
+            alt="Youtube"
           >
-            <svg
-              width="29"
-              height="20"
-              viewBox="0 0 29 20"
-              fill="none"
-              xmlns="http://www.w3.org/2000/svg"
-              alt="Youtube"
-            >
-              <path
-                fill-rule="evenodd"
-                clip-rule="evenodd"
-                d="M27.4896 1.52422C27.9301 1.96749 28.2463 2.51866 28.4068 3.12258C29.0004 5.35161 29.0004 10 29.0004 10C29.0004 10 29.0004 14.6484 28.4068 16.8774C28.2463 17.4813 27.9301 18.0325 27.4896 18.4758C27.0492 18.9191 26.5 19.2389 25.8972 19.4032C23.6778 20 14.8068 20 14.8068 20C14.8068 20 5.93586 20 3.71651 19.4032C3.11363 19.2389 2.56449 18.9191 2.12405 18.4758C1.68361 18.0325 1.36732 17.4813 1.20683 16.8774C0.613281 14.6484 0.613281 10 0.613281 10C0.613281 10 0.613281 5.35161 1.20683 3.12258C1.36732 2.51866 1.68361 1.96749 2.12405 1.52422C2.56449 1.08095 3.11363 0.76113 3.71651 0.596774C5.93586 0 14.8068 0 14.8068 0C14.8068 0 23.6778 0 25.8972 0.596774C26.5 0.76113 27.0492 1.08095 27.4896 1.52422ZM19.3229 10L11.9036 5.77905V14.221L19.3229 10Z"
-              />
-            </svg>
-          </a>
-        </div>
+            <path
+              fill-rule="evenodd"
+              clip-rule="evenodd"
+              d="M27.4896 1.52422C27.9301 1.96749 28.2463 2.51866 28.4068 3.12258C29.0004 5.35161 29.0004 10 29.0004 10C29.0004 10 29.0004 14.6484 28.4068 16.8774C28.2463 17.4813 27.9301 18.0325 27.4896 18.4758C27.0492 18.9191 26.5 19.2389 25.8972 19.4032C23.6778 20 14.8068 20 14.8068 20C14.8068 20 5.93586 20 3.71651 19.4032C3.11363 19.2389 2.56449 18.9191 2.12405 18.4758C1.68361 18.0325 1.36732 17.4813 1.20683 16.8774C0.613281 14.6484 0.613281 10 0.613281 10C0.613281 10 0.613281 5.35161 1.20683 3.12258C1.36732 2.51866 1.68361 1.96749 2.12405 1.52422C2.56449 1.08095 3.11363 0.76113 3.71651 0.596774C5.93586 0 14.8068 0 14.8068 0C14.8068 0 23.6778 0 25.8972 0.596774C26.5 0.76113 27.0492 1.08095 27.4896 1.52422ZM19.3229 10L11.9036 5.77905V14.221L19.3229 10Z"
+            />
+          </svg>
+        </a>
       </div>
-      <div class="right"></div>
     </div>
-  </main>
+    <div class="right"></div>
+  </div>
+</main>

+ 68 - 39
src/app/dashboard/dashboard.component.ts

@@ -1,4 +1,11 @@
-import { Component, computed, inject, OnInit, Signal } from '@angular/core';
+import {
+  Component,
+  computed,
+  inject,
+  OnInit,
+  Signal,
+  ChangeDetectionStrategy,
+} from '@angular/core';
 import { RouterModule } from '@angular/router';
 import { BaseComponent, untilDestroy } from 'angularlib/base.component';
 import { LoginModule } from 'angularlib/login';
@@ -16,22 +23,23 @@ import { TenderModule } from 'fis/tender/tender.module';
 import { FISAccess } from 'fis/fis.access';
 
 @Component({
-    selector: 'spts-sales-submission-dashitem',
-    imports: [
-        CommonModule,
-        RouterModule,
-        MatModule,
-        LoginModule,
-        LabelModule,
-        InputModule,
-        LeaveModule,
-        TenderModule
-    ],
-    providers: [ComponentService],
-    templateUrl: './dashboard.component.html',
-    styleUrl: './dashboard.component.scss'
+  selector: 'spts-sales-submission-dashitem',
+  imports: [
+    CommonModule,
+    RouterModule,
+    MatModule,
+    LoginModule,
+    LabelModule,
+    InputModule,
+    LeaveModule,
+    TenderModule,
+  ],
+  providers: [ComponentService],
+  templateUrl: './dashboard.component.html',
+  changeDetection: ChangeDetectionStrategy.Eager,
+  styleUrl: './dashboard.component.scss',
 })
-export class DashboardComponent extends BaseComponent implements OnInit{
+export class DashboardComponent extends BaseComponent implements OnInit {
   protected masterMenu = masterMenu;
   protected username: Signal<string> = computed(() => {
     const GIVEN_NAME = this.loginService?.userSignal()?.name?.givenName;
@@ -39,43 +47,53 @@ export class DashboardComponent extends BaseComponent implements OnInit{
     return GIVEN_NAME || FIS_NAME;
   });
   protected access = inject(FISAccess);
-  protected accessRight:any = {};
+  protected accessRight: any = {};
 
   protected goto = {
     field: {
       key: 'goto',
       type: 'select',
-      label: {key:'will_redirect_to',default:'Go to'},
+      label: { key: 'will_redirect_to', default: 'Go to' },
       selectOptions: [
-        {value:'home',label:{key:'home_page',default:'Home'}},
-        {value:'leave-new',label:{key:'new_leave',default:'Apply New Leave'}},
-        {value:'leave-applied',label:{key:'applied_leave',default:'Applied Leave'}},
-        {value:'leave-approval',label:{key:'leave_approval',default:'Leave Approval'}},
-      ]
+        { value: 'home', label: { key: 'home_page', default: 'Home' } },
+        {
+          value: 'leave-new',
+          label: { key: 'new_leave', default: 'Apply New Leave' },
+        },
+        {
+          value: 'leave-applied',
+          label: { key: 'applied_leave', default: 'Applied Leave' },
+        },
+        {
+          value: 'leave-approval',
+          label: { key: 'leave_approval', default: 'Leave Approval' },
+        },
+      ],
     },
     value: 'home',
     onChange: (event: EventI) => {
       switch (event?.payload?.value) {
-        case 'leave-new' : {
-          this.cs.navigate('/leave',{type:'new'});
+        case 'leave-new': {
+          this.cs.navigate('/leave', { type: 'new' });
           break;
         }
-        case 'leave-applied' : {
-          this.cs.navigate('/leave',{type:'view'});
+        case 'leave-applied': {
+          this.cs.navigate('/leave', { type: 'view' });
           break;
         }
-        case 'leave-approval' : {
+        case 'leave-approval': {
           this.cs.navigate('/leave/approval');
           break;
         }
-        case 'spts-sales' : {
-          this.cs.navigate('/tender',{type:'sales'});
+        case 'spts-sales': {
+          this.cs.navigate('/tender', { type: 'sales' });
           break;
         }
-        default: break;
+        default:
+          break;
       }
-    }
-  }
+    },
+  };
 
   constructor(
     protected store: Store,
@@ -88,15 +106,26 @@ export class DashboardComponent extends BaseComponent implements OnInit{
   ngOnInit(): void {
     super.ngOnInit();
   }
-  
+
   ngAfterViewInit() {
     this.loginService.user$.pipe(untilDestroy(this)).subscribe({
-      next: res => {
+      next: (res) => {
         this.accessRight = {
           ...this.accessRight,
-          leave: {approval: this.access.canActivate({data:{serviceId:'09 - Leave Application',accessRight:['canread','canapprove'],noprompt:true}},undefined)}
+          leave: {
+            approval: this.access.canActivate(
+              {
+                data: {
+                  serviceId: '09 - Leave Application',
+                  accessRight: ['canread', 'canapprove'],
+                  noprompt: true,
+                },
+              },
+              undefined
+            ),
+          },
         };
-      }
-    })
+      },
+    });
   }
-}
+}

+ 1 - 1
src/dependencies/angularlib

@@ -1 +1 @@
-Subproject commit f6ea88c741f73775ba9faf7e6992326acbad7dc5
+Subproject commit 2bb11827b923092839958136cccff70fe0fce16d

+ 1 - 1
src/dependencies/fis

@@ -1 +1 @@
-Subproject commit f79e605bfe63873846a0332ff24c05e9ba250873
+Subproject commit 3124f8b6d7ad8bd54ebaaa49b083a2bede41c6b3

+ 11 - 7
tsconfig.app.json

@@ -5,9 +5,7 @@
     "outDir": "./out-tsc/app",
     "types": []
   },
-  "files": [
-    "src/main.ts"
-  ],
+  "files": ["src/main.ts"],
   "include": [
     "src/**/*.d.ts",
     "src/**/fisappmessagejsdist/src/config/*.ts",
@@ -24,9 +22,15 @@
     "src/**/fisappmessagejsdist/src/types/*.ts",
     "src/**/fisappmessagejsdist/src/types/**/*.ts",
     "src/**/fisappmessagejsdist/src/utils/*.ts",
-    "src/**/fisappmessagejsdist/src/utils/**/*.ts",
+    "src/**/fisappmessagejsdist/src/utils/**/*.ts"
   ],
-  "exclude": [
-    "src/**/fisappmessagejsdist/src/schema/*.bat",
-  ]
+  "exclude": ["src/**/fisappmessagejsdist/src/schema/*.bat"],
+  "angularCompilerOptions": {
+    "extendedDiagnostics": {
+      "checks": {
+        "nullishCoalescingNotNullable": "suppress",
+        "optionalChainNotNullable": "suppress"
+      }
+    }
+  }
 }

+ 1 - 0
tsconfig.json

@@ -27,6 +27,7 @@
     "useDefineForClassFields": false,
     "resolveJsonModule": true,
     "baseUrl": "./",
+    "ignoreDeprecations": "6.0",
     "paths": {
       "fis-commons/*": [
         "src/dependencies/fis-commons/*"

+ 10 - 7
tsconfig.spec.json

@@ -3,12 +3,15 @@
   "extends": "./tsconfig.json",
   "compilerOptions": {
     "outDir": "./out-tsc/spec",
-    "types": [
-      "jasmine"
-    ]
+    "types": ["jasmine"]
   },
-  "include": [
-    "src/**/*.spec.ts",
-    "src/**/*.d.ts"
-  ]
+  "include": ["src/**/*.spec.ts", "src/**/*.d.ts"],
+  "angularCompilerOptions": {
+    "extendedDiagnostics": {
+      "checks": {
+        "nullishCoalescingNotNullable": "suppress",
+        "optionalChainNotNullable": "suppress"
+      }
+    }
+  }
 }