فهرست منبع

m3 theming enhancements

tigger 1 هفته پیش
والد
کامیت
a7c9ec95dc

+ 71 - 104
src/app/app.component.html

@@ -1,12 +1,3 @@
-<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
-<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
-<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
-<!-- * * * * * * * * * * and can be replaced.  * * * * * * * * * * -->
-<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
-<!-- * * * * * * * * * Delete the template below * * * * * * * * * -->
-<!-- * * * * * * * to get started with your project! * * * * * * * -->
-<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
-
 <style>
 <style>
   
   
 </style>
 </style>
@@ -15,71 +6,7 @@
   <ng-container *ngTemplateOutlet="toolbarItems"/>
   <ng-container *ngTemplateOutlet="toolbarItems"/>
 </mat-toolbar>
 </mat-toolbar>
 
 
-<ng-template #toolbarItems>
-  @for (item of [
-      {id:'menu',icon:'menu',title:'menu',key:'menu'},
-      {id:'home',icon:'home',link:'/',title:'Home',key:'home_page'},
-      {id:'notifs',icon:'notifications',title:'Notifications',key:'notifs',menu:notifications},
-      {id:'chat'},
-      {id:'user',icon:'account_circle',menu:userMenu,title:'User & Settings',key:'#{user} & #{settings}'}
-    ]; track $index) {
-      @switch (true) {
-        @case (item.link !== undefined) {
-          <div id="{{item.id}}" class="toolbar-item" [routerLink]="item.link" replaceUrl="{{item.id==='home'?'true':'false'}}">
-            <mat-icon>{{item.icon}}</mat-icon>
-            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
-          </div>
-        }
-        @case (item.id === 'menu') {
-          <div id="{{item.id}}" class="toolbar-item" (click)="sidenav.toggle()">
-            <mat-icon>{{item.icon}}</mat-icon>
-            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
-          </div>
-        }
-        @case (item.id === 'user') {
-          <div id="{{item.id}}" class="toolbar-item" [matMenuTriggerFor]="item.menu">
-            @if (loginService?.user?.pictures?.length > 0) {
-              <img title="{{'profile_pic'|tr:'Profile Picture'}}" class="profile-pic" src="{{loginService?.user?.pictures[0]?.value}}">
-            }
-            @else {
-              <mat-icon id="{{item.key}}-icon">{{item.icon}}</mat-icon>
-            }
-            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
-          </div>
-        }
-        @case (item.menu !== undefined) {
-          <div id="{{item.id}}" class="toolbar-item" [matMenuTriggerFor]="item.menu">
-            <mat-icon id="{{item.key}}-icon">{{item.icon}}</mat-icon>
-            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
-            @if (item.key === 'notifs' && notificationCount > 0) {
-              <div class="count-aria">{{notificationCount}}</div>
-            }
-          </div>
-        }
-        @case (item.id === 'chat') {
-          <div id="{{item.id}}" class="toolbar-item" (click)="mobile.toggleChat()">
-            <mat-icon>chat</mat-icon>
-            <mat-label>{{('fis_ai_chat'|tr:'FIS A.I. Chat')}}</mat-label>
-          </div>
-        }
-        @default {
-          <div id="{{item.id}}" class="toolbar-item">
-            <mat-icon>{{item.icon}}</mat-icon>
-            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
-          </div>
-        }
-      }
-    }
-</ng-template>
-
-<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
-<!-- * * * * * * * * * * * The content above * * * * * * * * * * * * -->
-<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * * -->
-<!-- * * * * * * * * * * and can be replaced.  * * * * * * * * * * * -->
-<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
-<!-- * * * * * * * * * * End of Placeholder  * * * * * * * * * * * * -->
-<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
-<div [ngClass]="theme" class="container">
+<div class="container">
   <div class="main">
   <div class="main">
     <mat-sidenav-container>
     <mat-sidenav-container>
       <mat-sidenav #sidenav [opened]="loginService?.user" [mode]="cs.isMobileClient? 'over': 'side'" class="sidenav">
       <mat-sidenav #sidenav [opened]="loginService?.user" [mode]="cs.isMobileClient? 'over': 'side'" class="sidenav">
@@ -97,7 +24,7 @@
         }
         }
         <ng-container *ngTemplateOutlet="routeMenu;context:{$implicit:'GENERAL',items:[
         <ng-container *ngTemplateOutlet="routeMenu;context:{$implicit:'GENERAL',items:[
           {path:'/company',icon:'business',title:{key:'company',default:'Company'}},
           {path:'/company',icon:'business',title:{key:'company',default:'Company'}},
