tigger 2 тижнів тому
батько
коміт
7f25ab7dfe

+ 50 - 17
src/app/app.component.html

@@ -10,20 +10,6 @@
 <style>
   
 </style>
-<mat-toolbar class="toolbar" color="primary">
-  <div class="toolbar-container">
-    <!--<button mat-icon-button aria-label="menu">
-      <mat-icon>menu</mat-icon>
-    </button>-->
-    <button mat-icon-button [routerLink]="'/'">
-      <mat-icon>home</mat-icon>
-    </button>
-    <h2 id="title"><i>{{pbTitle.getTitle()}}</i></h2>
-    <div class="right-toolbar-panel">
-      <ng-container *ngTemplateOutlet="toolbarItems"/>
-    </div>
-  </div>
-</mat-toolbar>
 <button mat-button id="installApp" hidden>{{'install_app'|tr:'Install APP'}}</button>
 <mat-toolbar class="mobile-toolbar" color="primary">
   <ng-container *ngTemplateOutlet="toolbarItems"/>
@@ -88,9 +74,40 @@
 <!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
 <div [ngClass]="theme" class="container">
   <div class="main">
-    <router-outlet></router-outlet>
-    <chat title="{{'fis_ai_chat'|tr:'FIS A.I. Chat'}}"></chat>
-    <div class="mobile-buffer">&nbsp;</div>
+    <mat-sidenav-container>
+      <mat-sidenav opened mode="side" class="sidenav">
+        <div class="logo-container">
+          <img
+            id="logo"
+            src="https://cdn.swopt.com/fis/image/fis-logo.webp"
+            alt="FIS"
+          />
+          <div class="app-name">{{info?.appName}}</div>
+        </div>
+        <ng-container *ngTemplateOutlet="routeMenu;context:{$implicit:'MAIN',items:[{path:'/dashboard',icon:'apps',key:'dashboard',title:'Dashboard'}]}"/>
+        @for (program of programs(); track program) {
+          <ng-container *ngTemplateOutlet="routeMenu;context:{$implicit:program.category,items:program.items}"/>
+        }
+        <ng-container *ngTemplateOutlet="routeMenu;context:{$implicit:'GENERAL',items:[
+          {path:'/company',icon:'business',title:{key:'company',default:'Company'}},
+          {path:'/settings',icon:'settings',title:{key:'settings',default:'Settings'}}
+        ]}"/>
+      </mat-sidenav>
+      <mat-sidenav-content>
+        <mat-toolbar class="toolbar">
+          <div class="toolbar-container">
+            <!--<button mat-icon-button aria-label="menu">
+              <mat-icon>menu</mat-icon>
+            </button>-->
+            <h2 id="title">{{pbTitle.getTitle()}}</h2>
+            <div class="right-toolbar-panel">
+              <ng-container *ngTemplateOutlet="toolbarItems"/>
+            </div>
+          </div>
+        </mat-toolbar>
+        <router-outlet></router-outlet>
+      </mat-sidenav-content>
+    </mat-sidenav-container>
   </div>
 </div>
 <footer>
@@ -100,6 +117,22 @@
   <a class="version-short">&nbsp;ver. {{cs.info?.version}}</a>
 </footer>
 
+<ng-template #routeMenu let-category let-items="items">
+  <mat-label class="route-menu-category">{{category.key?(category.key|tr:category.default):category}}</mat-label>
+  <div class="route-menu">
+    @for (item of items; track item) {
+      <button mat-button [routerLink]="[item.path]" 
+        [queryParams]="item.queryParams"
+        matBadge="{{item.badge}}" replaceUrl="{{item.path==='/'?'true':'false'}}"
+        [ngClass]="{'active':router.isActive(item.path,true)}"
+      >
+        <mat-icon>{{item.icon}}</mat-icon>
+        <span>{{item.title.key?(item.title.key|tr:item.title.default):item.title}}</span>
+       </button>
+    }
+  </div>
+</ng-template>
+
 <!--menus-->
 <mat-menu #userMenu="matMenu">
   <button mat-menu-item [matMenuTriggerFor]="account" id="account-menu-button">

+ 55 - 1
src/app/app.component.scss

@@ -4,6 +4,27 @@
     --pill-accent: var(--bright-blue);
 }
 
