mesauth-angular 1.6.3 → 1.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, provideAppInitializer, inject, NgZone, Injectable, NgModule, EventEmitter, signal, HostListener, HostBinding, Output, Component, ViewChild, Input } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, provideAppInitializer, inject, NgZone, Injectable, NgModule, EventEmitter, signal, HostListener, HostBinding, Output, Component, ViewChild, Input, resource } from '@angular/core';
3
3
  import * as i4 from '@angular/common/http';
4
4
  import { HttpClient } from '@angular/common/http';
5
5
  import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr';
6
- import { BehaviorSubject, Subject, EMPTY, of, timer, throwError, forkJoin } from 'rxjs';
7
- import { tap, catchError, switchMap, takeUntil } from 'rxjs/operators';
6
+ import { BehaviorSubject, Subject, EMPTY, of, timer, throwError, forkJoin, firstValueFrom } from 'rxjs';
7
+ import { tap, catchError, switchMap, takeUntil, map } from 'rxjs/operators';
8
8
  import * as i2 from '@angular/router';
9
9
  import { Router } from '@angular/router';
10
10
  import * as i3 from '@angular/common';
@@ -251,6 +251,19 @@ const mesAuthInterceptor = (req, next) => {
251
251
  return throwError(() => error);
252
252
  }));
253
253
  };
254
+ function appendPermissions(body, allowedActions) {
255
+ if (body === null || body === undefined) {
256
+ return { 'x-ma-perms': allowedActions };
257
+ }
258
+ if (Array.isArray(body)) {
259
+ return { data: body, 'x-ma-perms': allowedActions };
260
+ }
261
+ if (typeof body === 'object') {
262
+ return { ...body, 'x-ma-perms': allowedActions };
263
+ }
264
+ // Primitive (string, number, boolean)
265
+ return { data: body, 'x-ma-perms': allowedActions };
266
+ }
254
267
 
255
268
  class MesAuthModule {
256
269
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: MesAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -2816,9 +2829,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
2816
2829
  args: ['class']
2817
2830
  }] } });
2818
2831
 
2832
+ // ─── Utility: extract allowedActions from x-ma-perm header ───
2833
+ function extractXMaPerm(response) {
2834
+ const raw = response.headers.get('x-ma-perm');
2835
+ if (!raw)
2836
+ return [];
2837
+ try {
2838
+ const parsed = JSON.parse(raw);
2839
+ return parsed?.allowedActions ?? [];
2840
+ }
2841
+ catch {
2842
+ console.warn('[extractXMaPerm] Failed to parse x-ma-perm header:', raw);
2843
+ return [];
2844
+ }
2845
+ }
2846
+ // ─── RxJS operator: pipe it on any HttpClient call ───
2847
+ function withXMaPerm() {
2848
+ return map((response) => ({
2849
+ data: response.body,
2850
+ allowedActions: extractXMaPerm(response),
2851
+ }));
2852
+ }
2853
+
2854
+ function createXMaResource(url) {
2855
+ const http = inject(HttpClient);
2856
+ return resource({
2857
+ loader: async () => {
2858
+ const response = await firstValueFrom(http.get(url, { observe: 'response' }));
2859
+ return {
2860
+ data: response.body,
2861
+ allowedActions: extractXMaPerm(response),
2862
+ };
2863
+ },
2864
+ });
2865
+ }
2866
+
2819
2867
  /**
2820
2868
  * Generated bundle index. Do not edit.
2821
2869
  */
2822
2870
 