-          {path:'/settings',icon:'settings',title:{key:'settings',default:'Settings'}}
+          {path:'/settings',icon:'settings',title:{key:'settings',default:'Settings'},menu:settings}
         ]}"/>
         ]}"/>
       </mat-sidenav>
       </mat-sidenav>
       <mat-sidenav-content>
       <mat-sidenav-content>
@@ -130,11 +57,12 @@
   <mat-label class="route-menu-category">{{category.key?(category.key|tr:category.default):category}}</mat-label>
   <mat-label class="route-menu-category">{{category.key?(category.key|tr:category.default):category}}</mat-label>
   <div class="route-menu">
   <div class="route-menu">
     @for (item of items; track item) {
     @for (item of items; track item) {
-      <button mat-button [routerLink]="[item.path]"
+      <button mat-button [routerLink]="item.path"
         (click)="cs.isMobileClient? sidenav.close():undefined"
         (click)="cs.isMobileClient? sidenav.close():undefined"
         [queryParams]="item.queryParams"
         [queryParams]="item.queryParams"
         matBadge="{{item.badge}}" replaceUrl="{{item.path==='/'?'true':'false'}}"
         matBadge="{{item.badge}}" replaceUrl="{{item.path==='/'?'true':'false'}}"
         [ngClass]="{'active':router.isActive(item.path,{paths:'exact',queryParams:'ignored'})}"
         [ngClass]="{'active':router.isActive(item.path,{paths:'exact',queryParams:'ignored'})}"
+        [matMenuTriggerFor]="item.menu"
       >
       >
         <mat-icon>{{item.icon}}</mat-icon>
         <mat-icon>{{item.icon}}</mat-icon>
         <span>{{item.title.key?(item.title.key|tr:item.title.default):item.title}}</span>
         <span>{{item.title.key?(item.title.key|tr:item.title.default):item.title}}</span>
@@ -143,6 +71,73 @@
   </div>
   </div>
 </ng-template>
 </ng-template>
 
 
+<ng-template #toolbarItems>
+  <div mat-icon-button class="toolbar-item" style="border-radius: 50%;border:1px solid;" 
+    [style.color]="colorScheme.color"
+    matTooltip="{{'select_color'|tr:'Select color'}}" (click)="colorPop.toggle($event)">
+    <span style="font-size: x-large;">●</span>
+  </div>
+  <div class="toolbar-item" mat-icon-button matTooltip="{{'select_theme'|tr:'Select theme'}}" [matMenuTriggerFor]="theme">
+    <mat-icon>{{themeMode}}</mat-icon>
+  </div>
+  @for (item of [
+      {id:'home',icon:'home',path:'/',title:'Home',key:'home_page'},
+      {id:'notifs',icon:'notifications',title:'Notifications',key:'notifs',menu:notifications},
+      {id:'user',icon:'account_circle',menu:userMenu,title:'User & Settings',key:'#{user} & #{settings}'}
+    ]; track $index) {
+      @switch (true) {
+        @case (item.path !== undefined) {
+          <div id="{{item.id}}" class="toolbar-item" [routerLink]="item.path" replaceUrl="{{item.id==='home'?'true':'false'}}">
+            <mat-icon>{{item.icon}}</mat-icon>
+            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
+          </div>
+        }
+        @case (item.id === 'user') {
+          <div id="{{item.id}}" class="toolbar-item" [matMenuTriggerFor]="item.menu">
+            @if (loginService?.user?.pictures?.length > 0) {
+              <img title="{{'profile_pic'|tr:'Profile Picture'}}" class="profile-pic" src="{{loginService?.user?.pictures[0]?.value}}">
+            }
+            @else {
+              <mat-icon id="{{item.key}}-icon">{{item.icon}}</mat-icon>
+            }
+            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
+          </div>
+        }
+        @default {
+          <div id="{{item.id}}" class="toolbar-item">
+            <mat-icon>{{item.icon}}</mat-icon>
+            <mat-label>{{(item.key|tr:item.title)}}</mat-label>
+          </div>
+        }
+      }
+    }
+</ng-template>
+<p-popover #colorPop>
+  @for(item of [
+    {scheme:'crimson',color:'#7c0024'},
+    {scheme:'blue',color:'#00405d'}
+  ]; track item) {
+    <button mat-button (click)="changeColorScheme(item);colorPop.hide();">
+      <span class="color-circle" style="font-size: 40pt;border-radius:50%" [style.color]="item.color">●</span>
+    </button>
+  }
+</p-popover>
+
+<mat-menu #theme>
+  <button mat-menu-item (click)="cs.theming.changeTheme('system'); themeMode='computer'">
+    <mat-icon>computer</mat-icon>
+    {{'system_color'|tr:'System Color'}}
+  </button>
+  <button mat-menu-item (click)="cs.theming.changeTheme('light'); themeMode='light_mode'">
+    <mat-icon>light_mode</mat-icon>
+    {{'light_mode'|tr:'Light Mode'}}
+  </button>
+  <button mat-menu-item (click)="cs.theming.changeTheme('dark'); themeMode='dark_mode'">
+    <mat-icon>dark_mode</mat-icon>
+    {{'dark_mode'|tr:'Dark Mode'}}
+  </button>
+</mat-menu>
+
 <!--menus-->
 <!--menus-->
 <mat-menu #userMenu="matMenu">
 <mat-menu #userMenu="matMenu">
   <button mat-menu-item [matMenuTriggerFor]="account" id="account-menu-button">
   <button mat-menu-item [matMenuTriggerFor]="account" id="account-menu-button">
@@ -171,37 +166,9 @@
 </mat-menu>
 </mat-menu>
 
 
 <mat-menu #settings="matMenu">
 <mat-menu #settings="matMenu">
-  <button mat-menu-item [matMenuTriggerFor]="themes">{{'theme'|tr:'Theme'}}</button>
   <button mat-menu-item [matMenuTriggerFor]="language">{{'language'|tr:'Language'}}</button>
   <button mat-menu-item [matMenuTriggerFor]="language">{{'language'|tr:'Language'}}</button>
 </mat-menu>
 </mat-menu>
 
 
-<mat-menu #themes="matMenu">
-  <button mat-menu-item [matMenuTriggerFor]="lightThemes">{{'light'|tr:'Light'}}</button>
-  <button mat-menu-item [matMenuTriggerFor]="darkThemes">{{'dark'|tr:'Dark'}}</button>
-</mat-menu>
-
-<mat-menu #lightThemes="matMenu">
-  @for(theme of [
-    {name:'theme',label:'main'|tr:'Blue',color:"#3F51B6"},
-    {name:'theme-pink',label:'pink'|tr:'Pink',color:"#e91e63"}
-  ]; track $index) {
-    <button mat-menu-item (click)="cs.theming.changeTheme(theme.name)">
-      <mat-icon style="color:{{theme.color}}">fiber_manual_record</mat-icon>
-      {{theme.label}}</button>
-  }
-</mat-menu>
-
-<mat-menu #darkThemes="matMenu">
-  @for(theme of [
-    {name:'dark-theme',label:'main'|tr:'Blue',color:"#3F51B6"},
-    {name:'dark-theme-pink',label:'pink'|tr:'Pink',color:"#e91e63"}
-  ]; track $index) {
-    <button mat-menu-item (click)="cs.theming.changeTheme(theme.name)">
-      <mat-icon style="color:{{theme.color}}">fiber_manual_record</mat-icon>
-      {{theme.label}}</button>
-  }
-</mat-menu>
-
 <mat-menu #language="matMenu">
 <mat-menu #language="matMenu">
   @for(lang of [
   @for(lang of [
     {name:'en',label:'English',picture:'https://cdn.swopt.com/media/images/flags/GBR.png'},
     {name:'en',label:'English',picture:'https://cdn.swopt.com/media/images/flags/GBR.png'},

+ 19 - 32
src/app/app.component.ts

@@ -50,6 +50,7 @@ import { TranslatePipe } from 'angularlib/labels/translate.pipe';
 import { HttpClient } from '@angular/common/http';
 import { HttpClient } from '@angular/common/http';
 import { EventI } from 'fis-commons/event/event';
 import { EventI } from 'fis-commons/event/event';
 import { AppService } from 'angularlib/app';
 import { AppService } from 'angularlib/app';
+import { PopoverModule } from 'primeng/popover';
 
 
 @Component({
 @Component({
   selector: 'app-root',
   selector: 'app-root',
@@ -61,6 +62,7 @@ import { AppService } from 'angularlib/app';
     Angularlib,
     Angularlib,
     NotificationModule,
     NotificationModule,
     BusinessDataModule,
     BusinessDataModule,
+    PopoverModule
   ],
   ],
   providers: [DatePipe, FISMessaging, FISPrograms],
   providers: [DatePipe, FISMessaging, FISPrograms],
   templateUrl: './app.component.html',
   templateUrl: './app.component.html',
@@ -92,7 +94,7 @@ export class AppComponent extends BaseComponent implements OnInit {
   );
   );
 
 
   /**current theme of application */
   /**current theme of application */
-  protected theme;
+  protected themeMode:'light_mode'|'dark_mode'|'computer' = 'computer';
 
 
   /**number of notifications */
   /**number of notifications */
   protected notificationCount: number = 0;
   protected notificationCount: number = 0;
@@ -105,37 +107,7 @@ export class AppComponent extends BaseComponent implements OnInit {
 
 
   protected info = info;
   protected info = info;
 
 
-  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.3341 },
-        ],
-        fillColor: 'red',
-        strokeColor: 'red',
-      },
-    ],
-  };
-
+  protected colorScheme = {scheme:'blue',color:'#00405d'};
   protected programs = signal(inject(FISPrograms).list);
   protected programs = signal(inject(FISPrograms).list);
 
 
   private http = inject(HttpClient);
   private http = inject(HttpClient);
@@ -310,6 +282,21 @@ export class AppComponent extends BaseComponent implements OnInit {
     },
     },
   };
   };
 
 