+.sidenav {
+    width: 250px;
+    background: none;
+}
+
+.logo-container {
+    display: flex;
+    flex-flow: row;
+    align-items: center;
+}
+
+.logo-container #logo {
+    width: auto;
+    height: 70px
+}
+
+.logo-container > .app-name {
+    margin-left: 3px;
+    font-weight: bold;
+}
+
 .container {
     display: flex;
     flex-flow: row;
@@ -16,11 +37,15 @@
 .container > .main {
     flex-grow: 4;
     margin: 5px;
-    height: calc(100vh - 65px);
+    height: calc(100vh - 35px);
     max-width: 1920px;
     overflow-y: auto;
 }
 
+.container > .main > mat-sidenav-container {
+    min-height: 100%;
+}
+
 .container > .right {
     flex-grow: 1;
 }
@@ -181,6 +206,35 @@ chat {
     z-index: 100;
 }
 
+.route-menu-category {
+    font-weight: bold;
+    color: $title-color-light;
+    font-size: 10pt;
+    font-family: 'Tahoma','Verdana', sans-serif;
+}
+
+.route-menu {
+    display: flex;
+    flex-flow: column;
+    gap: 5px;
+    padding: 5px;
+    border-radius: 10px;
+}
+
+.route-menu button {
+    justify-content: flex-start;
+    text-align: left;
+}
+
+.route-menu .active {
+    background: color-mix(in srgb, var(--pill-accent) 15%, transparent);
+}
+
+::ng-deep .route-menu button .mat-badge-content {
+    top: 50%;
+    left: 92%;
+}
+
 /** Mobile styles */
 @media screen and (pointer: none), (pointer: coarse) {
     .toolbar {display: none;}

+ 33 - 2
src/app/app.component.ts

@@ -4,6 +4,7 @@ import {
   inject,
   OnInit,
   ChangeDetectionStrategy,
+  signal,
 } from '@angular/core';
 import {
   ActivatedRoute,
@@ -36,17 +37,20 @@ import { Notification } from 'angularlib/notification/notification.actions';
 import { generateId } from 'angularlib/base.service';
 import { Store } from '@ngxs/store';
 import config from '../config/config.json';
+import info from '../config/info.json';
 import { UIAuthActions } from 'angularlib/login/state/login.actions';
 import { Platform } from '@angular/cdk/platform';
 import { AppSettingsAction } from 'angularlib/ui.state/ui.state.actions';
 import { PushNotificationDecorator as LeavePushNotif } from 'fis/leave/decorators/push.notification.decorator';
-import { FISMessaging } from 'fis/index';
+import { FISMessaging, FISPrograms } from 'fis/index';
 import { BusinessDataModule } from 'fis/business.data/business.data.module';
 import { NotificationService } from 'angularlib/notification/notification.service';
 import { env } from 'angularlib/environments/environment';
 import { TranslatePipe } from 'angularlib/labels/translate.pipe';
 import { ChatComponent } from 'angularlib/chat/chat.component';
 import { HttpClient } from '@angular/common/http';
+import { EventI } from 'fis-commons/event/event';
+import { AppService } from 'angularlib/app';
 
 @Component({
   selector: 'app-root',
@@ -101,6 +105,8 @@ export class AppComponent extends BaseComponent implements OnInit {
   private notification = inject(NotificationService);
   private tr = inject(TranslatePipe);
 
+  protected info = info;
+
   protected sampleMap = {
     hidden: true,
     markers: [
@@ -132,10 +138,14 @@ export class AppComponent extends BaseComponent implements OnInit {
     ],
   };
 
+  protected programs = signal(FISPrograms);
+
   private http = inject(HttpClient);
 
+  private app = inject(AppService);
+
   constructor(
-    private router: Router,
+    protected router: Router,
     private store: Store,
     protected loginService: LoginService,
     /**Platform Browser title */
@@ -199,6 +209,8 @@ export class AppComponent extends BaseComponent implements OnInit {
       });
 
     if (this.platform.ANDROID || this.platform.IOS) this.pwaPrompt();
+    this.updateSidenavBadges();
+    console.debug('app initialized');
   }
 
   ngAfterViewInit() {
@@ -298,4 +310,23 @@ export class AppComponent extends BaseComponent implements OnInit {
         chat.style.display = chat.style.display === 'none' ? 'flex' : 'none';
     },
   };
+
+  private updateSidenavBadges() {
+    this.app.sidenav.badges.update.pipe(untilDestroy(this)).subscribe((event: EventI) => {
+      this.programs.update((programs) => {
+        return programs.map((program) => {
+          if (program.id === event.payload.categoryId) {
+            program.items = program.items.map((item:any) => {
+              if (item.id === event.payload.programId) item = {
+                ...item,
+                badge: event.payload.badge
+              }
+              return item;
+            });
+          }
+          return program;
+        })
+      })
+    });
+  }
 }

+ 1 - 1
src/dependencies/angularlib

@@ -1 +1 @@
-Subproject commit 0dcee18251561cb4c1278b2b2e80ffde896ced19
+Subproject commit 6452d672bf2be318b4c67a82898b54c932c683eb

+ 1 - 1
src/dependencies/fis

@@ -1 +1 @@
-Subproject commit bb264afcc2a0ffaaea6d47fd6e61239bc2e2d907
+Subproject commit 97e380936f7b74d2315d01741b979185ab401dc6