2823
- export { ApprovalActionType, ApprovalDocumentStatus, ApprovalStepMode, ApprovalStepStatus, MES_AUTH_CONFIG, MaApprovalPanelComponent, MaApprovalService, MaArvContainerComponent, MaUserComponent, MesAuthModule, MesAuthService, NotificationBadgeComponent, NotificationPanelComponent, NotificationType, ThemeService, ToastContainerComponent, ToastService, UserProfileComponent, mesAuthInterceptor, provideMesAuth };
2871
+ export { ApprovalActionType, ApprovalDocumentStatus, ApprovalStepMode, ApprovalStepStatus, MES_AUTH_CONFIG, MaApprovalPanelComponent, MaApprovalService, MaArvContainerComponent, MaUserComponent, MesAuthModule, MesAuthService, NotificationBadgeComponent, NotificationPanelComponent, NotificationType, ThemeService, ToastContainerComponent, ToastService, UserProfileComponent, createXMaResource, extractXMaPerm, mesAuthInterceptor, provideMesAuth, withXMaPerm };
2824
2872
  //# sourceMappingURL=mesauth-angular.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mesauth-angular.mjs","sources":["../../src/mes-auth.service.ts","../../src/mes-auth.interceptor.ts","../../src/mes-auth.module.ts","../../src/theme.service.ts","../../src/user-profile.component.ts","../../src/toast.service.ts","../../src/toast-container.component.ts","../../src/notification-panel.component.ts","../../src/approval.service.ts","../../src/approval.models.ts","../../src/ma-approval-panel.component.ts","../../src/ma-user.component.ts","../../src/notification-badge.component.ts","../../src/ma-arv-container.component.ts","../../src/mesauth-angular.ts"],"sourcesContent":["import { inject, Injectable, InjectionToken, EnvironmentProviders, makeEnvironmentProviders, provideAppInitializer, NgZone } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { HubConnection, HubConnectionBuilder, LogLevel } from '@microsoft/signalr';\nimport { BehaviorSubject, Subject, Observable, of, EMPTY } from 'rxjs';\nimport { tap, catchError } from 'rxjs/operators';\nimport { Router } from '@angular/router';\n\nexport interface MesAuthConfig {\n apiBaseUrl: string;\n withCredentials?: boolean;\n userBaseUrl?: string;\n}\n\n/** Injection token for MesAuth configuration */\nexport const MES_AUTH_CONFIG = new InjectionToken<MesAuthConfig>('MES_AUTH_CONFIG');\n\n/**\n * Provides MesAuth with configuration.\n * This is the recommended way to set up mesauth-angular in standalone apps.\n *\n * @example\n * ```typescript\n * // app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideHttpClient(withInterceptors([mesAuthInterceptor])),\n * provideMesAuth({\n * apiBaseUrl: 'https://auth.example.com',\n * userBaseUrl: 'https://app.example.com'\n * })\n * ]\n * };\n * ```\n */\nexport function provideMesAuth(config: MesAuthConfig): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: MES_AUTH_CONFIG, useValue: config },\n MesAuthService,\n provideAppInitializer(() => {\n const mesAuthService = inject(MesAuthService);\n const httpClient = inject(HttpClient);\n const router = inject(Router);\n const ngZone = inject(NgZone);\n mesAuthService.init(config, httpClient, router, ngZone);\n })\n ]);\n}\n\nexport interface IUser {\n userId?: string;\n userName?: string;\n fullName?: string;\n gender?: string;\n email?: string;\n phoneNumber?: string;\n department?: string;\n position?: string;\n tokenVersion?: string;\n permEndpoint?: string;\n perms?: Set<string>;\n employeeCode?: string;\n avatarPath?: string;\n loginMethod?: number;\n hrFullNameVn?: string;\n hrFullNameEn?: string;\n hrPosition?: string;\n hrJobTitle?: string;\n hrGender?: string;\n hrMobile?: string;\n hrEmail?: string;\n hrJoinDate?: string;\n hrBirthDate?: string;\n hrWorkStatus?: string;\n hrDoiTuong?: string;\n hrTeamCode?: string;\n hrLineCode?: string;\n}\n\nexport enum NotificationType {\n Info = 'Info',\n Warning = 'Warning',\n Error = 'Error',\n Success = 'Success'\n}\n\nexport interface NotificationDto {\n id: string;\n title: string;\n message: string;\n messageHtml?: string;\n url?: string;\n type: NotificationType;\n isRead: boolean;\n createdAt: string;\n sourceAppName: string;\n sourceAppIconUrl?: string;\n}\n\nexport interface FrontEndRoute {\n id: number;\n roleId: string;\n roleName: string;\n routePath: string;\n routeName: string;\n description?: string;\n icon?: string;\n cssClass?: string;\n parentId?: number | null;\n sortOrder: number;\n isLabel: boolean;\n isActive: boolean;\n createdAt: string;\n updatedAt?: string;\n children: FrontEndRoute[];\n}\n\nexport interface UserFrontEndRoutesGrouped {\n appId: string;\n appName: string;\n feUrl?: string;\n routes: FrontEndRoute[];\n}\n\nexport interface PagedList<T> {\n items: T[];\n totalCount: number;\n page: number;\n pageSize: number;\n totalPages: number;\n hasNext: boolean;\n hasPrevious: boolean;\n}\n\nexport interface RealTimeNotificationDto {\n id: string;\n title: string;\n message: string;\n messageHtml?: string;\n url?: string;\n type: NotificationType;\n createdAt: string;\n sourceAppName: string;\n sourceAppIconUrl?: string;\n}\n\n@Injectable()\nexport class MesAuthService {\n private hubConnection: HubConnection | null = null;\n private _currentUser = new BehaviorSubject<IUser | null>(null);\n public currentUser$: Observable<IUser | null> = this._currentUser.asObservable();\n private _notifications = new Subject<any>();\n public notifications$: Observable<any> = this._notifications.asObservable();\n private _approvalEvents = new Subject<any>();\n public approvalEvents$: Observable<any> = this._approvalEvents.asObservable();\n\n private apiBase = '';\n private config: MesAuthConfig | null = null;\n private http!: HttpClient;\n private router?: Router;\n private ngZone: NgZone | null = null;\n\n constructor() {\n // Empty constructor - all dependencies passed to init()\n }\n\n init(config: MesAuthConfig, httpClient: HttpClient, router?: Router, ngZone?: NgZone) {\n this.config = config;\n this.http = httpClient;\n this.router = router;\n this.ngZone = ngZone ?? null;\n this.apiBase = config.apiBaseUrl.replace(/\\/$/, '');\n\n // Fetch user once on init. Route changes do NOT re-fetch the user.\n // Auth state is maintained via cookies; 401 errors are handled by HTTP interceptors.\n // SignalR handles real-time notification delivery without polling.\n this.fetchCurrentUser().subscribe();\n }\n\n getConfig(): MesAuthConfig | null {\n return this.config;\n }\n\n private fetchCurrentUser(): Observable<any> {\n if (!this.apiBase) return EMPTY;\n const url = `${this.apiBase}/auth/me`;\n return this.http.get(url, { withCredentials: this.config?.withCredentials ?? true }).pipe(\n tap((u) => {\n this._currentUser.next(u);\n if (u && this.config) {\n this.startConnection(this.config);\n }\n }),\n catchError((err) => {\n // Silently handle auth errors (401/403) - user is not logged in\n if (err.status === 401 || err.status === 403) {\n this._currentUser.next(null);\n }\n return of(null);\n })\n );\n }\n\n public getUnreadCount(): Observable<any> {\n return this.http.get(`${this.apiBase}/notif/me/unread-count`, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public getNotifications(page: number = 1, pageSize: number = 20, includeRead: boolean = false, type?: string): Observable<any> {\n let url = `${this.apiBase}/notif/me?page=${page}&pageSize=${pageSize}&includeRead=${includeRead}`;\n if (type) {\n url += `&type=${type}`;\n }\n return this.http.get(url, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public markAsRead(notificationId: string): Observable<any> {\n return this.http.patch(`${this.apiBase}/notif/${notificationId}/read`, {}, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public markAllAsRead(): Observable<any> {\n return this.http.patch(`${this.apiBase}/notif/me/read-all`, {}, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public deleteNotification(notificationId: string): Observable<any> {\n return this.http.delete(`${this.apiBase}/notif/${notificationId}`, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n /**\n * Get frontend routes assigned to the current user\n * Returns routes grouped by application\n */\n public getFrontEndRoutes(): Observable<UserFrontEndRoutesGrouped[]> {\n if (!this.apiBase) throw new Error('MesAuth not initialized');\n return this.http.get<UserFrontEndRoutesGrouped[]>(`${this.apiBase}/fe-routes/me`, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n private startConnection(config: MesAuthConfig) {\n if (this.hubConnection) return;\n const signalrUrl = config.apiBaseUrl.replace(/\\/$/, '') + '/hub/notification';\n const builder = new HubConnectionBuilder()\n .withUrl(signalrUrl, { withCredentials: config.withCredentials ?? true })\n .withAutomaticReconnect()\n .configureLogging(LogLevel.Warning);\n\n this.hubConnection = builder.build();\n\n this.hubConnection.on('ReceiveNotification', (n: any) => {\n if (this.ngZone) {\n this.ngZone.run(() => this._notifications.next(n));\n } else {\n this._notifications.next(n);\n }\n });\n\n this.hubConnection.on('ApprovalCompleted', (e: any) => {\n if (this.ngZone) {\n this.ngZone.run(() => this._approvalEvents.next({ type: 'ApprovalCompleted', ...e }));\n } else {\n this._approvalEvents.next({ type: 'ApprovalCompleted', ...e });\n }\n });\n\n this.hubConnection.on('ApprovalStepChanged', (e: any) => {\n if (this.ngZone) {\n this.ngZone.run(() => this._approvalEvents.next({ type: 'ApprovalStepChanged', ...e }));\n } else {\n this._approvalEvents.next({ type: 'ApprovalStepChanged', ...e });\n }\n });\n\n this.hubConnection.start().then(() => {}).catch((err) => {});\n\n this.hubConnection.onclose(() => {});\n this.hubConnection.onreconnecting(() => {});\n this.hubConnection.onreconnected(() => {});\n }\n\n public stop() {\n if (!this.hubConnection) return;\n this.hubConnection.stop().catch(() => {});\n this.hubConnection = null;\n }\n\n public logout(): Observable<any> {\n const url = `${this.apiBase}/auth/logout`;\n return this.http.post(url, {}, { withCredentials: this.config?.withCredentials ?? true }).pipe(\n tap(() => {\n this._currentUser.next(null);\n this.stop();\n })\n );\n }\n\n public get currentUser(): IUser | null {\n return this._currentUser.value;\n }\n\n public get isAuthenticated(): boolean {\n return this._currentUser.value !== null;\n }\n\n /**\n * Refreshes the current user from the server.\n * Returns an Observable that completes when the user data is loaded.\n * Callers can subscribe to wait for completion before proceeding (e.g., navigating after login).\n */\n public refreshUser(): Observable<any> {\n return this.fetchCurrentUser();\n }\n}\n","import { inject } from '@angular/core';\nimport { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';\nimport { throwError, timer } from 'rxjs';\nimport { catchError, switchMap } from 'rxjs/operators';\nimport { Router } from '@angular/router';\nimport { MesAuthService } from './mes-auth.service';\n\n// Track if we're currently redirecting to prevent loopback\nlet isRedirecting = false;\n\n/**\n * Functional HTTP interceptor for handling 401/403 auth errors.\n * Redirects to login page on 401, and to 403 page on 403.\n * Includes loopback prevention to avoid infinite redirects.\n */\nexport const mesAuthInterceptor: HttpInterceptorFn = (req, next) => {\n const authService = inject(MesAuthService);\n const router = inject(Router);\n\n return next(req).pipe(\n catchError((error: HttpErrorResponse) => {\n const status = error.status;\n\n // Check if we should handle this error and prevent loopback\n if ((status === 401 || status === 403) && !isRedirecting) {\n const config = authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n\n const currentUrl = router.url + (window.location.hash || '');\n const returnUrl = encodeURIComponent(currentUrl);\n\n // Avoid loops if already on auth/unauth pages\n const isLoginPage = currentUrl.includes('/login');\n const is403Page = currentUrl.includes('/403');\n const isAuthPage = currentUrl.includes('/auth');\n // Public pages that should never trigger a 401 redirect (e.g., register, password reset)\n const isPublicPage = currentUrl.includes('/register')\n || currentUrl.includes('/forgot-password')\n || currentUrl.includes('/reset-password');\n // Skip redirect for the initial /auth/me check (app startup when not logged in)\n const isMeAuthPage = req.url.includes('/auth/me');\n\n if (status === 401 && !isLoginPage && !isAuthPage && !isMeAuthPage && !isPublicPage) {\n // Wait 1.5s for the concurrent refresh's Set-Cookie to be processed, then retry once.\n // If retry also gets 401, redirect to login.\n return timer(1500).pipe(\n switchMap(() => next(req)),\n catchError((retryError: HttpErrorResponse) => {\n if (retryError.status === 401) {\n isRedirecting = true;\n setTimeout(() => { isRedirecting = false; }, 5000);\n window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;\n }\n return throwError(() => retryError);\n })\n );\n } else if (status === 403 && !is403Page) {\n isRedirecting = true;\n setTimeout(() => { isRedirecting = false; }, 5000);\n let redirectUrl = `${baseUrl}/403?returnUrl=${returnUrl}`;\n if (error.error && error.error.required) {\n redirectUrl += `&required=${encodeURIComponent(error.error.required)}`;\n }\n window.location.href = redirectUrl;\n }\n }\n return throwError(() => error);\n })\n );\n};\n","import { NgModule } from '@angular/core';\nimport { MesAuthService } from './mes-auth.service';\n\n@NgModule({\n providers: [\n MesAuthService\n ]\n})\nexport class MesAuthModule {}\n","import { Injectable, OnDestroy } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport type Theme = 'light' | 'dark';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ThemeService implements OnDestroy {\n private _currentTheme = new BehaviorSubject<Theme>('light');\n public currentTheme$: Observable<Theme> = this._currentTheme.asObservable();\n private observer: MutationObserver | null = null;\n\n constructor() {\n this.detectTheme();\n this.startWatching();\n }\n\n ngOnDestroy(): void {\n this.stopWatching();\n }\n\n private detectTheme(): void {\n const html = document.documentElement;\n const isDark = html.classList.contains('dark') ||\n html.getAttribute('data-theme') === 'dark' ||\n html.getAttribute('theme') === 'dark' ||\n html.getAttribute('data-coreui-theme') === 'dark';\n\n this._currentTheme.next(isDark ? 'dark' : 'light');\n }\n\n private startWatching(): void {\n if (typeof MutationObserver === 'undefined') {\n // Fallback for older browsers - check periodically\n setInterval(() => this.detectTheme(), 1000);\n return;\n }\n\n this.observer = new MutationObserver(() => {\n this.detectTheme();\n });\n\n this.observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme', 'data-coreui-theme']\n });\n }\n\n private stopWatching(): void {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n }\n\n get currentTheme(): Theme {\n return this._currentTheme.value;\n }\n\n // Method to manually set theme if needed\n setTheme(theme: Theme): void {\n this._currentTheme.next(theme);\n }\n\n // Re-detect theme from DOM\n refreshTheme(): void {\n this.detectTheme();\n }\n}","import { Component, OnInit, OnDestroy, Output, EventEmitter, HostBinding, HostListener, signal, ChangeDetectorRef } from '@angular/core';\nimport { NgIf } from '@angular/common';\nimport { Router } from '@angular/router';\nimport { HttpClient } from '@angular/common/http';\nimport { MesAuthService, IUser } from './mes-auth.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-user-profile',\n standalone: true,\n imports: [NgIf],\n template: `\n <div class=\"user-profile-container\">\n <!-- Not logged in -->\n <ng-container *ngIf=\"!currentUser()\">\n <button class=\"login-btn\" (click)=\"onLogin()\">Login</button>\n </ng-container>\n\n <!-- Logged in -->\n <ng-container *ngIf=\"currentUser()\">\n <div class=\"user-header\">\n <!-- Notification Bell -->\n <button class=\"notification-btn\" [class.has-unread]=\"unreadCount > 0\" (click)=\"onNotificationClick()\" title=\"Notifications\" aria-label=\"Notifications\">\n <svg class=\"bell-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <span class=\"badge\" *ngIf=\"unreadCount > 0\">{{ unreadCount > 99 ? '99+' : unreadCount }}</span>\n </button>\n\n <!-- Approval Button -->\n <button class=\"notification-btn\" [class.has-unread]=\"pendingApprovalCount > 0\" (click)=\"onApprovalClick()\" title=\"Approvals\" aria-label=\"Approvals\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9 11l3 3L22 4\"/>\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\"/>\n </svg>\n <span class=\"badge\" *ngIf=\"pendingApprovalCount > 0\">{{ pendingApprovalCount > 99 ? '99+' : pendingApprovalCount }}</span>\n </button>\n\n <!-- User Avatar + Dropdown -->\n <div class=\"user-menu-wrapper\">\n <button class=\"user-menu-btn\" (click)=\"toggleDropdown()\" [attr.aria-label]=\"'User menu for ' + (currentUser().fullName || currentUser().userName)\" aria-haspopup=\"true\" [attr.aria-expanded]=\"dropdownOpen\">\n <div class=\"avatar-ring\" [class.active]=\"dropdownOpen\">\n <img\n *ngIf=\"currentUser().fullName || currentUser().userName\"\n [src]=\"getAvatarUrl(currentUser())\"\n [alt]=\"currentUser().fullName || currentUser().userName\"\n class=\"avatar\"\n />\n <span *ngIf=\"!(currentUser().fullName || currentUser().userName)\" class=\"avatar-initial\">\n {{ getLastNameInitial(currentUser()) }}\n </span>\n </div>\n </button>\n\n <div class=\"mes-dropdown-menu\" *ngIf=\"dropdownOpen\">\n <!-- User info header -->\n <div class=\"mes-dropdown-header\">\n <div class=\"dropdown-avatar-wrap\">\n <img\n *ngIf=\"currentUser().fullName || currentUser().userName\"\n [src]=\"getAvatarUrl(currentUser())\"\n [alt]=\"currentUser().fullName || currentUser().userName\"\n class=\"dropdown-avatar\"\n />\n <span *ngIf=\"!(currentUser().fullName || currentUser().userName)\" class=\"dropdown-avatar-initial\">\n {{ getLastNameInitial(currentUser()) }}\n </span>\n </div>\n <div class=\"dropdown-user-info\">\n <span class=\"dropdown-user-name\">{{ currentUser().fullName || currentUser().userName }}</span>\n <span class=\"dropdown-user-sub\" *ngIf=\"currentUser().position || currentUser().department\">\n {{ currentUser().position || currentUser().department }}\n </span>\n </div>\n </div>\n\n <div class=\"mes-dropdown-divider\"></div>\n\n <button class=\"mes-dropdown-item profile-link\" (click)=\"onViewProfile()\">\n <svg class=\"item-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/>\n </svg>\n View Profile\n </button>\n\n <div class=\"mes-dropdown-divider\"></div>\n\n <button class=\"mes-dropdown-item logout-item\" (click)=\"onLogout()\">\n <svg class=\"item-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\"/><polyline points=\"16 17 21 12 16 7\"/><line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/>\n </svg>\n Logout\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n `,\n styles: [`\n :host {\n --primary-color: #1976d2;\n --primary-hover: #1565c0;\n --primary-light: rgba(25, 118, 210, 0.12);\n --primary-glow: rgba(25, 118, 210, 0.3);\n --error-color: #f44336;\n --error-light: rgba(244, 67, 54, 0.1);\n --text-primary: #212121;\n --text-secondary: #616161;\n --text-muted: #9e9e9e;\n --bg-primary: #ffffff;\n --bg-secondary: #f8f9fa;\n --bg-hover: #f0f4ff;\n --border-color: #e0e0e0;\n --shadow: rgba(0, 0, 0, 0.12);\n --shadow-lg: rgba(0, 0, 0, 0.18);\n }\n\n :host(.theme-dark) {\n --primary-color: #90caf9;\n --primary-hover: #64b5f6;\n --primary-light: rgba(144, 202, 249, 0.12);\n --primary-glow: rgba(144, 202, 249, 0.25);\n --error-color: #ef5350;\n --error-light: rgba(239, 83, 80, 0.12);\n --text-primary: #e0e0e0;\n --text-secondary: #b0b0b0;\n --text-muted: #757575;\n --bg-primary: #1e1e2e;\n --bg-secondary: #27273a;\n --bg-hover: #2a2d4a;\n --border-color: #383850;\n --shadow: rgba(0, 0, 0, 0.35);\n --shadow-lg: rgba(0, 0, 0, 0.5);\n }\n\n .user-profile-container {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .login-btn {\n padding: 7px 18px;\n background-color: var(--primary-color);\n color: white;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-weight: 500;\n font-size: 13px;\n letter-spacing: 0.2px;\n transition: background-color 0.2s, transform 0.15s;\n }\n\n .login-btn:hover {\n background-color: var(--primary-hover);\n transform: translateY(-1px);\n }\n\n .user-header {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n /* ── Bell button ── */\n .notification-btn {\n position: relative;\n background: none;\n border: none;\n cursor: pointer;\n padding: 8px;\n border-radius: 10px;\n color: var(--text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.2s, background-color 0.2s;\n }\n\n .notification-btn:hover {\n background-color: var(--primary-light);\n color: var(--primary-color);\n }\n\n .notification-btn.has-unread {\n color: var(--primary-color);\n }\n\n .bell-icon {\n display: block;\n transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .notification-btn:hover .bell-icon {\n transform: rotate(-20deg) scale(1.15);\n }\n\n .badge {\n position: absolute;\n top: 2px;\n right: 2px;\n background-color: var(--error-color);\n color: white;\n border-radius: 10px;\n min-width: 17px;\n height: 17px;\n padding: 0 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n box-shadow: 0 0 0 2px var(--bg-primary);\n animation: badge-pop 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n @keyframes badge-pop {\n from { transform: scale(0); }\n to { transform: scale(1); }\n }\n\n /* ── Avatar ── */\n .user-menu-wrapper {\n position: relative;\n }\n\n .user-menu-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 2px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s;\n }\n\n .user-menu-btn:hover {\n transform: scale(1.06);\n }\n\n .avatar-ring {\n border-radius: 50%;\n padding: 2px;\n border: 2px solid transparent;\n transition: border-color 0.25s, box-shadow 0.25s;\n }\n\n .avatar-ring.active,\n .user-menu-btn:hover .avatar-ring {\n border-color: var(--primary-color);\n box-shadow: 0 0 0 3px var(--primary-glow);\n }\n\n .avatar {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n object-fit: cover;\n display: block;\n }\n\n .avatar-initial {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 15px;\n }\n\n /* ── Dropdown ── */\n .mes-dropdown-menu {\n position: absolute;\n top: calc(100% + 10px);\n right: 0;\n background: var(--bg-primary);\n border: 1px solid var(--border-color);\n border-radius: 14px;\n box-shadow: 0 8px 32px var(--shadow-lg), 0 2px 8px var(--shadow);\n min-width: 220px;\n z-index: 1000;\n overflow: hidden;\n animation: dropdown-in 0.16s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n @keyframes dropdown-in {\n from { opacity: 0; transform: translateY(-8px) scale(0.96); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .mes-dropdown-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--bg-secondary);\n }\n\n .dropdown-avatar-wrap {\n flex-shrink: 0;\n }\n\n .dropdown-avatar {\n width: 46px;\n height: 46px;\n border-radius: 50%;\n object-fit: cover;\n border: 2px solid var(--primary-color);\n display: block;\n }\n\n .dropdown-avatar-initial {\n width: 46px;\n height: 46px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 18px;\n border: 2px solid var(--primary-color);\n }\n\n .dropdown-user-info {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n }\n\n .dropdown-user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .dropdown-user-sub {\n font-size: 11px;\n color: var(--primary-color);\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .mes-dropdown-divider {\n height: 1px;\n background: var(--border-color);\n }\n\n .mes-dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 11px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 13.5px;\n font-weight: 500;\n transition: background-color 0.15s;\n }\n\n .item-icon {\n flex-shrink: 0;\n opacity: 0.8;\n }\n\n .profile-link {\n color: var(--primary-color);\n }\n\n .profile-link:hover {\n background-color: var(--primary-light);\n }\n\n .logout-item {\n color: var(--error-color);\n }\n\n .logout-item:hover {\n background-color: var(--error-light);\n }\n\n @media (max-width: 768px) {\n .avatar, .avatar-initial { width: 32px; height: 32px; font-size: 13px; }\n }\n `]\n})\nexport class UserProfileComponent implements OnInit, OnDestroy {\n @Output() notificationClick = new EventEmitter<void>();\n @Output() approvalClick = new EventEmitter<void>();\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n\n currentUser = signal<IUser | null>(null);\n currentTheme: Theme = 'light';\n unreadCount = 0;\n pendingApprovalCount = 0;\n dropdownOpen = false;\n private hasUser = false;\n private destroy$ = new Subject<void>();\n\n // Signal to force avatar refresh\n avatarRefresh = signal<number>(Date.now());\n\n constructor(private authService: MesAuthService, private router: Router, private themeService: ThemeService, private cdr: ChangeDetectorRef, private http: HttpClient) {}\n\n ngOnInit() {\n this.authService.currentUser$\n .pipe(takeUntil(this.destroy$))\n .subscribe(user => {\n this.currentUser.set(user);\n this.hasUser = !!user;\n // Force avatar refresh when user changes\n this.avatarRefresh.set(Date.now());\n if (!this.hasUser) {\n this.unreadCount = 0;\n this.pendingApprovalCount = 0;\n } else {\n this.loadUnreadCount();\n this.loadPendingApprovalCount();\n }\n this.cdr.markForCheck();\n });\n\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n\n // Listen for approval events (SignalR) to refresh pending count\n this.authService.approvalEvents$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.hasUser) this.loadPendingApprovalCount();\n });\n\n // Listen for new real-time notifications (SignalR only)\n this.authService.notifications$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.hasUser) {\n this.loadUnreadCount();\n }\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n loadUnreadCount() {\n if (!this.hasUser) {\n this.unreadCount = 0;\n return;\n }\n\n this.authService.getUnreadCount().subscribe({\n next: (response: any) => {\n this.unreadCount = response.unreadCount || 0;\n },\n error: (err) => {}\n });\n }\n\n loadPendingApprovalCount() {\n if (!this.hasUser) { this.pendingApprovalCount = 0; return; }\n const config = this.authService.getConfig();\n if (!config) return;\n const url = `${config.apiBaseUrl.replace(/\\/$/, '')}/approval/dashboard`;\n this.http.get(url, { withCredentials: config.withCredentials ?? true }).subscribe({\n next: (r: any) => { this.pendingApprovalCount = r?.pendingCount ?? 0; },\n error: () => {}\n });\n }\n\n onApprovalClick() {\n this.approvalClick.emit();\n }\n\n getAvatarUrl(user: IUser): string {\n // Use the refresh signal to force update\n const refresh = this.avatarRefresh();\n const config = this.authService.getConfig();\n const baseUrl = config?.apiBaseUrl || '';\n \n // If user has avatarPath, use it directly\n if (user.avatarPath) {\n // If avatarPath is already a full URL, use it as-is\n if (user.avatarPath.startsWith('http://') || user.avatarPath.startsWith('https://')) {\n return user.avatarPath;\n }\n // If it's a relative path, construct full URL with refresh timestamp\n return `${baseUrl.replace(/\\/$/, '')}${user.avatarPath}?t=${refresh}`;\n }\n\n // Fallback: construct URL using userId\n const userId = user.userId;\n if (userId && baseUrl) {\n return `${baseUrl.replace(/\\/$/, '')}/auth/${userId}/avatar?t=${refresh}`;\n }\n \n // Fallback to UI avatars service if no userId or baseUrl\n const displayName = user.userName || user.userId || 'User';\n return `https://ui-avatars.com/api/?name=${encodeURIComponent(displayName)}&background=1976d2&color=fff`;\n }\n\n getLastNameInitial(user: IUser): string {\n const fullName = user.fullName || user.userName || 'U';\n const parts = fullName.split(' ');\n const lastPart = parts[parts.length - 1];\n return lastPart.charAt(0).toUpperCase();\n }\n\n toggleDropdown() {\n this.dropdownOpen = !this.dropdownOpen;\n }\n\n @HostListener('document:click', ['$event'])\n onDocumentClick(event: Event) {\n const target = event.target as HTMLElement;\n const clickedInside = target.closest('.user-menu-wrapper');\n if (!clickedInside) {\n this.dropdownOpen = false;\n }\n }\n\n onLogin() {\n const config = this.authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n const returnUrl = encodeURIComponent(this.router.url);\n window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;\n }\n\n onViewProfile() {\n this.router.navigate(['/profile']);\n this.dropdownOpen = false;\n }\n\n onLogout() {\n this.authService.logout().subscribe({\n next: () => {\n // Clear current user after successful logout\n this.dropdownOpen = false;\n \n // Navigate to login with return URL\n const config = this.authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n const returnUrl = encodeURIComponent(window.location.href);\n window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;\n },\n error: (err) => {\n // Still navigate to login even if logout fails\n const config = this.authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n window.location.href = `${baseUrl}/login`;\n }\n });\n }\n\n onNotificationClick() {\n this.notificationClick.emit();\n }\n}\n\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport interface Toast {\n id: string;\n message: string;\n title?: string;\n type: 'info' | 'success' | 'warning' | 'error';\n duration?: number;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ToastService {\n private toasts$ = new BehaviorSubject<Toast[]>([]);\n public toasts: Observable<Toast[]> = this.toasts$.asObservable();\n\n show(message: string, title?: string, type: 'info' | 'success' | 'warning' | 'error' = 'info', duration: number = 5000) {\n const id = Math.random().toString(36).substr(2, 9);\n const toast: Toast = {\n id,\n message,\n title,\n type,\n duration\n };\n\n const currentToasts = this.toasts$.value;\n this.toasts$.next([...currentToasts, toast]);\n\n if (duration > 0) {\n setTimeout(() => {\n this.remove(id);\n }, duration);\n }\n\n return id;\n }\n\n remove(id: string) {\n const currentToasts = this.toasts$.value;\n this.toasts$.next(currentToasts.filter(t => t.id !== id));\n }\n\n clear() {\n this.toasts$.next([]);\n }\n}\n","import { Component, OnInit, OnDestroy, HostBinding } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ToastService, Toast } from './toast.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-toast-container',\n standalone: true,\n imports: [CommonModule],\n template: `\n <div class=\"toast-container\">\n <div *ngFor=\"let toast of toasts\" class=\"toast toast-{{ toast.type }}\">\n\n <!-- Type icon -->\n <div class=\"toast-icon\">\n <svg *ngIf=\"toast.type === 'info'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/><path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <svg *ngIf=\"toast.type === 'success'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/><polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n <svg *ngIf=\"toast.type === 'warning'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/>\n </svg>\n <svg *ngIf=\"toast.type === 'error'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n </div>\n\n <!-- Content -->\n <div class=\"toast-content\">\n <div *ngIf=\"toast.title\" class=\"toast-title\">{{ toast.title }}</div>\n <div class=\"toast-message\" [innerHTML]=\"toast.message\"></div>\n </div>\n\n <!-- Close -->\n <button class=\"toast-close\" (click)=\"close(toast.id)\" aria-label=\"Close\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n\n <!-- Auto-dismiss progress bar — hidden when duration <= 0 (persistent toast) -->\n <div class=\"toast-progress\" *ngIf=\"toast.duration == null || toast.duration > 0\" [style.animation-duration]=\"(toast.duration ?? 5000) + 'ms'\"></div>\n </div>\n </div>\n `,\n styles: [`\n :host {\n --info-color: #2196f3;\n --info-bg: rgba(33, 150, 243, 0.1);\n --success-color: #43a047;\n --success-bg: rgba(67, 160, 71, 0.1);\n --warning-color: #f57c00;\n --warning-bg: rgba(245, 124, 0, 0.1);\n --error-color: #e53935;\n --error-bg: rgba(229, 57, 53, 0.1);\n --text-primary: #212121;\n --text-secondary: #757575;\n --bg-primary: #ffffff;\n --border-color: rgba(0, 0, 0, 0.08);\n --shadow: rgba(0, 0, 0, 0.1);\n --shadow-lg: rgba(0, 0, 0, 0.18);\n }\n\n :host(.theme-dark) {\n --info-color: #64b5f6;\n --info-bg: rgba(100, 181, 246, 0.12);\n --success-color: #66bb6a;\n --success-bg: rgba(102, 187, 106, 0.12);\n --warning-color: #ffb74d;\n --warning-bg: rgba(255, 183, 77, 0.12);\n --error-color: #ef5350;\n --error-bg: rgba(239, 83, 80, 0.12);\n --text-primary: #e0e0e0;\n --text-secondary: #9e9e9e;\n --bg-primary: #1e1e2e;\n --border-color: rgba(255, 255, 255, 0.08);\n --shadow: rgba(0, 0, 0, 0.35);\n --shadow-lg: rgba(0, 0, 0, 0.5);\n }\n\n .toast-container {\n position: fixed;\n top: 20px;\n right: 20px;\n z-index: 9999;\n pointer-events: none;\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .toast {\n position: relative;\n display: flex;\n align-items: flex-start;\n gap: 11px;\n padding: 13px 13px 16px 16px;\n border-radius: 12px;\n background: var(--bg-primary);\n border: 1px solid var(--border-color);\n box-shadow: 0 8px 28px var(--shadow-lg), 0 2px 8px var(--shadow);\n pointer-events: auto;\n min-width: 300px;\n max-width: 420px;\n overflow: hidden;\n animation: toast-in 0.35s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n @keyframes toast-in {\n from { opacity: 0; transform: translateX(36px) scale(0.96); }\n to { opacity: 1; transform: translateX(0) scale(1); }\n }\n\n /* Left accent bar via ::before */\n .toast::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 4px;\n border-radius: 12px 0 0 12px;\n }\n\n .toast-info::before { background: var(--info-color); }\n .toast-success::before { background: var(--success-color); }\n .toast-warning::before { background: var(--warning-color); }\n .toast-error::before { background: var(--error-color); }\n\n /* Type icon bubble */\n .toast-icon {\n flex-shrink: 0;\n width: 34px;\n height: 34px;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-left: 2px;\n }\n\n .toast-info .toast-icon { color: var(--info-color); background: var(--info-bg); }\n .toast-success .toast-icon { color: var(--success-color); background: var(--success-bg); }\n .toast-warning .toast-icon { color: var(--warning-color); background: var(--warning-bg); }\n .toast-error .toast-icon { color: var(--error-color); background: var(--error-bg); }\n\n .toast-content {\n flex: 1;\n min-width: 0;\n padding-top: 1px;\n }\n\n .toast-title {\n font-weight: 700;\n font-size: 13.5px;\n margin-bottom: 3px;\n line-height: 1.3;\n }\n\n .toast-info .toast-title { color: var(--info-color); }\n .toast-success .toast-title { color: var(--success-color); }\n .toast-warning .toast-title { color: var(--warning-color); }\n .toast-error .toast-title { color: var(--error-color); }\n\n .toast-message {\n font-size: 12.5px;\n line-height: 1.45;\n color: var(--text-secondary);\n }\n\n .toast-close {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--text-secondary);\n width: 26px;\n height: 26px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n padding: 0;\n transition: color 0.15s, background-color 0.15s;\n }\n\n .toast-close:hover {\n color: var(--text-primary);\n background: var(--border-color);\n }\n\n /* Auto-dismiss progress bar */\n .toast-progress {\n position: absolute;\n bottom: 0;\n left: 4px;\n right: 0;\n height: 3px;\n border-radius: 0 0 12px 0;\n animation: toast-progress linear forwards;\n opacity: 0.7;\n }\n\n .toast-info .toast-progress { background: var(--info-color); }\n .toast-success .toast-progress { background: var(--success-color); }\n .toast-warning .toast-progress { background: var(--warning-color); }\n .toast-error .toast-progress { background: var(--error-color); }\n\n @keyframes toast-progress {\n from { width: calc(100% - 4px); }\n to { width: 0; }\n }\n\n @media (max-width: 600px) {\n .toast-container { top: 10px; right: 10px; left: 10px; }\n .toast { min-width: auto; max-width: 100%; }\n }\n `]\n})\nexport class ToastContainerComponent implements OnInit, OnDestroy {\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n\n toasts: Toast[] = [];\n currentTheme: Theme = 'light';\n private destroy$ = new Subject<void>();\n\n constructor(private toastService: ToastService, private themeService: ThemeService) {}\n\n ngOnInit() {\n this.toastService.toasts\n .pipe(takeUntil(this.destroy$))\n .subscribe(toasts => {\n this.toasts = toasts;\n });\n\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n close(id: string) {\n this.toastService.remove(id);\n }\n}\n","import { Component, OnInit, OnDestroy, HostBinding, Output, EventEmitter, inject } from '@angular/core';\nimport { NgIf, NgFor } from '@angular/common';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { MesAuthService, NotificationDto, PagedList, RealTimeNotificationDto } from './mes-auth.service';\nimport { ToastService } from './toast.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-notification-panel',\n standalone: true,\n imports: [NgIf, NgFor],\n template: `\n <div class=\"notification-panel\" [class.open]=\"isOpen\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-header-left\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <h3>Notifications</h3>\n </div>\n <button class=\"close-btn\" (click)=\"close()\" title=\"Close\" aria-label=\"Close notifications\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs\">\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'unread'\" (click)=\"switchTab('unread')\">\n Unread\n <span class=\"tab-badge\" *ngIf=\"unreadNotifications.length > 0\">{{ unreadNotifications.length }}</span>\n </button>\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'read'\" (click)=\"switchTab('read')\">\n Read\n <span class=\"tab-badge read-badge\" *ngIf=\"readNotifications.length > 0\">{{ readNotifications.length }}</span>\n </button>\n </div>\n\n <!-- Notifications List -->\n <div class=\"notifications-list\">\n <ng-container *ngIf=\"currentNotifications.length > 0\">\n <div\n *ngFor=\"let notification of currentNotifications\"\n class=\"notification-item\"\n [class.unread]=\"!notification.isRead\"\n (click)=\"openDetails(notification)\"\n >\n @let t = typeOf(notification);\n <div class=\"notif-accent\"\n [class.type-info]=\"t === 'Info'\"\n [class.type-success]=\"t === 'Success'\"\n [class.type-warning]=\"t === 'Warning'\"\n [class.type-error]=\"t === 'Error'\"></div>\n <div class=\"notif-type-icon\"\n [class.type-info]=\"t === 'Info'\"\n [class.type-success]=\"t === 'Success'\"\n [class.type-warning]=\"t === 'Warning'\"\n [class.type-error]=\"t === 'Error'\">\n <svg *ngIf=\"t === 'Info'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/><path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <svg *ngIf=\"t === 'Success'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>\n <svg *ngIf=\"t === 'Warning'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/>\n </svg>\n <svg *ngIf=\"t === 'Error'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n </div>\n <div class=\"notification-content\">\n <div class=\"notification-title\">{{ notification.title }}</div>\n <div class=\"notification-message\">{{ getNotificationMessage(notification) }}</div>\n <div class=\"notification-meta\">\n <span class=\"app-name\">{{ notification.sourceAppName }}</span>\n <span class=\"time\">{{ dateLabels.get(notification.id) }}</span>\n </div>\n </div>\n <button class=\"icon-btn read-btn\" (click)=\"markAsRead(notification.id, $event)\" title=\"Mark as read\" aria-label=\"Mark as read\" *ngIf=\"!notification.isRead\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>\n </button>\n <button class=\"icon-btn delete-btn\" (click)=\"delete(notification.id, $event)\" title=\"Delete\" aria-label=\"Delete notification\" *ngIf=\"notification.isRead\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6\"/><path d=\"M14 11v6\"/><path d=\"M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/>\n </svg>\n </button>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"currentNotifications.length === 0\">\n <div class=\"empty-state\">\n <svg class=\"empty-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"44\" height=\"44\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <p>No {{ activeTab }} notifications</p>\n </div>\n </ng-container>\n </div>\n\n <!-- Footer Actions -->\n <div class=\"panel-footer\" *ngIf=\"currentNotifications.length > 0\">\n <div class=\"footer-actions\" *ngIf=\"activeTab === 'unread'\">\n <button class=\"action-btn\" (click)=\"markAllAsRead()\" *ngIf=\"unreadNotifications.length > 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>\n Mark all read\n </button>\n <button class=\"action-btn delete-all-btn\" (click)=\"deleteAllUnread()\" *ngIf=\"unreadNotifications.length > 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/></svg>\n Delete all\n </button>\n </div>\n <button class=\"action-btn delete-all-btn\" (click)=\"deleteAllRead()\" *ngIf=\"activeTab === 'read' && readNotifications.length > 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/></svg>\n Delete all\n </button>\n </div>\n </div>\n\n <!-- Details Modal -->\n <div class=\"modal-overlay\" *ngIf=\"selectedNotification\" (click)=\"closeDetails()\">\n <div class=\"modal-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\"\n [class.modal-type-info]=\"typeOf(selectedNotification) === 'Info'\"\n [class.modal-type-success]=\"typeOf(selectedNotification) === 'Success'\"\n [class.modal-type-warning]=\"typeOf(selectedNotification) === 'Warning'\"\n [class.modal-type-error]=\"typeOf(selectedNotification) === 'Error'\">\n <div class=\"modal-header-left\">\n <div class=\"modal-type-icon\">\n <svg *ngIf=\"typeOf(selectedNotification) === 'Info'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/><path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <svg *ngIf=\"typeOf(selectedNotification) === 'Success'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/><polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n <svg *ngIf=\"typeOf(selectedNotification) === 'Warning'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/>\n </svg>\n <svg *ngIf=\"typeOf(selectedNotification) === 'Error'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n </div>\n <h3>{{ selectedNotification.title }}</h3>\n </div>\n <button class=\"close-btn\" (click)=\"closeDetails()\" title=\"Close\" aria-label=\"Close notification detail\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n <div class=\"modal-meta\">\n <span class=\"app-name\">{{ selectedNotification.sourceAppName }}</span>\n <span class=\"time\">{{ selectedNotificationDate }}</span>\n </div>\n <div class=\"modal-body\" [innerHTML]=\"selectedNotificationHtml\"></div>\n <div class=\"modal-footer\">\n <button class=\"action-btn see-details-btn\" *ngIf=\"selectedNotification.url?.trim()\" (click)=\"openUrl()\">See Details</button>\n <button class=\"action-btn\" (click)=\"closeDetails()\">Close</button>\n </div>\n </div>\n </div>\n `,\n styleUrls: ['./panel-shared.css', './notification-panel.component.css'],\n})\nexport class NotificationPanelComponent implements OnInit, OnDestroy {\n @Output() notificationRead = new EventEmitter<void>();\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n\n isOpen = false;\n notifications: NotificationDto[] = [];\n currentTheme: Theme = 'light';\n activeTab: 'unread' | 'read' = 'unread'; // Default to unread tab\n private destroy$ = new Subject<void>();\n\n // Cached filtered lists — updated explicitly to avoid re-filtering on every CD cycle\n private _unreadNotifications: NotificationDto[] = [];\n private _readNotifications: NotificationDto[] = [];\n\n // Stable time-ago strings keyed by notification id — refreshed every 30s\n dateLabels: Map<string, string> = new Map();\n private dateTimer: ReturnType<typeof setInterval> | null = null;\n\n get unreadNotifications(): NotificationDto[] {\n return this._unreadNotifications;\n }\n\n get readNotifications(): NotificationDto[] {\n return this._readNotifications;\n }\n\n get currentNotifications(): NotificationDto[] {\n return this.activeTab === 'unread' ? this._unreadNotifications : this._readNotifications;\n }\n\n selectedNotification: NotificationDto | null = null;\n selectedNotificationHtml: SafeHtml | null = null;\n selectedNotificationDate: string = '';\n\n // Returns plain text message for list display\n getNotificationMessage(notification: NotificationDto): string {\n return notification.message || '';\n }\n\n // Normalize type to string — API may return integer or string\n // Backend enum: Info=0, Success=1, Warning=2, Error=3\n typeOf(notification: { type: any }): 'Info' | 'Success' | 'Warning' | 'Error' {\n const t = notification.type;\n if (t === 0 || t === 'Info') return 'Info';\n if (t === 1 || t === 'Success') return 'Success';\n if (t === 2 || t === 'Warning') return 'Warning';\n if (t === 3 || t === 'Error') return 'Error';\n return 'Info';\n }\n\n private toastType(type: any): 'info' | 'warning' | 'error' | 'success' {\n const t = this.typeOf({ type });\n return t.toLowerCase() as 'info' | 'warning' | 'error' | 'success';\n }\n\n private readonly sanitizer = inject(DomSanitizer);\n\n constructor(private authService: MesAuthService, private toastService: ToastService, private themeService: ThemeService) {}\n\n ngOnInit() {\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n\n this.loadNotifications();\n\n // Refresh time-ago labels every 30s to avoid NG0100 from live new Date() in template\n this.dateTimer = setInterval(() => this.refreshDateLabels(), 30000);\n\n // Listen for new real-time notifications\n this.authService.notifications$\n .pipe(takeUntil(this.destroy$))\n .subscribe((notification: RealTimeNotificationDto) => {\n // Show toast for new notification\n this.toastService.show(\n notification.messageHtml || notification.message || '',\n notification.title,\n this.toastType(notification.type),\n 5000\n );\n // Reload notifications list\n this.loadNotifications();\n });\n }\n\n ngOnDestroy() {\n if (this.dateTimer !== null) {\n clearInterval(this.dateTimer);\n this.dateTimer = null;\n }\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private loadNotifications() {\n this.authService.getNotifications(1, 50, true).subscribe({ // includeRead = true to get both read and unread\n next: (response: PagedList<NotificationDto>) => {\n this.notifications = response.items || [];\n this.onNotificationsChanged();\n },\n error: (err) => {}\n });\n }\n\n open() {\n this.isOpen = true;\n this.activeTab = 'unread'; // Reset to unread tab when opening\n }\n\n close() {\n this.isOpen = false;\n }\n\n switchTab(tab: 'unread' | 'read') {\n this.activeTab = tab;\n }\n\n openDetails(notification: NotificationDto) {\n this.selectedNotification = notification;\n // Cache computed values to avoid re-rendering on every change detection cycle\n const html = notification.messageHtml || notification.message || '';\n this.selectedNotificationHtml = this.sanitizer.bypassSecurityTrustHtml(html);\n this.selectedNotificationDate = this.formatDate(notification.createdAt);\n // Mark as read when opening details (if not already read)\n if (!notification.isRead) {\n this.authService.markAsRead(notification.id).subscribe({\n next: () => {\n notification.isRead = true;\n this.notificationRead.emit();\n this.onNotificationsChanged();\n },\n error: () => {}\n });\n }\n }\n\n closeDetails() {\n this.selectedNotification = null;\n this.selectedNotificationHtml = null;\n this.selectedNotificationDate = '';\n }\n\n openUrl() {\n const url = this.selectedNotification?.url?.trim();\n if (url) {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n }\n\n markAsRead(notificationId: string, event?: Event) {\n if (event) {\n event.stopPropagation();\n }\n this.authService.markAsRead(notificationId).subscribe({\n next: () => {\n const notification = this.notifications.find(n => n.id === notificationId);\n if (notification) {\n notification.isRead = true;\n this.notificationRead.emit();\n this.onNotificationsChanged();\n }\n },\n error: (err) => {}\n });\n }\n\n markAllAsRead() {\n this.authService.markAllAsRead().subscribe({\n next: () => {\n this.notifications.forEach(n => n.isRead = true);\n this.notificationRead.emit();\n this.onNotificationsChanged();\n },\n error: (err) => {}\n });\n }\n\n deleteAllRead() {\n const readNotificationIds = this.notifications\n .filter(n => n.isRead)\n .map(n => n.id);\n\n // Delete all read notifications\n const deletePromises = readNotificationIds.map(id =>\n this.authService.deleteNotification(id).toPromise()\n );\n\n Promise.all(deletePromises).then(() => {\n // Remove all read notifications from the local array\n this.notifications = this.notifications.filter(n => !n.isRead);\n this.onNotificationsChanged();\n }).catch((err) => {\n // If bulk delete fails, reload notifications to get current state\n this.loadNotifications();\n });\n }\n\n deleteAllUnread() {\n const unreadNotificationIds = this.notifications\n .filter(n => !n.isRead)\n .map(n => n.id);\n\n // Delete all unread notifications\n const deletePromises = unreadNotificationIds.map(id =>\n this.authService.deleteNotification(id).toPromise()\n );\n\n Promise.all(deletePromises).then(() => {\n // Remove all unread notifications from the local array\n this.notifications = this.notifications.filter(n => n.isRead);\n this.notificationRead.emit();\n this.onNotificationsChanged();\n }).catch((err) => {\n // If bulk delete fails, reload notifications to get current state\n this.loadNotifications();\n });\n }\n\n delete(notificationId: string, event: Event) {\n event.stopPropagation();\n const wasUnread = this.notifications.find(n => n.id === notificationId && !n.isRead) !== undefined;\n this.authService.deleteNotification(notificationId).subscribe({\n next: () => {\n this.notifications = this.notifications.filter(n => n.id !== notificationId);\n if (wasUnread) {\n this.notificationRead.emit();\n }\n this.onNotificationsChanged();\n },\n error: (err) => {}\n });\n }\n\n formatDate(dateString: string): string {\n return this.computeTimeAgo(dateString, new Date());\n }\n\n // Pure computation — takes now as param so it never calls new Date() internally\n private computeTimeAgo(dateString: string, now: Date): string {\n const normalizedDateString = this.parseUtcDate(dateString);\n const date = new Date(normalizedDateString);\n\n if (isNaN(date.getTime())) {\n return 'Invalid date';\n }\n\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return 'Now';\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n\n return date.toLocaleDateString();\n }\n\n // Rebuild dateLabels map using a single shared now — prevents mid-loop clock drift\n private refreshDateLabels(): void {\n const now = new Date();\n for (const n of this.notifications) {\n this.dateLabels.set(n.id, this.computeTimeAgo(n.createdAt, now));\n }\n }\n\n // Re-run filter once and store results in stable arrays\n private recomputeFilteredLists(): void {\n this._unreadNotifications = this.notifications.filter(n => !n.isRead);\n this._readNotifications = this.notifications.filter(n => n.isRead);\n }\n\n // Single call-site after every notification mutation\n private onNotificationsChanged(): void {\n this.recomputeFilteredLists();\n this.refreshDateLabels();\n }\n\n // Parse date string from server (stored in UTC but without 'Z' suffix or 'T' separator)\n private parseUtcDate(dateStr: string): string {\n // Handle date strings that might be missing the 'T' separator\n // Convert formats like \"2023-12-01 12:30:45\" to \"2023-12-01T12:30:45\"\n let normalized = dateStr.includes('T') ? dateStr : dateStr.replace(' ', 'T');\n\n // If no timezone indicator, assume UTC by appending 'Z'\n if (!normalized.endsWith('Z') && !normalized.includes('+') && !normalized.includes('-', 10)) {\n normalized += 'Z';\n }\n\n return normalized;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { MesAuthConfig, PagedList } from './mes-auth.service';\nimport {\n ApprovalDocumentDto,\n ApprovalDocumentSummaryDto,\n ApprovalDocumentStatus,\n ApprovalDashboardDto,\n ApprovalHistoryDto,\n ApprovalTemplateSummaryDto,\n ApprovalTemplateDto,\n RolePreviewUserDto,\n CreateApprovalRequest,\n CreateApprovalResponseDto,\n CreateApprovalTemplateRequest,\n UpdateApprovalTemplateRequest,\n ApproveRejectRequest,\n DelegateRequest\n} from './approval.models';\n\n@Injectable()\nexport class MaApprovalService {\n private apiBase = '';\n private http!: HttpClient;\n private config: MesAuthConfig | null = null;\n\n constructor() {}\n\n init(config: MesAuthConfig, httpClient: HttpClient) {\n this.config = config;\n this.http = httpClient;\n this.apiBase = config.apiBaseUrl.replace(/\\/$/, '');\n }\n\n private get opts() {\n return { withCredentials: this.config?.withCredentials ?? true };\n }\n\n // ====================== Dashboard ======================\n\n getDashboard(): Observable<ApprovalDashboardDto> {\n return this.http.get<ApprovalDashboardDto>(`${this.apiBase}/approval/dashboard`, this.opts);\n }\n\n // ====================== Pending & My Requests ======================\n\n getPendingApprovals(page = 1, pageSize = 20): Observable<PagedList<ApprovalDocumentSummaryDto>> {\n return this.http.get<PagedList<ApprovalDocumentSummaryDto>>(\n `${this.apiBase}/approval/pending?page=${page}&pageSize=${pageSize}`,\n this.opts\n );\n }\n\n getMyRequests(page = 1, pageSize = 20, status?: ApprovalDocumentStatus): Observable<PagedList<ApprovalDocumentSummaryDto>> {\n let url = `${this.apiBase}/approval/my-requests?page=${page}&pageSize=${pageSize}`;\n if (status !== undefined) url += `&status=${status}`;\n return this.http.get<PagedList<ApprovalDocumentSummaryDto>>(url, this.opts);\n }\n\n // ====================== Document ======================\n\n getDocument(id: string): Observable<ApprovalDocumentDto> {\n return this.http.get<ApprovalDocumentDto>(`${this.apiBase}/approval/documents/${id}`, this.opts);\n }\n\n getDocumentHistory(id: string): Observable<ApprovalHistoryDto[]> {\n return this.http.get<ApprovalHistoryDto[]>(`${this.apiBase}/approval/documents/${id}/history`, this.opts);\n }\n\n getDocumentContentUrl(id: string): string {\n return `${this.apiBase}/approval/documents/${id}/content`;\n }\n\n getDocumentThumbnailUrl(id: string): string {\n return `${this.apiBase}/approval/documents/${id}/thumbnail`;\n }\n\n // ====================== Actions ======================\n\n approve(documentId: string, comment?: string): Observable<void> {\n const body: ApproveRejectRequest = { comment };\n return this.http.post<void>(`${this.apiBase}/approval/documents/${documentId}/approve`, body, this.opts);\n }\n\n reject(documentId: string, comment: string): Observable<void> {\n const body: ApproveRejectRequest = { comment };\n return this.http.post<void>(`${this.apiBase}/approval/documents/${documentId}/reject`, body, this.opts);\n }\n\n delegate(documentId: string, toUserId: string, reason?: string): Observable<void> {\n const body: DelegateRequest = { toUserId, reason };\n return this.http.post<void>(`${this.apiBase}/approval/documents/${documentId}/delegate`, body, this.opts);\n }\n\n cancel(documentId: string, reason?: string): Observable<void> {\n let url = `${this.apiBase}/approval/documents/${documentId}`;\n if (reason) url += `?reason=${encodeURIComponent(reason)}`;\n return this.http.delete<void>(url, this.opts);\n }\n\n // ====================== Templates ======================\n\n getTemplates(appId?: string): Observable<ApprovalTemplateSummaryDto[]> {\n let url = `${this.apiBase}/approval/templates`;\n if (appId) url += `?appId=${encodeURIComponent(appId)}`;\n return this.http.get<ApprovalTemplateSummaryDto[]>(url, this.opts);\n }\n\n getTemplate(id: number): Observable<ApprovalTemplateDto> {\n return this.http.get<ApprovalTemplateDto>(`${this.apiBase}/approval/templates/${id}`, this.opts);\n }\n\n createTemplate(request: CreateApprovalTemplateRequest): Observable<ApprovalTemplateDto> {\n return this.http.post<ApprovalTemplateDto>(`${this.apiBase}/approval/templates`, request, this.opts);\n }\n\n updateTemplate(id: number, request: UpdateApprovalTemplateRequest): Observable<ApprovalTemplateDto> {\n return this.http.put<ApprovalTemplateDto>(`${this.apiBase}/approval/templates/${id}`, request, this.opts);\n }\n\n deleteTemplate(id: number): Observable<void> {\n return this.http.delete<void>(`${this.apiBase}/approval/templates/${id}`, this.opts);\n }\n\n previewRole(orgCode: string, level: string): Observable<RolePreviewUserDto[]> {\n return this.http.get<RolePreviewUserDto[]>(\n `${this.apiBase}/approval/roles/preview?orgCode=${encodeURIComponent(orgCode)}&level=${encodeURIComponent(level)}`,\n this.opts\n );\n }\n\n // ====================== Create (used by ma-arv-container) ======================\n\n createApproval(request: CreateApprovalRequest): Observable<CreateApprovalResponseDto> {\n return this.http.post<CreateApprovalResponseDto>(`${this.apiBase}/approval/documents`, request, this.opts);\n }\n}\n","// ====================== Enums ======================\n\nexport enum ApprovalStepMode {\n Sequential = 0,\n Parallel = 1\n}\n\nexport enum ApprovalDocumentStatus {\n Draft = 0,\n Pending = 1,\n Approved = 2,\n Rejected = 3,\n Cancelled = 4,\n Expired = 5\n}\n\nexport enum ApprovalStepStatus {\n Waiting = 0,\n Active = 1,\n Approved = 2,\n Rejected = 3,\n Delegated = 4,\n Expired = 5,\n Skipped = 6\n}\n\nexport enum ApprovalActionType {\n Created = 0,\n Submitted = 1,\n Approved = 2,\n Rejected = 3,\n Delegated = 4,\n Cancelled = 5,\n Commented = 6,\n Expired = 7,\n StepAdvanced = 8\n}\n\n// ====================== DTOs ======================\n\nexport interface ApprovalDocumentSummaryDto {\n id: string;\n title: string;\n description?: string;\n thumbnailPath?: string;\n sourceAppId: string;\n referenceId: string;\n requestedByUserName: string;\n status: ApprovalDocumentStatus;\n currentStepOrder: number;\n totalSteps: number;\n currentStepName?: string;\n createdAt: string;\n completedAt?: string;\n}\n\nexport interface ApprovalStepDto {\n id: number;\n stepOrder: number;\n stepName: string;\n mode: ApprovalStepMode;\n assignedUserId: string;\n assignedUserName: string;\n delegatedToUserId?: string;\n delegatedToUserName?: string;\n status: ApprovalStepStatus;\n comment?: string;\n decidedAt?: string;\n deadlineAt?: string;\n}\n\nexport interface ApprovalReferenceDto {\n userId: string;\n userName: string;\n addedAt: string;\n}\n\nexport interface ApprovalDocumentDto {\n id: string;\n title: string;\n description?: string;\n contentPath: string;\n thumbnailPath?: string;\n sourceAppId: string;\n referenceId: string;\n templateId?: number;\n requestedByUserId: string;\n requestedByUserName: string;\n status: ApprovalDocumentStatus;\n currentStepOrder: number;\n callbackUrl?: string;\n createdAt: string;\n updatedAt: string;\n completedAt?: string;\n deadlineAt?: string;\n steps: ApprovalStepDto[];\n references: ApprovalReferenceDto[];\n}\n\nexport interface ApprovalHistoryDto {\n id: number;\n documentId: string;\n stepId?: number;\n action: ApprovalActionType;\n actorUserId: string;\n actorUserName: string;\n comment?: string;\n details?: string;\n timestamp: string;\n}\n\nexport interface ApprovalTemplateSummaryDto {\n id: number;\n name: string;\n description?: string;\n sourceAppId: string;\n stepCount: number;\n referenceCount: number;\n isActive: boolean;\n createdAt: string;\n}\n\nexport interface StepRoleDto {\n orgCode: string;\n positionLevel: string;\n orgName?: string;\n}\n\nexport interface RolePreviewUserDto {\n userId: string;\n fullName?: string;\n position?: string;\n department?: string;\n employeeCode?: string;\n}\n\nexport interface ApprovalTemplateStepDto {\n id: number;\n stepOrder: number;\n stepName: string;\n mode: ApprovalStepMode;\n deadlineHours?: number;\n assigneeUserIds: string[];\n roles: StepRoleDto[];\n}\n\nexport interface ApprovalTemplateDto {\n id: number;\n name: string;\n description?: string;\n sourceAppId: string;\n createdByUserId: string;\n isActive: boolean;\n createdAt: string;\n updatedAt: string;\n steps: ApprovalTemplateStepDto[];\n referenceUserIds: string[];\n}\n\nexport interface ApprovalDashboardDto {\n pendingCount: number;\n approvedTodayCount: number;\n rejectedTodayCount: number;\n recentActivity: ApprovalDocumentSummaryDto[];\n}\n\nexport interface CreateApprovalResponseDto {\n documentId: string;\n message: string;\n}\n\n// ====================== Requests ======================\n\nexport interface ApprovalStepRequest {\n stepOrder: number;\n stepName: string;\n mode?: ApprovalStepMode;\n approverUserIds: string[];\n deadlineHours?: number;\n}\n\nexport interface CreateApprovalRequest {\n title: string;\n description?: string;\n contentHtml: string;\n thumbnailBase64?: string;\n referenceId: string;\n templateId?: number;\n requestedByUserId?: string;\n callbackUrl?: string;\n deadlineHours?: number;\n steps?: ApprovalStepRequest[];\n referenceUserIds?: string[];\n}\n\nexport interface ApproveRejectRequest {\n comment?: string;\n}\n\nexport interface DelegateRequest {\n toUserId: string;\n reason?: string;\n}\n\nexport interface CreateApprovalTemplateRequest {\n name: string;\n description?: string;\n sourceAppId: string;\n steps: ApprovalStepRequest[];\n referenceUserIds?: string[];\n}\n\nexport interface UpdateApprovalTemplateRequest {\n name: string;\n description?: string;\n steps: ApprovalStepRequest[];\n referenceUserIds?: string[];\n}\n\n// ====================== Submit Result ======================\n\nexport interface ApprovalSubmitResult {\n documentId: string;\n message: string;\n}\n","import {\n Component, Output, EventEmitter, OnInit, OnDestroy, inject, HostListener\n} from '@angular/core';\nimport { NgIf, NgFor, DatePipe } from '@angular/common';\nimport { Router } from '@angular/router';\nimport { MesAuthService, MesAuthConfig } from './mes-auth.service';\nimport { MaApprovalService } from './approval.service';\nimport { ApprovalDocumentSummaryDto, ApprovalDocumentStatus } from './approval.models';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { HttpClient } from '@angular/common/http';\n\ntype PanelTab = 'processing' | 'approved' | 'rejected';\n\n@Component({\n selector: 'ma-approval-panel',\n standalone: true,\n imports: [NgIf, NgFor, DatePipe],\n template: `\n <div class=\"approval-backdrop\" [class.open]=\"isOpen\" (click)=\"close()\"></div>\n <div class=\"approval-panel\" [class.open]=\"isOpen\">\n\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-header-left\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9 11l3 3L22 4\"/>\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\"/>\n </svg>\n <h3>Approvals</h3>\n </div>\n <button class=\"close-btn\" (click)=\"close()\" aria-label=\"Close\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs\">\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'processing'\" (click)=\"switchTab('processing')\">\n Processing\n <span class=\"tab-badge\" *ngIf=\"processingItems.length > 0\">{{ processingItems.length }}</span>\n </button>\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'approved'\" (click)=\"switchTab('approved')\">\n Approved\n </button>\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'rejected'\" (click)=\"switchTab('rejected')\">\n Rejected\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Loading -->\n <div class=\"loading-state\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n <span>Loading...</span>\n </div>\n\n <!-- Processing tab -->\n <ng-container *ngIf=\"!loading && activeTab === 'processing'\">\n <div class=\"empty-state\" *ngIf=\"processingItems.length === 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" opacity=\"0.4\"><path d=\"M9 11l3 3L22 4\"/><path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\"/></svg>\n <p>No pending approvals</p>\n </div>\n <div class=\"approval-item\" *ngFor=\"let item of processingItems\" (click)=\"navigateToDetail(item.id)\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div class=\"item-meta\">\n <span class=\"item-requester\">By {{ item.requestedByUserName }}</span>\n <span class=\"item-step\" *ngIf=\"item.currentStepName\">· {{ item.currentStepName }}</span>\n </div>\n <div class=\"item-footer\">\n <span class=\"item-time\">{{ item.createdAt | date:'shortDate' }}</span>\n <span class=\"item-link\">View &rarr;</span>\n </div>\n </div>\n </ng-container>\n\n <!-- Approved tab -->\n <ng-container *ngIf=\"!loading && activeTab === 'approved'\">\n <div class=\"empty-state\" *ngIf=\"approvedItems.length === 0\">\n <p>No approved documents</p>\n </div>\n <div class=\"approval-item approved\" *ngFor=\"let item of approvedItems\" (click)=\"navigateToDetail(item.id)\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div class=\"item-meta\">\n <span class=\"item-requester\">By {{ item.requestedByUserName }}</span>\n </div>\n <div class=\"item-footer\">\n <span class=\"status-badge approved-badge\">Approved</span>\n <span class=\"item-time\">{{ item.completedAt | date:'shortDate' }}</span>\n <span class=\"item-link\">View &rarr;</span>\n </div>\n </div>\n <div class=\"show-more\" *ngIf=\"approvedItems.length >= 10\" (click)=\"showMore('approved')\">\n Show more &rarr;\n </div>\n </ng-container>\n\n <!-- Rejected tab -->\n <ng-container *ngIf=\"!loading && activeTab === 'rejected'\">\n <div class=\"empty-state\" *ngIf=\"rejectedItems.length === 0\">\n <p>No rejected documents</p>\n </div>\n <div class=\"approval-item rejected\" *ngFor=\"let item of rejectedItems\" (click)=\"navigateToDetail(item.id)\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div class=\"item-meta\">\n <span class=\"item-requester\">By {{ item.requestedByUserName }}</span>\n </div>\n <div class=\"item-footer\">\n <span class=\"status-badge rejected-badge\">Rejected</span>\n <span class=\"item-time\">{{ item.completedAt | date:'shortDate' }}</span>\n <span class=\"item-link\">View &rarr;</span>\n </div>\n </div>\n <div class=\"show-more\" *ngIf=\"rejectedItems.length >= 10\" (click)=\"showMore('rejected')\">\n Show more &rarr;\n </div>\n </ng-container>\n </div>\n </div>\n `,\n styleUrls: ['./panel-shared.css', './ma-approval-panel.component.css']\n})\nexport class MaApprovalPanelComponent implements OnInit, OnDestroy {\n @Output() approvalActioned = new EventEmitter<void>();\n\n isOpen = false;\n loading = false;\n activeTab: PanelTab = 'processing';\n\n processingItems: ApprovalDocumentSummaryDto[] = [];\n approvedItems: ApprovalDocumentSummaryDto[] = [];\n rejectedItems: ApprovalDocumentSummaryDto[] = [];\n\n private destroy$ = new Subject<void>();\n private mesAuth = inject(MesAuthService);\n private http = inject(HttpClient);\n private router = inject(Router);\n private approvalSvc: MaApprovalService | null = null;\n\n ngOnInit() {\n const config = this.mesAuth.getConfig();\n if (config) {\n this.approvalSvc = new MaApprovalService();\n this.approvalSvc.init(config, this.http);\n }\n\n this.mesAuth.approvalEvents$.pipe(takeUntil(this.destroy$)).subscribe(() => {\n if (this.isOpen) this.loadCurrentTab();\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n open() {\n this.isOpen = true;\n this.loadAllTabs();\n }\n\n close() {\n this.isOpen = false;\n }\n\n toggle() {\n if (this.isOpen) this.close();\n else this.open();\n }\n\n switchTab(tab: PanelTab) {\n this.activeTab = tab;\n this.loadCurrentTab();\n }\n\n private loadAllTabs() {\n this.loading = true;\n if (!this.approvalSvc) { this.loading = false; return; }\n\n let pending = 3;\n const done = () => { if (--pending === 0) this.loading = false; };\n\n this.approvalSvc.getPendingApprovals(1, 100).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => { this.processingItems = r.items; done(); },\n error: () => done()\n });\n\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Approved).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => { this.approvedItems = r.items; done(); },\n error: () => done()\n });\n\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Rejected).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => { this.rejectedItems = r.items; done(); },\n error: () => done()\n });\n }\n\n private loadCurrentTab() {\n if (!this.approvalSvc) return;\n\n if (this.activeTab === 'processing') {\n this.approvalSvc.getPendingApprovals(1, 100).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => this.processingItems = r.items,\n error: () => {}\n });\n } else if (this.activeTab === 'approved') {\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Approved).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => this.approvedItems = r.items,\n error: () => {}\n });\n } else {\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Rejected).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => this.rejectedItems = r.items,\n error: () => {}\n });\n }\n }\n\n navigateToDetail(id: string) {\n this.close();\n this.router.navigate(['/auth/approval/detail', id]);\n this.approvalActioned.emit();\n }\n\n showMore(status: 'approved' | 'rejected') {\n this.close();\n this.router.navigate(['/auth/approval/my-requests'], { queryParams: { status } });\n }\n}\n","import { Component, ViewChild, AfterViewInit } from '@angular/core';\nimport { ToastContainerComponent } from './toast-container.component';\nimport { UserProfileComponent } from './user-profile.component';\nimport { NotificationPanelComponent } from './notification-panel.component';\nimport { MaApprovalPanelComponent } from './ma-approval-panel.component';\n\n@Component({\n selector: 'ma-user',\n standalone: true,\n imports: [ToastContainerComponent, UserProfileComponent, NotificationPanelComponent, MaApprovalPanelComponent],\n template: `\n <ma-toast-container></ma-toast-container>\n <div class=\"user-header\">\n <ma-user-profile\n (notificationClick)=\"notificationPanel.open()\"\n (approvalClick)=\"approvalPanel.open()\">\n </ma-user-profile>\n </div>\n <ma-notification-panel #notificationPanel (notificationRead)=\"onNotificationRead()\"></ma-notification-panel>\n <ma-approval-panel #approvalPanel (approvalActioned)=\"onApprovalActioned()\"></ma-approval-panel>\n `,\n styles: [`\n .user-header {\n display: flex;\n justify-content: flex-end;\n }\n `]\n})\nexport class MaUserComponent implements AfterViewInit {\n @ViewChild(UserProfileComponent) userProfile?: UserProfileComponent;\n @ViewChild(MaApprovalPanelComponent) approvalPanel!: MaApprovalPanelComponent;\n\n ngAfterViewInit() {\n if (this.userProfile) {\n this.userProfile.loadUnreadCount();\n this.userProfile.loadPendingApprovalCount();\n }\n }\n\n onNotificationRead() {\n if (this.userProfile) {\n this.userProfile.loadUnreadCount();\n }\n }\n\n onApprovalActioned() {\n if (this.userProfile) {\n this.userProfile.loadPendingApprovalCount();\n }\n }\n}\n","import { Component, OnInit, OnDestroy, Output, EventEmitter, HostBinding } from '@angular/core';\nimport { NgIf } from '@angular/common';\nimport { MesAuthService } from './mes-auth.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-notification-badge',\n standalone: true,\n imports: [NgIf],\n template: `\n <button class=\"notification-btn\" (click)=\"onNotificationClick()\" title=\"Notifications\">\n <span class=\"icon\">🔔</span>\n <span class=\"badge\" *ngIf=\"unreadCount > 0\">{{ unreadCount }}</span>\n </button>\n `,\n styles: [`\n :host {\n --error-color: #f44336;\n }\n\n :host(.theme-dark) {\n --error-color: #ef5350;\n }\n\n .notification-btn {\n position: relative;\n background: none;\n border: none;\n font-size: 24px;\n cursor: pointer;\n padding: 8px;\n transition: opacity 0.2s;\n }\n\n .notification-btn:hover {\n opacity: 0.7;\n }\n\n .icon {\n display: inline-block;\n }\n\n .badge {\n position: absolute;\n top: 0;\n right: 0;\n background-color: var(--error-color);\n color: white;\n border-radius: 50%;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: bold;\n }\n `]\n})\nexport class NotificationBadgeComponent implements OnInit, OnDestroy {\n @Output() notificationClick = new EventEmitter<void>();\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n \n unreadCount = 0;\n currentTheme: Theme = 'light';\n private hasUser = false;\n private destroy$ = new Subject<void>();\n\n constructor(private authService: MesAuthService, private themeService: ThemeService) {}\n\n ngOnInit() {\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n\n this.authService.currentUser$\n .pipe(takeUntil(this.destroy$))\n .subscribe(user => {\n this.hasUser = !!user;\n if (!this.hasUser) {\n this.unreadCount = 0;\n return;\n }\n this.loadUnreadCount();\n });\n \n // Listen for new notifications\n this.authService.notifications$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.hasUser) {\n this.loadUnreadCount();\n }\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private loadUnreadCount() {\n if (!this.hasUser) {\n this.unreadCount = 0;\n return;\n }\n\n this.authService.getUnreadCount().subscribe({\n next: (response: any) => {\n this.unreadCount = response.unreadCount || 0;\n },\n error: (err) => console.error('Error loading unread count:', err)\n });\n }\n\n onNotificationClick() {\n this.notificationClick.emit();\n }\n}\n","import {\n Component, Input, Output, EventEmitter, OnInit, OnDestroy,\n ElementRef, ViewChild, HostBinding\n} from '@angular/core';\nimport { NgIf, NgFor } from '@angular/common';\nimport { MesAuthService, MesAuthConfig } from './mes-auth.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { MaApprovalService } from './approval.service';\nimport {\n ApprovalTemplateSummaryDto,\n ApprovalTemplateDto,\n ApprovalTemplateStepDto,\n RolePreviewUserDto,\n ApprovalStepRequest,\n ApprovalStepMode,\n CreateApprovalRequest,\n ApprovalSubmitResult\n} from './approval.models';\nimport { Subject, forkJoin, of } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { HttpClient } from '@angular/common/http';\nimport { inject } from '@angular/core';\n\n@Component({\n selector: 'ma-arv-container',\n standalone: true,\n imports: [NgIf, NgFor],\n template: `\n <div class=\"arv-container\">\n <!-- Content Area -->\n <div class=\"arv-content-body\" #contentBody>\n <ng-content></ng-content>\n </div>\n\n <!-- Approval Footer -->\n <div class=\"arv-footer\" *ngIf=\"!isSubmitted\">\n <div class=\"arv-footer-inner\">\n\n <!-- Routing mode -->\n <div class=\"arv-routing\">\n <div class=\"arv-routing-header\">\n <h4 class=\"arv-section-title\">Approval Routing</h4>\n <!-- Show routing toggle only when templateId is NOT locked -->\n <div *ngIf=\"!templateId\" class=\"arv-routing-mode\">\n <label class=\"arv-radio\">\n <input type=\"radio\" name=\"routingMode\" value=\"template\" [checked]=\"routingMode === 'template'\" (change)=\"routingMode = 'template'\"> Use Template\n </label>\n <label class=\"arv-radio\">\n <input type=\"radio\" name=\"routingMode\" value=\"adhoc\" [checked]=\"routingMode === 'adhoc'\" (change)=\"routingMode = 'adhoc'\"> Custom Steps\n </label>\n </div>\n </div>\n\n <!-- Locked template: show name only, no selector -->\n <div *ngIf=\"templateId && routingMode === 'template'\" class=\"arv-template-select\">\n <div *ngIf=\"loadingTemplate\" class=\"arv-template-loading\">Loading template...</div>\n <div *ngIf=\"selectedTemplate && !loadingTemplate\" class=\"arv-locked-template\">\n <span class=\"arv-locked-label\">Template</span>\n <span class=\"arv-locked-name\">{{ selectedTemplate.name }}</span>\n </div>\n </div>\n\n <!-- Free template selector (no locked templateId) -->\n <div *ngIf=\"!templateId && routingMode === 'template'\" class=\"arv-template-select\">\n <label class=\"arv-label\">Select Template</label>\n <select class=\"arv-select\" (change)=\"onTemplateChange($event)\">\n <option value=\"\">-- Select a template --</option>\n <option *ngFor=\"let t of templates\" [value]=\"t.id\" [selected]=\"t.id === selectedTemplateId\">{{ t.name }}</option>\n </select>\n </div>\n\n <!-- Step pickers (shared for both locked and free template) -->\n <div *ngIf=\"routingMode === 'template'\" class=\"arv-template-select\">\n <div *ngIf=\"!loadingTemplate && selectedTemplate\" class=\"arv-template-steps\">\n <div class=\"arv-step-card\" *ngFor=\"let s of selectedTemplate.steps; let i = index\">\n <div class=\"arv-step-card-header\">\n <span class=\"arv-step-preview-num\">Step {{ s.stepOrder }}</span>\n <span class=\"arv-step-preview-name\">{{ s.stepName }}</span>\n <span *ngIf=\"s.roles && s.roles.length > 0\" class=\"arv-step-role-badge\">\n {{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}\n </span>\n </div>\n <!-- Selectable step (role-based or multi-assignee): show approver picker -->\n <div *ngIf=\"stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]\" class=\"arv-step-picker\">\n <div *ngIf=\"stepLoadingCandidates[i]\" class=\"arv-template-loading\">Loading candidates...</div>\n <select *ngIf=\"!stepLoadingCandidates[i]\" class=\"arv-select arv-select-sm\"\n (change)=\"onStepUserChange(i, $event)\">\n <option value=\"\">-- Select approver --</option>\n <option *ngFor=\"let u of stepCandidates[i]\" [value]=\"u.userId\"\n [selected]=\"u.userId === stepSelectedUsers[i]\">\n {{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}\n </option>\n </select>\n </div>\n <!-- Single fixed-user step: show who is assigned -->\n <div *ngIf=\"!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1\" class=\"arv-step-fixed\">\n {{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}\n </div>\n </div>\n <div *ngIf=\"selectedTemplate.referenceUserIds.length > 0\" class=\"arv-step-preview arv-step-preview-cc\">\n <span class=\"arv-step-preview-num\">CC</span>\n <span class=\"arv-step-preview-name\">{{ selectedTemplate.referenceUserIds.length }} reference user(s) from template</span>\n </div>\n </div>\n </div>\n\n <!-- Ad-hoc steps -->\n <div *ngIf=\"routingMode === 'adhoc'\" class=\"arv-steps\">\n <div class=\"arv-step\" *ngFor=\"let step of adHocSteps; let i = index\">\n <div class=\"arv-step-header\">\n <span class=\"arv-step-num\">Step {{ i + 1 }}</span>\n <input class=\"arv-input\" [value]=\"step.stepName\" (input)=\"step.stepName = $any($event.target).value\" placeholder=\"Step name\" />\n <button class=\"arv-btn-icon arv-btn-danger\" (click)=\"removeStep(i)\" title=\"Remove step\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>\n </button>\n </div>\n <div class=\"arv-approvers\">\n <div class=\"arv-approver-tags\">\n <span class=\"arv-tag\" *ngFor=\"let uid of step.approverUserIds; let j = index\">\n {{ userLabelMap[uid] || uid }}\n <button class=\"arv-tag-remove\" (click)=\"removeApprover(i, j)\">x</button>\n </span>\n </div>\n <div class=\"arv-user-search\">\n <input class=\"arv-input arv-input-sm\" [value]=\"userSearchQuery[i] || ''\"\n (input)=\"onUserSearchInput(i, $any($event.target).value)\"\n placeholder=\"Search approver...\" />\n <div class=\"arv-search-results\" *ngIf=\"userSearchResults[i]?.length\">\n <div class=\"arv-search-item\"\n *ngFor=\"let u of userSearchResults[i]\"\n (click)=\"addApprover(i, u.id)\">\n {{ u.fullName || u.userName }}\n </div>\n </div>\n </div>\n </div>\n </div>\n <button class=\"arv-btn arv-btn-outline\" (click)=\"addStep()\">+ Add Step</button>\n </div>\n </div>\n\n <!-- Reference / CC users -->\n <div class=\"arv-references\">\n <h4 class=\"arv-section-title\">CC / Reference</h4>\n <p class=\"arv-hint\">These users will be notified when the approval completes, but won't be asked to approve.</p>\n <div class=\"arv-approver-tags\">\n <span class=\"arv-tag\" *ngFor=\"let uid of referenceUserIds; let j = index\">\n {{ userLabelMap[uid] || uid }}\n <button class=\"arv-tag-remove\" (click)=\"removeReference(j)\">x</button>\n </span>\n </div>\n <div class=\"arv-user-search\">\n <input class=\"arv-input arv-input-sm\" [value]=\"refSearchQuery\"\n (input)=\"onRefSearchInput($any($event.target).value)\"\n placeholder=\"Search CC user...\" />\n <div class=\"arv-search-results\" *ngIf=\"refSearchResults?.length\">\n <div class=\"arv-search-item\"\n *ngFor=\"let u of refSearchResults\"\n (click)=\"addReference(u.id)\">\n {{ u.fullName || u.userName }}\n </div>\n </div>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"arv-actions\">\n <button class=\"arv-btn arv-btn-secondary\" (click)=\"onCancel()\">Cancel</button>\n <button class=\"arv-btn arv-btn-primary\" [disabled]=\"submitting\" (click)=\"submit()\">\n <span *ngIf=\"submitting\" class=\"arv-spinner\"></span>\n {{ submitting ? 'Submitting...' : 'Submit for Approval' }}\n </button>\n </div>\n\n <div class=\"arv-error\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\n </div>\n </div>\n\n <!-- Success state -->\n <div class=\"arv-success\" *ngIf=\"isSubmitted\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#66bb6a\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/>\n <polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n <p>Submitted for approval successfully.</p>\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n --arv-primary: #90caf9;\n --arv-primary-hover: #64b5f6;\n --arv-success: #66bb6a;\n --arv-danger: #ef5350;\n --arv-text: #e0e0e0;\n --arv-text-muted: #9e9e9e;\n --arv-bg: #1e1e2e;\n --arv-bg2: #27273a;\n --arv-border: #383850;\n --arv-radius: 8px;\n }\n :host(.theme-light) {\n --arv-primary: #1565c0;\n --arv-primary-hover: #0d47a1;\n --arv-success: #2e7d32;\n --arv-danger: #c62828;\n --arv-text: #212121;\n --arv-text-muted: #616161;\n --arv-bg: #ffffff;\n --arv-bg2: #f5f5f5;\n --arv-border: #e0e0e0;\n }\n\n .arv-container { display: flex; flex-direction: column; height: 100%; }\n .arv-content-body { flex: 1; overflow: auto; }\n .arv-footer { border-top: 1px solid var(--arv-border); background: var(--arv-bg2); }\n .arv-footer-inner { padding: 16px; display: flex; flex-direction: column; gap: 14px; }\n\n .arv-section-title { margin: 0 0 8px; font-size: 13px; font-weight: 700; color: var(--arv-primary); text-transform: uppercase; letter-spacing: 0.5px; }\n .arv-routing-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; }\n .arv-routing-mode { display: flex; gap: 12px; }\n .arv-radio { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--arv-text); cursor: pointer; }\n\n .arv-label { font-size: 12px; color: var(--arv-text-muted); display: block; margin-bottom: 4px; }\n .arv-select { width: 100%; padding: 8px 10px; border: 1px solid var(--arv-border); border-radius: var(--arv-radius); background: var(--arv-bg); color: var(--arv-text); font-size: 13px; }\n .arv-input { padding: 7px 10px; border: 1px solid var(--arv-border); border-radius: var(--arv-radius); background: var(--arv-bg); color: var(--arv-text); font-size: 13px; }\n .arv-input-sm { width: 100%; margin-top: 4px; }\n\n .arv-steps { display: flex; flex-direction: column; gap: 10px; }\n .arv-step { background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); padding: 10px; }\n .arv-step-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }\n .arv-step-num { font-size: 12px; font-weight: 700; color: var(--arv-primary); min-width: 44px; }\n\n .arv-approver-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }\n .arv-tag { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; background: rgba(144,202,249,0.12); border: 1px solid rgba(144,202,249,0.3); border-radius: 12px; font-size: 12px; color: var(--arv-primary); }\n .arv-tag-remove { background: none; border: none; cursor: pointer; color: var(--arv-text-muted); font-size: 11px; padding: 0 2px; line-height: 1; }\n .arv-tag-remove:hover { color: var(--arv-danger); }\n\n .arv-user-search { position: relative; }\n .arv-search-results { position: absolute; left: 0; right: 0; z-index: 100; background: var(--arv-bg2); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); max-height: 150px; overflow-y: auto; }\n .arv-search-item { padding: 8px 12px; cursor: pointer; font-size: 13px; color: var(--arv-text); }\n .arv-search-item:hover { background: var(--arv-bg); }\n\n .arv-hint { font-size: 12px; color: var(--arv-text-muted); margin: 0 0 8px; }\n\n .arv-btn-icon { background: none; border: none; cursor: pointer; padding: 2px; border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; }\n .arv-btn-danger { color: var(--arv-danger); }\n .arv-btn-danger:hover { background: rgba(239,83,80,0.1); }\n\n .arv-actions { display: flex; justify-content: flex-end; gap: 10px; }\n .arv-btn { padding: 9px 18px; border-radius: var(--arv-radius); font-size: 13px; font-weight: 600; cursor: pointer; border: none; transition: background 0.15s; }\n .arv-btn-primary { background: var(--arv-primary); color: #fff; }\n .arv-btn-primary:hover:not(:disabled) { background: var(--arv-primary-hover); }\n .arv-btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }\n .arv-btn-secondary { background: transparent; border: 1px solid var(--arv-border); color: var(--arv-text-muted); }\n .arv-btn-secondary:hover { color: var(--arv-text); border-color: var(--arv-text-muted); }\n .arv-btn-outline { background: transparent; border: 1px dashed var(--arv-border); color: var(--arv-text-muted); font-size: 12px; padding: 6px 12px; }\n .arv-btn-outline:hover { border-color: var(--arv-primary); color: var(--arv-primary); }\n\n .arv-spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: #fff; border-radius: 50%; animation: arv-spin 0.6s linear infinite; margin-right: 6px; }\n @keyframes arv-spin { to { transform: rotate(360deg); } }\n\n .arv-error { padding: 8px 12px; background: rgba(239,83,80,0.1); border: 1px solid rgba(239,83,80,0.3); border-radius: var(--arv-radius); font-size: 13px; color: var(--arv-danger); }\n\n .arv-success { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 32px; gap: 12px; text-align: center; }\n .arv-success p { color: var(--arv-success); font-size: 15px; font-weight: 600; margin: 0; }\n\n .arv-references { border-top: 1px solid var(--arv-border); padding-top: 12px; }\n\n .arv-template-loading { font-size: 12px; color: var(--arv-text-muted); margin-top: 8px; padding: 4px 0; }\n .arv-template-steps { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }\n\n .arv-step-card { background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); overflow: hidden; }\n .arv-step-card-header { display: flex; align-items: center; gap: 8px; padding: 7px 10px; background: rgba(0,0,0,0.03); border-bottom: 1px solid var(--arv-border); flex-wrap: wrap; }\n .arv-step-preview { display: flex; align-items: center; gap: 8px; padding: 5px 8px; background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: 4px; font-size: 12px; }\n .arv-step-preview-num { font-weight: 700; color: var(--arv-primary); min-width: 44px; flex-shrink: 0; font-size: 12px; }\n .arv-step-preview-name { flex: 1; color: var(--arv-text); font-size: 12px; font-weight: 600; }\n .arv-step-role-badge { font-size: 11px; color: var(--arv-text-muted); background: rgba(144,202,249,0.1); border: 1px solid rgba(144,202,249,0.25); border-radius: 10px; padding: 1px 7px; }\n .arv-step-preview-cc .arv-step-preview-num { color: var(--arv-text-muted); }\n\n .arv-locked-template { display: flex; align-items: center; gap: 8px; padding: 7px 10px; background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); margin-top: 6px; }\n .arv-locked-label { font-size: 11px; color: var(--arv-text-muted); text-transform: uppercase; letter-spacing: 0.5px; flex-shrink: 0; }\n .arv-locked-name { font-size: 13px; font-weight: 600; color: var(--arv-text); }\n\n .arv-step-picker { padding: 8px 10px; }\n .arv-select-sm { font-size: 12px; padding: 6px 8px; }\n .arv-step-fixed { padding: 6px 10px; font-size: 12px; color: var(--arv-text-muted); }\n `]\n})\nexport class MaArvContainerComponent implements OnInit, OnDestroy {\n @Input() title = '';\n @Input() description?: string;\n @Input() referenceId = '';\n @Input() templateId?: number;\n @Input() callbackUrl?: string;\n @Input() deadlineHours?: number;\n\n @Output() approvalSubmitted = new EventEmitter<ApprovalSubmitResult>();\n @Output() approvalSubmitting = new EventEmitter<void>();\n @Output() cancelled = new EventEmitter<void>();\n\n @ViewChild('contentBody', { static: true }) contentBody!: ElementRef<HTMLElement>;\n\n routingMode: 'template' | 'adhoc' = 'template';\n templates: ApprovalTemplateSummaryDto[] = [];\n selectedTemplateId: number | null = null;\n selectedTemplate: ApprovalTemplateDto | null = null;\n loadingTemplate = false;\n\n // Per-step role candidates and selected user\n stepCandidates: RolePreviewUserDto[][] = [];\n stepLoadingCandidates: boolean[] = [];\n stepSelectedUsers: string[] = [];\n adHocSteps: ApprovalStepRequest[] = [];\n\n referenceUserIds: string[] = [];\n refSearchQuery = '';\n refSearchResults: any[] = [];\n\n userSearchQuery: string[] = [];\n userSearchResults: any[][] = [];\n\n submitting = false;\n isSubmitted = false;\n errorMessage = '';\n userLabelMap: Record<string, string> = {};\n\n @HostBinding('class') get themeClass(): string { return `theme-${this.currentTheme}`; }\n currentTheme: Theme = 'light';\n\n private destroy$ = new Subject<void>();\n private mesAuth = inject(MesAuthService);\n private themeService = inject(ThemeService);\n private approvalSvc: MaApprovalService | null = null;\n private http = inject(HttpClient);\n\n ngOnInit() {\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(t => this.currentTheme = t);\n\n const config = this.mesAuth.getConfig();\n if (config) {\n this.approvalSvc = new MaApprovalService();\n this.approvalSvc.init(config, this.http);\n this.loadTemplates();\n }\n this.addStep();\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private loadTemplates() {\n this.approvalSvc!.getTemplates().pipe(takeUntil(this.destroy$)).subscribe({\n next: (t) => {\n this.templates = t;\n if (this.templateId != null && this.selectedTemplateId == null) {\n this.selectedTemplateId = this.templateId;\n this.loadTemplateDetail(this.templateId);\n }\n },\n error: () => {}\n });\n }\n\n private loadTemplateDetail(id: number) {\n this.loadingTemplate = true;\n this.selectedTemplate = null;\n this.stepCandidates = [];\n this.stepLoadingCandidates = [];\n this.stepSelectedUsers = [];\n this.approvalSvc!.getTemplate(id).pipe(takeUntil(this.destroy$)).subscribe({\n next: (t) => {\n this.selectedTemplate = t;\n this.loadingTemplate = false;\n this.loadStepCandidates(t.steps);\n },\n error: () => { this.loadingTemplate = false; }\n });\n }\n\n private loadStepCandidates(steps: ApprovalTemplateStepDto[]) {\n this.stepCandidates = steps.map(() => []);\n this.stepLoadingCandidates = steps.map(() => false);\n this.stepSelectedUsers = steps.map(() => '');\n\n const config = this.mesAuth.getConfig();\n\n steps.forEach((step, i) => {\n if (step.roles && step.roles.length > 0) {\n // Role-based: fetch candidates via role preview\n this.stepLoadingCandidates[i] = true;\n const calls = step.roles.map(r => this.approvalSvc!.previewRole(r.orgCode, r.positionLevel));\n forkJoin(calls.length > 0 ? calls : [of([] as RolePreviewUserDto[])])\n .pipe(takeUntil(this.destroy$))\n .subscribe({\n next: results => {\n const merged = new Map<string, RolePreviewUserDto>();\n results.forEach(list => list.forEach(u => merged.set(u.userId, u)));\n this.stepCandidates[i] = Array.from(merged.values());\n this.stepLoadingCandidates[i] = false;\n },\n error: () => { this.stepLoadingCandidates[i] = false; }\n });\n } else if (step.assigneeUserIds && step.assigneeUserIds.length > 0 && config) {\n // Search-selected employees: resolve IDs to display names\n this.stepLoadingCandidates[i] = true;\n const base = config.apiBaseUrl.replace(/\\/$/, '');\n const opts = { withCredentials: config.withCredentials ?? true };\n const calls = step.assigneeUserIds.map(uid =>\n this.http.get<any>(`${base}/urs/users/${encodeURIComponent(uid)}`, opts)\n );\n forkJoin(calls)\n .pipe(takeUntil(this.destroy$))\n .subscribe({\n next: results => {\n this.stepCandidates[i] = results.map((u: any) => ({\n userId: u.id || u.Id,\n fullName: u.fullName || u.FullName || u.userName || u.UserName,\n department: u.department || u.Department,\n position: u.position || u.Position\n } as RolePreviewUserDto));\n // Single assignee — pre-select automatically\n if (this.stepCandidates[i].length === 1) {\n this.stepSelectedUsers[i] = this.stepCandidates[i][0].userId;\n }\n this.stepLoadingCandidates[i] = false;\n },\n error: () => { this.stepLoadingCandidates[i] = false; }\n });\n }\n });\n }\n\n onStepUserChange(stepIndex: number, event: Event) {\n this.stepSelectedUsers[stepIndex] = (event.target as HTMLSelectElement).value;\n }\n\n onTemplateChange(event: Event) {\n const val = (event.target as HTMLSelectElement).value;\n this.selectedTemplateId = val ? parseInt(val, 10) : null;\n this.selectedTemplate = null;\n if (this.selectedTemplateId) {\n this.loadTemplateDetail(this.selectedTemplateId);\n }\n }\n\n addStep() {\n const order = this.adHocSteps.length + 1;\n this.adHocSteps.push({ stepOrder: order, stepName: `Step ${order}`, approverUserIds: [] });\n this.userSearchQuery.push('');\n this.userSearchResults.push([]);\n }\n\n removeStep(i: number) {\n this.adHocSteps.splice(i, 1);\n this.userSearchQuery.splice(i, 1);\n this.userSearchResults.splice(i, 1);\n this.adHocSteps.forEach((s, idx) => s.stepOrder = idx + 1);\n }\n\n addApprover(stepIndex: number, userId: string) {\n if (!this.adHocSteps[stepIndex].approverUserIds.includes(userId)) {\n this.adHocSteps[stepIndex].approverUserIds.push(userId);\n }\n this.storeLabelFromResults(userId, this.userSearchResults[stepIndex]);\n this.userSearchQuery[stepIndex] = '';\n this.userSearchResults[stepIndex] = [];\n }\n\n removeApprover(stepIndex: number, approverIndex: number) {\n this.adHocSteps[stepIndex].approverUserIds.splice(approverIndex, 1);\n }\n\n addReference(userId: string) {\n if (!this.referenceUserIds.includes(userId)) {\n this.referenceUserIds.push(userId);\n }\n this.storeLabelFromResults(userId, this.refSearchResults);\n this.refSearchQuery = '';\n this.refSearchResults = [];\n }\n\n private storeLabelFromResults(userId: string, results: any[]) {\n const user = results.find((u: any) => u.id === userId);\n if (user) {\n const parts = [user.department, user.position, user.fullName].filter(Boolean);\n this.userLabelMap[userId] = parts.length > 0 ? parts.join(' - ') : (user.userName || userId);\n }\n }\n\n removeReference(j: number) {\n this.referenceUserIds.splice(j, 1);\n }\n\n onUserSearchInput(stepIndex: number, query: string) {\n this.userSearchQuery[stepIndex] = query;\n if (!query || query.length < 2) { this.userSearchResults[stepIndex] = []; return; }\n this.searchUsers(query).then(r => this.userSearchResults[stepIndex] = r);\n }\n\n onRefSearchInput(query: string) {\n this.refSearchQuery = query;\n if (!query || query.length < 2) { this.refSearchResults = []; return; }\n this.searchUsers(query).then(r => this.refSearchResults = r);\n }\n\n private searchUsers(query: string): Promise<any[]> {\n const config = this.mesAuth.getConfig();\n if (!config) return Promise.resolve([]);\n const url = `${config.apiBaseUrl.replace(/\\/$/, '')}/urs/users?search=${encodeURIComponent(query)}&page=1&pageSize=20`;\n return this.http.get<any>(url, { withCredentials: config.withCredentials ?? true })\n .toPromise()\n .then((r: any) => {\n const items = r?.data || r?.Data || r?.items || r || [];\n // Normalize PascalCase to camelCase for template binding\n return (Array.isArray(items) ? items : []).map((u: any) => ({\n id: u.id || u.Id,\n userName: u.userName || u.UserName,\n fullName: u.fullName || u.FullName,\n email: u.email || u.Email,\n department: u.department || u.Department,\n position: u.position || u.Position\n }));\n })\n .catch(() => []);\n }\n\n async submit() {\n if (this.submitting) return;\n this.errorMessage = '';\n\n if (!this.approvalSvc) { this.errorMessage = 'Approval service not initialized. Ensure provideMesAuth() is configured.'; return; }\n if (!this.referenceId) { this.errorMessage = 'ReferenceId is required.'; return; }\n if (!this.title) { this.errorMessage = 'Title is required.'; return; }\n\n if (this.routingMode === 'template' && !this.selectedTemplateId && !this.templateId) {\n this.errorMessage = 'Please select a template or switch to Custom Steps.'; return;\n }\n if (this.routingMode === 'adhoc' && this.adHocSteps.length === 0) {\n this.errorMessage = 'Please add at least one approval step.'; return;\n }\n // Validate selectable steps (role-based or multi-assignee) have a selected approver\n if (this.routingMode === 'template' && this.selectedTemplate) {\n for (let i = 0; i < this.selectedTemplate.steps.length; i++) {\n const step = this.selectedTemplate.steps[i];\n const isSelectable = (this.stepCandidates[i]?.length ?? 0) > 1;\n if (isSelectable && !this.stepSelectedUsers[i]) {\n this.errorMessage = `Please select an approver for step \"${step.stepName}\".`; return;\n }\n }\n }\n\n // Emit before capture so parent can hide edit controls (inputs, buttons)\n // then wait one tick for Angular CD to update the DOM before snapshotting\n this.approvalSubmitting.emit();\n await new Promise(resolve => setTimeout(resolve));\n\n this.submitting = true;\n\n try {\n const contentHtml = await this.captureContent();\n const thumbnailBase64 = await this.captureThumbnail().catch(() => undefined);\n\n const request: CreateApprovalRequest = {\n title: this.title,\n description: this.description,\n contentHtml,\n thumbnailBase64,\n referenceId: this.referenceId,\n callbackUrl: this.callbackUrl,\n deadlineHours: this.deadlineHours,\n referenceUserIds: this.referenceUserIds.length > 0 ? this.referenceUserIds : undefined\n };\n\n if (this.routingMode === 'template') {\n request.templateId = this.selectedTemplateId ?? this.templateId;\n // If template has role-based steps with selected approvers, pass explicit steps\n if (this.selectedTemplate) {\n const hasSelectableSteps = this.selectedTemplate.steps.some(\n (s, i) => (this.stepCandidates[i]?.length ?? 0) > 0\n );\n if (hasSelectableSteps) {\n request.steps = this.selectedTemplate.steps.map((s, i) => ({\n stepOrder: s.stepOrder,\n stepName: s.stepName,\n mode: s.mode,\n approverUserIds: this.stepSelectedUsers[i]\n ? [this.stepSelectedUsers[i]]\n : s.assigneeUserIds\n }));\n }\n }\n } else {\n request.steps = this.adHocSteps.map((s, i) => ({\n stepOrder: i + 1,\n stepName: s.stepName,\n mode: ApprovalStepMode.Sequential,\n approverUserIds: s.approverUserIds\n }));\n }\n\n this.approvalSvc!.createApproval(request).pipe(takeUntil(this.destroy$)).subscribe({\n next: (result) => {\n this.isSubmitted = true;\n this.submitting = false;\n this.approvalSubmitted.emit({ documentId: result.documentId, message: result.message });\n },\n error: (err) => {\n this.submitting = false;\n this.errorMessage = err?.error?.message || 'Failed to submit approval. Please try again.';\n }\n });\n } catch (err: any) {\n this.submitting = false;\n this.errorMessage = err?.message || 'Failed to capture content.';\n }\n }\n\n onCancel() {\n this.cancelled.emit();\n }\n\n // ====================== Content Capture ======================\n\n async captureContent(): Promise<string> {\n const host = this.contentBody.nativeElement;\n\n // Step 1: Build canvas -> img map from the live DOM\n const canvasMap = new Map<Element, HTMLImageElement>();\n host.querySelectorAll('canvas').forEach((canvas) => {\n try {\n const img = document.createElement('img');\n img.src = (canvas as HTMLCanvasElement).toDataURL('image/png');\n img.style.width = canvas.offsetWidth + 'px';\n img.style.height = canvas.offsetHeight + 'px';\n canvasMap.set(canvas, img);\n } catch {}\n });\n\n // Step 2: Deep clone\n const clone = host.cloneNode(true) as HTMLElement;\n\n // Step 3: Replace canvas nodes in clone with img snapshots\n const originalCanvases = Array.from(host.querySelectorAll('canvas'));\n clone.querySelectorAll('canvas').forEach((cloneCanvas, idx) => {\n const img = canvasMap.get(originalCanvases[idx]);\n if (img) cloneCanvas.replaceWith(img.cloneNode(true));\n });\n\n // Step 4: Inline all <img> sources as base64 data URIs for content integrity\n const imgElements = Array.from(clone.querySelectorAll('img')) as HTMLImageElement[];\n await Promise.all(imgElements.map(async (img) => {\n const src = img.getAttribute('src');\n if (!src || src.startsWith('data:')) return;\n try {\n const resp = await fetch(src, { mode: 'cors', credentials: 'same-origin' });\n if (!resp.ok) return;\n const blob = await resp.blob();\n const dataUri = await new Promise<string>((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result as string);\n reader.readAsDataURL(blob);\n });\n img.setAttribute('src', dataUri);\n } catch { /* keep original src if fetch fails */ }\n }));\n\n // Step 5: Inline only essential layout styles (skip colors, widths, cursors)\n const liveElements = Array.from(host.querySelectorAll('*'));\n const cloneElements = Array.from(clone.querySelectorAll('*'));\n const styleProps = this.getStyleProperties();\n\n liveElements.forEach((liveEl, i) => {\n const cloneEl = cloneElements[i] as HTMLElement;\n if (!cloneEl || typeof cloneEl.setAttribute !== 'function') return;\n try {\n const computed = window.getComputedStyle(liveEl as Element);\n const styles: string[] = [];\n styleProps.forEach(prop => {\n const val = computed.getPropertyValue(prop);\n if (val && val !== '' && val !== 'initial' && val !== 'normal' && val !== 'none' && val !== 'auto') {\n styles.push(`${prop}:${val}`);\n }\n });\n if (styles.length) cloneEl.setAttribute('style', styles.join(';'));\n } catch {}\n });\n\n // Step 6: Strip scripts, Angular attributes, style/link tags, and form elements\n clone.querySelectorAll('script, link, style').forEach(el => el.remove());\n clone.querySelectorAll('*').forEach(el => {\n // Remove Angular-specific attributes\n Array.from(el.attributes).forEach(attr => {\n if (attr.name.startsWith('_ngcontent-') ||\n attr.name.startsWith('_nghost-') ||\n attr.name.startsWith('ng-reflect-') ||\n attr.name.startsWith('ng-version') ||\n attr.name.startsWith('on') ||\n attr.name === 'cformcontrol' ||\n attr.name === 'clabel') {\n el.removeAttribute(attr.name);\n }\n });\n // Remove class attribute (framework-specific classes add no value)\n el.removeAttribute('class');\n });\n\n // Step 7: Wrap in a clean, print-friendly HTML document\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n *, *::before, *::after { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n margin: 0; padding: 24px;\n color: #212121; background: #fff;\n font-size: 14px; line-height: 1.6;\n max-width: 210mm;\n }\n h1, h2, h3, h4, h5, h6 { color: #1565c0; margin: 0 0 12px; }\n p { margin: 0 0 8px; }\n img { max-width: 100%; }\n table { border-collapse: collapse; width: 100%; }\n td, th { padding: 8px 12px; border: 1px solid #ddd; text-align: left; vertical-align: top; }\n input, textarea, select { \n border: 1px solid #ccc; border-radius: 4px; padding: 6px 10px;\n font-size: 14px; width: 100%; background: #fafafa; color: #333;\n }\n label { font-weight: 500; display: block; margin-bottom: 4px; color: #333; }\n div { max-width: 100%; }\n </style>\n</head>\n<body>\n${clone.outerHTML}\n</body>\n</html>`;\n }\n\n private async captureThumbnail(): Promise<string | undefined> {\n const html2canvas = (window as any)['html2canvas'];\n if (!html2canvas) return undefined;\n\n const canvas: HTMLCanvasElement = await html2canvas(this.contentBody.nativeElement, {\n scale: 1, useCORS: true, logging: false, width: 600, height: 400\n });\n return canvas.toDataURL('image/png').split(',')[1];\n }\n\n private getStyleProperties(): string[] {\n // Only capture essential layout/typography — NOT colors, widths, or cursor styles\n // Colors and backgrounds are handled by the clean document stylesheet instead\n return [\n 'font-size', 'font-weight', 'font-style', 'line-height', 'text-align', 'text-decoration',\n 'border', 'border-top', 'border-right', 'border-bottom', 'border-left',\n 'border-width', 'border-style', 'border-radius',\n 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'display', 'flex-direction', 'flex-wrap', 'justify-content', 'align-items', 'gap',\n 'vertical-align', 'table-layout', 'border-collapse', 'border-spacing',\n 'text-transform', 'letter-spacing', 'white-space', 'word-break'\n ];\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.MesAuthService","i3.ThemeService","i1.ToastService","i2.ThemeService","i2.ToastService"],"mappings":"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"}