+  protected changeColorScheme(colorScheme) {
+    this.colorScheme = colorScheme;
+    switch (this.themeMode) {
+      case 'dark_mode':
+        if (colorScheme.scheme === 'blue') this.cs.theming.changeTheme('dark');
+        else this.cs.theming.changeTheme(`${colorScheme.scheme}-dark`);
+        break;
+      default: {
+        if (colorScheme.scheme === 'blue') this.cs.theming.changeTheme('light');
+        else this.cs.theming.changeTheme(colorScheme.scheme);
+        break;
+      }
+    }
+  }
+
   private updateSidenavBadges() {
   private updateSidenavBadges() {
     this.app.sidenav.badges.update.pipe(untilDestroy(this)).subscribe((event: EventI) => {
     this.app.sidenav.badges.update.pipe(untilDestroy(this)).subscribe((event: EventI) => {
       this.programs.update((programs) => {
       this.programs.update((programs) => {

+ 6 - 1
src/assets/language.packs/en_US.json

@@ -4744,5 +4744,10 @@
     "start_date_1": "Start Date",
     "start_date_1": "Start Date",
     "tender_submission_items": "Tender Submission Items",
     "tender_submission_items": "Tender Submission Items",
     "bidder_remark": "Bidder's Remark",
     "bidder_remark": "Bidder's Remark",
-    "add_remark": "Add remark"
+    "add_remark": "Add remark",
+    "system_color": "System Color",
+    "light_mode": "Light Mode",
+    "dark_mode": "Dark Mode",
+    "select_theme": "Select Theme",
+    "select_color": "Select Color"
 }
 }

+ 6 - 1
src/assets/language.packs/ms_MY.json

@@ -4727,5 +4727,10 @@
     "start_date_1": "Tarikh Mula",
     "start_date_1": "Tarikh Mula",
     "tender_submission_items": "Tender Submission Items",
     "tender_submission_items": "Tender Submission Items",
     "bidder_remark": "Catatan Pembida",
     "bidder_remark": "Catatan Pembida",
-    "add_remark": "Masukkan catatan"
+    "add_remark": "Masukkan catatan",
+    "system_color": "Warna Sistem",
+    "light_mode": "Mod Terang",
+    "dark_mode": "Mod Gelap",
+    "select_theme": "Pilih Tema",
+    "select_color": "Pilih Warna"
 }
 }

+ 6 - 1
src/assets/language.packs/zh_Hans.json

@@ -4697,5 +4697,10 @@
     "start_date_1": "开始日期",
     "start_date_1": "开始日期",
     "tender_submission_items": "Tender Submission Items",
     "tender_submission_items": "Tender Submission Items",
     "bidder_remark": "投标者备注",
     "bidder_remark": "投标者备注",
-    "add_remark": "输入备注"
+    "add_remark": "输入备注",
+    "system_color": "系统颜色",
+    "light_mode": "浅色模式",
+    "dark_mode": "深色模式",
+    "select_theme": "选择主题",
+    "select_color": "选择颜色"
 }
 }

+ 1 - 1
src/dependencies/angularlib

@@ -1 +1 @@
-Subproject commit 553fc3ec7ef2a765699316c7bf9895c82fdd71d6
+Subproject commit 8a11d34c84fd72d39dd704a1acbebf9e7b0005c2

+ 1 - 1
src/dependencies/fis

@@ -1 +1 @@
-Subproject commit 370e1bcd9ae07f9700f2bb3c9ff60b4d72931daf
+Subproject commit 2c585eeae8ee3e9264487c8c0a519e156545b3df