1
+ {"version":3,"file":"mesauth-angular.mjs","sources":["../../src/mes-auth.service.ts","../../src/mes-auth.interceptor.ts","../../src/mes-auth.module.ts","../../src/theme.service.ts","../../src/user-profile.component.ts","../../src/toast.service.ts","../../src/toast-container.component.ts","../../src/notification-panel.component.ts","../../src/approval.service.ts","../../src/approval.models.ts","../../src/ma-approval-panel.component.ts","../../src/ma-user.component.ts","../../src/notification-badge.component.ts","../../src/ma-arv-container.component.ts","../../src/x-ma-perm.pipe.ts","../../src/x-ma-resource.ts","../../src/mesauth-angular.ts"],"sourcesContent":["import { inject, Injectable, InjectionToken, EnvironmentProviders, makeEnvironmentProviders, provideAppInitializer, NgZone } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { HubConnection, HubConnectionBuilder, LogLevel } from '@microsoft/signalr';\nimport { BehaviorSubject, Subject, Observable, of, EMPTY } from 'rxjs';\nimport { tap, catchError } from 'rxjs/operators';\nimport { Router } from '@angular/router';\n\nexport interface MesAuthConfig {\n apiBaseUrl: string;\n withCredentials?: boolean;\n userBaseUrl?: string;\n}\n\n/** Injection token for MesAuth configuration */\nexport const MES_AUTH_CONFIG = new InjectionToken<MesAuthConfig>('MES_AUTH_CONFIG');\n\n/**\n * Provides MesAuth with configuration.\n * This is the recommended way to set up mesauth-angular in standalone apps.\n *\n * @example\n * ```typescript\n * // app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideHttpClient(withInterceptors([mesAuthInterceptor])),\n * provideMesAuth({\n * apiBaseUrl: 'https://auth.example.com',\n * userBaseUrl: 'https://app.example.com'\n * })\n * ]\n * };\n * ```\n */\nexport function provideMesAuth(config: MesAuthConfig): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: MES_AUTH_CONFIG, useValue: config },\n MesAuthService,\n provideAppInitializer(() => {\n const mesAuthService = inject(MesAuthService);\n const httpClient = inject(HttpClient);\n const router = inject(Router);\n const ngZone = inject(NgZone);\n mesAuthService.init(config, httpClient, router, ngZone);\n })\n ]);\n}\n\nexport interface IUser {\n userId?: string;\n userName?: string;\n fullName?: string;\n gender?: string;\n email?: string;\n phoneNumber?: string;\n department?: string;\n position?: string;\n tokenVersion?: string;\n permEndpoint?: string;\n perms?: Set<string>;\n employeeCode?: string;\n avatarPath?: string;\n loginMethod?: number;\n hrFullNameVn?: string;\n hrFullNameEn?: string;\n hrPosition?: string;\n hrJobTitle?: string;\n hrGender?: string;\n hrMobile?: string;\n hrEmail?: string;\n hrJoinDate?: string;\n hrBirthDate?: string;\n hrWorkStatus?: string;\n hrDoiTuong?: string;\n hrTeamCode?: string;\n hrLineCode?: string;\n}\n\nexport enum NotificationType {\n Info = 'Info',\n Warning = 'Warning',\n Error = 'Error',\n Success = 'Success'\n}\n\nexport interface NotificationDto {\n id: string;\n title: string;\n message: string;\n messageHtml?: string;\n url?: string;\n type: NotificationType;\n isRead: boolean;\n createdAt: string;\n sourceAppName: string;\n sourceAppIconUrl?: string;\n}\n\nexport interface FrontEndRoute {\n id: number;\n roleId: string;\n roleName: string;\n routePath: string;\n routeName: string;\n description?: string;\n icon?: string;\n cssClass?: string;\n parentId?: number | null;\n sortOrder: number;\n isLabel: boolean;\n isActive: boolean;\n createdAt: string;\n updatedAt?: string;\n children: FrontEndRoute[];\n}\n\nexport interface UserFrontEndRoutesGrouped {\n appId: string;\n appName: string;\n feUrl?: string;\n routes: FrontEndRoute[];\n}\n\nexport interface PagedList<T> {\n items: T[];\n totalCount: number;\n page: number;\n pageSize: number;\n totalPages: number;\n hasNext: boolean;\n hasPrevious: boolean;\n}\n\nexport interface RealTimeNotificationDto {\n id: string;\n title: string;\n message: string;\n messageHtml?: string;\n url?: string;\n type: NotificationType;\n createdAt: string;\n sourceAppName: string;\n sourceAppIconUrl?: string;\n}\n\n@Injectable()\nexport class MesAuthService {\n private hubConnection: HubConnection | null = null;\n private _currentUser = new BehaviorSubject<IUser | null>(null);\n public currentUser$: Observable<IUser | null> = this._currentUser.asObservable();\n private _notifications = new Subject<any>();\n public notifications$: Observable<any> = this._notifications.asObservable();\n private _approvalEvents = new Subject<any>();\n public approvalEvents$: Observable<any> = this._approvalEvents.asObservable();\n\n private apiBase = '';\n private config: MesAuthConfig | null = null;\n private http!: HttpClient;\n private router?: Router;\n private ngZone: NgZone | null = null;\n\n constructor() {\n // Empty constructor - all dependencies passed to init()\n }\n\n init(config: MesAuthConfig, httpClient: HttpClient, router?: Router, ngZone?: NgZone) {\n this.config = config;\n this.http = httpClient;\n this.router = router;\n this.ngZone = ngZone ?? null;\n this.apiBase = config.apiBaseUrl.replace(/\\/$/, '');\n\n // Fetch user once on init. Route changes do NOT re-fetch the user.\n // Auth state is maintained via cookies; 401 errors are handled by HTTP interceptors.\n // SignalR handles real-time notification delivery without polling.\n this.fetchCurrentUser().subscribe();\n }\n\n getConfig(): MesAuthConfig | null {\n return this.config;\n }\n\n private fetchCurrentUser(): Observable<any> {\n if (!this.apiBase) return EMPTY;\n const url = `${this.apiBase}/auth/me`;\n return this.http.get(url, { withCredentials: this.config?.withCredentials ?? true }).pipe(\n tap((u) => {\n this._currentUser.next(u);\n if (u && this.config) {\n this.startConnection(this.config);\n }\n }),\n catchError((err) => {\n // Silently handle auth errors (401/403) - user is not logged in\n if (err.status === 401 || err.status === 403) {\n this._currentUser.next(null);\n }\n return of(null);\n })\n );\n }\n\n public getUnreadCount(): Observable<any> {\n return this.http.get(`${this.apiBase}/notif/me/unread-count`, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public getNotifications(page: number = 1, pageSize: number = 20, includeRead: boolean = false, type?: string): Observable<any> {\n let url = `${this.apiBase}/notif/me?page=${page}&pageSize=${pageSize}&includeRead=${includeRead}`;\n if (type) {\n url += `&type=${type}`;\n }\n return this.http.get(url, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public markAsRead(notificationId: string): Observable<any> {\n return this.http.patch(`${this.apiBase}/notif/${notificationId}/read`, {}, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public markAllAsRead(): Observable<any> {\n return this.http.patch(`${this.apiBase}/notif/me/read-all`, {}, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n public deleteNotification(notificationId: string): Observable<any> {\n return this.http.delete(`${this.apiBase}/notif/${notificationId}`, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n /**\n * Get frontend routes assigned to the current user\n * Returns routes grouped by application\n */\n public getFrontEndRoutes(): Observable<UserFrontEndRoutesGrouped[]> {\n if (!this.apiBase) throw new Error('MesAuth not initialized');\n return this.http.get<UserFrontEndRoutesGrouped[]>(`${this.apiBase}/fe-routes/me`, { withCredentials: this.config?.withCredentials ?? true });\n }\n\n private startConnection(config: MesAuthConfig) {\n if (this.hubConnection) return;\n const signalrUrl = config.apiBaseUrl.replace(/\\/$/, '') + '/hub/notification';\n const builder = new HubConnectionBuilder()\n .withUrl(signalrUrl, { withCredentials: config.withCredentials ?? true })\n .withAutomaticReconnect()\n .configureLogging(LogLevel.Warning);\n\n this.hubConnection = builder.build();\n\n this.hubConnection.on('ReceiveNotification', (n: any) => {\n if (this.ngZone) {\n this.ngZone.run(() => this._notifications.next(n));\n } else {\n this._notifications.next(n);\n }\n });\n\n this.hubConnection.on('ApprovalCompleted', (e: any) => {\n if (this.ngZone) {\n this.ngZone.run(() => this._approvalEvents.next({ type: 'ApprovalCompleted', ...e }));\n } else {\n this._approvalEvents.next({ type: 'ApprovalCompleted', ...e });\n }\n });\n\n this.hubConnection.on('ApprovalStepChanged', (e: any) => {\n if (this.ngZone) {\n this.ngZone.run(() => this._approvalEvents.next({ type: 'ApprovalStepChanged', ...e }));\n } else {\n this._approvalEvents.next({ type: 'ApprovalStepChanged', ...e });\n }\n });\n\n this.hubConnection.start().then(() => {}).catch((err) => {});\n\n this.hubConnection.onclose(() => {});\n this.hubConnection.onreconnecting(() => {});\n this.hubConnection.onreconnected(() => {});\n }\n\n public stop() {\n if (!this.hubConnection) return;\n this.hubConnection.stop().catch(() => {});\n this.hubConnection = null;\n }\n\n public logout(): Observable<any> {\n const url = `${this.apiBase}/auth/logout`;\n return this.http.post(url, {}, { withCredentials: this.config?.withCredentials ?? true }).pipe(\n tap(() => {\n this._currentUser.next(null);\n this.stop();\n })\n );\n }\n\n public get currentUser(): IUser | null {\n return this._currentUser.value;\n }\n\n public get isAuthenticated(): boolean {\n return this._currentUser.value !== null;\n }\n\n /**\n * Refreshes the current user from the server.\n * Returns an Observable that completes when the user data is loaded.\n * Callers can subscribe to wait for completion before proceeding (e.g., navigating after login).\n */\n public refreshUser(): Observable<any> {\n return this.fetchCurrentUser();\n }\n}\n","import { inject } from '@angular/core';\nimport { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';\nimport { throwError, timer } from 'rxjs';\nimport { catchError, switchMap } from 'rxjs/operators';\nimport { Router } from '@angular/router';\nimport { MesAuthService } from './mes-auth.service';\n\n// Track if we're currently redirecting to prevent loopback\nlet isRedirecting = false;\n\ninterface PermissionHeader {\n resource: string;\n allowedActions: string[];\n}\n/**\n * Functional HTTP interceptor for handling 401/403 auth errors.\n * Redirects to login page on 401, and to 403 page on 403.\n * Includes loopback prevention to avoid infinite redirects.\n */\nexport const mesAuthInterceptor: HttpInterceptorFn = (req, next) => {\n const authService = inject(MesAuthService);\n const router = inject(Router);\n\n return next(req).pipe(\n catchError((error: HttpErrorResponse) => {\n const status = error.status;\n\n // Check if we should handle this error and prevent loopback\n if ((status === 401 || status === 403) && !isRedirecting) {\n const config = authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n\n const currentUrl = router.url + (window.location.hash || '');\n const returnUrl = encodeURIComponent(currentUrl);\n\n // Avoid loops if already on auth/unauth pages\n const isLoginPage = currentUrl.includes('/login');\n const is403Page = currentUrl.includes('/403');\n const isAuthPage = currentUrl.includes('/auth');\n // Public pages that should never trigger a 401 redirect (e.g., register, password reset)\n const isPublicPage = currentUrl.includes('/register')\n || currentUrl.includes('/forgot-password')\n || currentUrl.includes('/reset-password');\n // Skip redirect for the initial /auth/me check (app startup when not logged in)\n const isMeAuthPage = req.url.includes('/auth/me');\n\n if (status === 401 && !isLoginPage && !isAuthPage && !isMeAuthPage && !isPublicPage) {\n // Wait 1.5s for the concurrent refresh's Set-Cookie to be processed, then retry once.\n // If retry also gets 401, redirect to login.\n return timer(1500).pipe(\n switchMap(() => next(req)),\n catchError((retryError: HttpErrorResponse) => {\n if (retryError.status === 401) {\n isRedirecting = true;\n setTimeout(() => { isRedirecting = false; }, 5000);\n window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;\n }\n return throwError(() => retryError);\n })\n );\n } else if (status === 403 && !is403Page) {\n isRedirecting = true;\n setTimeout(() => { isRedirecting = false; }, 5000);\n let redirectUrl = `${baseUrl}/403?returnUrl=${returnUrl}`;\n if (error.error && error.error.required) {\n redirectUrl += `&required=${encodeURIComponent(error.error.required)}`;\n }\n window.location.href = redirectUrl;\n }\n }\n return throwError(() => error);\n })\n );\n};\n\n\nfunction appendPermissions(body: unknown, allowedActions: string[]): unknown {\n if (body === null || body === undefined) {\n return { 'x-ma-perms': allowedActions };\n }\n\n if (Array.isArray(body)) {\n return { data: body, 'x-ma-perms': allowedActions };\n }\n\n if (typeof body === 'object') {\n return { ...(body as object), 'x-ma-perms': allowedActions };\n }\n\n // Primitive (string, number, boolean)\n return { data: body, 'x-ma-perms': allowedActions };\n}","import { NgModule } from '@angular/core';\nimport { MesAuthService } from './mes-auth.service';\n\n@NgModule({\n providers: [\n MesAuthService\n ]\n})\nexport class MesAuthModule {}\n","import { Injectable, OnDestroy } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport type Theme = 'light' | 'dark';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ThemeService implements OnDestroy {\n private _currentTheme = new BehaviorSubject<Theme>('light');\n public currentTheme$: Observable<Theme> = this._currentTheme.asObservable();\n private observer: MutationObserver | null = null;\n\n constructor() {\n this.detectTheme();\n this.startWatching();\n }\n\n ngOnDestroy(): void {\n this.stopWatching();\n }\n\n private detectTheme(): void {\n const html = document.documentElement;\n const isDark = html.classList.contains('dark') ||\n html.getAttribute('data-theme') === 'dark' ||\n html.getAttribute('theme') === 'dark' ||\n html.getAttribute('data-coreui-theme') === 'dark';\n\n this._currentTheme.next(isDark ? 'dark' : 'light');\n }\n\n private startWatching(): void {\n if (typeof MutationObserver === 'undefined') {\n // Fallback for older browsers - check periodically\n setInterval(() => this.detectTheme(), 1000);\n return;\n }\n\n this.observer = new MutationObserver(() => {\n this.detectTheme();\n });\n\n this.observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'theme', 'data-coreui-theme']\n });\n }\n\n private stopWatching(): void {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n }\n\n get currentTheme(): Theme {\n return this._currentTheme.value;\n }\n\n // Method to manually set theme if needed\n setTheme(theme: Theme): void {\n this._currentTheme.next(theme);\n }\n\n // Re-detect theme from DOM\n refreshTheme(): void {\n this.detectTheme();\n }\n}","import { Component, OnInit, OnDestroy, Output, EventEmitter, HostBinding, HostListener, signal, ChangeDetectorRef } from '@angular/core';\nimport { NgIf } from '@angular/common';\nimport { Router } from '@angular/router';\nimport { HttpClient } from '@angular/common/http';\nimport { MesAuthService, IUser } from './mes-auth.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-user-profile',\n standalone: true,\n imports: [NgIf],\n template: `\n <div class=\"user-profile-container\">\n <!-- Not logged in -->\n <ng-container *ngIf=\"!currentUser()\">\n <button class=\"login-btn\" (click)=\"onLogin()\">Login</button>\n </ng-container>\n\n <!-- Logged in -->\n <ng-container *ngIf=\"currentUser()\">\n <div class=\"user-header\">\n <!-- Notification Bell -->\n <button class=\"notification-btn\" [class.has-unread]=\"unreadCount > 0\" (click)=\"onNotificationClick()\" title=\"Notifications\" aria-label=\"Notifications\">\n <svg class=\"bell-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <span class=\"badge\" *ngIf=\"unreadCount > 0\">{{ unreadCount > 99 ? '99+' : unreadCount }}</span>\n </button>\n\n <!-- Approval Button -->\n <button class=\"notification-btn\" [class.has-unread]=\"pendingApprovalCount > 0\" (click)=\"onApprovalClick()\" title=\"Approvals\" aria-label=\"Approvals\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9 11l3 3L22 4\"/>\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\"/>\n </svg>\n <span class=\"badge\" *ngIf=\"pendingApprovalCount > 0\">{{ pendingApprovalCount > 99 ? '99+' : pendingApprovalCount }}</span>\n </button>\n\n <!-- User Avatar + Dropdown -->\n <div class=\"user-menu-wrapper\">\n <button class=\"user-menu-btn\" (click)=\"toggleDropdown()\" [attr.aria-label]=\"'User menu for ' + (currentUser().fullName || currentUser().userName)\" aria-haspopup=\"true\" [attr.aria-expanded]=\"dropdownOpen\">\n <div class=\"avatar-ring\" [class.active]=\"dropdownOpen\">\n <img\n *ngIf=\"currentUser().fullName || currentUser().userName\"\n [src]=\"getAvatarUrl(currentUser())\"\n [alt]=\"currentUser().fullName || currentUser().userName\"\n class=\"avatar\"\n />\n <span *ngIf=\"!(currentUser().fullName || currentUser().userName)\" class=\"avatar-initial\">\n {{ getLastNameInitial(currentUser()) }}\n </span>\n </div>\n </button>\n\n <div class=\"mes-dropdown-menu\" *ngIf=\"dropdownOpen\">\n <!-- User info header -->\n <div class=\"mes-dropdown-header\">\n <div class=\"dropdown-avatar-wrap\">\n <img\n *ngIf=\"currentUser().fullName || currentUser().userName\"\n [src]=\"getAvatarUrl(currentUser())\"\n [alt]=\"currentUser().fullName || currentUser().userName\"\n class=\"dropdown-avatar\"\n />\n <span *ngIf=\"!(currentUser().fullName || currentUser().userName)\" class=\"dropdown-avatar-initial\">\n {{ getLastNameInitial(currentUser()) }}\n </span>\n </div>\n <div class=\"dropdown-user-info\">\n <span class=\"dropdown-user-name\">{{ currentUser().fullName || currentUser().userName }}</span>\n <span class=\"dropdown-user-sub\" *ngIf=\"currentUser().position || currentUser().department\">\n {{ currentUser().position || currentUser().department }}\n </span>\n </div>\n </div>\n\n <div class=\"mes-dropdown-divider\"></div>\n\n <button class=\"mes-dropdown-item profile-link\" (click)=\"onViewProfile()\">\n <svg class=\"item-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/>\n </svg>\n View Profile\n </button>\n\n <div class=\"mes-dropdown-divider\"></div>\n\n <button class=\"mes-dropdown-item logout-item\" (click)=\"onLogout()\">\n <svg class=\"item-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\"/><polyline points=\"16 17 21 12 16 7\"/><line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/>\n </svg>\n Logout\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n `,\n styles: [`\n :host {\n --primary-color: #1976d2;\n --primary-hover: #1565c0;\n --primary-light: rgba(25, 118, 210, 0.12);\n --primary-glow: rgba(25, 118, 210, 0.3);\n --error-color: #f44336;\n --error-light: rgba(244, 67, 54, 0.1);\n --text-primary: #212121;\n --text-secondary: #616161;\n --text-muted: #9e9e9e;\n --bg-primary: #ffffff;\n --bg-secondary: #f8f9fa;\n --bg-hover: #f0f4ff;\n --border-color: #e0e0e0;\n --shadow: rgba(0, 0, 0, 0.12);\n --shadow-lg: rgba(0, 0, 0, 0.18);\n }\n\n :host(.theme-dark) {\n --primary-color: #90caf9;\n --primary-hover: #64b5f6;\n --primary-light: rgba(144, 202, 249, 0.12);\n --primary-glow: rgba(144, 202, 249, 0.25);\n --error-color: #ef5350;\n --error-light: rgba(239, 83, 80, 0.12);\n --text-primary: #e0e0e0;\n --text-secondary: #b0b0b0;\n --text-muted: #757575;\n --bg-primary: #1e1e2e;\n --bg-secondary: #27273a;\n --bg-hover: #2a2d4a;\n --border-color: #383850;\n --shadow: rgba(0, 0, 0, 0.35);\n --shadow-lg: rgba(0, 0, 0, 0.5);\n }\n\n .user-profile-container {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .login-btn {\n padding: 7px 18px;\n background-color: var(--primary-color);\n color: white;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-weight: 500;\n font-size: 13px;\n letter-spacing: 0.2px;\n transition: background-color 0.2s, transform 0.15s;\n }\n\n .login-btn:hover {\n background-color: var(--primary-hover);\n transform: translateY(-1px);\n }\n\n .user-header {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n /* ── Bell button ── */\n .notification-btn {\n position: relative;\n background: none;\n border: none;\n cursor: pointer;\n padding: 8px;\n border-radius: 10px;\n color: var(--text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.2s, background-color 0.2s;\n }\n\n .notification-btn:hover {\n background-color: var(--primary-light);\n color: var(--primary-color);\n }\n\n .notification-btn.has-unread {\n color: var(--primary-color);\n }\n\n .bell-icon {\n display: block;\n transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .notification-btn:hover .bell-icon {\n transform: rotate(-20deg) scale(1.15);\n }\n\n .badge {\n position: absolute;\n top: 2px;\n right: 2px;\n background-color: var(--error-color);\n color: white;\n border-radius: 10px;\n min-width: 17px;\n height: 17px;\n padding: 0 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n box-shadow: 0 0 0 2px var(--bg-primary);\n animation: badge-pop 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n @keyframes badge-pop {\n from { transform: scale(0); }\n to { transform: scale(1); }\n }\n\n /* ── Avatar ── */\n .user-menu-wrapper {\n position: relative;\n }\n\n .user-menu-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 2px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s;\n }\n\n .user-menu-btn:hover {\n transform: scale(1.06);\n }\n\n .avatar-ring {\n border-radius: 50%;\n padding: 2px;\n border: 2px solid transparent;\n transition: border-color 0.25s, box-shadow 0.25s;\n }\n\n .avatar-ring.active,\n .user-menu-btn:hover .avatar-ring {\n border-color: var(--primary-color);\n box-shadow: 0 0 0 3px var(--primary-glow);\n }\n\n .avatar {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n object-fit: cover;\n display: block;\n }\n\n .avatar-initial {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 15px;\n }\n\n /* ── Dropdown ── */\n .mes-dropdown-menu {\n position: absolute;\n top: calc(100% + 10px);\n right: 0;\n background: var(--bg-primary);\n border: 1px solid var(--border-color);\n border-radius: 14px;\n box-shadow: 0 8px 32px var(--shadow-lg), 0 2px 8px var(--shadow);\n min-width: 220px;\n z-index: 1000;\n overflow: hidden;\n animation: dropdown-in 0.16s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n @keyframes dropdown-in {\n from { opacity: 0; transform: translateY(-8px) scale(0.96); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .mes-dropdown-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--bg-secondary);\n }\n\n .dropdown-avatar-wrap {\n flex-shrink: 0;\n }\n\n .dropdown-avatar {\n width: 46px;\n height: 46px;\n border-radius: 50%;\n object-fit: cover;\n border: 2px solid var(--primary-color);\n display: block;\n }\n\n .dropdown-avatar-initial {\n width: 46px;\n height: 46px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 18px;\n border: 2px solid var(--primary-color);\n }\n\n .dropdown-user-info {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n }\n\n .dropdown-user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .dropdown-user-sub {\n font-size: 11px;\n color: var(--primary-color);\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .mes-dropdown-divider {\n height: 1px;\n background: var(--border-color);\n }\n\n .mes-dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 11px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 13.5px;\n font-weight: 500;\n transition: background-color 0.15s;\n }\n\n .item-icon {\n flex-shrink: 0;\n opacity: 0.8;\n }\n\n .profile-link {\n color: var(--primary-color);\n }\n\n .profile-link:hover {\n background-color: var(--primary-light);\n }\n\n .logout-item {\n color: var(--error-color);\n }\n\n .logout-item:hover {\n background-color: var(--error-light);\n }\n\n @media (max-width: 768px) {\n .avatar, .avatar-initial { width: 32px; height: 32px; font-size: 13px; }\n }\n `]\n})\nexport class UserProfileComponent implements OnInit, OnDestroy {\n @Output() notificationClick = new EventEmitter<void>();\n @Output() approvalClick = new EventEmitter<void>();\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n\n currentUser = signal<IUser | null>(null);\n currentTheme: Theme = 'light';\n unreadCount = 0;\n pendingApprovalCount = 0;\n dropdownOpen = false;\n private hasUser = false;\n private destroy$ = new Subject<void>();\n\n // Signal to force avatar refresh\n avatarRefresh = signal<number>(Date.now());\n\n constructor(private authService: MesAuthService, private router: Router, private themeService: ThemeService, private cdr: ChangeDetectorRef, private http: HttpClient) {}\n\n ngOnInit() {\n this.authService.currentUser$\n .pipe(takeUntil(this.destroy$))\n .subscribe(user => {\n this.currentUser.set(user);\n this.hasUser = !!user;\n // Force avatar refresh when user changes\n this.avatarRefresh.set(Date.now());\n if (!this.hasUser) {\n this.unreadCount = 0;\n this.pendingApprovalCount = 0;\n } else {\n this.loadUnreadCount();\n this.loadPendingApprovalCount();\n }\n this.cdr.markForCheck();\n });\n\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n\n // Listen for approval events (SignalR) to refresh pending count\n this.authService.approvalEvents$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.hasUser) this.loadPendingApprovalCount();\n });\n\n // Listen for new real-time notifications (SignalR only)\n this.authService.notifications$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.hasUser) {\n this.loadUnreadCount();\n }\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n loadUnreadCount() {\n if (!this.hasUser) {\n this.unreadCount = 0;\n return;\n }\n\n this.authService.getUnreadCount().subscribe({\n next: (response: any) => {\n this.unreadCount = response.unreadCount || 0;\n },\n error: (err) => {}\n });\n }\n\n loadPendingApprovalCount() {\n if (!this.hasUser) { this.pendingApprovalCount = 0; return; }\n const config = this.authService.getConfig();\n if (!config) return;\n const url = `${config.apiBaseUrl.replace(/\\/$/, '')}/approval/dashboard`;\n this.http.get(url, { withCredentials: config.withCredentials ?? true }).subscribe({\n next: (r: any) => { this.pendingApprovalCount = r?.pendingCount ?? 0; },\n error: () => {}\n });\n }\n\n onApprovalClick() {\n this.approvalClick.emit();\n }\n\n getAvatarUrl(user: IUser): string {\n // Use the refresh signal to force update\n const refresh = this.avatarRefresh();\n const config = this.authService.getConfig();\n const baseUrl = config?.apiBaseUrl || '';\n \n // If user has avatarPath, use it directly\n if (user.avatarPath) {\n // If avatarPath is already a full URL, use it as-is\n if (user.avatarPath.startsWith('http://') || user.avatarPath.startsWith('https://')) {\n return user.avatarPath;\n }\n // If it's a relative path, construct full URL with refresh timestamp\n return `${baseUrl.replace(/\\/$/, '')}${user.avatarPath}?t=${refresh}`;\n }\n\n // Fallback: construct URL using userId\n const userId = user.userId;\n if (userId && baseUrl) {\n return `${baseUrl.replace(/\\/$/, '')}/auth/${userId}/avatar?t=${refresh}`;\n }\n \n // Fallback to UI avatars service if no userId or baseUrl\n const displayName = user.userName || user.userId || 'User';\n return `https://ui-avatars.com/api/?name=${encodeURIComponent(displayName)}&background=1976d2&color=fff`;\n }\n\n getLastNameInitial(user: IUser): string {\n const fullName = user.fullName || user.userName || 'U';\n const parts = fullName.split(' ');\n const lastPart = parts[parts.length - 1];\n return lastPart.charAt(0).toUpperCase();\n }\n\n toggleDropdown() {\n this.dropdownOpen = !this.dropdownOpen;\n }\n\n @HostListener('document:click', ['$event'])\n onDocumentClick(event: Event) {\n const target = event.target as HTMLElement;\n const clickedInside = target.closest('.user-menu-wrapper');\n if (!clickedInside) {\n this.dropdownOpen = false;\n }\n }\n\n onLogin() {\n const config = this.authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n const returnUrl = encodeURIComponent(this.router.url);\n window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;\n }\n\n onViewProfile() {\n this.router.navigate(['/profile']);\n this.dropdownOpen = false;\n }\n\n onLogout() {\n this.authService.logout().subscribe({\n next: () => {\n // Clear current user after successful logout\n this.dropdownOpen = false;\n \n // Navigate to login with return URL\n const config = this.authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n const returnUrl = encodeURIComponent(window.location.href);\n window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;\n },\n error: (err) => {\n // Still navigate to login even if logout fails\n const config = this.authService.getConfig();\n const baseUrl = config?.userBaseUrl || '';\n window.location.href = `${baseUrl}/login`;\n }\n });\n }\n\n onNotificationClick() {\n this.notificationClick.emit();\n }\n}\n\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\nexport interface Toast {\n id: string;\n message: string;\n title?: string;\n type: 'info' | 'success' | 'warning' | 'error';\n duration?: number;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ToastService {\n private toasts$ = new BehaviorSubject<Toast[]>([]);\n public toasts: Observable<Toast[]> = this.toasts$.asObservable();\n\n show(message: string, title?: string, type: 'info' | 'success' | 'warning' | 'error' = 'info', duration: number = 5000) {\n const id = Math.random().toString(36).substr(2, 9);\n const toast: Toast = {\n id,\n message,\n title,\n type,\n duration\n };\n\n const currentToasts = this.toasts$.value;\n this.toasts$.next([...currentToasts, toast]);\n\n if (duration > 0) {\n setTimeout(() => {\n this.remove(id);\n }, duration);\n }\n\n return id;\n }\n\n remove(id: string) {\n const currentToasts = this.toasts$.value;\n this.toasts$.next(currentToasts.filter(t => t.id !== id));\n }\n\n clear() {\n this.toasts$.next([]);\n }\n}\n","import { Component, OnInit, OnDestroy, HostBinding } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ToastService, Toast } from './toast.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-toast-container',\n standalone: true,\n imports: [CommonModule],\n template: `\n <div class=\"toast-container\">\n <div *ngFor=\"let toast of toasts\" class=\"toast toast-{{ toast.type }}\">\n\n <!-- Type icon -->\n <div class=\"toast-icon\">\n <svg *ngIf=\"toast.type === 'info'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/><path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <svg *ngIf=\"toast.type === 'success'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/><polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n <svg *ngIf=\"toast.type === 'warning'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/>\n </svg>\n <svg *ngIf=\"toast.type === 'error'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n </div>\n\n <!-- Content -->\n <div class=\"toast-content\">\n <div *ngIf=\"toast.title\" class=\"toast-title\">{{ toast.title }}</div>\n <div class=\"toast-message\" [innerHTML]=\"toast.message\"></div>\n </div>\n\n <!-- Close -->\n <button class=\"toast-close\" (click)=\"close(toast.id)\" aria-label=\"Close\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n\n <!-- Auto-dismiss progress bar — hidden when duration <= 0 (persistent toast) -->\n <div class=\"toast-progress\" *ngIf=\"toast.duration == null || toast.duration > 0\" [style.animation-duration]=\"(toast.duration ?? 5000) + 'ms'\"></div>\n </div>\n </div>\n `,\n styles: [`\n :host {\n --info-color: #2196f3;\n --info-bg: rgba(33, 150, 243, 0.1);\n --success-color: #43a047;\n --success-bg: rgba(67, 160, 71, 0.1);\n --warning-color: #f57c00;\n --warning-bg: rgba(245, 124, 0, 0.1);\n --error-color: #e53935;\n --error-bg: rgba(229, 57, 53, 0.1);\n --text-primary: #212121;\n --text-secondary: #757575;\n --bg-primary: #ffffff;\n --border-color: rgba(0, 0, 0, 0.08);\n --shadow: rgba(0, 0, 0, 0.1);\n --shadow-lg: rgba(0, 0, 0, 0.18);\n }\n\n :host(.theme-dark) {\n --info-color: #64b5f6;\n --info-bg: rgba(100, 181, 246, 0.12);\n --success-color: #66bb6a;\n --success-bg: rgba(102, 187, 106, 0.12);\n --warning-color: #ffb74d;\n --warning-bg: rgba(255, 183, 77, 0.12);\n --error-color: #ef5350;\n --error-bg: rgba(239, 83, 80, 0.12);\n --text-primary: #e0e0e0;\n --text-secondary: #9e9e9e;\n --bg-primary: #1e1e2e;\n --border-color: rgba(255, 255, 255, 0.08);\n --shadow: rgba(0, 0, 0, 0.35);\n --shadow-lg: rgba(0, 0, 0, 0.5);\n }\n\n .toast-container {\n position: fixed;\n top: 20px;\n right: 20px;\n z-index: 9999;\n pointer-events: none;\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .toast {\n position: relative;\n display: flex;\n align-items: flex-start;\n gap: 11px;\n padding: 13px 13px 16px 16px;\n border-radius: 12px;\n background: var(--bg-primary);\n border: 1px solid var(--border-color);\n box-shadow: 0 8px 28px var(--shadow-lg), 0 2px 8px var(--shadow);\n pointer-events: auto;\n min-width: 300px;\n max-width: 420px;\n overflow: hidden;\n animation: toast-in 0.35s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n @keyframes toast-in {\n from { opacity: 0; transform: translateX(36px) scale(0.96); }\n to { opacity: 1; transform: translateX(0) scale(1); }\n }\n\n /* Left accent bar via ::before */\n .toast::before {\n content: '';\n position: absolute;\n left: 0; top: 0; bottom: 0;\n width: 4px;\n border-radius: 12px 0 0 12px;\n }\n\n .toast-info::before { background: var(--info-color); }\n .toast-success::before { background: var(--success-color); }\n .toast-warning::before { background: var(--warning-color); }\n .toast-error::before { background: var(--error-color); }\n\n /* Type icon bubble */\n .toast-icon {\n flex-shrink: 0;\n width: 34px;\n height: 34px;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-left: 2px;\n }\n\n .toast-info .toast-icon { color: var(--info-color); background: var(--info-bg); }\n .toast-success .toast-icon { color: var(--success-color); background: var(--success-bg); }\n .toast-warning .toast-icon { color: var(--warning-color); background: var(--warning-bg); }\n .toast-error .toast-icon { color: var(--error-color); background: var(--error-bg); }\n\n .toast-content {\n flex: 1;\n min-width: 0;\n padding-top: 1px;\n }\n\n .toast-title {\n font-weight: 700;\n font-size: 13.5px;\n margin-bottom: 3px;\n line-height: 1.3;\n }\n\n .toast-info .toast-title { color: var(--info-color); }\n .toast-success .toast-title { color: var(--success-color); }\n .toast-warning .toast-title { color: var(--warning-color); }\n .toast-error .toast-title { color: var(--error-color); }\n\n .toast-message {\n font-size: 12.5px;\n line-height: 1.45;\n color: var(--text-secondary);\n }\n\n .toast-close {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--text-secondary);\n width: 26px;\n height: 26px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n padding: 0;\n transition: color 0.15s, background-color 0.15s;\n }\n\n .toast-close:hover {\n color: var(--text-primary);\n background: var(--border-color);\n }\n\n /* Auto-dismiss progress bar */\n .toast-progress {\n position: absolute;\n bottom: 0;\n left: 4px;\n right: 0;\n height: 3px;\n border-radius: 0 0 12px 0;\n animation: toast-progress linear forwards;\n opacity: 0.7;\n }\n\n .toast-info .toast-progress { background: var(--info-color); }\n .toast-success .toast-progress { background: var(--success-color); }\n .toast-warning .toast-progress { background: var(--warning-color); }\n .toast-error .toast-progress { background: var(--error-color); }\n\n @keyframes toast-progress {\n from { width: calc(100% - 4px); }\n to { width: 0; }\n }\n\n @media (max-width: 600px) {\n .toast-container { top: 10px; right: 10px; left: 10px; }\n .toast { min-width: auto; max-width: 100%; }\n }\n `]\n})\nexport class ToastContainerComponent implements OnInit, OnDestroy {\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n\n toasts: Toast[] = [];\n currentTheme: Theme = 'light';\n private destroy$ = new Subject<void>();\n\n constructor(private toastService: ToastService, private themeService: ThemeService) {}\n\n ngOnInit() {\n this.toastService.toasts\n .pipe(takeUntil(this.destroy$))\n .subscribe(toasts => {\n this.toasts = toasts;\n });\n\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n close(id: string) {\n this.toastService.remove(id);\n }\n}\n","import { Component, OnInit, OnDestroy, HostBinding, Output, EventEmitter, inject } from '@angular/core';\nimport { NgIf, NgFor } from '@angular/common';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { MesAuthService, NotificationDto, PagedList, RealTimeNotificationDto } from './mes-auth.service';\nimport { ToastService } from './toast.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-notification-panel',\n standalone: true,\n imports: [NgIf, NgFor],\n template: `\n <div class=\"notification-panel\" [class.open]=\"isOpen\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-header-left\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <h3>Notifications</h3>\n </div>\n <button class=\"close-btn\" (click)=\"close()\" title=\"Close\" aria-label=\"Close notifications\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs\">\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'unread'\" (click)=\"switchTab('unread')\">\n Unread\n <span class=\"tab-badge\" *ngIf=\"unreadNotifications.length > 0\">{{ unreadNotifications.length }}</span>\n </button>\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'read'\" (click)=\"switchTab('read')\">\n Read\n <span class=\"tab-badge read-badge\" *ngIf=\"readNotifications.length > 0\">{{ readNotifications.length }}</span>\n </button>\n </div>\n\n <!-- Notifications List -->\n <div class=\"notifications-list\">\n <ng-container *ngIf=\"currentNotifications.length > 0\">\n <div\n *ngFor=\"let notification of currentNotifications\"\n class=\"notification-item\"\n [class.unread]=\"!notification.isRead\"\n (click)=\"openDetails(notification)\"\n >\n @let t = typeOf(notification);\n <div class=\"notif-accent\"\n [class.type-info]=\"t === 'Info'\"\n [class.type-success]=\"t === 'Success'\"\n [class.type-warning]=\"t === 'Warning'\"\n [class.type-error]=\"t === 'Error'\"></div>\n <div class=\"notif-type-icon\"\n [class.type-info]=\"t === 'Info'\"\n [class.type-success]=\"t === 'Success'\"\n [class.type-warning]=\"t === 'Warning'\"\n [class.type-error]=\"t === 'Error'\">\n <svg *ngIf=\"t === 'Info'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/><path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <svg *ngIf=\"t === 'Success'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>\n <svg *ngIf=\"t === 'Warning'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/>\n </svg>\n <svg *ngIf=\"t === 'Error'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n </div>\n <div class=\"notification-content\">\n <div class=\"notification-title\">{{ notification.title }}</div>\n <div class=\"notification-message\">{{ getNotificationMessage(notification) }}</div>\n <div class=\"notification-meta\">\n <span class=\"app-name\">{{ notification.sourceAppName }}</span>\n <span class=\"time\">{{ dateLabels.get(notification.id) }}</span>\n </div>\n </div>\n <button class=\"icon-btn read-btn\" (click)=\"markAsRead(notification.id, $event)\" title=\"Mark as read\" aria-label=\"Mark as read\" *ngIf=\"!notification.isRead\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>\n </button>\n <button class=\"icon-btn delete-btn\" (click)=\"delete(notification.id, $event)\" title=\"Delete\" aria-label=\"Delete notification\" *ngIf=\"notification.isRead\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/><path d=\"M10 11v6\"/><path d=\"M14 11v6\"/><path d=\"M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/>\n </svg>\n </button>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"currentNotifications.length === 0\">\n <div class=\"empty-state\">\n <svg class=\"empty-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"44\" height=\"44\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <p>No {{ activeTab }} notifications</p>\n </div>\n </ng-container>\n </div>\n\n <!-- Footer Actions -->\n <div class=\"panel-footer\" *ngIf=\"currentNotifications.length > 0\">\n <div class=\"footer-actions\" *ngIf=\"activeTab === 'unread'\">\n <button class=\"action-btn\" (click)=\"markAllAsRead()\" *ngIf=\"unreadNotifications.length > 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>\n Mark all read\n </button>\n <button class=\"action-btn delete-all-btn\" (click)=\"deleteAllUnread()\" *ngIf=\"unreadNotifications.length > 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/></svg>\n Delete all\n </button>\n </div>\n <button class=\"action-btn delete-all-btn\" (click)=\"deleteAllRead()\" *ngIf=\"activeTab === 'read' && readNotifications.length > 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\"/></svg>\n Delete all\n </button>\n </div>\n </div>\n\n <!-- Details Modal -->\n <div class=\"modal-overlay\" *ngIf=\"selectedNotification\" (click)=\"closeDetails()\">\n <div class=\"modal-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\"\n [class.modal-type-info]=\"typeOf(selectedNotification) === 'Info'\"\n [class.modal-type-success]=\"typeOf(selectedNotification) === 'Success'\"\n [class.modal-type-warning]=\"typeOf(selectedNotification) === 'Warning'\"\n [class.modal-type-error]=\"typeOf(selectedNotification) === 'Error'\">\n <div class=\"modal-header-left\">\n <div class=\"modal-type-icon\">\n <svg *ngIf=\"typeOf(selectedNotification) === 'Info'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/><path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>\n </svg>\n <svg *ngIf=\"typeOf(selectedNotification) === 'Success'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/><polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n <svg *ngIf=\"typeOf(selectedNotification) === 'Warning'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/>\n </svg>\n <svg *ngIf=\"typeOf(selectedNotification) === 'Error'\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n </div>\n <h3>{{ selectedNotification.title }}</h3>\n </div>\n <button class=\"close-btn\" (click)=\"closeDetails()\" title=\"Close\" aria-label=\"Close notification detail\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n <div class=\"modal-meta\">\n <span class=\"app-name\">{{ selectedNotification.sourceAppName }}</span>\n <span class=\"time\">{{ selectedNotificationDate }}</span>\n </div>\n <div class=\"modal-body\" [innerHTML]=\"selectedNotificationHtml\"></div>\n <div class=\"modal-footer\">\n <button class=\"action-btn see-details-btn\" *ngIf=\"selectedNotification.url?.trim()\" (click)=\"openUrl()\">See Details</button>\n <button class=\"action-btn\" (click)=\"closeDetails()\">Close</button>\n </div>\n </div>\n </div>\n `,\n styleUrls: ['./panel-shared.css', './notification-panel.component.css'],\n})\nexport class NotificationPanelComponent implements OnInit, OnDestroy {\n @Output() notificationRead = new EventEmitter<void>();\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n\n isOpen = false;\n notifications: NotificationDto[] = [];\n currentTheme: Theme = 'light';\n activeTab: 'unread' | 'read' = 'unread'; // Default to unread tab\n private destroy$ = new Subject<void>();\n\n // Cached filtered lists — updated explicitly to avoid re-filtering on every CD cycle\n private _unreadNotifications: NotificationDto[] = [];\n private _readNotifications: NotificationDto[] = [];\n\n // Stable time-ago strings keyed by notification id — refreshed every 30s\n dateLabels: Map<string, string> = new Map();\n private dateTimer: ReturnType<typeof setInterval> | null = null;\n\n get unreadNotifications(): NotificationDto[] {\n return this._unreadNotifications;\n }\n\n get readNotifications(): NotificationDto[] {\n return this._readNotifications;\n }\n\n get currentNotifications(): NotificationDto[] {\n return this.activeTab === 'unread' ? this._unreadNotifications : this._readNotifications;\n }\n\n selectedNotification: NotificationDto | null = null;\n selectedNotificationHtml: SafeHtml | null = null;\n selectedNotificationDate: string = '';\n\n // Returns plain text message for list display\n getNotificationMessage(notification: NotificationDto): string {\n return notification.message || '';\n }\n\n // Normalize type to string — API may return integer or string\n // Backend enum: Info=0, Success=1, Warning=2, Error=3\n typeOf(notification: { type: any }): 'Info' | 'Success' | 'Warning' | 'Error' {\n const t = notification.type;\n if (t === 0 || t === 'Info') return 'Info';\n if (t === 1 || t === 'Success') return 'Success';\n if (t === 2 || t === 'Warning') return 'Warning';\n if (t === 3 || t === 'Error') return 'Error';\n return 'Info';\n }\n\n private toastType(type: any): 'info' | 'warning' | 'error' | 'success' {\n const t = this.typeOf({ type });\n return t.toLowerCase() as 'info' | 'warning' | 'error' | 'success';\n }\n\n private readonly sanitizer = inject(DomSanitizer);\n\n constructor(private authService: MesAuthService, private toastService: ToastService, private themeService: ThemeService) {}\n\n ngOnInit() {\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n\n this.loadNotifications();\n\n // Refresh time-ago labels every 30s to avoid NG0100 from live new Date() in template\n this.dateTimer = setInterval(() => this.refreshDateLabels(), 30000);\n\n // Listen for new real-time notifications\n this.authService.notifications$\n .pipe(takeUntil(this.destroy$))\n .subscribe((notification: RealTimeNotificationDto) => {\n // Show toast for new notification\n this.toastService.show(\n notification.messageHtml || notification.message || '',\n notification.title,\n this.toastType(notification.type),\n 5000\n );\n // Reload notifications list\n this.loadNotifications();\n });\n }\n\n ngOnDestroy() {\n if (this.dateTimer !== null) {\n clearInterval(this.dateTimer);\n this.dateTimer = null;\n }\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private loadNotifications() {\n this.authService.getNotifications(1, 50, true).subscribe({ // includeRead = true to get both read and unread\n next: (response: PagedList<NotificationDto>) => {\n this.notifications = response.items || [];\n this.onNotificationsChanged();\n },\n error: (err) => {}\n });\n }\n\n open() {\n this.isOpen = true;\n this.activeTab = 'unread'; // Reset to unread tab when opening\n }\n\n close() {\n this.isOpen = false;\n }\n\n switchTab(tab: 'unread' | 'read') {\n this.activeTab = tab;\n }\n\n openDetails(notification: NotificationDto) {\n this.selectedNotification = notification;\n // Cache computed values to avoid re-rendering on every change detection cycle\n const html = notification.messageHtml || notification.message || '';\n this.selectedNotificationHtml = this.sanitizer.bypassSecurityTrustHtml(html);\n this.selectedNotificationDate = this.formatDate(notification.createdAt);\n // Mark as read when opening details (if not already read)\n if (!notification.isRead) {\n this.authService.markAsRead(notification.id).subscribe({\n next: () => {\n notification.isRead = true;\n this.notificationRead.emit();\n this.onNotificationsChanged();\n },\n error: () => {}\n });\n }\n }\n\n closeDetails() {\n this.selectedNotification = null;\n this.selectedNotificationHtml = null;\n this.selectedNotificationDate = '';\n }\n\n openUrl() {\n const url = this.selectedNotification?.url?.trim();\n if (url) {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n }\n\n markAsRead(notificationId: string, event?: Event) {\n if (event) {\n event.stopPropagation();\n }\n this.authService.markAsRead(notificationId).subscribe({\n next: () => {\n const notification = this.notifications.find(n => n.id === notificationId);\n if (notification) {\n notification.isRead = true;\n this.notificationRead.emit();\n this.onNotificationsChanged();\n }\n },\n error: (err) => {}\n });\n }\n\n markAllAsRead() {\n this.authService.markAllAsRead().subscribe({\n next: () => {\n this.notifications.forEach(n => n.isRead = true);\n this.notificationRead.emit();\n this.onNotificationsChanged();\n },\n error: (err) => {}\n });\n }\n\n deleteAllRead() {\n const readNotificationIds = this.notifications\n .filter(n => n.isRead)\n .map(n => n.id);\n\n // Delete all read notifications\n const deletePromises = readNotificationIds.map(id =>\n this.authService.deleteNotification(id).toPromise()\n );\n\n Promise.all(deletePromises).then(() => {\n // Remove all read notifications from the local array\n this.notifications = this.notifications.filter(n => !n.isRead);\n this.onNotificationsChanged();\n }).catch((err) => {\n // If bulk delete fails, reload notifications to get current state\n this.loadNotifications();\n });\n }\n\n deleteAllUnread() {\n const unreadNotificationIds = this.notifications\n .filter(n => !n.isRead)\n .map(n => n.id);\n\n // Delete all unread notifications\n const deletePromises = unreadNotificationIds.map(id =>\n this.authService.deleteNotification(id).toPromise()\n );\n\n Promise.all(deletePromises).then(() => {\n // Remove all unread notifications from the local array\n this.notifications = this.notifications.filter(n => n.isRead);\n this.notificationRead.emit();\n this.onNotificationsChanged();\n }).catch((err) => {\n // If bulk delete fails, reload notifications to get current state\n this.loadNotifications();\n });\n }\n\n delete(notificationId: string, event: Event) {\n event.stopPropagation();\n const wasUnread = this.notifications.find(n => n.id === notificationId && !n.isRead) !== undefined;\n this.authService.deleteNotification(notificationId).subscribe({\n next: () => {\n this.notifications = this.notifications.filter(n => n.id !== notificationId);\n if (wasUnread) {\n this.notificationRead.emit();\n }\n this.onNotificationsChanged();\n },\n error: (err) => {}\n });\n }\n\n formatDate(dateString: string): string {\n return this.computeTimeAgo(dateString, new Date());\n }\n\n // Pure computation — takes now as param so it never calls new Date() internally\n private computeTimeAgo(dateString: string, now: Date): string {\n const normalizedDateString = this.parseUtcDate(dateString);\n const date = new Date(normalizedDateString);\n\n if (isNaN(date.getTime())) {\n return 'Invalid date';\n }\n\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return 'Now';\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n\n return date.toLocaleDateString();\n }\n\n // Rebuild dateLabels map using a single shared now — prevents mid-loop clock drift\n private refreshDateLabels(): void {\n const now = new Date();\n for (const n of this.notifications) {\n this.dateLabels.set(n.id, this.computeTimeAgo(n.createdAt, now));\n }\n }\n\n // Re-run filter once and store results in stable arrays\n private recomputeFilteredLists(): void {\n this._unreadNotifications = this.notifications.filter(n => !n.isRead);\n this._readNotifications = this.notifications.filter(n => n.isRead);\n }\n\n // Single call-site after every notification mutation\n private onNotificationsChanged(): void {\n this.recomputeFilteredLists();\n this.refreshDateLabels();\n }\n\n // Parse date string from server (stored in UTC but without 'Z' suffix or 'T' separator)\n private parseUtcDate(dateStr: string): string {\n // Handle date strings that might be missing the 'T' separator\n // Convert formats like \"2023-12-01 12:30:45\" to \"2023-12-01T12:30:45\"\n let normalized = dateStr.includes('T') ? dateStr : dateStr.replace(' ', 'T');\n\n // If no timezone indicator, assume UTC by appending 'Z'\n if (!normalized.endsWith('Z') && !normalized.includes('+') && !normalized.includes('-', 10)) {\n normalized += 'Z';\n }\n\n return normalized;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { MesAuthConfig, PagedList } from './mes-auth.service';\nimport {\n ApprovalDocumentDto,\n ApprovalDocumentSummaryDto,\n ApprovalDocumentStatus,\n ApprovalDashboardDto,\n ApprovalHistoryDto,\n ApprovalTemplateSummaryDto,\n ApprovalTemplateDto,\n RolePreviewUserDto,\n CreateApprovalRequest,\n CreateApprovalResponseDto,\n CreateApprovalTemplateRequest,\n UpdateApprovalTemplateRequest,\n ApproveRejectRequest,\n DelegateRequest\n} from './approval.models';\n\n@Injectable()\nexport class MaApprovalService {\n private apiBase = '';\n private http!: HttpClient;\n private config: MesAuthConfig | null = null;\n\n constructor() {}\n\n init(config: MesAuthConfig, httpClient: HttpClient) {\n this.config = config;\n this.http = httpClient;\n this.apiBase = config.apiBaseUrl.replace(/\\/$/, '');\n }\n\n private get opts() {\n return { withCredentials: this.config?.withCredentials ?? true };\n }\n\n // ====================== Dashboard ======================\n\n getDashboard(): Observable<ApprovalDashboardDto> {\n return this.http.get<ApprovalDashboardDto>(`${this.apiBase}/approval/dashboard`, this.opts);\n }\n\n // ====================== Pending & My Requests ======================\n\n getPendingApprovals(page = 1, pageSize = 20): Observable<PagedList<ApprovalDocumentSummaryDto>> {\n return this.http.get<PagedList<ApprovalDocumentSummaryDto>>(\n `${this.apiBase}/approval/pending?page=${page}&pageSize=${pageSize}`,\n this.opts\n );\n }\n\n getMyRequests(page = 1, pageSize = 20, status?: ApprovalDocumentStatus): Observable<PagedList<ApprovalDocumentSummaryDto>> {\n let url = `${this.apiBase}/approval/my-requests?page=${page}&pageSize=${pageSize}`;\n if (status !== undefined) url += `&status=${status}`;\n return this.http.get<PagedList<ApprovalDocumentSummaryDto>>(url, this.opts);\n }\n\n // ====================== Document ======================\n\n getDocument(id: string): Observable<ApprovalDocumentDto> {\n return this.http.get<ApprovalDocumentDto>(`${this.apiBase}/approval/documents/${id}`, this.opts);\n }\n\n getDocumentHistory(id: string): Observable<ApprovalHistoryDto[]> {\n return this.http.get<ApprovalHistoryDto[]>(`${this.apiBase}/approval/documents/${id}/history`, this.opts);\n }\n\n getDocumentContentUrl(id: string): string {\n return `${this.apiBase}/approval/documents/${id}/content`;\n }\n\n getDocumentThumbnailUrl(id: string): string {\n return `${this.apiBase}/approval/documents/${id}/thumbnail`;\n }\n\n // ====================== Actions ======================\n\n approve(documentId: string, comment?: string): Observable<void> {\n const body: ApproveRejectRequest = { comment };\n return this.http.post<void>(`${this.apiBase}/approval/documents/${documentId}/approve`, body, this.opts);\n }\n\n reject(documentId: string, comment: string): Observable<void> {\n const body: ApproveRejectRequest = { comment };\n return this.http.post<void>(`${this.apiBase}/approval/documents/${documentId}/reject`, body, this.opts);\n }\n\n delegate(documentId: string, toUserId: string, reason?: string): Observable<void> {\n const body: DelegateRequest = { toUserId, reason };\n return this.http.post<void>(`${this.apiBase}/approval/documents/${documentId}/delegate`, body, this.opts);\n }\n\n cancel(documentId: string, reason?: string): Observable<void> {\n let url = `${this.apiBase}/approval/documents/${documentId}`;\n if (reason) url += `?reason=${encodeURIComponent(reason)}`;\n return this.http.delete<void>(url, this.opts);\n }\n\n // ====================== Templates ======================\n\n getTemplates(appId?: string): Observable<ApprovalTemplateSummaryDto[]> {\n let url = `${this.apiBase}/approval/templates`;\n if (appId) url += `?appId=${encodeURIComponent(appId)}`;\n return this.http.get<ApprovalTemplateSummaryDto[]>(url, this.opts);\n }\n\n getTemplate(id: number): Observable<ApprovalTemplateDto> {\n return this.http.get<ApprovalTemplateDto>(`${this.apiBase}/approval/templates/${id}`, this.opts);\n }\n\n createTemplate(request: CreateApprovalTemplateRequest): Observable<ApprovalTemplateDto> {\n return this.http.post<ApprovalTemplateDto>(`${this.apiBase}/approval/templates`, request, this.opts);\n }\n\n updateTemplate(id: number, request: UpdateApprovalTemplateRequest): Observable<ApprovalTemplateDto> {\n return this.http.put<ApprovalTemplateDto>(`${this.apiBase}/approval/templates/${id}`, request, this.opts);\n }\n\n deleteTemplate(id: number): Observable<void> {\n return this.http.delete<void>(`${this.apiBase}/approval/templates/${id}`, this.opts);\n }\n\n previewRole(orgCode: string, level: string): Observable<RolePreviewUserDto[]> {\n return this.http.get<RolePreviewUserDto[]>(\n `${this.apiBase}/approval/roles/preview?orgCode=${encodeURIComponent(orgCode)}&level=${encodeURIComponent(level)}`,\n this.opts\n );\n }\n\n // ====================== Create (used by ma-arv-container) ======================\n\n createApproval(request: CreateApprovalRequest): Observable<CreateApprovalResponseDto> {\n return this.http.post<CreateApprovalResponseDto>(`${this.apiBase}/approval/documents`, request, this.opts);\n }\n}\n","// ====================== Enums ======================\n\nexport enum ApprovalStepMode {\n Sequential = 0,\n Parallel = 1\n}\n\nexport enum ApprovalDocumentStatus {\n Draft = 0,\n Pending = 1,\n Approved = 2,\n Rejected = 3,\n Cancelled = 4,\n Expired = 5\n}\n\nexport enum ApprovalStepStatus {\n Waiting = 0,\n Active = 1,\n Approved = 2,\n Rejected = 3,\n Delegated = 4,\n Expired = 5,\n Skipped = 6\n}\n\nexport enum ApprovalActionType {\n Created = 0,\n Submitted = 1,\n Approved = 2,\n Rejected = 3,\n Delegated = 4,\n Cancelled = 5,\n Commented = 6,\n Expired = 7,\n StepAdvanced = 8\n}\n\n// ====================== DTOs ======================\n\nexport interface ApprovalDocumentSummaryDto {\n id: string;\n title: string;\n description?: string;\n thumbnailPath?: string;\n sourceAppId: string;\n referenceId: string;\n requestedByUserName: string;\n status: ApprovalDocumentStatus;\n currentStepOrder: number;\n totalSteps: number;\n currentStepName?: string;\n createdAt: string;\n completedAt?: string;\n}\n\nexport interface ApprovalStepDto {\n id: number;\n stepOrder: number;\n stepName: string;\n mode: ApprovalStepMode;\n assignedUserId: string;\n assignedUserName: string;\n delegatedToUserId?: string;\n delegatedToUserName?: string;\n status: ApprovalStepStatus;\n comment?: string;\n decidedAt?: string;\n deadlineAt?: string;\n}\n\nexport interface ApprovalReferenceDto {\n userId: string;\n userName: string;\n addedAt: string;\n}\n\nexport interface ApprovalDocumentDto {\n id: string;\n title: string;\n description?: string;\n contentPath: string;\n thumbnailPath?: string;\n sourceAppId: string;\n referenceId: string;\n templateId?: number;\n requestedByUserId: string;\n requestedByUserName: string;\n status: ApprovalDocumentStatus;\n currentStepOrder: number;\n callbackUrl?: string;\n createdAt: string;\n updatedAt: string;\n completedAt?: string;\n deadlineAt?: string;\n steps: ApprovalStepDto[];\n references: ApprovalReferenceDto[];\n}\n\nexport interface ApprovalHistoryDto {\n id: number;\n documentId: string;\n stepId?: number;\n action: ApprovalActionType;\n actorUserId: string;\n actorUserName: string;\n comment?: string;\n details?: string;\n timestamp: string;\n}\n\nexport interface ApprovalTemplateSummaryDto {\n id: number;\n name: string;\n description?: string;\n sourceAppId: string;\n stepCount: number;\n referenceCount: number;\n isActive: boolean;\n createdAt: string;\n}\n\nexport interface StepRoleDto {\n orgCode: string;\n positionLevel: string;\n orgName?: string;\n}\n\nexport interface RolePreviewUserDto {\n userId: string;\n fullName?: string;\n position?: string;\n department?: string;\n employeeCode?: string;\n}\n\nexport interface ApprovalTemplateStepDto {\n id: number;\n stepOrder: number;\n stepName: string;\n mode: ApprovalStepMode;\n deadlineHours?: number;\n assigneeUserIds: string[];\n roles: StepRoleDto[];\n}\n\nexport interface ApprovalTemplateDto {\n id: number;\n name: string;\n description?: string;\n sourceAppId: string;\n createdByUserId: string;\n isActive: boolean;\n createdAt: string;\n updatedAt: string;\n steps: ApprovalTemplateStepDto[];\n referenceUserIds: string[];\n}\n\nexport interface ApprovalDashboardDto {\n pendingCount: number;\n approvedTodayCount: number;\n rejectedTodayCount: number;\n recentActivity: ApprovalDocumentSummaryDto[];\n}\n\nexport interface CreateApprovalResponseDto {\n documentId: string;\n message: string;\n}\n\n// ====================== Requests ======================\n\nexport interface ApprovalStepRequest {\n stepOrder: number;\n stepName: string;\n mode?: ApprovalStepMode;\n approverUserIds: string[];\n deadlineHours?: number;\n}\n\nexport interface CreateApprovalRequest {\n title: string;\n description?: string;\n contentHtml: string;\n thumbnailBase64?: string;\n referenceId: string;\n templateId?: number;\n requestedByUserId?: string;\n callbackUrl?: string;\n deadlineHours?: number;\n steps?: ApprovalStepRequest[];\n referenceUserIds?: string[];\n}\n\nexport interface ApproveRejectRequest {\n comment?: string;\n}\n\nexport interface DelegateRequest {\n toUserId: string;\n reason?: string;\n}\n\nexport interface CreateApprovalTemplateRequest {\n name: string;\n description?: string;\n sourceAppId: string;\n steps: ApprovalStepRequest[];\n referenceUserIds?: string[];\n}\n\nexport interface UpdateApprovalTemplateRequest {\n name: string;\n description?: string;\n steps: ApprovalStepRequest[];\n referenceUserIds?: string[];\n}\n\n// ====================== Submit Result ======================\n\nexport interface ApprovalSubmitResult {\n documentId: string;\n message: string;\n}\n","import {\n Component, Output, EventEmitter, OnInit, OnDestroy, inject, HostListener\n} from '@angular/core';\nimport { NgIf, NgFor, DatePipe } from '@angular/common';\nimport { Router } from '@angular/router';\nimport { MesAuthService, MesAuthConfig } from './mes-auth.service';\nimport { MaApprovalService } from './approval.service';\nimport { ApprovalDocumentSummaryDto, ApprovalDocumentStatus } from './approval.models';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { HttpClient } from '@angular/common/http';\n\ntype PanelTab = 'processing' | 'approved' | 'rejected';\n\n@Component({\n selector: 'ma-approval-panel',\n standalone: true,\n imports: [NgIf, NgFor, DatePipe],\n template: `\n <div class=\"approval-backdrop\" [class.open]=\"isOpen\" (click)=\"close()\"></div>\n <div class=\"approval-panel\" [class.open]=\"isOpen\">\n\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-header-left\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9 11l3 3L22 4\"/>\n <path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\"/>\n </svg>\n <h3>Approvals</h3>\n </div>\n <button class=\"close-btn\" (click)=\"close()\" aria-label=\"Close\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs\">\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'processing'\" (click)=\"switchTab('processing')\">\n Processing\n <span class=\"tab-badge\" *ngIf=\"processingItems.length > 0\">{{ processingItems.length }}</span>\n </button>\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'approved'\" (click)=\"switchTab('approved')\">\n Approved\n </button>\n <button class=\"tab-btn\" [class.active]=\"activeTab === 'rejected'\" (click)=\"switchTab('rejected')\">\n Rejected\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Loading -->\n <div class=\"loading-state\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n <span>Loading...</span>\n </div>\n\n <!-- Processing tab -->\n <ng-container *ngIf=\"!loading && activeTab === 'processing'\">\n <div class=\"empty-state\" *ngIf=\"processingItems.length === 0\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" opacity=\"0.4\"><path d=\"M9 11l3 3L22 4\"/><path d=\"M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11\"/></svg>\n <p>No pending approvals</p>\n </div>\n <div class=\"approval-item\" *ngFor=\"let item of processingItems\" (click)=\"navigateToDetail(item.id)\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div class=\"item-meta\">\n <span class=\"item-requester\">By {{ item.requestedByUserName }}</span>\n <span class=\"item-step\" *ngIf=\"item.currentStepName\">· {{ item.currentStepName }}</span>\n </div>\n <div class=\"item-footer\">\n <span class=\"item-time\">{{ item.createdAt | date:'shortDate' }}</span>\n <span class=\"item-link\">View &rarr;</span>\n </div>\n </div>\n </ng-container>\n\n <!-- Approved tab -->\n <ng-container *ngIf=\"!loading && activeTab === 'approved'\">\n <div class=\"empty-state\" *ngIf=\"approvedItems.length === 0\">\n <p>No approved documents</p>\n </div>\n <div class=\"approval-item approved\" *ngFor=\"let item of approvedItems\" (click)=\"navigateToDetail(item.id)\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div class=\"item-meta\">\n <span class=\"item-requester\">By {{ item.requestedByUserName }}</span>\n </div>\n <div class=\"item-footer\">\n <span class=\"status-badge approved-badge\">Approved</span>\n <span class=\"item-time\">{{ item.completedAt | date:'shortDate' }}</span>\n <span class=\"item-link\">View &rarr;</span>\n </div>\n </div>\n <div class=\"show-more\" *ngIf=\"approvedItems.length >= 10\" (click)=\"showMore('approved')\">\n Show more &rarr;\n </div>\n </ng-container>\n\n <!-- Rejected tab -->\n <ng-container *ngIf=\"!loading && activeTab === 'rejected'\">\n <div class=\"empty-state\" *ngIf=\"rejectedItems.length === 0\">\n <p>No rejected documents</p>\n </div>\n <div class=\"approval-item rejected\" *ngFor=\"let item of rejectedItems\" (click)=\"navigateToDetail(item.id)\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div class=\"item-meta\">\n <span class=\"item-requester\">By {{ item.requestedByUserName }}</span>\n </div>\n <div class=\"item-footer\">\n <span class=\"status-badge rejected-badge\">Rejected</span>\n <span class=\"item-time\">{{ item.completedAt | date:'shortDate' }}</span>\n <span class=\"item-link\">View &rarr;</span>\n </div>\n </div>\n <div class=\"show-more\" *ngIf=\"rejectedItems.length >= 10\" (click)=\"showMore('rejected')\">\n Show more &rarr;\n </div>\n </ng-container>\n </div>\n </div>\n `,\n styleUrls: ['./panel-shared.css', './ma-approval-panel.component.css']\n})\nexport class MaApprovalPanelComponent implements OnInit, OnDestroy {\n @Output() approvalActioned = new EventEmitter<void>();\n\n isOpen = false;\n loading = false;\n activeTab: PanelTab = 'processing';\n\n processingItems: ApprovalDocumentSummaryDto[] = [];\n approvedItems: ApprovalDocumentSummaryDto[] = [];\n rejectedItems: ApprovalDocumentSummaryDto[] = [];\n\n private destroy$ = new Subject<void>();\n private mesAuth = inject(MesAuthService);\n private http = inject(HttpClient);\n private router = inject(Router);\n private approvalSvc: MaApprovalService | null = null;\n\n ngOnInit() {\n const config = this.mesAuth.getConfig();\n if (config) {\n this.approvalSvc = new MaApprovalService();\n this.approvalSvc.init(config, this.http);\n }\n\n this.mesAuth.approvalEvents$.pipe(takeUntil(this.destroy$)).subscribe(() => {\n if (this.isOpen) this.loadCurrentTab();\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n open() {\n this.isOpen = true;\n this.loadAllTabs();\n }\n\n close() {\n this.isOpen = false;\n }\n\n toggle() {\n if (this.isOpen) this.close();\n else this.open();\n }\n\n switchTab(tab: PanelTab) {\n this.activeTab = tab;\n this.loadCurrentTab();\n }\n\n private loadAllTabs() {\n this.loading = true;\n if (!this.approvalSvc) { this.loading = false; return; }\n\n let pending = 3;\n const done = () => { if (--pending === 0) this.loading = false; };\n\n this.approvalSvc.getPendingApprovals(1, 100).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => { this.processingItems = r.items; done(); },\n error: () => done()\n });\n\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Approved).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => { this.approvedItems = r.items; done(); },\n error: () => done()\n });\n\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Rejected).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => { this.rejectedItems = r.items; done(); },\n error: () => done()\n });\n }\n\n private loadCurrentTab() {\n if (!this.approvalSvc) return;\n\n if (this.activeTab === 'processing') {\n this.approvalSvc.getPendingApprovals(1, 100).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => this.processingItems = r.items,\n error: () => {}\n });\n } else if (this.activeTab === 'approved') {\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Approved).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => this.approvedItems = r.items,\n error: () => {}\n });\n } else {\n this.approvalSvc.getMyRequests(1, 10, ApprovalDocumentStatus.Rejected).pipe(takeUntil(this.destroy$)).subscribe({\n next: r => this.rejectedItems = r.items,\n error: () => {}\n });\n }\n }\n\n navigateToDetail(id: string) {\n this.close();\n this.router.navigate(['/auth/approval/detail', id]);\n this.approvalActioned.emit();\n }\n\n showMore(status: 'approved' | 'rejected') {\n this.close();\n this.router.navigate(['/auth/approval/my-requests'], { queryParams: { status } });\n }\n}\n","import { Component, ViewChild, AfterViewInit } from '@angular/core';\nimport { ToastContainerComponent } from './toast-container.component';\nimport { UserProfileComponent } from './user-profile.component';\nimport { NotificationPanelComponent } from './notification-panel.component';\nimport { MaApprovalPanelComponent } from './ma-approval-panel.component';\n\n@Component({\n selector: 'ma-user',\n standalone: true,\n imports: [ToastContainerComponent, UserProfileComponent, NotificationPanelComponent, MaApprovalPanelComponent],\n template: `\n <ma-toast-container></ma-toast-container>\n <div class=\"user-header\">\n <ma-user-profile\n (notificationClick)=\"notificationPanel.open()\"\n (approvalClick)=\"approvalPanel.open()\">\n </ma-user-profile>\n </div>\n <ma-notification-panel #notificationPanel (notificationRead)=\"onNotificationRead()\"></ma-notification-panel>\n <ma-approval-panel #approvalPanel (approvalActioned)=\"onApprovalActioned()\"></ma-approval-panel>\n `,\n styles: [`\n .user-header {\n display: flex;\n justify-content: flex-end;\n }\n `]\n})\nexport class MaUserComponent implements AfterViewInit {\n @ViewChild(UserProfileComponent) userProfile?: UserProfileComponent;\n @ViewChild(MaApprovalPanelComponent) approvalPanel!: MaApprovalPanelComponent;\n\n ngAfterViewInit() {\n if (this.userProfile) {\n this.userProfile.loadUnreadCount();\n this.userProfile.loadPendingApprovalCount();\n }\n }\n\n onNotificationRead() {\n if (this.userProfile) {\n this.userProfile.loadUnreadCount();\n }\n }\n\n onApprovalActioned() {\n if (this.userProfile) {\n this.userProfile.loadPendingApprovalCount();\n }\n }\n}\n","import { Component, OnInit, OnDestroy, Output, EventEmitter, HostBinding } from '@angular/core';\nimport { NgIf } from '@angular/common';\nimport { MesAuthService } from './mes-auth.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\n@Component({\n selector: 'ma-notification-badge',\n standalone: true,\n imports: [NgIf],\n template: `\n <button class=\"notification-btn\" (click)=\"onNotificationClick()\" title=\"Notifications\">\n <span class=\"icon\">🔔</span>\n <span class=\"badge\" *ngIf=\"unreadCount > 0\">{{ unreadCount }}</span>\n </button>\n `,\n styles: [`\n :host {\n --error-color: #f44336;\n }\n\n :host(.theme-dark) {\n --error-color: #ef5350;\n }\n\n .notification-btn {\n position: relative;\n background: none;\n border: none;\n font-size: 24px;\n cursor: pointer;\n padding: 8px;\n transition: opacity 0.2s;\n }\n\n .notification-btn:hover {\n opacity: 0.7;\n }\n\n .icon {\n display: inline-block;\n }\n\n .badge {\n position: absolute;\n top: 0;\n right: 0;\n background-color: var(--error-color);\n color: white;\n border-radius: 50%;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: bold;\n }\n `]\n})\nexport class NotificationBadgeComponent implements OnInit, OnDestroy {\n @Output() notificationClick = new EventEmitter<void>();\n @HostBinding('class') get themeClass(): string {\n return `theme-${this.currentTheme}`;\n }\n \n unreadCount = 0;\n currentTheme: Theme = 'light';\n private hasUser = false;\n private destroy$ = new Subject<void>();\n\n constructor(private authService: MesAuthService, private themeService: ThemeService) {}\n\n ngOnInit() {\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(theme => {\n this.currentTheme = theme;\n });\n\n this.authService.currentUser$\n .pipe(takeUntil(this.destroy$))\n .subscribe(user => {\n this.hasUser = !!user;\n if (!this.hasUser) {\n this.unreadCount = 0;\n return;\n }\n this.loadUnreadCount();\n });\n \n // Listen for new notifications\n this.authService.notifications$\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n if (this.hasUser) {\n this.loadUnreadCount();\n }\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private loadUnreadCount() {\n if (!this.hasUser) {\n this.unreadCount = 0;\n return;\n }\n\n this.authService.getUnreadCount().subscribe({\n next: (response: any) => {\n this.unreadCount = response.unreadCount || 0;\n },\n error: (err) => console.error('Error loading unread count:', err)\n });\n }\n\n onNotificationClick() {\n this.notificationClick.emit();\n }\n}\n","import {\n Component, Input, Output, EventEmitter, OnInit, OnDestroy,\n ElementRef, ViewChild, HostBinding\n} from '@angular/core';\nimport { NgIf, NgFor } from '@angular/common';\nimport { MesAuthService, MesAuthConfig } from './mes-auth.service';\nimport { ThemeService, Theme } from './theme.service';\nimport { MaApprovalService } from './approval.service';\nimport {\n ApprovalTemplateSummaryDto,\n ApprovalTemplateDto,\n ApprovalTemplateStepDto,\n RolePreviewUserDto,\n ApprovalStepRequest,\n ApprovalStepMode,\n CreateApprovalRequest,\n ApprovalSubmitResult\n} from './approval.models';\nimport { Subject, forkJoin, of } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { HttpClient } from '@angular/common/http';\nimport { inject } from '@angular/core';\n\n@Component({\n selector: 'ma-arv-container',\n standalone: true,\n imports: [NgIf, NgFor],\n template: `\n <div class=\"arv-container\">\n <!-- Content Area -->\n <div class=\"arv-content-body\" #contentBody>\n <ng-content></ng-content>\n </div>\n\n <!-- Approval Footer -->\n <div class=\"arv-footer\" *ngIf=\"!isSubmitted\">\n <div class=\"arv-footer-inner\">\n\n <!-- Routing mode -->\n <div class=\"arv-routing\">\n <div class=\"arv-routing-header\">\n <h4 class=\"arv-section-title\">Approval Routing</h4>\n <!-- Show routing toggle only when templateId is NOT locked -->\n <div *ngIf=\"!templateId\" class=\"arv-routing-mode\">\n <label class=\"arv-radio\">\n <input type=\"radio\" name=\"routingMode\" value=\"template\" [checked]=\"routingMode === 'template'\" (change)=\"routingMode = 'template'\"> Use Template\n </label>\n <label class=\"arv-radio\">\n <input type=\"radio\" name=\"routingMode\" value=\"adhoc\" [checked]=\"routingMode === 'adhoc'\" (change)=\"routingMode = 'adhoc'\"> Custom Steps\n </label>\n </div>\n </div>\n\n <!-- Locked template: show name only, no selector -->\n <div *ngIf=\"templateId && routingMode === 'template'\" class=\"arv-template-select\">\n <div *ngIf=\"loadingTemplate\" class=\"arv-template-loading\">Loading template...</div>\n <div *ngIf=\"selectedTemplate && !loadingTemplate\" class=\"arv-locked-template\">\n <span class=\"arv-locked-label\">Template</span>\n <span class=\"arv-locked-name\">{{ selectedTemplate.name }}</span>\n </div>\n </div>\n\n <!-- Free template selector (no locked templateId) -->\n <div *ngIf=\"!templateId && routingMode === 'template'\" class=\"arv-template-select\">\n <label class=\"arv-label\">Select Template</label>\n <select class=\"arv-select\" (change)=\"onTemplateChange($event)\">\n <option value=\"\">-- Select a template --</option>\n <option *ngFor=\"let t of templates\" [value]=\"t.id\" [selected]=\"t.id === selectedTemplateId\">{{ t.name }}</option>\n </select>\n </div>\n\n <!-- Step pickers (shared for both locked and free template) -->\n <div *ngIf=\"routingMode === 'template'\" class=\"arv-template-select\">\n <div *ngIf=\"!loadingTemplate && selectedTemplate\" class=\"arv-template-steps\">\n <div class=\"arv-step-card\" *ngFor=\"let s of selectedTemplate.steps; let i = index\">\n <div class=\"arv-step-card-header\">\n <span class=\"arv-step-preview-num\">Step {{ s.stepOrder }}</span>\n <span class=\"arv-step-preview-name\">{{ s.stepName }}</span>\n <span *ngIf=\"s.roles && s.roles.length > 0\" class=\"arv-step-role-badge\">\n {{ s.roles[0].positionLevel }}{{ s.roles[0].orgName ? ' · ' + s.roles[0].orgName : '' }}\n </span>\n </div>\n <!-- Selectable step (role-based or multi-assignee): show approver picker -->\n <div *ngIf=\"stepCandidates[i]?.length > 1 || stepLoadingCandidates[i]\" class=\"arv-step-picker\">\n <div *ngIf=\"stepLoadingCandidates[i]\" class=\"arv-template-loading\">Loading candidates...</div>\n <select *ngIf=\"!stepLoadingCandidates[i]\" class=\"arv-select arv-select-sm\"\n (change)=\"onStepUserChange(i, $event)\">\n <option value=\"\">-- Select approver --</option>\n <option *ngFor=\"let u of stepCandidates[i]\" [value]=\"u.userId\"\n [selected]=\"u.userId === stepSelectedUsers[i]\">\n {{ u.fullName || u.userId }}{{ u.department ? ' · ' + u.department : '' }}{{ u.position ? ' (' + u.position + ')' : '' }}\n </option>\n </select>\n </div>\n <!-- Single fixed-user step: show who is assigned -->\n <div *ngIf=\"!stepLoadingCandidates[i] && stepCandidates[i]?.length === 1\" class=\"arv-step-fixed\">\n {{ stepCandidates[i][0].fullName || stepCandidates[i][0].userId }}{{ stepCandidates[i][0].department ? ' · ' + stepCandidates[i][0].department : '' }}{{ stepCandidates[i][0].position ? ' (' + stepCandidates[i][0].position + ')' : '' }}\n </div>\n </div>\n <div *ngIf=\"selectedTemplate.referenceUserIds.length > 0\" class=\"arv-step-preview arv-step-preview-cc\">\n <span class=\"arv-step-preview-num\">CC</span>\n <span class=\"arv-step-preview-name\">{{ selectedTemplate.referenceUserIds.length }} reference user(s) from template</span>\n </div>\n </div>\n </div>\n\n <!-- Ad-hoc steps -->\n <div *ngIf=\"routingMode === 'adhoc'\" class=\"arv-steps\">\n <div class=\"arv-step\" *ngFor=\"let step of adHocSteps; let i = index\">\n <div class=\"arv-step-header\">\n <span class=\"arv-step-num\">Step {{ i + 1 }}</span>\n <input class=\"arv-input\" [value]=\"step.stepName\" (input)=\"step.stepName = $any($event.target).value\" placeholder=\"Step name\" />\n <button class=\"arv-btn-icon arv-btn-danger\" (click)=\"removeStep(i)\" title=\"Remove step\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>\n </button>\n </div>\n <div class=\"arv-approvers\">\n <div class=\"arv-approver-tags\">\n <span class=\"arv-tag\" *ngFor=\"let uid of step.approverUserIds; let j = index\">\n {{ userLabelMap[uid] || uid }}\n <button class=\"arv-tag-remove\" (click)=\"removeApprover(i, j)\">x</button>\n </span>\n </div>\n <div class=\"arv-user-search\">\n <input class=\"arv-input arv-input-sm\" [value]=\"userSearchQuery[i] || ''\"\n (input)=\"onUserSearchInput(i, $any($event.target).value)\"\n placeholder=\"Search approver...\" />\n <div class=\"arv-search-results\" *ngIf=\"userSearchResults[i]?.length\">\n <div class=\"arv-search-item\"\n *ngFor=\"let u of userSearchResults[i]\"\n (click)=\"addApprover(i, u.id)\">\n {{ u.fullName || u.userName }}\n </div>\n </div>\n </div>\n </div>\n </div>\n <button class=\"arv-btn arv-btn-outline\" (click)=\"addStep()\">+ Add Step</button>\n </div>\n </div>\n\n <!-- Reference / CC users -->\n <div class=\"arv-references\">\n <h4 class=\"arv-section-title\">CC / Reference</h4>\n <p class=\"arv-hint\">These users will be notified when the approval completes, but won't be asked to approve.</p>\n <div class=\"arv-approver-tags\">\n <span class=\"arv-tag\" *ngFor=\"let uid of referenceUserIds; let j = index\">\n {{ userLabelMap[uid] || uid }}\n <button class=\"arv-tag-remove\" (click)=\"removeReference(j)\">x</button>\n </span>\n </div>\n <div class=\"arv-user-search\">\n <input class=\"arv-input arv-input-sm\" [value]=\"refSearchQuery\"\n (input)=\"onRefSearchInput($any($event.target).value)\"\n placeholder=\"Search CC user...\" />\n <div class=\"arv-search-results\" *ngIf=\"refSearchResults?.length\">\n <div class=\"arv-search-item\"\n *ngFor=\"let u of refSearchResults\"\n (click)=\"addReference(u.id)\">\n {{ u.fullName || u.userName }}\n </div>\n </div>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"arv-actions\">\n <button class=\"arv-btn arv-btn-secondary\" (click)=\"onCancel()\">Cancel</button>\n <button class=\"arv-btn arv-btn-primary\" [disabled]=\"submitting\" (click)=\"submit()\">\n <span *ngIf=\"submitting\" class=\"arv-spinner\"></span>\n {{ submitting ? 'Submitting...' : 'Submit for Approval' }}\n </button>\n </div>\n\n <div class=\"arv-error\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\n </div>\n </div>\n\n <!-- Success state -->\n <div class=\"arv-success\" *ngIf=\"isSubmitted\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#66bb6a\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/>\n <polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n <p>Submitted for approval successfully.</p>\n </div>\n </div>\n `,\n styles: [`\n :host {\n display: block;\n --arv-primary: #90caf9;\n --arv-primary-hover: #64b5f6;\n --arv-success: #66bb6a;\n --arv-danger: #ef5350;\n --arv-text: #e0e0e0;\n --arv-text-muted: #9e9e9e;\n --arv-bg: #1e1e2e;\n --arv-bg2: #27273a;\n --arv-border: #383850;\n --arv-radius: 8px;\n }\n :host(.theme-light) {\n --arv-primary: #1565c0;\n --arv-primary-hover: #0d47a1;\n --arv-success: #2e7d32;\n --arv-danger: #c62828;\n --arv-text: #212121;\n --arv-text-muted: #616161;\n --arv-bg: #ffffff;\n --arv-bg2: #f5f5f5;\n --arv-border: #e0e0e0;\n }\n\n .arv-container { display: flex; flex-direction: column; height: 100%; }\n .arv-content-body { flex: 1; overflow: auto; }\n .arv-footer { border-top: 1px solid var(--arv-border); background: var(--arv-bg2); }\n .arv-footer-inner { padding: 16px; display: flex; flex-direction: column; gap: 14px; }\n\n .arv-section-title { margin: 0 0 8px; font-size: 13px; font-weight: 700; color: var(--arv-primary); text-transform: uppercase; letter-spacing: 0.5px; }\n .arv-routing-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; }\n .arv-routing-mode { display: flex; gap: 12px; }\n .arv-radio { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--arv-text); cursor: pointer; }\n\n .arv-label { font-size: 12px; color: var(--arv-text-muted); display: block; margin-bottom: 4px; }\n .arv-select { width: 100%; padding: 8px 10px; border: 1px solid var(--arv-border); border-radius: var(--arv-radius); background: var(--arv-bg); color: var(--arv-text); font-size: 13px; }\n .arv-input { padding: 7px 10px; border: 1px solid var(--arv-border); border-radius: var(--arv-radius); background: var(--arv-bg); color: var(--arv-text); font-size: 13px; }\n .arv-input-sm { width: 100%; margin-top: 4px; }\n\n .arv-steps { display: flex; flex-direction: column; gap: 10px; }\n .arv-step { background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); padding: 10px; }\n .arv-step-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }\n .arv-step-num { font-size: 12px; font-weight: 700; color: var(--arv-primary); min-width: 44px; }\n\n .arv-approver-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }\n .arv-tag { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; background: rgba(144,202,249,0.12); border: 1px solid rgba(144,202,249,0.3); border-radius: 12px; font-size: 12px; color: var(--arv-primary); }\n .arv-tag-remove { background: none; border: none; cursor: pointer; color: var(--arv-text-muted); font-size: 11px; padding: 0 2px; line-height: 1; }\n .arv-tag-remove:hover { color: var(--arv-danger); }\n\n .arv-user-search { position: relative; }\n .arv-search-results { position: absolute; left: 0; right: 0; z-index: 100; background: var(--arv-bg2); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); max-height: 150px; overflow-y: auto; }\n .arv-search-item { padding: 8px 12px; cursor: pointer; font-size: 13px; color: var(--arv-text); }\n .arv-search-item:hover { background: var(--arv-bg); }\n\n .arv-hint { font-size: 12px; color: var(--arv-text-muted); margin: 0 0 8px; }\n\n .arv-btn-icon { background: none; border: none; cursor: pointer; padding: 2px; border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; }\n .arv-btn-danger { color: var(--arv-danger); }\n .arv-btn-danger:hover { background: rgba(239,83,80,0.1); }\n\n .arv-actions { display: flex; justify-content: flex-end; gap: 10px; }\n .arv-btn { padding: 9px 18px; border-radius: var(--arv-radius); font-size: 13px; font-weight: 600; cursor: pointer; border: none; transition: background 0.15s; }\n .arv-btn-primary { background: var(--arv-primary); color: #fff; }\n .arv-btn-primary:hover:not(:disabled) { background: var(--arv-primary-hover); }\n .arv-btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }\n .arv-btn-secondary { background: transparent; border: 1px solid var(--arv-border); color: var(--arv-text-muted); }\n .arv-btn-secondary:hover { color: var(--arv-text); border-color: var(--arv-text-muted); }\n .arv-btn-outline { background: transparent; border: 1px dashed var(--arv-border); color: var(--arv-text-muted); font-size: 12px; padding: 6px 12px; }\n .arv-btn-outline:hover { border-color: var(--arv-primary); color: var(--arv-primary); }\n\n .arv-spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: #fff; border-radius: 50%; animation: arv-spin 0.6s linear infinite; margin-right: 6px; }\n @keyframes arv-spin { to { transform: rotate(360deg); } }\n\n .arv-error { padding: 8px 12px; background: rgba(239,83,80,0.1); border: 1px solid rgba(239,83,80,0.3); border-radius: var(--arv-radius); font-size: 13px; color: var(--arv-danger); }\n\n .arv-success { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 32px; gap: 12px; text-align: center; }\n .arv-success p { color: var(--arv-success); font-size: 15px; font-weight: 600; margin: 0; }\n\n .arv-references { border-top: 1px solid var(--arv-border); padding-top: 12px; }\n\n .arv-template-loading { font-size: 12px; color: var(--arv-text-muted); margin-top: 8px; padding: 4px 0; }\n .arv-template-steps { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }\n\n .arv-step-card { background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); overflow: hidden; }\n .arv-step-card-header { display: flex; align-items: center; gap: 8px; padding: 7px 10px; background: rgba(0,0,0,0.03); border-bottom: 1px solid var(--arv-border); flex-wrap: wrap; }\n .arv-step-preview { display: flex; align-items: center; gap: 8px; padding: 5px 8px; background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: 4px; font-size: 12px; }\n .arv-step-preview-num { font-weight: 700; color: var(--arv-primary); min-width: 44px; flex-shrink: 0; font-size: 12px; }\n .arv-step-preview-name { flex: 1; color: var(--arv-text); font-size: 12px; font-weight: 600; }\n .arv-step-role-badge { font-size: 11px; color: var(--arv-text-muted); background: rgba(144,202,249,0.1); border: 1px solid rgba(144,202,249,0.25); border-radius: 10px; padding: 1px 7px; }\n .arv-step-preview-cc .arv-step-preview-num { color: var(--arv-text-muted); }\n\n .arv-locked-template { display: flex; align-items: center; gap: 8px; padding: 7px 10px; background: var(--arv-bg); border: 1px solid var(--arv-border); border-radius: var(--arv-radius); margin-top: 6px; }\n .arv-locked-label { font-size: 11px; color: var(--arv-text-muted); text-transform: uppercase; letter-spacing: 0.5px; flex-shrink: 0; }\n .arv-locked-name { font-size: 13px; font-weight: 600; color: var(--arv-text); }\n\n .arv-step-picker { padding: 8px 10px; }\n .arv-select-sm { font-size: 12px; padding: 6px 8px; }\n .arv-step-fixed { padding: 6px 10px; font-size: 12px; color: var(--arv-text-muted); }\n `]\n})\nexport class MaArvContainerComponent implements OnInit, OnDestroy {\n @Input() title = '';\n @Input() description?: string;\n @Input() referenceId = '';\n @Input() templateId?: number;\n @Input() callbackUrl?: string;\n @Input() deadlineHours?: number;\n\n @Output() approvalSubmitted = new EventEmitter<ApprovalSubmitResult>();\n @Output() approvalSubmitting = new EventEmitter<void>();\n @Output() cancelled = new EventEmitter<void>();\n\n @ViewChild('contentBody', { static: true }) contentBody!: ElementRef<HTMLElement>;\n\n routingMode: 'template' | 'adhoc' = 'template';\n templates: ApprovalTemplateSummaryDto[] = [];\n selectedTemplateId: number | null = null;\n selectedTemplate: ApprovalTemplateDto | null = null;\n loadingTemplate = false;\n\n // Per-step role candidates and selected user\n stepCandidates: RolePreviewUserDto[][] = [];\n stepLoadingCandidates: boolean[] = [];\n stepSelectedUsers: string[] = [];\n adHocSteps: ApprovalStepRequest[] = [];\n\n referenceUserIds: string[] = [];\n refSearchQuery = '';\n refSearchResults: any[] = [];\n\n userSearchQuery: string[] = [];\n userSearchResults: any[][] = [];\n\n submitting = false;\n isSubmitted = false;\n errorMessage = '';\n userLabelMap: Record<string, string> = {};\n\n @HostBinding('class') get themeClass(): string { return `theme-${this.currentTheme}`; }\n currentTheme: Theme = 'light';\n\n private destroy$ = new Subject<void>();\n private mesAuth = inject(MesAuthService);\n private themeService = inject(ThemeService);\n private approvalSvc: MaApprovalService | null = null;\n private http = inject(HttpClient);\n\n ngOnInit() {\n this.themeService.currentTheme$\n .pipe(takeUntil(this.destroy$))\n .subscribe(t => this.currentTheme = t);\n\n const config = this.mesAuth.getConfig();\n if (config) {\n this.approvalSvc = new MaApprovalService();\n this.approvalSvc.init(config, this.http);\n this.loadTemplates();\n }\n this.addStep();\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n private loadTemplates() {\n this.approvalSvc!.getTemplates().pipe(takeUntil(this.destroy$)).subscribe({\n next: (t) => {\n this.templates = t;\n if (this.templateId != null && this.selectedTemplateId == null) {\n this.selectedTemplateId = this.templateId;\n this.loadTemplateDetail(this.templateId);\n }\n },\n error: () => {}\n });\n }\n\n private loadTemplateDetail(id: number) {\n this.loadingTemplate = true;\n this.selectedTemplate = null;\n this.stepCandidates = [];\n this.stepLoadingCandidates = [];\n this.stepSelectedUsers = [];\n this.approvalSvc!.getTemplate(id).pipe(takeUntil(this.destroy$)).subscribe({\n next: (t) => {\n this.selectedTemplate = t;\n this.loadingTemplate = false;\n this.loadStepCandidates(t.steps);\n },\n error: () => { this.loadingTemplate = false; }\n });\n }\n\n private loadStepCandidates(steps: ApprovalTemplateStepDto[]) {\n this.stepCandidates = steps.map(() => []);\n this.stepLoadingCandidates = steps.map(() => false);\n this.stepSelectedUsers = steps.map(() => '');\n\n const config = this.mesAuth.getConfig();\n\n steps.forEach((step, i) => {\n if (step.roles && step.roles.length > 0) {\n // Role-based: fetch candidates via role preview\n this.stepLoadingCandidates[i] = true;\n const calls = step.roles.map(r => this.approvalSvc!.previewRole(r.orgCode, r.positionLevel));\n forkJoin(calls.length > 0 ? calls : [of([] as RolePreviewUserDto[])])\n .pipe(takeUntil(this.destroy$))\n .subscribe({\n next: results => {\n const merged = new Map<string, RolePreviewUserDto>();\n results.forEach(list => list.forEach(u => merged.set(u.userId, u)));\n this.stepCandidates[i] = Array.from(merged.values());\n this.stepLoadingCandidates[i] = false;\n },\n error: () => { this.stepLoadingCandidates[i] = false; }\n });\n } else if (step.assigneeUserIds && step.assigneeUserIds.length > 0 && config) {\n // Search-selected employees: resolve IDs to display names\n this.stepLoadingCandidates[i] = true;\n const base = config.apiBaseUrl.replace(/\\/$/, '');\n const opts = { withCredentials: config.withCredentials ?? true };\n const calls = step.assigneeUserIds.map(uid =>\n this.http.get<any>(`${base}/urs/users/${encodeURIComponent(uid)}`, opts)\n );\n forkJoin(calls)\n .pipe(takeUntil(this.destroy$))\n .subscribe({\n next: results => {\n this.stepCandidates[i] = results.map((u: any) => ({\n userId: u.id || u.Id,\n fullName: u.fullName || u.FullName || u.userName || u.UserName,\n department: u.department || u.Department,\n position: u.position || u.Position\n } as RolePreviewUserDto));\n // Single assignee — pre-select automatically\n if (this.stepCandidates[i].length === 1) {\n this.stepSelectedUsers[i] = this.stepCandidates[i][0].userId;\n }\n this.stepLoadingCandidates[i] = false;\n },\n error: () => { this.stepLoadingCandidates[i] = false; }\n });\n }\n });\n }\n\n onStepUserChange(stepIndex: number, event: Event) {\n this.stepSelectedUsers[stepIndex] = (event.target as HTMLSelectElement).value;\n }\n\n onTemplateChange(event: Event) {\n const val = (event.target as HTMLSelectElement).value;\n this.selectedTemplateId = val ? parseInt(val, 10) : null;\n this.selectedTemplate = null;\n if (this.selectedTemplateId) {\n this.loadTemplateDetail(this.selectedTemplateId);\n }\n }\n\n addStep() {\n const order = this.adHocSteps.length + 1;\n this.adHocSteps.push({ stepOrder: order, stepName: `Step ${order}`, approverUserIds: [] });\n this.userSearchQuery.push('');\n this.userSearchResults.push([]);\n }\n\n removeStep(i: number) {\n this.adHocSteps.splice(i, 1);\n this.userSearchQuery.splice(i, 1);\n this.userSearchResults.splice(i, 1);\n this.adHocSteps.forEach((s, idx) => s.stepOrder = idx + 1);\n }\n\n addApprover(stepIndex: number, userId: string) {\n if (!this.adHocSteps[stepIndex].approverUserIds.includes(userId)) {\n this.adHocSteps[stepIndex].approverUserIds.push(userId);\n }\n this.storeLabelFromResults(userId, this.userSearchResults[stepIndex]);\n this.userSearchQuery[stepIndex] = '';\n this.userSearchResults[stepIndex] = [];\n }\n\n removeApprover(stepIndex: number, approverIndex: number) {\n this.adHocSteps[stepIndex].approverUserIds.splice(approverIndex, 1);\n }\n\n addReference(userId: string) {\n if (!this.referenceUserIds.includes(userId)) {\n this.referenceUserIds.push(userId);\n }\n this.storeLabelFromResults(userId, this.refSearchResults);\n this.refSearchQuery = '';\n this.refSearchResults = [];\n }\n\n private storeLabelFromResults(userId: string, results: any[]) {\n const user = results.find((u: any) => u.id === userId);\n if (user) {\n const parts = [user.department, user.position, user.fullName].filter(Boolean);\n this.userLabelMap[userId] = parts.length > 0 ? parts.join(' - ') : (user.userName || userId);\n }\n }\n\n removeReference(j: number) {\n this.referenceUserIds.splice(j, 1);\n }\n\n onUserSearchInput(stepIndex: number, query: string) {\n this.userSearchQuery[stepIndex] = query;\n if (!query || query.length < 2) { this.userSearchResults[stepIndex] = []; return; }\n this.searchUsers(query).then(r => this.userSearchResults[stepIndex] = r);\n }\n\n onRefSearchInput(query: string) {\n this.refSearchQuery = query;\n if (!query || query.length < 2) { this.refSearchResults = []; return; }\n this.searchUsers(query).then(r => this.refSearchResults = r);\n }\n\n private searchUsers(query: string): Promise<any[]> {\n const config = this.mesAuth.getConfig();\n if (!config) return Promise.resolve([]);\n const url = `${config.apiBaseUrl.replace(/\\/$/, '')}/urs/users?search=${encodeURIComponent(query)}&page=1&pageSize=20`;\n return this.http.get<any>(url, { withCredentials: config.withCredentials ?? true })\n .toPromise()\n .then((r: any) => {\n const items = r?.data || r?.Data || r?.items || r || [];\n // Normalize PascalCase to camelCase for template binding\n return (Array.isArray(items) ? items : []).map((u: any) => ({\n id: u.id || u.Id,\n userName: u.userName || u.UserName,\n fullName: u.fullName || u.FullName,\n email: u.email || u.Email,\n department: u.department || u.Department,\n position: u.position || u.Position\n }));\n })\n .catch(() => []);\n }\n\n async submit() {\n if (this.submitting) return;\n this.errorMessage = '';\n\n if (!this.approvalSvc) { this.errorMessage = 'Approval service not initialized. Ensure provideMesAuth() is configured.'; return; }\n if (!this.referenceId) { this.errorMessage = 'ReferenceId is required.'; return; }\n if (!this.title) { this.errorMessage = 'Title is required.'; return; }\n\n if (this.routingMode === 'template' && !this.selectedTemplateId && !this.templateId) {\n this.errorMessage = 'Please select a template or switch to Custom Steps.'; return;\n }\n if (this.routingMode === 'adhoc' && this.adHocSteps.length === 0) {\n this.errorMessage = 'Please add at least one approval step.'; return;\n }\n // Validate selectable steps (role-based or multi-assignee) have a selected approver\n if (this.routingMode === 'template' && this.selectedTemplate) {\n for (let i = 0; i < this.selectedTemplate.steps.length; i++) {\n const step = this.selectedTemplate.steps[i];\n const isSelectable = (this.stepCandidates[i]?.length ?? 0) > 1;\n if (isSelectable && !this.stepSelectedUsers[i]) {\n this.errorMessage = `Please select an approver for step \"${step.stepName}\".`; return;\n }\n }\n }\n\n // Emit before capture so parent can hide edit controls (inputs, buttons)\n // then wait one tick for Angular CD to update the DOM before snapshotting\n this.approvalSubmitting.emit();\n await new Promise(resolve => setTimeout(resolve));\n\n this.submitting = true;\n\n try {\n const contentHtml = await this.captureContent();\n const thumbnailBase64 = await this.captureThumbnail().catch(() => undefined);\n\n const request: CreateApprovalRequest = {\n title: this.title,\n description: this.description,\n contentHtml,\n thumbnailBase64,\n referenceId: this.referenceId,\n callbackUrl: this.callbackUrl,\n deadlineHours: this.deadlineHours,\n referenceUserIds: this.referenceUserIds.length > 0 ? this.referenceUserIds : undefined\n };\n\n if (this.routingMode === 'template') {\n request.templateId = this.selectedTemplateId ?? this.templateId;\n // If template has role-based steps with selected approvers, pass explicit steps\n if (this.selectedTemplate) {\n const hasSelectableSteps = this.selectedTemplate.steps.some(\n (s, i) => (this.stepCandidates[i]?.length ?? 0) > 0\n );\n if (hasSelectableSteps) {\n request.steps = this.selectedTemplate.steps.map((s, i) => ({\n stepOrder: s.stepOrder,\n stepName: s.stepName,\n mode: s.mode,\n approverUserIds: this.stepSelectedUsers[i]\n ? [this.stepSelectedUsers[i]]\n : s.assigneeUserIds\n }));\n }\n }\n } else {\n request.steps = this.adHocSteps.map((s, i) => ({\n stepOrder: i + 1,\n stepName: s.stepName,\n mode: ApprovalStepMode.Sequential,\n approverUserIds: s.approverUserIds\n }));\n }\n\n this.approvalSvc!.createApproval(request).pipe(takeUntil(this.destroy$)).subscribe({\n next: (result) => {\n this.isSubmitted = true;\n this.submitting = false;\n this.approvalSubmitted.emit({ documentId: result.documentId, message: result.message });\n },\n error: (err) => {\n this.submitting = false;\n this.errorMessage = err?.error?.message || 'Failed to submit approval. Please try again.';\n }\n });\n } catch (err: any) {\n this.submitting = false;\n this.errorMessage = err?.message || 'Failed to capture content.';\n }\n }\n\n onCancel() {\n this.cancelled.emit();\n }\n\n // ====================== Content Capture ======================\n\n async captureContent(): Promise<string> {\n const host = this.contentBody.nativeElement;\n\n // Step 1: Build canvas -> img map from the live DOM\n const canvasMap = new Map<Element, HTMLImageElement>();\n host.querySelectorAll('canvas').forEach((canvas) => {\n try {\n const img = document.createElement('img');\n img.src = (canvas as HTMLCanvasElement).toDataURL('image/png');\n img.style.width = canvas.offsetWidth + 'px';\n img.style.height = canvas.offsetHeight + 'px';\n canvasMap.set(canvas, img);\n } catch {}\n });\n\n // Step 2: Deep clone\n const clone = host.cloneNode(true) as HTMLElement;\n\n // Step 3: Replace canvas nodes in clone with img snapshots\n const originalCanvases = Array.from(host.querySelectorAll('canvas'));\n clone.querySelectorAll('canvas').forEach((cloneCanvas, idx) => {\n const img = canvasMap.get(originalCanvases[idx]);\n if (img) cloneCanvas.replaceWith(img.cloneNode(true));\n });\n\n // Step 4: Inline all <img> sources as base64 data URIs for content integrity\n const imgElements = Array.from(clone.querySelectorAll('img')) as HTMLImageElement[];\n await Promise.all(imgElements.map(async (img) => {\n const src = img.getAttribute('src');\n if (!src || src.startsWith('data:')) return;\n try {\n const resp = await fetch(src, { mode: 'cors', credentials: 'same-origin' });\n if (!resp.ok) return;\n const blob = await resp.blob();\n const dataUri = await new Promise<string>((resolve) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result as string);\n reader.readAsDataURL(blob);\n });\n img.setAttribute('src', dataUri);\n } catch { /* keep original src if fetch fails */ }\n }));\n\n // Step 5: Inline only essential layout styles (skip colors, widths, cursors)\n const liveElements = Array.from(host.querySelectorAll('*'));\n const cloneElements = Array.from(clone.querySelectorAll('*'));\n const styleProps = this.getStyleProperties();\n\n liveElements.forEach((liveEl, i) => {\n const cloneEl = cloneElements[i] as HTMLElement;\n if (!cloneEl || typeof cloneEl.setAttribute !== 'function') return;\n try {\n const computed = window.getComputedStyle(liveEl as Element);\n const styles: string[] = [];\n styleProps.forEach(prop => {\n const val = computed.getPropertyValue(prop);\n if (val && val !== '' && val !== 'initial' && val !== 'normal' && val !== 'none' && val !== 'auto') {\n styles.push(`${prop}:${val}`);\n }\n });\n if (styles.length) cloneEl.setAttribute('style', styles.join(';'));\n } catch {}\n });\n\n // Step 6: Strip scripts, Angular attributes, style/link tags, and form elements\n clone.querySelectorAll('script, link, style').forEach(el => el.remove());\n clone.querySelectorAll('*').forEach(el => {\n // Remove Angular-specific attributes\n Array.from(el.attributes).forEach(attr => {\n if (attr.name.startsWith('_ngcontent-') ||\n attr.name.startsWith('_nghost-') ||\n attr.name.startsWith('ng-reflect-') ||\n attr.name.startsWith('ng-version') ||\n attr.name.startsWith('on') ||\n attr.name === 'cformcontrol' ||\n attr.name === 'clabel') {\n el.removeAttribute(attr.name);\n }\n });\n // Remove class attribute (framework-specific classes add no value)\n el.removeAttribute('class');\n });\n\n // Step 7: Wrap in a clean, print-friendly HTML document\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n *, *::before, *::after { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n margin: 0; padding: 24px;\n color: #212121; background: #fff;\n font-size: 14px; line-height: 1.6;\n max-width: 210mm;\n }\n h1, h2, h3, h4, h5, h6 { color: #1565c0; margin: 0 0 12px; }\n p { margin: 0 0 8px; }\n img { max-width: 100%; }\n table { border-collapse: collapse; width: 100%; }\n td, th { padding: 8px 12px; border: 1px solid #ddd; text-align: left; vertical-align: top; }\n input, textarea, select { \n border: 1px solid #ccc; border-radius: 4px; padding: 6px 10px;\n font-size: 14px; width: 100%; background: #fafafa; color: #333;\n }\n label { font-weight: 500; display: block; margin-bottom: 4px; color: #333; }\n div { max-width: 100%; }\n </style>\n</head>\n<body>\n${clone.outerHTML}\n</body>\n</html>`;\n }\n\n private async captureThumbnail(): Promise<string | undefined> {\n const html2canvas = (window as any)['html2canvas'];\n if (!html2canvas) return undefined;\n\n const canvas: HTMLCanvasElement = await html2canvas(this.contentBody.nativeElement, {\n scale: 1, useCORS: true, logging: false, width: 600, height: 400\n });\n return canvas.toDataURL('image/png').split(',')[1];\n }\n\n private getStyleProperties(): string[] {\n // Only capture essential layout/typography — NOT colors, widths, or cursor styles\n // Colors and backgrounds are handled by the clean document stylesheet instead\n return [\n 'font-size', 'font-weight', 'font-style', 'line-height', 'text-align', 'text-decoration',\n 'border', 'border-top', 'border-right', 'border-bottom', 'border-left',\n 'border-width', 'border-style', 'border-radius',\n 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'display', 'flex-direction', 'flex-wrap', 'justify-content', 'align-items', 'gap',\n 'vertical-align', 'table-layout', 'border-collapse', 'border-spacing',\n 'text-transform', 'letter-spacing', 'white-space', 'word-break'\n ];\n }\n}\n","import { HttpResponse } from '@angular/common/http';\nimport { map } from 'rxjs/operators';\nimport { OperatorFunction } from 'rxjs';\n\nexport interface PermissionHeader {\n resource: string;\n allowedActions: string[];\n}\n// ─── Utility: extract allowedActions from x-ma-perm header ───\n \nexport function extractXMaPerm(response: HttpResponse<unknown>): string[] {\n const raw = response.headers.get('x-ma-perm');\n if (!raw) return [];\n \n try {\n const parsed = JSON.parse(raw) as PermissionHeader;\n return parsed?.allowedActions ?? [];\n } catch {\n console.warn('[extractXMaPerm] Failed to parse x-ma-perm header:', raw);\n return [];\n }\n}\n \n// ─── RxJS operator: pipe it on any HttpClient call ───\n \nexport function withXMaPerm<T>(): OperatorFunction<\n HttpResponse<T>,\n { data: T; allowedActions: string[] }\n> {\n return map((response: HttpResponse<T>) => ({\n data: response.body as T,\n allowedActions: extractXMaPerm(response),\n }));\n}","import { resource, inject } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { firstValueFrom } from 'rxjs';\nimport { extractXMaPerm } from './x-ma-perm.pipe';\n\nexport function createXMaResource<T>(url: string) {\n const http = inject(HttpClient);\n\n return resource({\n loader: async () => {\n const response = await firstValueFrom(\n http.get<T>(url, { observe: 'response' })\n );\n\n return {\n data: response.body as T,\n allowedActions: extractXMaPerm(response),\n };\n },\n });\n}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.MesAuthService","i3.ThemeService","i1.ToastService","i2.ThemeService","i2.ToastService"],"mappings":"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"}
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, NgZone, EnvironmentProviders, OnDestroy, OnInit, EventEmitter, ChangeDetectorRef, AfterViewInit, ElementRef } from '@angular/core';
3
- import { HttpClient, HttpInterceptorFn } from '@angular/common/http';
4
- import { Observable } from 'rxjs';
3
+ import { HttpClient, HttpInterceptorFn, HttpResponse } from '@angular/common/http';
4
+ import { Observable, OperatorFunction } from 'rxjs';
5
5
  import { Router } from '@angular/router';
6
6
  import { SafeHtml } from '@angular/platform-browser';
7
7
 
@@ -655,5 +655,20 @@ declare class MaArvContainerComponent implements OnInit, OnDestroy {
655
655
  static ɵcmp: i0.ɵɵComponentDeclaration<MaArvContainerComponent, "ma-arv-container", never, { "title": { "alias": "title"; "required": false; }; "description": { "alias": "description"; "required": false; }; "referenceId": { "alias": "referenceId"; "required": false; }; "templateId": { "alias": "templateId"; "required": false; }; "callbackUrl": { "alias": "callbackUrl"; "required": false; }; "deadlineHours": { "alias": "deadlineHours"; "required": false; }; }, { "approvalSubmitted": "approvalSubmitted"; "approvalSubmitting": "approvalSubmitting"; "cancelled": "cancelled"; }, never, ["*"], true, never>;
656
656
  }
657
657
 
658
- export { ApprovalActionType, ApprovalDocumentStatus, ApprovalStepMode, ApprovalStepStatus, MES_AUTH_CONFIG, MaApprovalPanelComponent, MaApprovalService, MaArvContainerComponent, MaUserComponent, MesAuthModule, MesAuthService, NotificationBadgeComponent, NotificationPanelComponent, NotificationType, ThemeService, ToastContainerComponent, ToastService, UserProfileComponent, mesAuthInterceptor, provideMesAuth };
659
- export type { ApprovalDashboardDto, ApprovalDocumentDto, ApprovalDocumentSummaryDto, ApprovalHistoryDto, ApprovalReferenceDto, ApprovalStepDto, ApprovalStepRequest, ApprovalSubmitResult, ApprovalTemplateDto, ApprovalTemplateStepDto, ApprovalTemplateSummaryDto, ApproveRejectRequest, CreateApprovalRequest, CreateApprovalResponseDto, CreateApprovalTemplateRequest, DelegateRequest, FrontEndRoute, IUser, MesAuthConfig, NotificationDto, PagedList, RealTimeNotificationDto, RolePreviewUserDto, StepRoleDto, Theme, Toast, UpdateApprovalTemplateRequest, UserFrontEndRoutesGrouped };
658
+ interface PermissionHeader {
659
+ resource: string;
660
+ allowedActions: string[];
661
+ }
662
+ declare function extractXMaPerm(response: HttpResponse<unknown>): string[];
663
+ declare function withXMaPerm<T>(): OperatorFunction<HttpResponse<T>, {
664
+ data: T;
665
+ allowedActions: string[];
666
+ }>;
667
+
668
+ declare function createXMaResource<T>(url: string): i0.ResourceRef<{
669
+ data: T;
670
+ allowedActions: string[];
671
+ }>;
672
+
673
+ export { ApprovalActionType, ApprovalDocumentStatus, ApprovalStepMode, ApprovalStepStatus, MES_AUTH_CONFIG, MaApprovalPanelComponent, MaApprovalService, MaArvContainerComponent, MaUserComponent, MesAuthModule, MesAuthService, NotificationBadgeComponent, NotificationPanelComponent, NotificationType, ThemeService, ToastContainerComponent, ToastService, UserProfileComponent, createXMaResource, extractXMaPerm, mesAuthInterceptor, provideMesAuth, withXMaPerm };
674
+ export type { ApprovalDashboardDto, ApprovalDocumentDto, ApprovalDocumentSummaryDto, ApprovalHistoryDto, ApprovalReferenceDto, ApprovalStepDto, ApprovalStepRequest, ApprovalSubmitResult, ApprovalTemplateDto, ApprovalTemplateStepDto, ApprovalTemplateSummaryDto, ApproveRejectRequest, CreateApprovalRequest, CreateApprovalResponseDto, CreateApprovalTemplateRequest, DelegateRequest, FrontEndRoute, IUser, MesAuthConfig, NotificationDto, PagedList, PermissionHeader, RealTimeNotificationDto, RolePreviewUserDto, StepRoleDto, Theme, Toast, UpdateApprovalTemplateRequest, UserFrontEndRoutesGrouped };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mesauth-angular",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "Angular helper library to connect to a backend API and SignalR hub to surface the current logged-in user and incoming notifications with dark/light theme support",
5
5
  "keywords": [
6
6
  "angular",
@@ -18,9 +18,16 @@
18
18
  "@angular/router": "^20.0.0",
19
19
  "rxjs": "^7"
20
20
  },
21
+ "peerDependenciesMeta": {
22
+ "@angular/platform-browser": {
23
+ "optional": true
24
+ },
25
+ "@angular/router": {
26
+ "optional": true
27
+ }
28
+ },
21
29
  "dependencies": {
22
30
  "@microsoft/signalr": "^7.0.0",
23
- "rxjs": "^7",
24
31
  "tslib": "^2.3.0"
25
32
  },
26
33
  "angularCompilerOptions": {